Webhook なしでカード支払いを受け付ける
サーバでカード決済を確定して、カードの認証リクエストを処理する方法をご紹介します。
For a wider range of support and future proofing, use the standard integration for asynchronous payments.
この組み込みは、Webhook を使用したり、オフラインイベントを処理したりせずに、クライアントからサーバーへの単一フローを使用して支払いを受け付けます。この組み込みはシンプルに見えるかもしれませんが、ビジネスの成長に合わせて拡張するのが難しく、以下のような制限もあります。
- カードのみをサポート: ACH や現地で一般的な支払い方法に個別に対応するには、追加のコードを記述する必要があります。
- Double-charge risk—By synchronously creating a new PaymentIntent each time your customer attempts to pay, you risk accidentally double-charging your customer. Be sure to follow best practices.
- 手動認証処理: 3D セキュアを備えたカード、または強力な顧客認証 (SCA) などの規制の対象となるカードでは、クライアント側での追加の手順が必要になります。
Keep these limitations in mind if you decide to use this integration. Otherwise, use the standard integration.
Stripe を設定するサーバ側クライアント側
サーバ側
この組み込みには、Stripe API と通信するエンドポイントがサーバ上に必要です。Stripe の公式ライブラリを使用して、サーバから Stripe API にアクセスします。
クライアント側
React Native SDK はオープンソースであり、詳細なドキュメントが提供されています。内部では、ネイティブの iOS および Android の SDK を使用します。Stripe の React Native SDK をインストールするには、プロジェクトのディレクトリーで (使用するパッケージマネージャーによって異なる) 次のいずれかのコマンドを実行します。
次に、その他の必要な依存関係をインストールします。
- iOS の場合は、ios ディレクトリーに移動して
pod install
を実行し、必要なネイティブ依存関係もインストールします。 - Android の場合は、依存関係をインストールする必要はありません。
Stripe の初期化
React Native アプリで Stripe を初期化するには、決済画面を StripeProvider
コンポーネントでラップするか、initStripe
初期化メソッドを使用します。publishableKey
の API 公開可能キーのみが必要です。次の例は、StripeProvider
コンポーネントを使用して Stripe を初期化する方法を示しています。
import { StripeProvider } from '@stripe/stripe-react-native'; function App() { const [publishableKey, setPublishableKey] = useState(''); const fetchPublishableKey = async () => { const key = await fetchKey(); // fetch key from your server here setPublishableKey(key); }; useEffect(() => { fetchPublishableKey(); }, []); return ( <StripeProvider publishableKey={publishableKey} merchantIdentifier="merchant.identifier" // required for Apple Pay urlScheme="your-url-scheme" // required for 3D Secure and bank redirects > // Your app code here </StripeProvider> ); }
決済ページを作成するクライアント側
カード番号、有効期限、セキュリティコード、郵便番号を収集する、SDK が提供する UI コンポーネント、CardField
を使用して、クライアント側でカード情報を安全に収集します。
CardField
は、リアルタイムで検証と形式の設定を行います。
CardField
コンポーネントを支払い画面に追加することで、顧客からカード詳細を安全に収集します。onCardChange
コールバックを使用して、カードのブランドや詳細情報の欠落の有無など、カードに関する機密性の低い情報を検査します。
import { CardField, useStripe } from '@stripe/stripe-react-native'; function PaymentScreen() { // ... return ( <View> <CardField postalCodeEnabled={true} placeholders={{ number: '4242 4242 4242 4242', }} cardStyle={{ backgroundColor: '#FFFFFF', textColor: '#000000', }} style={{ width: '100%', height: 50, marginVertical: 30, }} onCardChange={(cardDetails) => { console.log('cardDetails', cardDetails); }} onFocus={(focusedField) => { console.log('focusField', focusedField); }} /> </View> ); }
アプリを実行し、決済ページに CardField
コンポーネントが表示されることを確認します。
カード詳細を収集するクライアント側
顧客が購入する準備が整ったら、CardField
コンポーネントによって収集された詳細情報を使用して PaymentMethod (支払い方法) を作成します。
import { CardField, useStripe } from '@stripe/stripe-react-native'; function PaymentScreen() { const { createPaymentMethod, handleNextAction } = useStripe(); const pay = () => { // Gather customer billing information (for example, email) const billingDetails: CreatePaymentMethod.BillingDetails = { email: 'email@stripe.com', phone: '+48888000888', addressCity: 'Houston', addressCountry: 'US', addressLine1: '1459 Circle Drive', addressLine2: 'Texas', addressPostalCode: '77063', }; // Create payment method const { paymentMethod, error } = await createPaymentMethod({ paymentMethodType: 'Card', paymentMethodData: { billingDetails, } }); }; // ... }
サーバに PaymentMethod を送信するクライアント側
PaymentMethod が正常に作成されたら、その ID をサーバに送信します。
// ... const pay = () => { // ... // Send the PaymentMethod to your server to create a PaymentIntent const response = await fetch(`/pay`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ paymentMethodId: paymentMethod.id }), }); const { error, requires_action, payment_intent_client_secret } = await response.json(); if (error) { // Error creating or confirming PaymentIntent Alert.alert('Error', paymentIntentError); return; } if (payment_intent_client_secret && !requires_action) { // Payment succeeded Alert.alert('Success', 'The payment was confirmed successfully!'); } if (payment_intent_client_secret && requires_action) { // ...continued below } }; // ...
PaymentIntent を作成するサーバ側
リクエストを受信するためにサーバにエンドポイントを設定します。このエンドポイントは、後で でも、追加の認証ステップが必要なカードの処理に使用されます。
Create a new PaymentIntent with the ID of the PaymentMethod created on your client. You can confirm the PaymentIntent by setting the confirm property to true when the PaymentIntent is created or by calling confirm after creation. Separate authorization and capture is also supported for card payments.
支払いで 3D セキュアの認証など、追加のアクションが求められる場合、PaymentIntent のステータスは requires_
に設定されます。支払いが失敗すると、ステータスは requires_
に戻され、ユーザにエラーを表示する必要があります。支払いで追加認証が求められない場合は、支払いが作成され、PaymentIntent のステータスは succeeded
に設定されます。
注
2019-02-11 以前の API のバージョンでは、requires_
の代わりに requires_
、requires_
の代わりに requires_
が表示されます。
If you want to save the card to reuse later, create a Customer to store the PaymentMethod and pass the following additional parameters when creating the PaymentIntent:
- customer. Set to the ID of the Customer.
- setup_future_usage. Set to
off_
to tell Stripe that you plan to reuse this PaymentMethod for off-session payments when your customer is not present. Setting this property saves the PaymentMethod to the Customer after the PaymentIntent is confirmed and any required actions from the user are complete. See the code sample on saving cards after a payment for more details.session
次のアクションを処理するクライアント側
通常、ステップ 4 のサーバーでの確定後に支払いは成功しますが、決済フローによっては、3D セキュアによる認証など、顧客による追加の対応が必要になることがあります。
For cases that require any next actions, the PaymentIntent’s status is requires_
. On the client, pass the PaymentIntent’s client secret to handleNextAction
. The native handler presents a view and walks the customer through the authentication flow. After handling required actions on the client, the status of the PaymentIntent changes to requires_
. This enables your integration to fulfill the order on your backend and return the fulfillment result to your client.
PaymentIntent ID をバックエンドに送信し、1 時間以内に再度確定して、支払いを完了します。1 時間以内に確定しない場合、支払いの試行は失敗し、requires_
に戻ります。
// ... const pay = () => { // ... // If PaymentIntent requires action, call handleNextAction if (payment_intent_client_secret && requires_action) { const { error, paymentIntent } = await handleNextAction(payment_intent_client_secret); if (error) { Alert.alert(`Error code: ${error.code}`, error.message); } else if (paymentIntent) { if ( paymentIntent.status === PaymentIntents.Status.RequiresConfirmation ) { // Confirm the PaymentIntent again on your server const response = await fetch(`/pay`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ payment_intent_id: paymentIntent.id }), }); const { error, success } = await response.json(); if (error) { // Error during confirming Intent Alert.alert('Error', error); } else if (success) { Alert.alert('Success', 'The payment was confirmed successfully!'); } } else { // Payment succedeed Alert.alert('Success', 'The payment was confirmed successfully!'); } } } }; // ...
PaymentIntent を再度確定するサーバ側
このコードは、前のステップでの処理と同様に、支払いに追加の認証が必要なときにのみ実行されます。どの支払いでもこの追加ステップが必要になる場合があるため、コード自体はオプションではありません。
上記で設定したものと同じエンドポイントを使用し、PaymentIntent を再度確定することにより、支払いを完了して注文のフルフィルメントを実行します。この確定は支払い試行から 1 時間以内に実行してください。実行されない場合は、支払いが失敗して取引が requires_
に戻されます。
組み込みをテストする
Several test cards are available for you to use in a sandbox to make sure this integration is ready. Use them with any CVC and an expiration date in the future.
番号 | 説明 |
---|---|
支払いが成功し、すぐに処理されます。 | |
認証が必要です。Stripe は、顧客に認証を求めるモーダルをトリガーします。 | |
常に支払い拒否コード insufficient_ で失敗します。 |
テストカードの一覧については、テストに関するガイドを参照してください。