在PHP中使用Stripe Webhook时出现“无法从标头中提取时间戳和签名”错误

时间:2019-08-07 10:28:05

标签: php stripe-payments webhooks

我正在使用客户端PHP代码(此处为测试模式)将站点从使用Stripe Checkout v2迁移到v3。我已经成功设置了结帐流程,付款后将重定向到成功页面。

在成功页面上,我要输入webhook代码以确认已付款,然后显示一个表格。

已在Stripe仪表板中设置了Webhook,并在Webhook日志中显示为“成功”。

这是结帐的PHP代码:

require('includes/stripe/stripe-v3/init.php');

\Stripe\Stripe::setApiKey('sk_test_...');

$session = \Stripe\Checkout\Session::create([
  'payment_method_types' => ['card'],
  'line_items' => [[
    'name' => 'Example',
    'description' => 'Example description',
    'images' => ['https://example/com/image.png'],
    'amount' => 99,
    'currency' => 'gbp',
    'quantity' => 1,
  ]],
  'success_url' => 'https://example.com/test-payment.php?checkout=v3&payment=success&session_id={CHECKOUT_SESSION_ID}',
  'cancel_url' => 'https://example.com/test-payment?payment=failed',
]);

$session_id = $session->id;

这是JavaScript:

var stripe = Stripe('pk_test_4iEnGexyFSJgXFumnmEXWDlG');
function checkout_redirect() {
    stripe.redirectToCheckout({
      // Make the id field from the Checkout Session creation API response
      // available to this file, so you can provide it as parameter here
      // instead of the {{CHECKOUT_SESSION_ID}} placeholder.
      sessionId: '<?php echo $session_id; ?>'
    }).then(function (result) {
      // If `redirectToCheckout` fails due to a browser or network
      // error, display the localized error message to your customer
      // using `result.error.message`.
    });
}

然后这是用于验证test-payment.php中的webhook的代码:

require('includes/stripe/stripe-v3/init.php');

\Stripe\Stripe::setApiKey('sk_test_...');

$endpoint_secret = 'whsec_...';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
  $event = \Stripe\Webhook::constructEvent(
    $payload, $sig_header, $endpoint_secret
  );
} catch(\UnexpectedValueException $e) {
  // Invalid payload
  http_response_code(400); // PHP 5.4 or greater
  exit();
} catch(\Stripe\Error\SignatureVerification $e) {
  // Invalid signature
  http_response_code(400); // PHP 5.4 or greater
  exit();
}

// Handle the checkout.session.completed event
if ($event->type == 'checkout.session.completed') {
  $session = $event->data->object;

  // Fulfill the purchase...
  handle_checkout_session($session);
}

http_response_code(200);

当重定向到test-payment.php时,它在“ SignatureVerification”上失败,并显示以下错误:

  

异常“ Stripe \ Error \ SignatureVerification”,消息为“无法从标头中提取时间戳和签名”

我试图回显$ _SERVER ['HTTP_STRIPE_SIGNATURE'],但它为空,因此我认为这可能是问题所在,但在解决方法上却陷入困境。

有创意的人吗?还是有一种更简单的方法来验证已付款?

1 个答案:

答案 0 :(得分:0)

问题在于解析sigHeader时。 标头值为[t=1571998117,v1=ba786269057f295aa2a67795f7a70e07f71ff8eb4f5a24ecde0721453a09a461,v0=2d3802ff7fd896b7c4c01b297997e126405e5e2af7938b7ae2a28c11f3ef0d8f]

在传递给constuct()之前,需要先修剪掉[[和']'。

代码:

String signature = headers.get(HEADER_STRIPE_SIGNATURE);
signature = trimSignature(signature)    
Event event = StripeUtil.constructEvent(request, signature, key)