api.use(async (ctx, next) => {
if (ctx.path === '/webhook') {
const sig = ctx.request.headers['stripe-signature'];
unparsed = Symbol.for('unparsedBody')
try {
event = stripe.webhooks.constructEvent(ctx.request.body[unparsed], sig, endpointSecret);
}
catch (err) {
console.log("error", err)
}
构造事件函数报告此错误: StripeSignatureVerificationError:未找到与有效负载的预期签名匹配的签名。
所以我确信endpointSecret是正确的,我也传递了unparsedBody。所以我猜测这是签名错误,所以我使用这个函数来验证签名:
function verifyWebhookSignature(signatureHeader, payload, secret) {
try {
// Step 1: Extract the timestamp and signatures
const elements = signatureHeader.split(',');
let timestamp = null;
const signatures = {};
for (const element of elements) {
const [key, value] = element.split('=');
if (key === 't') {
timestamp = parseInt(value, 10);
} else if (key.startsWith('v0')) {
signatures['v0'] = value;
}
}
// If there's no timestamp or signature, or if the timestamp is too old, return false.
console.log("timestamp: ", timestamp)
if (!timestamp || (Date.now() / 1000 - timestamp) > 300) {
return false;
}
// Step 2: Prepare the signed_payload string
const signedPayload = `${timestamp}.${payload}`;
console.log("signedPayload: ", signedPayload)
// Step 3: Determine the expected signature
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
console.log("expectedSignature: ", expectedSignature)
console.log("signatures[v0]: ", signatures['v0'])
// Step 4: Compare the signatures
if (signatures['v0']) {
console.log(100)
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(signatures['v0'], 'hex')
);
} else {
console.log(888)
return false;
}
} catch (error) {
console.log(999)
// Handle any exceptions or errors
console.error(`Signature verification failed: ${error}`);
return false;
}
}
原来这行:
return crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(signatures['v0'], 'hex')
);
始终返回 false。
我打印了大部分数据,如果您需要任何额外的数据,请随时告诉我。
有人知道为什么吗?非常感谢!
据我所知,签名验证可能在几个不同的地方出错。
这些问题通常是由以下几种情况引起的:
const endpointSecret = 'whsec_...';