Cartalyst Stripe(PHP)技术咨询:PaymentIntent与支付网关衔接疑问
解决方案:从PaymentIntent衔接Stripe支付表单的正确流程
你之前自行收集支付数据创建Charge的方式确实不符合Stripe的安全规范——Stripe要求所有支付敏感数据必须直接提交给Stripe服务器,绝对不能经过你的后端系统。结合Cartalyst v2 + PHP的场景,正确的衔接流程如下:
1. 后端创建PaymentIntent并返回客户端密钥
在PHP后端通过Cartalyst v2创建PaymentIntent,核心是获取client_secret,这个密钥是前端和Stripe通信的唯一凭证。
示例代码:
use Cartalyst\Stripe\Stripe; $stripe = Stripe::make('你的Stripe秘钥'); $paymentIntent = $stripe->paymentIntents()->create([ 'amount' => 1000, // 单位为分,对应10美元 'currency' => 'usd', // 可选:关联客户ID、订单元数据等 'customer' => 'cus_XXXXXX', 'metadata' => ['order_id' => '12345'] ]); // 将client_secret返回给前端(可通过API接口或渲染到页面模板) $clientSecret = $paymentIntent['client_secret'];
2. 前端用Stripe Elements收集支付信息
前端引入Stripe官方的Elements组件,用拿到的client_secret初始化,渲染安全的支付表单——用户在这里输入的卡号、CVV等敏感数据会直接提交给Stripe,完全不经过你的服务器。
示例前端代码:
<!-- 引入Stripe.js --> <script src="https://js.stripe.com/v3/"></script> <!-- 支付卡片输入容器 --> <div id="card-element"></div> <button id="pay-btn">完成支付</button> <script> // 初始化Stripe实例 const stripe = Stripe('你的Stripe公钥'); const elements = stripe.elements(); // 创建并挂载卡片输入组件 const cardElement = elements.create('card'); cardElement.mount('#card-element'); // 绑定支付提交事件 document.getElementById('pay-btn').addEventListener('click', async () => { const { error, paymentIntent } = await stripe.confirmCardPayment( '后端返回的client_secret', { payment_method: { card: cardElement, billing_details: { name: '客户姓名' } } } ); if (error) { // 处理支付错误,比如提示用户 alert(error.message); } else { // 前端仅做初步反馈,最终状态以Webhook通知为准 if (paymentIntent.status === 'succeeded') { alert('支付提交成功,等待确认'); } } }); </script>
3. 依赖Webhook完成后端最终逻辑
无论前端返回什么状态,都必须以Stripe的Webhook通知作为支付结果的最终依据(比如监听payment_intent.succeeded事件),在后端处理订单更新、库存扣减等核心业务。
Cartalyst v2处理Webhook的示例:
use Cartalyst\Stripe\Webhook; $webhook = Webhook::make('你的Webhook签名密钥'); // 获取请求原始内容和签名头 $payload = file_get_contents('php://input'); $signature = $_SERVER['HTTP_STRIPE_SIGNATURE']; try { $event = $webhook->constructEvent($payload, $signature, '你的Webhook端点Secret'); if ($event->type === 'payment_intent.succeeded') { $paymentIntent = $event->data->object; // 根据元数据中的订单ID更新状态 $orderId = $paymentIntent['metadata']['order_id']; // 执行订单完成逻辑:标记支付成功、发送通知等 } } catch (\Exception $e) { // 签名验证失败,返回400状态码 http_response_code(400); exit(); }
补充:更简化的托管式支付方案
如果不想自己开发前端表单,也可以用Stripe Checkout:后端创建PaymentIntent后生成Checkout会话,直接引导用户跳转至Stripe托管的支付页面,支付完成后自动跳转回你的网站,全程无需自己处理支付信息收集。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

