Spring Boot集成Stripe支付报错:需改用Payment Intents API
解决Stripe Payment元素支付报错及Token创建问题
问题原因分析
- Charge API报错:后端使用的
ChargeAPI属于Stripe旧版支付流程,而payment元素生成的是PaymentMethod对象,无法通过ChargeAPI的source参数传递,Stripe明确要求此类场景必须使用Payment Intents API。 - createToken失败:
stripe.createToken()仅适配旧版card元素,新版payment元素不支持该方法,调用后必然进入catch块。
具体修复步骤
一、前端代码修改
保留payment元素创建逻辑,调整表单提交流程,直接用Stripe的confirmPayment方法完成支付确认(无需手动传递PaymentMethod到后端):
<form id="payment-form" method="post"> <input id="api-key" type="hidden" value="${stripePublicKey}"> <div class="form-group mb-3"> <div class="w-100" id="card-element"> <!-- A Stripe Element will be inserted here. --> </div> <div id="card-errors" class="text-danger mt-2"></div> </div> <button class="btn w-100 btn-success mt-4" type="submit" id="submitButton">Pay $230</button> </form> <script> const stripe = Stripe($('#api-key').val()); const elements = stripe.elements({clientSecret:'${client_secret}'}); const paymentElement = elements.create('payment'); paymentElement.mount('#card-element'); paymentElement.addEventListener('change', function (event) { $('#card-errors').text(event.error ? event.error.message : ''); }); $('#payment-form').on('submit', async function (e) { e.preventDefault(); $('#submitButton').prop('disabled', true); const { error } = await stripe.confirmPayment({ elements: elements, confirmParams: { return_url: 'https://your-domain.com/payment-success', // 替换为你的支付成功跳转地址 receipt_email: '${customer.email}' }, }); if (error) { $('#card-errors').text(error.message); $('#submitButton').prop('disabled', false); } else { // 支付成功后会自动跳转到return_url,无需额外处理 } }); </script>
二、后端代码修改
移除Charge相关逻辑,改用Payment Intents API处理支付。注意:前端用到的client_secret必须来自后端提前创建的Payment Intent。
1. 调整支付接口
@PostMapping("/create-charge") public @ResponseBody StripeResponse createCharge(String email) { try { Stripe.apiKey = API_SECRET_KEY; // 创建Payment Intent并自动确认支付(根据业务需求调整confirm参数) Map<String, Object> params = new HashMap<>(); params.put("amount", 23000); // $230,单位为分 params.put("currency", "usd"); params.put("receipt_email", email); params.put("payment_method_types", Arrays.asList("card")); params.put("confirm", true); PaymentIntent paymentIntent = PaymentIntent.create(params); return new StripeResponse(true, "支付成功,Intent ID: " + paymentIntent.getId()); } catch (Exception e) { e.printStackTrace(); return new StripeResponse(false, "支付失败: " + e.getMessage()); } }
2. 替换原createCharge方法
@Override public String createCharge(String email, int amount) { try { Stripe.apiKey = API_SECRET_KEY; Map<String, Object> params = new HashMap<>(); params.put("amount", amount); params.put("currency", "usd"); params.put("receipt_email", email); params.put("payment_method_types", Arrays.asList("card")); PaymentIntent intent = PaymentIntent.create(params); return intent.getId(); } catch (Exception e) { e.printStackTrace(); return null; } }
关键注意事项
- 前端的
client_secret必须由后端提前创建Payment Intent生成,不能凭空赋值。 - 建议开启Stripe Webhook监听
payment_intent.succeeded等事件,避免前端跳转异常导致支付状态不一致。 - 若需自定义
payment元素布局,可通过style参数配置,无需退回旧版card元素。
内容的提问来源于stack exchange,提问作者Subhan Pugh
相关产品推荐
相关产品推荐

