w7corp/easywechat · error · HttpException

Failed to get jssdk ticket: %s

Error message

Failed to get jssdk ticket: %s

What it means

Thrown by JsApiTicket::getTicket() when GET /cgi-bin/get_jsapi_ticket returns no ticket field. The request rides on the corp access_token (injected by middleware), so a missing ticket almost always means the underlying access_token was invalid/expired and WeChat returned an errcode body instead of a ticket.

Source

Thrown at src/Work/JsApiTicket.php:76

        return sha1(sprintf('jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s', $ticket, $nonce, $timestamp, $url));
    }

    /**
     * @throws HttpException
     */
    public function getTicket(): string
    {
        $key = $this->getKey();
        $ticket = $this->cache->get($key);

        if ($ticket && is_string($ticket)) {
            return $ticket;
        }

        $response = $this->httpClient->request('GET', '/cgi-bin/get_jsapi_ticket')->toArray(false);

        if (empty($response['ticket'])) {
            throw new HttpException('Failed to get jssdk ticket: '.json_encode($response, JSON_UNESCAPED_UNICODE));
        }

        $this->cache->set($key, $response['ticket'], intval($response['expires_in']));

        return $response['ticket'];
    }

    public function setKey(string $key): static
    {
        $this->key = $key;

        return $this;
    }

    public function getKey(): string
    {
        return $this->key ?? $this->key = sprintf('work.jsapi_ticket.%s', $this->corpId);
    }

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Inspect the embedded JSON for errcode; 42001/40014 mean the access_token chain is bad
  2. Flush the cached access_token and jsapi_ticket (both keys) so fresh ones are fetched with current credentials
  3. Verify corpid/secret still match the app; re-copy if rotated
  4. Check the JS-SDK trusted domain and app permissions in the admin console

Example fix

// before
$work->jsapi_ticket->getTicket(); // fails with stale cached token
// after - force fresh credentials
$work->access_token->cache->delete($work->access_token->getKey());
$work->jsapi_ticket->cache->delete($work->jsapi_ticket->getKey());
$ticket = $work->jsapi_ticket->getTicket();
Defensive patterns

Strategy: try-catch

Validate before calling

if (! preg_match('/^ww[0-9a-f]+$/', $config['corp_id'])) { /* fail fast */ }

Try / catch

use EasyWeChat\Kernel\Exceptions\HttpException;
try {
    $ticket = $work->jsapi_ticket->getTicket();
} catch (HttpException $e) {
    // likely bad access_token chain: clear caches once and retry
    $work->access_token->cache->delete($work->access_token->getKey());
    $work->jsapi_ticket->cache->delete($work->jsapi_ticket->getKey());
    $ticket = $work->jsapi_ticket->getTicket();
}

Prevention

When it happens

Trigger: Calling getTicket() (or JS-SDK config/signature generation) after the cached jsapi_ticket expires. Produced by invalid corpsecret (access_token already bad), stale cached access_token (e.g. secret rotated while token cached, errcode 40014/42001), or missing JS-SDK domain permission.

Common situations: Building a JS-SDK signature in a web page after a secret rotation; cache holding an access_token obtained with old credentials; the trusted domain for JS-SDK not configured; multi-process apps with a split cache writing tokens from different secrets.

Related errors


AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21). Data as JSON: /api/errors/3031888a7cf7521d. Report an issue: GitHub.