w7corp/easywechat · error · HttpException
Failed to get provider_access_token: %s
Error message
Failed to get provider_access_token: %s
What it means
Thrown by ProviderAccessToken::refresh() when the POST to cgi-bin/service/get_provider_token succeeds at HTTP level but the response body contains no provider_access_token key. The full WeChat response (with errcode/errmsg) is JSON-embedded in the exception message, so the real reason is the errcode, not the token itself. This is the service-provider (ISV) token for WeChat Work open platform APIs.
Source
Thrown at src/OpenWork/ProviderAccessToken.php:82
public function toQuery(): array
{
return ['provider_access_token' => $this->getToken()];
}
/**
* @throws HttpException
*/
public function refresh(): string
{
$response = $this->httpClient->request('POST', 'cgi-bin/service/get_provider_token', [
'json' => [
'corpid' => $this->corpId,
'provider_secret' => $this->providerSecret,
],
])->toArray(false);
if (empty($response['provider_access_token'])) {
throw new HttpException('Failed to get provider_access_token: '.\json_encode(
$response,
JSON_UNESCAPED_UNICODE
));
}
$this->cache->set($this->getKey(), $response['provider_access_token'], intval($response['expires_in']));
return $response['provider_access_token'];
}
}
View on GitHub (pinned to f0cf0a8b83)
Solutions
- Read the embedded JSON in the exception message and look up the errcode (40001 invalid secret, 60020 IP not in allowlist, 40013 invalid corpid)
- Verify corpid + provider_secret in the WeChat Work service-provider admin console (login as the provider, not a member corp)
- Add the outbound server IP to the provider IP allowlist and retry
- Clear the token cache key after fixing credentials so refresh() actually re-requests
Example fix
// before (wrong credentials)
$config = ['corp_id' => $memberCorpId, 'provider_secret' => $corpAppSecret];
// after (ISV provider credentials)
$config = [
'corp_id' => $providerCorpId, // the service provider's corpid
'provider_secret' => $providerSecret, // from provider admin console
'secret' => $suiteSecret,
'token' => ..., 'aes_key' => ...,
]; Defensive patterns
Strategy: try-catch
Validate before calling
$candidate = [$corpId, $providerSecret];
if (in_array(null, $candidate, true) || $providerSecret === '') {
throw new \InvalidArgumentException('corp_id/provider_secret missing');
} Try / catch
use EasyWeChat\Kernel\Exceptions\HttpException;
try {
$token = $openWork->provider_access_token->getToken();
} catch (HttpException $e) {
$body = json_decode(substr($e->getMessage(), strlen('Failed to get provider_access_token: ')), true);
logger()->warning('provider token failed', ['errcode' => $body['errcode'] ?? null]);
// 40001/60020 -> credentials/allowlist: do NOT retry; -> alert
} Prevention
- Store provider credentials in one env-driven config validated at boot
- Keep the outbound IP allowlist updated when infrastructure changes
- Cache tokens per the library default so refresh only happens on expiry
When it happens
Trigger: Calling any OpenWork API that needs provider_access_token (e.g. getting auth corp info, corp token) after a cache miss. Fails when: provider_secret is wrong/revoked, corpid of the service provider is wrong, the secret belongs to a different suite/app, or the calling IP is not in the provider's IP allowlist (errcode 40001/40013/60020).
Common situations: Copied provider_secret from the wrong panel (corp app secret instead of provider secret); rotated secret but stale value in .env; server IP changed so allowlist blocks it; confusions between corpid of the ISV vs the authed corp.
Related errors
- Failed to get suite_access_token: %s
- Failed to get auth_corp_info: %s
- Failed to get access_token: %s
- Failed to get jssdk ticket: %s
- Failed to get jssdk agentTicket: %s
AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21).
Data as JSON: /api/errors/c84526683b51a2b4.
Report an issue: GitHub.