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);
  }

这里有一些步骤可以帮助人们尝试同样的事情(一些步骤是一般步骤,与上面的问题没有直接关系)。

  1. 确保在端点菜单下启用了网络操作。
  2. 在同一屏幕下检查原始 HTTP 处理选项(您将看到的大多数文档与使用 Node.js + Express 有关。人们在 Express 中遇到的错误是相同的,即header 和 body 数据中的原始签名数据是验证签名所必需的。这适用于无论您是使用 Stripe 的包还是手动验证签名。)
  3. 处理'base64'编码的正文数据。
  4. 如果来自 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'}
   };
};