w7corp/easywechat · error · InvalidConfigException

Missing platform certificate.

Error message

Missing platform certificate.

What it means

Thrown by Pay/Utils::encryptWithRsaPublicKey() when no platform certificate/public key can be resolved for the target serial: either Merchant has zero platform certs, or the explicit $serial (e.g. taken from a notification's Wechatpay-Serial header) is not among the loaded ones. Sensitive fields (bank card, real name, etc.) must be RSA-OAEP encrypted with WeChat Pay's platform public key identified by serial.

Source

Thrown at src/Pay/Utils.php:164

     * @link https://pay.weixin.qq.com/doc/v3/merchant/4013053257
     * @link https://pay.weixin.qq.com/doc/v3/partner/4013059044
     *
     * @param  string  $plaintext  The text to be encrypted.
     * @param  string|null  $serial  The serial number of the platform certificate to use for encryption. If null, the first available certificate will be used.
     * @return string The base64-encoded encrypted text.
     *
     * @throws InvalidConfigException If no platform certificate is found.
     * @throws EncryptionFailureException If the encryption process fails.
     */
    public function encryptWithRsaPublicKey(string $plaintext, ?string $serial = null): string
    {
        $platformCerts = $this->merchant->getPlatformCerts();
        /** @var string $identifier - One of the serial number of the platform certificates OR the weixin pay's public key identifier. */
        $identifier = $serial ?? array_key_first($platformCerts);
        $platformCert = $this->merchant->getPlatformCert($identifier);

        if (empty($platformCert)) {
            throw new InvalidConfigException('Missing platform certificate.');
        }

        if (! openssl_public_encrypt($plaintext, $encrypted, $platformCert, OPENSSL_PKCS1_OAEP_PADDING)) {
            throw new EncryptionFailureException('Encrypt failed.');
        }

        return base64_encode($encrypted);
    }

    /**
     * @throws InvalidConfigException
     */
    public function createV2Signature(array $params): string
    {
        $secretKey = $this->merchant->getV2SecretKey();

        if (empty($secretKey)) {
            throw new InvalidConfigException('Missing v2 secret key.');

View on GitHub (pinned to f0cf0a8b83)

Solutions

  1. Download the current platform cert(s)/public key via GET /v3/certificates or the public key from console, load them into Merchant, and key them by their serial number
  2. When $serial comes from a notification header, keep multiple cert generations loaded simultaneously so old and new serials both resolve
  3. At boot, assert count($merchant->getPlatformCerts()) > 0 and re-download on a schedule

Example fix

// before
$merchant = new Merchant($mchId, $privateKey, $certificate, $secretKey, $v2Key); // no certs
$utils->encryptWithRsaPublicKey($idNumber); // throws
// after - load keyed by serial so header serials resolve
$merchant = new Merchant($mchId, $privateKey, $certificate, $secretKey, $v2Key, [
    $platformCertPem, // auto-keyed by its serial number
]);
Defensive patterns

Strategy: validation

Validate before calling

$serial = $notificationHeaderWechatpaySerial ?? null;
if ($serial !== null && $merchant->getPlatformCert($serial) === null) {
    // cert generation not loaded: fetch via GET /v3/certificates and register before encrypting
}

Type guard

function canResolvePlatformCert(\EasyWeChat\Pay\Merchant $m, ?string $serial): bool
{
    return $m->getPlatformCert($serial ?? (string) array_key_first($m->getPlatformCerts())) !== null;
}

Try / catch

try {
    $enc = $app->utils->encryptWithRsaPublicKey($value, $serial);
} catch (\EasyWeChat\Kernel\Exceptions\InvalidConfigException $e) {
    if ($e->getMessage() === 'Missing platform certificate.') {
        // load cert generation for $serial, then retry once
    }
}

Prevention

When it happens

Trigger: Calling utils->encryptWithRsaPublicKey($name/number) for sensitive-payment APIs: with no certs loaded at all, with $serial from the callback header while you only loaded an older cert generation, or after WeChat rotated platform certs (new serial in headers, old cert in config).

Common situations: Never downloading platform certs (fresh setup); WeChat's 2024 switch from platform certificates to the 'wechatpay public key' with new serial format (PUB_KEY_ID_xxx) not loaded; certs cached in config but rotation happened after they expire (every 5 years for public key).

Understand the failure class

Related errors


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