如何在 symfony 5 中实现条带 webhook?
Posted
技术标签:
【中文标题】如何在 symfony 5 中实现条带 webhook?【英文标题】:How to implement stripe webhook in symfony 5? 【发布时间】:2021-06-22 18:26:11 【问题描述】:我已经在我的 symfony 项目中集成了 Stripe 以进行订阅,从 stripe 订阅计划和付款它工作得很好,但问题是我无法以正确的方式实现 webhook,所以我可以知道是否订阅创建、支付等。
到目前为止我做了什么: 在我的订阅控制器中,我创建了到 webhook 的路由:
class SubscriptionController extends AbstractController
/**
* webhook page
*
* @Route("/bonsai_webhook",name="webhookPage")
*/
public function bonsai_webook(Request $request,Response $response)
\Stripe\Stripe::setApiKey('sk_test_...');
$webhookSecret = "whsec_...";
$event = $request->query;
// Parse the message body and check the signature
$signature = $request->headers->get('stripe-signature');
if ($webhookSecret)
try
$event = \Stripe\Webhook::constructEvent(
$request->getcontent(),
$signature,
$webhookSecret
);
catch (\Exception $e)
return new JsonResponse([['error' => $e->getMessage(),'status'=>403]]);
else
$request->query;
$type = $event['type'];
$object = $event['data']['object'];
$manager = $this->getDoctrine()->getManager();
$today = date("Y-m-d",strtotime('today'));
switch ($type)
case 'checkout.session.completed':
// Payment is successful and the subscription is created.
// You should provision the subscription.
$user->setSubEndDate($today);
$manager->persist($user);
$manager->flush();
break;
case 'invoice.paid':
// Continue to provision the subscription as payments continue to be made.
// Store the status in your database and check when a user accesses your service.
// This approach helps you avoid hitting rate limits.
break;
case 'invoice.payment_failed':
// The payment failed or the customer does not have a valid payment method.
// The subscription becomes past_due. Notify your customer and send them to the
// customer portal to update their payment information.
break;
// ... handle other event types
default:
// Unhandled event type
return new JsonResponse([['session'=>$session,'status'=>200]]);
当我跑步时./stripe listen --forward-to https://localhost:8000/bonsai_webhook
并尝试创建我得到的订阅
customer.created [evt_1IYs4HKoLZxEIn3zDY5tFGZV]
2021-03-25 13:13:41 [307] POST http://localhost:8000/bonsai_webhook [evt_1IZ2SeKoLZxEIn3zvx1urxJ1]
在 webhook 路由中我得到了["error":"Unable to extract timestamp and signatures from header","status":403]
没有条纹签名总是空的,我不知道我做错了什么。
我还添加了一些日志
$logger->info($request->headers->get('stripe-signature'),$request->headers->all());
$logger->error($request->headers->get('stripe-signature'),$request->headers->all());
$logger->critical($request->headers->get('stripe-signature'),$request->headers->all());
我从未收到来自触发器 create.subscription.event 的日志
所以我的问题是:如何获得条纹签名?我希望它是我的代码中唯一缺少的东西。
谢谢。
【问题讨论】:
【参考方案1】:您看到的错误表明您在本地使用的 HTTPS 证书未被 Stripe CLI 识别为有效。
我建议使用http://
而不是https://
尝试该命令:
./stripe listen --forward-to http://localhost:8000/bonsai_webhook
如果您的网络服务器允许不安全的本地连接,应该可以正常工作。
【讨论】:
我做到了,但我仍然遇到同样的问题,我得到了["error":"Unable to extract timestamp and signatures from header","status":403]
并在听众[307] POST http://localhost:8000/bonsai_webhook [evt_1IZ2SeKoLZxEIn3zvx1urxJ1]
中得到了这个
尝试取消注释这一行://$signature = $_SERVER['HTTP_STRIPE_SIGNATURE'];
警告:未定义的数组键“HTTP_STRIPE_SIGNATURE”
哦,我认为 Symfony 可能会阻止标头在 $_SERVER
变量中暴露。请改用$signature = $request->headers->get('Stripe-Signature');
。
是的,但这是我一开始所做的。我还有 307 码【参考方案2】:
我只是在条带社区的帮助下弄清楚了,我的服务器试图重定向到 https:// URL(这就是 307 重定向)。在 webhook URL 中设置 https:// 不起作用,因为它是自签名证书。解决方案是在本地应用程序上完全禁用 SSL/HTTPS,而是切换到服务器上的 https 环境。
【讨论】:
我正在使用相同的代码,我正在使用没有 https 的“localhost/webhook”进行测试,我得到“无法从标头中提取时间戳和签名”以上是关于如何在 symfony 5 中实现条带 webhook?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Doctrine 在 Symfony2 中实现子查询?
尝试在我的项目中实现没有 Symfony2 的 Twig 和 Assetic
如何使用node js(服务器端)在移动应用中实现支付机制?