{"record":{"id":"01719c8a58734431","repo":"w7corp/easywechat","slug":"failed-to-get-authorizer-access-token-s","errorCode":null,"errorMessage":"Failed to get authorizer_access_token: %s","messagePattern":"Failed to get authorizer_access_token: (.+?)","errorType":"exception","errorClass":"HttpException","httpStatus":null,"severity":"error","filePath":"src/OpenPlatform/Application.php","lineNumber":216,"sourceCode":"    /**\n     * @throws HttpException\n     */\n    public function refreshAuthorizerToken(string $authorizerAppId, string $authorizerRefreshToken): array\n    {\n        $response = $this->getClient()->request(\n            'POST',\n            'cgi-bin/component/api_authorizer_token',\n            [\n                'json' => [\n                    'component_appid' => $this->getAccount()->getAppId(),\n                    'authorizer_appid' => $authorizerAppId,\n                    'authorizer_refresh_token' => $authorizerRefreshToken,\n                ],\n            ]\n        )->toArray(false);\n\n        if (empty($response['authorizer_access_token'])) {\n            throw new HttpException('Failed to get authorizer_access_token: '.json_encode(\n                $response,\n                JSON_UNESCAPED_UNICODE\n            ));\n        }\n\n        return $response;\n    }\n\n    /**\n     * @throws HttpException\n     */\n    public function createPreAuthorizationCode(): array\n    {\n        $response = $this->getClient()->request(\n            'POST',\n            'cgi-bin/component/api_create_preauthcode',\n            [\n                'json' => [","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/w7corp/easywechat/blob/f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8/src/OpenPlatform/Application.php#L198-L234","documentation":"refreshAuthorizerToken() exchanges the stored authorizer_refresh_token for a new authorizer_access_token via cgi-bin/component/api_authorizer_token and throws HttpException with the raw JSON when authorizer_access_token is absent. The refresh token is long-lived but dies when the authorizer cancels the authorization or a re-authorization rotates it, so this error usually means the stored refresh token is no longer current.","triggerScenarios":"The authorizer removed the third-party app or reset authorization in the MP console; an older refresh token is stored after a newer re-authorization overwrote it; a truncated or wrong token was passed; component credentials invalid so the whole call is rejected.","commonSituations":"Re-auth flows that fail to persist the newly returned authorizer_refresh_token; long-lived DB rows going stale after the authorizer re-authorized from another environment sharing the appid; partial writes losing the token column.","solutions":["Read the embedded errcode: an invalid refresh token means re-authorization is required — nothing recovers it in place","Always persist the latest authorizer_refresh_token returned by every handleAuthorizationCode()/refresh call","Trigger the pre-auth flow again to obtain a fresh authorization and replace the stored tokens","Keep one storage (DB row per authorizer_appid) as the single source of truth across environments"],"exampleFix":"// before: refresh token kept from the very first authorization, never updated\n$tokens = $openPlatform->refreshAuthorizerToken($appId, $row->refresh_token);\n\n// after: store whatever the API returns after each refresh\n$tokens = $openPlatform->refreshAuthorizerToken($appId, $row->refresh_token);\n$row->update(['refresh_token' => $tokens['authorizer_refresh_token']]);","handlingStrategy":"try-catch","validationCode":"if (blank($row->refresh_token)) {\n    throw new \\RuntimeException(\"No authorizer_refresh_token stored for {$appId}; re-authorization required.\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    $tokens = $openPlatform->refreshAuthorizerToken($appId, $row->refresh_token);\n} catch (\\EasyWeChat\\Kernel\\Exceptions\\HttpException $e) {\n    // treat as revoked authorization: flag the row, notify ops, start the re-auth flow\n    $row->update(['status' => 'reauth_required']);\n    report($e);\n}","preventionTips":["Persist the rotated authorizer_refresh_token on every exchange and refresh","Model 're-authorization required' as a first-class state in the authorizer table","Never share authorizer credentials between dev and prod flows that re-auth independently"],"tags":["php","easywechat","wechat","open-platform","refresh-token","authorization","http-error"],"backgroundTag":"refresh-token-invalid-or-revoked","analyzedSha":"f0cf0a8b8361417ed683b8246d0ecbaf0aafcaa8","analyzedAt":"2026-08-21T05:29:19.565Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}