fix: 微信支付回调验签 PEM 格式自动补全,Stripe webhook 失败重试

- wxpay client: 添加 formatPublicKey() 自动包裹 PEM 头尾,修复裸 base64 公钥导致的 DECODER routines::unsupported 错误
- stripe webhook: 处理失败时返回 500 让 Stripe 重试
- 修正支付宝测试用例与实际代码对齐

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
erio
2026-03-07 04:27:38 +08:00
parent 698df1ee47
commit f50a180ec4
4 changed files with 19 additions and 6 deletions

View File

@@ -3,6 +3,12 @@ import crypto from 'crypto';
import { getEnv } from '@/lib/config';
import type { WxpayPcOrderParams, WxpayH5OrderParams, WxpayRefundParams } from './types';
/** 自动补全 PEM 格式(公钥) */
function formatPublicKey(key: string): string {
if (key.includes('-----BEGIN')) return key;
return `-----BEGIN PUBLIC KEY-----\n${key}\n-----END PUBLIC KEY-----`;
}
const BASE_URL = 'https://api.mch.weixin.qq.com';
function assertWxpayEnv(env: ReturnType<typeof getEnv>) {
@@ -29,7 +35,7 @@ function getPayInstance(): WxPay {
if (!env.WXPAY_PUBLIC_KEY) {
throw new Error('WXPAY_PUBLIC_KEY is required');
}
const publicKey = Buffer.from(env.WXPAY_PUBLIC_KEY);
const publicKey = Buffer.from(formatPublicKey(env.WXPAY_PUBLIC_KEY));
payInstance = new WxPay({
appid: env.WXPAY_APP_ID,
@@ -166,5 +172,5 @@ export async function verifyNotifySign(params: {
const message = `${params.timestamp}\n${params.nonce}\n${params.body}\n`;
const verify = crypto.createVerify('RSA-SHA256');
verify.update(message);
return verify.verify(env.WXPAY_PUBLIC_KEY, params.signature, 'base64');
return verify.verify(formatPublicKey(env.WXPAY_PUBLIC_KEY), params.signature, 'base64');
}