支付请求按钮
注意
Payment Request Button Element 在结账过程中动态显示钱包,为您提供一个统一的 Apple Pay、Google Pay 和 Link 集成。此外,您可以用 Express Checkout Element 为您的客户提供多个一键支付按钮。对比 Express Checkout Element 和 Payment Request Button 的功能。
如果客户在自己的设备上启用了 Apple Pay 或 Google Pay,就会看到这两种支付方式,具体取决于他们使用的浏览器。如果 Link 出现,可能是因为客户:
- 不要在其设备上启用 Apple Pay 或 Google Pay。
- 在 Chrome 上使用活跃的已验证的 Link 会话。
前提条件
开始前,您需要:
- 查看每种支付按钮类型的要求:
- Apple Pay 要求 macOS 10.12.1+ 或 iOS 10.1+。
- 兼容设备自动支持 Google Pay。
- 在测试和真实模式下都**注册并验证您的域名**。
- 向浏览器添加支付方式。 例如,您可以在 Chrome 中保存银行卡,向 Google Pay 添加银行卡或向 Safari 上的钱包中添加银行卡。
- **通过 HTTPS 服务您的应用程序。**开发模式和生产模式下都要求这样。其中一个方式是使用类似 ngrok 这样的服务。
设置 Stripe Elements
备注
可通过 CodeSandbox 内的演示尝试 React Stripe.js,不需要新建项目。
在您的页面添加 Stripe.js 和 Elements
使用 Element 组件时,将您的结账页面包装到某个 Elements 提供程序中。用您的公钥调用 loadStripe
,并将返回的 Promise
传递到 Elements
提供程序。
import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './CheckoutForm'; // Make sure to call `loadStripe` outside of a component's render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe(
); function App() { return ( <Elements stripe={stripePromise}> <CheckoutForm /> </Elements> ); }; ReactDOM.render(<App />, document.getElementById('root'));'pk_test_TYooMQauvdEDq54NiTphI7jx'
创建 paymentRequest 实例客户端
在您的结账表单组件中,创建一个包含所有必选项的 stripe.paymentRequest 实例。
import React, {useState, useEffect} from 'react'; import {PaymentRequestButtonElement, useStripe} from '@stripe/react-stripe-js'; const CheckoutForm = () => { const stripe = useStripe(); const [paymentRequest, setPaymentRequest] = useState(null); useEffect(() => { if (stripe) { const pr = stripe.paymentRequest({ country: 'US', currency: 'usd', total: { label: 'Demo total', amount: 1099, }, requestPayerName: true, requestPayerEmail: true, }); } }, [stripe]); // Use a traditional checkout form. return 'Insert your form or button component here.'; }
备注
用 requestPayerName
参数为 Apple Pay 付款收集付款人的账单地址。可以用账单地址来执行地址验证,并阻止欺诈性付款。在有账单地址的情况下,所有其他支付方式都会自动收集账单地址。
呈现 Payment Request Button Element客户端
用 canMakePayment 检查,确保您的客户有有效的支付方式。如果他们有,则呈现 <PaymentRequestButtonElement>
。如果没有,则不能呈现 Element;这种情况下,最好是呈现一个传统的结账表单。
import React, {useState, useEffect} from 'react'; import {PaymentRequestButtonElement, useStripe} from '@stripe/react-stripe-js'; const CheckoutForm = () => { const stripe = useStripe(); const [paymentRequest, setPaymentRequest] = useState(null); useEffect(() => { if (stripe) { const pr = stripe.paymentRequest({ country: 'US', currency: 'usd', total: { label: 'Demo total', amount: 1099, }, requestPayerName: true, requestPayerEmail: true, }); // Check the availability of the Payment Request API. pr.canMakePayment().then(result => { if (result) { setPaymentRequest(pr); } }); } }, [stripe]); if (paymentRequest) { return <PaymentRequestButtonElement options={{paymentRequest}} /> } // Use a traditional checkout form. return 'Insert your form or button component here.'; }
创建 PaymentIntent服务器端
Stripe 用一个 PaymentIntent 对象来表示您从客户收款的意图,跟踪收款尝试及整个过程中付款状态的变化情况。
用金额和货币在您的服务器上创建一个 PaymentIntent
。始终在服务器端决定扣款金额,这是一个可信的环境,客户端不行。这样可防止客户自己选择价格。
返回的 PaymentIntent 中包含的是一个客户端私钥,您需要用它在客户端安全地完成支付流程,而非传递整个 PaymentIntent 对象。将客户端私钥回发给客户,在下一步中使用。
完成付款客户端
侦听 paymentmethod
事件来接收 PaymentMethod 对象。将 PaymentMethod ID 和 PaymentIntent 的客户端私钥传递给 stripe.confirmCardPayment,来完成付款。
paymentRequest.on('paymentmethod', async (ev) => { // Confirm the PaymentIntent without handling potential next actions (yet). const {paymentIntent, error: confirmError} = await stripe.confirmCardPayment( clientSecret, {payment_method: ev.paymentMethod.id}, {handleActions: false} ); if (confirmError) { // Report to the browser that the payment failed, prompting it to // re-show the payment interface, or show an error message and close // the payment interface. ev.complete('fail'); } else { // Report to the browser that the confirmation was successful, prompting // it to close the browser payment method collection interface. ev.complete('success'); // Check if the PaymentIntent requires any actions and, if so, let Stripe.js // handle the flow. If using an API version older than "2019-02-11" // instead check for: `paymentIntent.status === "requires_source_action"`. if (paymentIntent.status === "requires_action") { // Let Stripe.js handle the rest of the payment flow. const {error} = await stripe.confirmCardPayment(clientSecret); if (error) { // The payment failed -- ask your customer for a new payment method. } else { // The payment has succeeded -- show a success message to your customer. } } else { // The payment has succeeded -- show a success message to your customer. } } });
注意
客户可能会在一些浏览器中离开支付页面,甚至是在授权了付款之后。这意味着,在收到 token
或 paymentmethod
事件之后,您可能会在您的 PaymentRequest 对象上收到一个取消事件的请求。如果您用 cancel
事件来勾住取消的客户订单,则一定还要退还刚创建的付款。
测试您的集成应用
测试集成时,必须使用 HTTPS 及支持的浏览器。如果您在 iframe 内使用了 paymentRequestButton
Element,则 iframe 必须要将允许 属性设置到等于“支付”。
此外,对每种支付方式和浏览器都有具体的要求:
收集配送信息
要收集配送信息,先在创建付款请求时包含 requestShipping: true
。
如果您的配送选项不依赖于客户的地址,那么这时还可以提供一个 shippingOptions
数组。
const paymentRequest = stripe.paymentRequest({ country: 'US', currency: 'usd', total: { label: 'Demo total', amount: 1099, }, requestShipping: true, // `shippingOptions` is optional at this point: shippingOptions: [ // The first shipping option in this list appears as the default // option in the browser payment interface. { id: 'free-shipping', label: 'Free shipping', detail: 'Arrives in 5 to 7 days', amount: 0, }, ], });
接下来,侦听客户选择收货地址后要检测的 shippingaddresschange
事件。用地址从您的服务器获取有效的配送选项,更新总额,或执行其他业务逻辑。shippingaddresschange
事件上的地址数据可以被浏览器做了匿名处理,目的是不泄露与运费计算无关的敏感信息。
客户必须在这个时候提供有效的 shippingOptions
才能继续该流程。
paymentRequest.on('shippingaddresschange', async (ev) => { if (ev.shippingAddress.country !== 'US') { ev.updateWith({status: 'invalid_shipping_address'}); } else { // Perform server-side request to fetch shipping options const response = await fetch('/calculateShipping', { data: JSON.stringify({ shippingAddress: ev.shippingAddress }) }); const result = await response.json(); ev.updateWith({ status: 'success', shippingOptions: result.supportedShippingOptions, }); } });
显示行项目
用 displayItems
在浏览器的支付界面显示 PaymentItem
对象并显示价格明细。
const pr = stripe.paymentRequest({ country: 'US', currency: 'usd', total: { label: 'Demo total', amount: 2000, }, displayItems: [ { label: 'Sample item', amount: 1000, }, { label: 'Shipping cost', amount: 1000, } ], });
设计按钮样式
用以下参数自定义 Element:
const options = { paymentRequest, style: { paymentRequestButton: { type: 'default', // One of 'default', 'book', 'buy', or 'donate' // Defaults to 'default' theme: 'dark', // One of 'dark', 'light', or 'light-outline' // Defaults to 'dark' height: '64px', // Defaults to '40px'. The width is always '100%'. }, } } <PaymentRequestButtonElement options={options} />
使用自己的按钮
如果您不想使用 paymentRequestButton
Element,而是要设计自己的按钮,则可以根据 paymentRequest.canMakePayment() 的结果现实您的自定义按钮。然后,用 paymentRequest.show() 在按钮被点击时显示浏览器界面。
构建自己的按钮时,请遵从 Apple Pay 的用户界面指南和 Google Pay 的品牌指南。
在 Stripe Connect 上使用支付请求按钮
在您的前端,先设置 Stripe 上的
stripeAccount
选项,然后再创建PaymentRequest
实例:const stripe = Stripe(
, { apiVersion: "2024-04-10", stripeAccount: 'CONNECTED_STRIPE_ACCOUNT_ID', });'pk_test_TYooMQauvdEDq54NiTphI7jx'在您打算显示付款请求按钮的地方注册所有域名。
Payment Request Button 的链接
当新客户来到您的网站时,他们使用 Link in the Payment Request Button,用他们保存的支付详情进行付款。通过 Link,他们不需要手动输入其支付信息。Link 需要域名注册。
向您的客户披露 Stripe
Stripe 收集有关客户与 Elements 互动的信息,以向您提供服务、防范欺诈并改进其服务。这包括使用 Cookie 和 IP 地址来识别客户在单次结账会话中看到的 Elements。您有责任披露并获得 Stripe 以这些方式使用数据所需的所有权利和许可。有关更多信息,请访问我们的隐私中心。