w7corp/easywechat · error · EncryptionFailureException
Encrypt failed.
Error message
Encrypt failed.
What it means
Thrown by Pay/Utils::encryptWithRsaPublicKey() when openssl_public_encrypt() returns false for the resolved platform key. The key object existed, but OpenSSL rejected the operation: the loaded PEM is not a usable public key, the plaintext exceeds the RSA-OAEP payload limit (~214 bytes for 2048-bit, ~446 for 3072), or the key/cert material is corrupt.
Source
Thrown at src/Pay/Utils.php:168
* @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.');
}
ksort($params);
View on GitHub (pinned to f0cf0a8b83)
Solutions
- Verify the loaded PEM is WeChat Pay's PLATFORM public key/cert (subject = WeChat Pay), not your merchant cert or private key
- Check the plaintext length against the key size: for 2048-bit RSA-OAEP keep it under ~214 bytes; encrypt field-by-field, never a JSON blob
- Re-download the cert file and confirm it starts with '-----BEGIN CERTIFICATE-----' (or PUBLIC KEY) and is not truncated; validate with openssl_x509_checkpurpose/openssl_pkey_get_public
Example fix
// before
$platformCerts = [ file_get_contents('/certs/apiclient_cert.pem') ]; // merchant's own cert
// after
$platformCerts = [ file_get_contents('/certs/wechatpay-platform-cert.pem') ];
// and encrypt only the short field:
$enc = $utils->encryptWithRsaPublicKey($bankCard['account_no']); Defensive patterns
Strategy: validation
Validate before calling
$pub = openssl_pkey_get_public($pem);
if ($pub === false) {
throw new \RuntimeException('platform PEM is not a valid public key/cert');
}
$details = openssl_pkey_get_details($pub);
$maxLen = $details['bits'] / 8 - 42; // OAEP overhead
if (strlen($plaintext) > $maxLen) {
throw new \InvalidArgumentException('plaintext too long for RSA-OAEP: encrypt fields separately');
} Type guard
function isUsableRsaPublicKey(string $pem): bool
{
return openssl_pkey_get_public($pem) !== false;
} Try / catch
try {
$enc = $app->utils->encryptWithRsaPublicKey($field);
} catch (\EasyWeChat\Kernel\Exceptions\EncryptionFailureException $e) {
// check: wrong PEM (merchant cert instead of platform key) or payload over OAEP limit
throw new \RuntimeException('RSA encrypt failed - verify platform cert and payload size', 0, $e);
} Prevention
- Validate each cert with openssl_pkey_get_public at load time
- Encrypt one short field per call, never serialized structures
- Keep cert files immutable and checksummed after download
When it happens
Trigger: Encrypting sensitive fields where platformCerts contains a certificate/private key/wrong PEM (normalize only wraps strings into PublicKey, it doesn't verify they're valid public keys), or passing a long buffer (e.g. a concatenated address or JSON blob) beyond the OAEP limit for the key size.
Common situations: Loading the merchant's own certificate instead of WeChat's platform cert/public key; loading a private key PEM; truncated cert file (partial download); encrypting a whole JSON structure instead of a single short field like a name or card number.
Related errors
- Missing platform certificate.
- Encrypt AES ECB failed.
- Read the $certificate failed, please check it whether or nor
- Missing platform certificate.
- Invalid platform certficate.
AI-assisted analysis of w7corp/easywechat@f0cf0a8b83 (2026-08-21).
Data as JSON: /api/errors/da97659266517c49.
Report an issue: GitHub.