{"record":{"id":"3031888a7cf7521d","repo":"w7corp/easywechat","slug":"failed-to-get-jssdk-ticket-s-303188","errorCode":null,"errorMessage":"Failed to get jssdk ticket: %s","messagePattern":"Failed to get jssdk ticket: (.+?)","errorType":"exception","errorClass":"HttpException","httpStatus":null,"severity":"error","filePath":"src/Work/JsApiTicket.php","lineNumber":76,"sourceCode":"        return sha1(sprintf('jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s', $ticket, $nonce, $timestamp, $url));\n    }\n\n    /**\n     * @throws HttpException\n     */\n    public function getTicket(): string\n    {\n        $key = $this->getKey();\n        $ticket = $this->cache->get($key);\n\n        if ($ticket && is_string($ticket)) {\n            return $ticket;\n        }\n\n        $response = $this->httpClient->request('GET', '/cgi-bin/get_jsapi_ticket')->toArray(false);\n\n        if (empty($response['ticket'])) {\n            throw new HttpException('Failed to get jssdk ticket: '.json_encode($response, JSON_UNESCAPED_UNICODE));\n        }\n\n        $this->cache->set($key, $response['ticket'], intval($response['expires_in']));\n\n        return $response['ticket'];\n    }\n\n    public function setKey(string $key): static\n    {\n        $this->key = $key;\n\n        return $this;\n    }\n\n    public function getKey(): string\n    {\n        return $this->key ?? $this->key = sprintf('work.jsapi_ticket.%s', $this->corpId);\n    }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/w7corp/easywechat/blob/f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8/src/Work/JsApiTicket.php#L58-L94","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the embedded JSON for errcode; 42001/40014 mean the access_token chain is bad","Flush the cached access_token and jsapi_ticket (both keys) so fresh ones are fetched with current credentials","Verify corpid/secret still match the app; re-copy if rotated","Check the JS-SDK trusted domain and app permissions in the admin console"],"exampleFix":"// before\n$work->jsapi_ticket->getTicket(); // fails with stale cached token\n// after - force fresh credentials\n$work->access_token->cache->delete($work->access_token->getKey());\n$work->jsapi_ticket->cache->delete($work->jsapi_ticket->getKey());\n$ticket = $work->jsapi_ticket->getTicket();","handlingStrategy":"try-catch","validationCode":"if (! preg_match('/^ww[0-9a-f]+$/', $config['corp_id'])) { /* fail fast */ }","typeGuard":null,"tryCatchPattern":"use EasyWeChat\\Kernel\\Exceptions\\HttpException;\ntry {\n    $ticket = $work->jsapi_ticket->getTicket();\n} catch (HttpException $e) {\n    // likely bad access_token chain: clear caches once and retry\n    $work->access_token->cache->delete($work->access_token->getKey());\n    $work->jsapi_ticket->cache->delete($work->jsapi_ticket->getKey());\n    $ticket = $work->jsapi_ticket->getTicket();\n}","preventionTips":["Use the same Application/credentials everywhere so cached tokens stay consistent","On secret rotation, delete both cached tokens in the same deploy","Check errcode embedded in the message before retrying"],"tags":["wechat-work","jsapi-ticket","js-sdk","access-token","cache"],"backgroundTag":"jsapi-ticket-request-failed","analyzedSha":"f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8","analyzedAt":"2026-08-21T05:29:19.565Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}