{"record":{"id":"649cbb5703cce1a8","repo":"JeffreySu/WeiXinMPSDK","slug":"api-id","errorCode":null,"errorMessage":"品牌 API 响应的微信支付公钥 ID 与配置不匹配。","messagePattern":"品牌 API 响应的微信支付公钥 ID 与配置不匹配。","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/HttpHandlers/TenPayApiRequest.cs","lineNumber":492,"sourceCode":"                    {\n                        result = new T { VerifySignSuccess = true };\n                    }\n                    else\n                    {\n                        result = content.GetObject<T>();\n                        if (checkSign)\n                        {\n                            var timestamp = responseMessage.Headers.GetValues(\"Wechatpay-Timestamp\").First();\n                            var nonce = responseMessage.Headers.GetValues(\"Wechatpay-Nonce\").First();\n                            var signature = responseMessage.Headers.GetValues(\"Wechatpay-Signature\").First();\n                            var serial = responseMessage.Headers.GetValues(\"Wechatpay-Serial\").First();\n                            if (_brandApiCredentials != null)\n                            {\n                                if (!string.Equals(serial,\n                                    _brandApiCredentials.WechatpayPublicKeyId,\n                                    StringComparison.Ordinal))\n                                {\n                                    throw new InvalidOperationException(\n                                        \"品牌 API 响应的微信支付公钥 ID 与配置不匹配。\");\n                                }\n\n                                result.VerifySignSuccess =\n                                    TenPaySignHelper.VerifyTenpaySign(\n                                        CertType.RSA, timestamp, nonce,\n                                        signature, content,\n                                        _brandApiCredentials.WechatpayPublicKey,\n                                        true);\n                            }\n                            else\n                            {\n                                var publicKey = await TenPayV3InfoCollection\n                                    .GetAPIv3PublicKeyAsync(_tenpayV3Setting,\n                                        serial, cancellationToken)\n                                    .ConfigureAwait(false);\n\n                                if (_tenpayV3Setting.EncryptionType == CertType.SM)","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.TenPay/Senparc.Weixin.TenPayV3/HttpHandlers/TenPayApiRequest.cs#L474-L510","documentation":"When brand API credentials are configured, the multipart response's Wechatpay-Serial header is compared with _brandApiCredentials.WechatpayPublicKeyId using an ordinal comparison; on mismatch the library throws InvalidOperationException because the response could not be verified with the configured public key. This guards against MITM or misconfigured platform credentials.","triggerScenarios":"RequestMultipart* call against a brand API endpoint where the response's Wechatpay-Serial differs from the configured WechatpayPublicKeyId (rotated key not updated in config, wrong public key ID configured, or environment mismatch).","commonSituations":"WeChat Pay rotated its platform public key and the app still holds the old ID; copying credentials from sandbox to production; typos or whitespace in the configured key ID.","solutions":["Update WechatpayPublicKeyId in TenPayBrandApiCredentials to the current serial returned in the response's Wechatpay-Serial header.","Confirm you are using brand API credentials only for brand API endpoints (non-brand endpoints use a different verification path).","Re-download the current WeChat Pay platform public key and reconfigure both key and key ID.","Log the response's serial value and compare it with your configured ID to spot the mismatch."],"exampleFix":"// before\nvar creds = new TenPayBrandApiCredentials(mchId, serial: \"PUB_KEY_ID_OLD\", publicKeyPem, privateKey);\n// after — use the serial from the latest Wechatpay-Serial header\nvar creds = new TenPayBrandApiCredentials(mchId, serial: \"PUB_KEY_ID_0114xxxxxxxx\", publicKeyPem, privateKey);","handlingStrategy":"try-catch","validationCode":"// Compare expected serial with what the platform advertises before sending\nvar expectedSerial = brandCredentials.WechatpayPublicKeyId;\nif (string.IsNullOrWhiteSpace(expectedSerial)) throw new InvalidOperationException(\"Brand public key ID not configured.\");","typeGuard":null,"tryCatchPattern":"try { /* multipart request */ }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"公钥 ID\"))\n{\n    logger.LogError(ex, \"Brand key ID mismatch: configured={Expected}\", brandCredentials.WechatpayPublicKeyId);\n    throw; // rotate/refresh credentials before retrying\n}","preventionTips":["Track WeChat Pay key-rotation announcements and update WechatpayPublicKeyId promptly.","Use ordinal-exact serial values copied from the Wechatpay-Serial response header.","Keep brand credentials only on handlers used for brand API endpoints.","Alert on VerifySignSuccess=false / key mismatch in production."],"tags":["signature-verification","configuration","security"],"backgroundTag":"checksum-mismatch","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}