w7corp/easywechat · error · InvalidConfigException
Missing platform certificate.
Error message
Missing platform certificate.
What it means
Thrown by Pay/Client::withSerialHeader() when the merchant config carries no platform certificates, so there is no serial number to put in the Wechatpay-Serial header. Sensitive-request encryption and certificate-related endpoints require telling WeChat Pay which platform cert/public key you encrypt with; with zero certs loaded there is nothing to choose from.
Source
Thrown at src/Pay/Client.php:198
$uri = '/'.ltrim((new Uri($url))->getPath(), '/');
foreach (self::V3_URI_PREFIXES as $prefix) {
if (str_starts_with($uri, $prefix)) {
return true;
}
}
return false;
}
/**
* @throws InvalidArgumentException
*/
public function withSerialHeader(?string $serial = null): static
{
$platformCerts = $this->merchant->getPlatformCerts();
if (empty($platformCerts)) {
throw new InvalidConfigException('Missing platform certificate.');
}
$serial ??= array_key_first($platformCerts);
$this->withHeader('Wechatpay-Serial', $serial);
return $this;
}
/**
* @param array<int, mixed> $arguments
*/
public function __call(string $name, array $arguments): mixed
{
if (\str_starts_with($name, 'with')) {
return $this->handleMagicWithCall($name, $arguments[0] ?? null);
}
return $this->client->$name(...$arguments);View on GitHub (pinned to f0cf0a8b83)
Solutions
- Download current platform certificate(s) via GET /v3/certificates (the official CertificateDownloader tool) and pass them as the platformCerts array when constructing Merchant
- Load the PEM file contents (or PublicKey instances) from a persistent path instead of env-only config
- Verify the array is non-empty right after building the Application and fail fast at boot
Example fix
// before
$merchant = new \EasyWeChat\Pay\Merchant($mchId, $privateKey, $cert, $secretKey, null /* v2key */);
// no platform certs -> withSerialHeader() throws
// after
$merchant = new \EasyWeChat\Pay\Merchant(
$mchId, $privateKey, $cert, $secretKey, $v2Key,
[ file_get_contents('/certs/wechatpay-platform.pem') ]
); Defensive patterns
Strategy: validation
Validate before calling
$merchant = new Merchant($mchId, $priv, $cert, $key, $v2, $platformCerts);
if (count($merchant->getPlatformCerts()) === 0) {
throw new \RuntimeException('No WeChat Pay platform certs loaded - run CertificateDownloader');
} Type guard
function hasPlatformCerts(\EasyWeChat\Pay\Contracts\Merchant $m): bool
{
return count($m->getPlatformCerts()) > 0;
} Try / catch
try {
$app->client->withSerialHeader();
} catch (\EasyWeChat\Kernel\Exceptions\InvalidConfigException $e) {
// download certs, rebuild Merchant, retry once
} Prevention
- Download platform certs during provisioning and load them from a known path
- Boot-time assertions on merchant config completeness
- Track WeChat cert/public-key rotation notices and keep multiple generations loaded
When it happens
Trigger: Calling pay APIs that trigger withSerialHeader() — e.g. POST with encryption (marketing/redemption codes), GET /v3/certificates flow setups — when the Merchant was constructed without the platformCerts array (default []) or it resolved empty.
Common situations: Fresh integration that only set mchId/privateKey/certificate/secretKey but never downloaded platform certs; certs loaded from env var that is empty; passing an empty string instead of an array; new deployments after cert rotation removed old files.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Invalid platform certficate.
- Missing platform certificate.
- Missing V2 API key.
- V2 secret key is required.
- Encrypt failed.
AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21).
Data as JSON: /api/errors/60c3817c3d10a458.
Report an issue: GitHub.