Stripe Webhook 签名检查 - Node js - IBM Functions / OpenWhisk
Stripe Webhook Signature Checks - Node js - IBM Functions / OpenWhisk
当我尝试验证 Stripe Webhook 的签名时出现某种编码问题。我知道这不是 Stripe 包本身的问题,因为我在尝试手动散列 body 数据并将 HMAC-256SHA 签名与 headers 中来自 Stripe 的签名进行比较时得到了不同的签名。我对很多不同的部分尝试了很多不同的东西,所以我可能犯了很多错误。
您在这里看不到,但 IBM Cloud Function 已设置为传递原始 HTTP 数据,这就是您使用解码函数的原因。
webhook 成功,无需验证签名。
Stripe 事件函数生成的错误是,“找不到与有效负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求 body?”
注意:尝试调试此问题时,此处的错误处理不正确。
const stripe = require('stripe')('sk_test_********’);
var crypto = require('crypto');
// tried with the CLI secret and the one from the dashboard.
const endpointSecret = 'whsec_****’;
// Convert the stripe signature in string format to a JSON object
function sig_conversion(data){
var sig_obj = {}
var data_list = data.split(",").map((x)=>x.split("="));
var data_json = data_list.map((x)=>{sig_obj[x[0]] = x[1]})
return sig_obj
}
function decode(args) {
var decoded = new Buffer.from(args.__ow_body, 'base64')//.toString('utf-8')
return {body: decoded}
}
function main(params){
//let sig = sig_conversion(params.__ow_headers['stripe-signature']);
let sig = params.__ow_headers['stripe-signature']
let signature = sig_conversion(params.__ow_headers['stripe-signature']);
//console.log(222, signature);
var data = decode(params);
let event;
// Trying to see the result from manually checking the signatures.
var signed_payload = data.body + "." + signature.t
var hmac = crypto.createHmac('sha256', endpointSecret);
var hmac_sig = hmac.update(signed_payload);
var gen_hmac= hmac_sig.digest('hex');
console.log(gen_hmac, 222, signature, 444)
try {
event = stripe.webhooks.constructEvent(JSON.parse(data.body), sig, endpointSecret);
//event = JSON.parse(data.body);
}
这里有一些步骤可以帮助人们尝试同样的事情(一些步骤是一般步骤,与上面的问题没有直接关系)。
- 确保在端点菜单下启用了网络操作。
- 在同一屏幕下检查原始 HTTP 处理选项(您将看到的大多数文档与使用 Node.js + Express 有关。人们在 Express 中遇到的错误是相同的,即header 和 body 数据中的原始签名数据是验证签名所必需的。这适用于无论您是使用 Stripe 的包还是手动验证签名。)
- 处理'base64'编码的正文数据。
- 如果来自 Stripe CLI 工具的端点密码不起作用,请尝试来自仪表板的那个;反之亦然。
注意:使用 Google Cloud Functions 或 Pub-sub 的人可能会遇到类似的签名验证问题。
function decode(args) {
var decoded = new Buffer.from(args.__ow_body, 'base64')
return {body: decoded}
}
// Match the raw body to content type application/json
function main(params){
let sig = params.__ow_headers['stripe-signature']
var data = decode(params);
let event;
try {
event = stripe.webhooks.constructEvent(data.body, sig, endpointSecret);
}
// The rest is the same as the stripe boilerplate code.
catch (err) {
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('PaymentIntent was successful!')
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
console.log('PaymentMethod was attached to a Customer!')
break;
// ... handle other event types
default:
// Unexpected event type
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
}
// Return a response to acknowledge receipt of the event
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
};
当我尝试验证 Stripe Webhook 的签名时出现某种编码问题。我知道这不是 Stripe 包本身的问题,因为我在尝试手动散列 body 数据并将 HMAC-256SHA 签名与 headers 中来自 Stripe 的签名进行比较时得到了不同的签名。我对很多不同的部分尝试了很多不同的东西,所以我可能犯了很多错误。
您在这里看不到,但 IBM Cloud Function 已设置为传递原始 HTTP 数据,这就是您使用解码函数的原因。
webhook 成功,无需验证签名。
Stripe 事件函数生成的错误是,“找不到与有效负载的预期签名匹配的签名。您是否传递了从 Stripe 收到的原始请求 body?”
注意:尝试调试此问题时,此处的错误处理不正确。
const stripe = require('stripe')('sk_test_********’);
var crypto = require('crypto');
// tried with the CLI secret and the one from the dashboard.
const endpointSecret = 'whsec_****’;
// Convert the stripe signature in string format to a JSON object
function sig_conversion(data){
var sig_obj = {}
var data_list = data.split(",").map((x)=>x.split("="));
var data_json = data_list.map((x)=>{sig_obj[x[0]] = x[1]})
return sig_obj
}
function decode(args) {
var decoded = new Buffer.from(args.__ow_body, 'base64')//.toString('utf-8')
return {body: decoded}
}
function main(params){
//let sig = sig_conversion(params.__ow_headers['stripe-signature']);
let sig = params.__ow_headers['stripe-signature']
let signature = sig_conversion(params.__ow_headers['stripe-signature']);
//console.log(222, signature);
var data = decode(params);
let event;
// Trying to see the result from manually checking the signatures.
var signed_payload = data.body + "." + signature.t
var hmac = crypto.createHmac('sha256', endpointSecret);
var hmac_sig = hmac.update(signed_payload);
var gen_hmac= hmac_sig.digest('hex');
console.log(gen_hmac, 222, signature, 444)
try {
event = stripe.webhooks.constructEvent(JSON.parse(data.body), sig, endpointSecret);
//event = JSON.parse(data.body);
}
这里有一些步骤可以帮助人们尝试同样的事情(一些步骤是一般步骤,与上面的问题没有直接关系)。
- 确保在端点菜单下启用了网络操作。
- 在同一屏幕下检查原始 HTTP 处理选项(您将看到的大多数文档与使用 Node.js + Express 有关。人们在 Express 中遇到的错误是相同的,即header 和 body 数据中的原始签名数据是验证签名所必需的。这适用于无论您是使用 Stripe 的包还是手动验证签名。)
- 处理'base64'编码的正文数据。
- 如果来自 Stripe CLI 工具的端点密码不起作用,请尝试来自仪表板的那个;反之亦然。
注意:使用 Google Cloud Functions 或 Pub-sub 的人可能会遇到类似的签名验证问题。
function decode(args) {
var decoded = new Buffer.from(args.__ow_body, 'base64')
return {body: decoded}
}
// Match the raw body to content type application/json
function main(params){
let sig = params.__ow_headers['stripe-signature']
var data = decode(params);
let event;
try {
event = stripe.webhooks.constructEvent(data.body, sig, endpointSecret);
}
// The rest is the same as the stripe boilerplate code.
catch (err) {
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
}
// Handle the event
switch (event.type) {
case 'payment_intent.succeeded':
const paymentIntent = event.data.object;
console.log('PaymentIntent was successful!')
break;
case 'payment_method.attached':
const paymentMethod = event.data.object;
console.log('PaymentMethod was attached to a Customer!')
break;
// ... handle other event types
default:
// Unexpected event type
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
}
// Return a response to acknowledge receipt of the event
return {
body: {payload:''},
statusCode:200,
headers:{ 'Content-Type': 'application/json'}
};
};