添加收货地址后Stripe Payment Request Button无法完成支付
问题分析与修复方案
启用requestShipping: true后支付流程卡住,核心原因集中在三个环节:
- 前端
shippingaddresschange事件的fetch请求格式错误,导致无法正常返回运费选项,弹窗持续等待 - 服务器端返回的运费选项不符合Stripe要求的规范格式
- 确认PaymentIntent时未关联用户选择的收货地址
修复步骤
1. 修正前端fetch请求配置
原代码未指定请求方法、未设置JSON请求头,且数据传递方式错误,修改后代码如下:
paymentRequest.on('shippingaddresschange', function(ev) { if (ev.shippingAddress.country !== 'US') { ev.updateWith({status: 'invalid_shipping_address'}); } else { fetch('/calculateShipping', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content // 适配Laravel CSRF验证 }, body: JSON.stringify({ shippingAddress: ev.shippingAddress }) }).then(function(response) { if (!response.ok) throw new Error('运费计算请求失败'); return response.json(); }).then(function(result) { ev.updateWith({ status: 'success', shippingOptions: result.supportedShippingOptions, }); }).catch(function(error) { ev.updateWith({status: 'fail'}); console.error('请求错误:', error); }); } });
2. 修正服务器端运费选项返回格式
Stripe要求shippingOptions数组的每个选项必须包含id、label、detail、amount四个核心字段,修改服务器端代码:
// 解析前端传递的收货地址 $requestData = json_decode(request()->getContent(), true); $shippingAddress = $requestData['shippingAddress']; // 根据实际业务逻辑生成符合规范的运费选项 $supportedShippingOptions = [ [ 'id' => 'standard', 'label' => 'Standard Shipping', 'detail' => '3-5 business days', 'amount' => 500, // 单位为货币最小单位,此处代表5美元 ], [ 'id' => 'express', 'label' => 'Express Shipping', 'detail' => '1-2 business days', 'amount' => 1000, // 代表10美元 ] ]; return response()->json([ 'supportedShippingOptions' => $supportedShippingOptions ]);
3. 确认PaymentIntent时关联收货地址
在paymentmethod事件中,将用户选择的收货地址传递给Stripe,更新确认支付的参数:
paymentRequest.on('paymentmethod', function(ev) { stripe.confirmCardPayment( clientSecret, { payment_method: ev.paymentMethod.id, // 新增收货地址参数 shipping: { name: ev.shippingAddress.recipient, address: { line1: ev.shippingAddress.addressLine[0], line2: ev.shippingAddress.addressLine[1] || '', city: ev.shippingAddress.city, state: ev.shippingAddress.region, postal_code: ev.shippingAddress.postalCode, country: ev.shippingAddress.country } } }, { handleActions: false } ).then(function(confirmResult) { // 原有逻辑保持不变 if (confirmResult.error) { ev.complete('fail'); } else { ev.complete('success'); if (confirmResult.paymentIntent.status === "requires_action") { stripe.confirmCardPayment(clientSecret).then(function(result) { result.error ? alert('payment failed, try again') : window.location.href = "{{ route('checkout.thankyou') }}"; }); } else { window.location.href = "{{ route('checkout.thankyou') }}"; } } }); });
验证要点
- 打开浏览器控制台,检查
shippingaddresschange事件的fetch请求是否返回200状态码,且JSON格式符合要求 - 查看Stripe Dashboard中的PaymentIntent详情,确认收货地址已正确关联
- 测试非美国地址,验证弹窗是否会提示地址无效
内容的提问来源于stack exchange,提问作者Muhammad Usman
相关产品推荐
相关产品推荐

