不用 Webhook 接受银行卡付款
了解如何在您的服务器确认银行卡付款并处理银行卡验证要求。
注意
Stripe 建议使用较新的 Payment Element,而非 Card Element。它可以让您用单个的 Element 接受多种支付方式。了解有关何时使用 Card Element 和 Payment Element 的更多信息。
为获得更广泛的支持并且未来可继续使用,请为异步付款使用标准集成。
该集成会等待客户端返回的响应,并在服务器上完成付款,而不使用 webhooks 或处理离线事件。虽然看似更简单了,但随着您业务的增长,这种集成很难扩展,并且有几个限制:
- 仅支持卡 — 必须编写更多代码来分别支持 ACH 及流行的区域性支付方式。
- 重复扣款风险——通过在客户每次尝试付款时同步创建新的 PaymentIntent,您可能会意外地对客户进行重复扣款。请务必遵循最佳实践。
- 在客户端的额外步骤 — 需进行 3DS 验证或受强客户认证等法规约束的银行卡需要在客户端执行额外的步骤。
如果您打算使用这种集成,请留意这些限制。否则,请使用标准集成。
收集银行卡详情客户端
用 Stripe.js 和 Stripe Elements 在客户端收集银行卡信息。Elements 是一组预构建的 UI 组件,用于收集并验证银行卡卡号、邮编和有效期。
Stripe Element 中包含一个 iframe,它通过一个 HTTPS 连接安全地将支付信息发送到 Stripe。结账页面上的地址也必须以 https:// 开头,不能是 http://,否则您的集成不能工作。
您可以在不使用 HTTPS 的情况下测试您的集成。准备好进行真实收款时启用它。
向服务器提交 PaymentMethod客户端
如果 PaymentMethod 创建成功,则将它的 ID 发送到您的服务器。
const stripePaymentMethodHandler = async (result) => { if (result.error) { // Show error in payment form } else { // Otherwise send paymentMethod.id to your server (see Step 4) const res = await fetch('/pay', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_method_id: result.paymentMethod.id, }), }) const paymentResponse = await res.json(); // Handle server response (see Step 4) handleServerResponse(paymentResponse); } }
创建 PaymentIntent服务器端
在您的服务器上设置一个端点来接收请求。稍后在处理需要额外验证的付款时,也会用到此端点。
用在您的客户端创建的 PaymentMethod 的 ID 创建新的 PaymentIntent。您可以通过在创建 PaymentIntent 时将 confirm 属性设置为 true 或在创建后调用 confirm 来 确认 PaymentIntent。也支持对银行卡付款进行单独授权和捕获。
如果支付需要额外的操作,如 3DS 验证,PaymentIntent 的状态将设置为 requires_
。如果支付失败,状态将设置回 requires_
,您应该向用户显示错误。如果支付不需要任何额外的验证,则创建一个收款,且 PaymentIntent 状态设置为 succeeded
。
注意
在 2019-02-11 以前的 API 版本中,requires_
显示为 requires_
,而 requires_
显示为 requires_
。
如果您想保存该卡以便以后重复使用,请创建一个 Customer 来存储 PaymentMethod,并在创建 PaymentIntent 时传递以下附加参数:
- customer。设置为 Customer 的 ID。
- setup_future_usage。设置为
off_
可告诉 Stripe 您打算在客户不在场时将这个 PaymentMethod 用于会话外付款。设置这个属性便可在确认 PaymentIntent 并且用户完成所需的任何操作后,将 PaymentMethod 保存到 Customer。详见付款后保存银行卡中的代码示例。session
处理任何后续操作客户端
编写代码来处理需要客户干预的情况。您在第 4 步时在服务器上确认后,付款会直接成功。但是,当 PaymentIntent 要求客户采取额外操作时,例如通过 3DS 验证进行身份验证,这个代码就开始发挥作用。
用 stripe.handleCardAction 触发处理客户操作的 UI。如果验证成功,则 PaymentIntent 的状态变为 requires_
。在服务器上再次确认 PaymentIntent,以完成付款。
测试时,使用需要验证的测试卡卡号(例如,)来强制实现该流程。使用不需要验证的卡(例如,)会跳过流程中的这个部分,然后在第 4 步去完成。
const handleServerResponse = async (response) => { if (response.error) { // Show error from server on payment form } else if (response.requires_action) { // Use Stripe.js to handle the required card action const { error: errorAction, paymentIntent } = await stripe.handleCardAction(response.payment_intent_client_secret); if (errorAction) { // Show error from Stripe.js in payment form } else { // The card action has been handled // The PaymentIntent can be confirmed again on the server const serverResponse = await fetch('/pay', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_intent_id: paymentIntent.id }) }); handleServerResponse(await serverResponse.json()); } } else { // Show success message } }
注意
stripe.
可能需要几秒才能完成。该时间内,禁止表单重复提交,并显示一个类似于微调器的等待指示器。如果收到错误,则向客户显示,重新启用表单,然后隐藏掉等待指示器。如果客户必须执行额外的步骤来完成付款,如身份验证,Stripe.js 将引导其完成该流程。
再次确认 PaymentIntent服务器端
该代码仅在支付需要额外验证时才执行,这与上一步的处理方式类似。该代码本身不是可选的,因为任何支付都需要这个额外步骤。
使用您在上方设置的同一个端点再次确认 PaymentIntent 以完成付款,并履行订单。请务必在尝试付款后一小时内确认。否则,付款将失败,并回到 requires_
。