# 銀行認証なしのカード支払い よりシンプルな地域限定の実装を構築します。 この導入は、アメリカとカナダのカードのみを受け付けるビジネスをサポートしています。初期統合はシンプルですが、グローバルな顧客ベースをサポートするように成長することはできません。 ### この導入の仕組み ヨーロッパやインドなどの地域の銀行は、購入を確定するために二要素認証を求めることがよくあります。主にアメリカとカナダでビジネスを行っている場合には、これらの地域の銀行はほとんど 2 段階認証を求めないため、*カード認証* (A bank might require the customer to authenticate a card payment before processing. Implementation varies by bank but commonly consists of a customer entering in a security code sent to their phone)を配慮しないことで実装がシンプルになります。 銀行が認証を要求すると、この基本的な組み込みは、決済を非同期で完了するための認証処理は行わず、直ちに決済を拒否します (カード拒否のように)。この利点は、決済の成功や失敗が直ちに決定され、決済確定がサーバーで行われるため、*Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) を使用せずに直ちに決済後のアクションを処理できることです。 ### グローバル導入との比較 | 機能 | この組み込み | グローバル組み込み | | ---------------------------- | ------ | --------- | | カスタムの支払いフォーム | ✔ | ✔ | | 機密データがお客様のサーバに触れない | ✔ | ✔ | | アメリカとカナダの顧客に対応 | ✔ | ✔ | | カード詳細が不正確な場合や残高不足の場合に支払いを拒否 | ✔ | ✔ | | 銀行から認証要求があると支払いを拒否 | ✔ | | | グローバルな顧客に対応 | | ✔ | | 銀行の認証が必要なカード支払いを自動的に処理 | | ✔ | | 支払い後のタスクに推奨される Webhook | | ✔ | | 他の支払い方法 (銀行引き落としなど) に簡単に拡張可能 | | ✔ | 成長を遂げている企業やグローバル企業には、Stripe の[グローバルなシステム](https://docs.stripe.com/payments/accept-a-payment.md)を使用して、銀行の 2 段階認証の要求に対応し、顧客がより広範な支払い方法を使用できるようにすることをお勧めします。 決済フロー (See full diagram at https://docs.stripe.com/payments/without-card-authentication) ## 決済フォームの構築 [クライアント側] Stripe.js の一部である [Elements](https://docs.stripe.com/payments/elements.md) は、顧客からカード情報を収集するドロップイン UI コンポーネントを提供します。Stripe はこれらをホストし、iframe として支払いフォームに配置するため、顧客のカード情報がコードに触れることはありません。 #### HTML + JS まず、お客様のサイトの各ページの先頭に [Stripe.js](https://docs.stripe.com/js.md) スクリプトを含めます。 ```html ``` サイトの各ページにスクリプトを含めることで、Stripe の[アドバンス不正利用検出機能](https://docs.stripe.com/radar.md)および異常な閲覧動作を検知する能力を活用できます。 ### セキュリティ要件 [PCI 準拠](https://docs.stripe.com/security/guide.md)を保持するには、このスクリプトを常に **js.stripe.com** から直接読み込んでください。このスクリプトをバンドルに含めたり、そのコピーを自身でホストすることはできません。 Elements を使用する際には、すべての情報は安全な HTTPS 接続を介して送信されます。 また、Elements を含むページのアドレスの先頭は、**http://** ではなく、**https://** にする必要もあります。SSL 証明書の取得や、それをサーバに組み込んで安全な HTTPS 接続を有効化する方法については、[セキュリティ](https://docs.stripe.com/security.md)のドキュメントをご覧ください。 ### Elements をページに追加する 次に、Stripe アカウントが必要です。[今すぐ登録](https://dashboard.stripe.com/register)してください。 支払いフォーム内に、一意の ID を持つ空の DOM Elements (コンテナ) を作成してください。 ```html

``` [Stripe オブジェクト](https://docs.stripe.com/js.md#stripe-function)のインスタンスを作成し、公開可能な [API キー](https://docs.stripe.com/keys.md)を最初のパラメーターとして指定します。その後、[Elements オブジェクト](https://docs.stripe.com/js.md#stripe-elements)のインスタンスを作成し、それを使用してページにある空の DOM Element コンテナに Card Element を[マウント](https://docs.stripe.com/js.md#element-mount)します。 ```javascript const stripe = Stripe('<>'); const elements = stripe.elements(); const cardElement = elements.create('card'); cardElement.mount('#card-element'); ``` クライアントで [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) を使用してカード詳細を収集し、顧客が支払いフォームを送信したら、[PaymentMethod (支払い方法)](https://docs.stripe.com/api/payment_methods.md) を作成します。その PaymentMethod の ID をサーバに送信します。 ```javascript const form = document.getElementById("payment-form"); var resultContainer = document.getElementById('payment-result'); // cardElement is defined in the previous step cardElement.on('change', function(event) { if (event.error) { resultContainer.textContent = event.error.message; } else { resultContainer.textContent = ''; } }); form.addEventListener('submit', async event => { event.preventDefault(); resultContainer.textContent = ''; const result = await stripe.createPaymentMethod({ type: 'card', card: cardElement, }); handlePaymentMethodResult(result); }); const handlePaymentMethodResult = async ({ paymentMethod, error }) => { if (error) { // An error happened when collecting card details, show error in payment form resultContainer.textContent = error.message; } else { // Send paymentMethod.id to your server (see Step 3) const response = await fetch("/pay", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ payment_method_id: paymentMethod.id }) }); const responseJson = await response.json(); handleServerResponse(responseJson); } }; const handleServerResponse = async responseJson => { if (responseJson.error) { // An error happened when charging the card, show it in the payment form resultContainer.textContent = responseJson.error; } else { // Show a success message resultContainer.textContent = 'Success!'; } }; ``` #### React まず、[Stripe.js](https://github.com/stripe/stripe-js) と [React Stripe.js](https://docs.stripe.com/sdks/stripejs-react.md) をインストールします。 ```bash npm install --save @stripe/stripe-js @stripe/react-stripe-js ``` > このガイドは、React の基本的な実務知識があり、React プロジェクトがすでに設定されていることを前提としています。React を初めて使用する場合は、続行する前に React [使用開始](https://reactjs.org/docs/getting-started.html)ガイドを読むことをお勧めします。 > > 新しいプロジェクトを構築することなく React Stripe.js を簡単に試す方法をお探しの場合は、この [CodeSandbox のデモ](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark)から始めてください。 ### セキュリティ要件 Elements を使用する際には、すべての情報は安全な HTTPS 接続を介して送信されます。 また、Elements を含むページのアドレスの先頭は、**http://** ではなく、**https://** にする必要もあります。SSL 証明書の取得や、それをサーバに組み込んで安全な HTTPS 接続を有効化する方法については、[セキュリティ](https://docs.stripe.com/security.md)のドキュメントをご覧ください。 ### お客様のページへの Stripe.js および Elements の読み込み Elements を使用するには、React アプリのルートを [Elements](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider) プロバイダーでラップします。公開可能キーを使用して [loadStripe](https://github.com/stripe/stripe-js#loadstripe) を呼び出し、返された `Promise` を `Elements` プロバイダーに渡します。 Stripe の[アドバンス不正利用機能](https://docs.stripe.com/radar.md)および特異な閲覧動作を検知する能力を活用するため、React アプリのルートで `loadStripe` をインポートし、呼び出すことが重要です。 ```jsx 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 ( ); }; ReactDOM.render(, document.getElementById('root')); ``` ### PaymentMethod の作成 クライアントで、`CardElement` および [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) を使用してカード詳細を収集し、顧客が支払いフォームを送信したら、[PaymentMethod (支払い方法)](https://docs.stripe.com/api/payment_methods.md) を作成します。その PaymentMethod の ID をサーバに送信します。 支払いフォームコンポーネントから `stripe.createPaymentMethod` を呼び出すには、[useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) フックと [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook) フックを使用します。フックではなく従来のクラスコンポーネントを使用する場合は、代わりに [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer) を使用します。 #### フック ```jsx import React from 'react'; import {useStripe, useElements, CardElement} from '@stripe/react-stripe-js'; export default function CheckoutForm() { const stripe = useStripe(); const elements = useElements(); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); const result = await stripe.createPaymentMethod({ type: 'card', card: elements.getElement(CardElement), billing_details: { // Include any additional collected billing details. name: 'Jenny Rosen', }, }); handlePaymentMethodResult(result); }; const handlePaymentMethodResult = async (result) => { if (result.error) { // An error happened when collecting card details, // show `result.error.message` in the payment form. } else { // Otherwise send paymentMethod.id to your server (see Step 3) const response = await fetch('/pay', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ payment_method_id: result.paymentMethod.id, }), }); const serverResponse = await response.json(); handleServerResponse(serverResponse); } }; const handleServerResponse = (serverResponse) => { if (serverResponse.error) { // An error happened when charging the card, // show the error in the payment form. } else { // Show a success message } }; const handleCardChange = (event) => { if (event.error) { // Show `event.error.message` in the payment form. } }; return (
); } ``` ## Stripe の設定 [サーバ側] アプリケーションから Stripe API にリクエストを作成するには、公式ライブラリを使用します。 #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## 支払いの作成 [サーバ側] サーバにエンドポイントを設定し、クライアントからリクエストを受信します。 Stripe は [PaymentIntent (支払いインテント)](https://docs.stripe.com/api/payment_intents.md) オブジェクトを使用して、顧客から支払いを回収する意図を示し、プロセス全体を通して請求の実施と支払い状態の変化を追跡します。 クライアント側ではなく、信頼できる環境のサーバ側で常に支払い金額を指定してください。これにより、悪意のある顧客が独自の金額を選択できないようにします。 ステップ 1 の AJAX リクエストに応答する HTTP エンドポイントを作成します。そのエンドポイントで、顧客にいくら請求するかを決定します。決済を作成するには、以下のコードで、ステップ 1 からの *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) ID を使用して PaymentIntent を作成します。 #### curl ```curl # Check the status of the PaymentIntent to make sure it succeeded curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d amount=1099 \ -d currency=usd \ # A PaymentIntent can be confirmed some time after creation, # but here we want to confirm (collect payment) immediately. -d confirm=true \ -d payment_method="{{PAYMENT_METHOD_ID}}" \ # If the payment requires any follow-up actions from the # customer, like two-factor authentication, Stripe will error # and you will need to prompt them for a new payment method. -d error_on_requires_action=true ``` > 支払いを確定する際に、[error_on_requires_action](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-error_on_requires_action) を `true` に設定すると、ユーザーから 2 段階認証が必要とされる場合、Stripe はその支払いを自動的に拒否します。 #### Payment Intents API レスポンス API で支払いを作成すると、そのレスポンスには PaymentIntent のステータスが含まれます。支払いが成功した場合には、ステータスは `succeeded` になります。 ```json { "id": "pi_0FdpcX589O8KAxCGR6tGNyWj", "object": "payment_intent", "amount": 1099, "charges": { "object": "list", "data": [ { "id": "ch_GA9w4aF29fYajT", "object": "charge", "amount": 1099, "refunded": false, "status": "succeeded", } ] }, "client_secret": "pi_0FdpcX589O8KAxCGR6tGNyWj_secret_e00tjcVrSv2tjjufYqPNZBKZc", "currency": "usd", "last_payment_error": null,"status": "succeeded", } ``` 支払いが拒否されると、そのレスポンスにはエラーコードとエラーメッセージが含まれます。以下は、カードに 2 段階認証が必要とされるために支払いが拒否された例です。 ```json { "error": {"code": "authentication_required", "decline_code": "authentication_not_handled", "doc_url": "https://docs.stripe.com/error-codes#authentication-required", "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.", "payment_intent": { "id": "pi_1G8JtxDpqHItWkFAnB32FhtI", "object": "payment_intent", "amount": 1099, "status": "requires_payment_method", "last_payment_error": { "code": "authentication_required", "decline_code": "authentication_not_handled", "doc_url": "https://docs.stripe.com/error-codes#authentication-required", "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.", "type": "card_error" }, }, "type": "card_error" } } ``` ## 組み込みのテスト Stripe では、この実装の準備ができていることを確認するために、*サンドボックス* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes)で使用できるテストカードをいくつか提供しています。任意のセキュリティコード、郵便番号、および今後の有効期限を指定して使用します。 | 番号 | 説明 | | ---------------- | -------------------------------------------------------------- | | 4242424242424242 | 成功し、すぐに支払いを処理します。 | | 4000000000009995 | 支払い拒否コード `insufficient_funds` で常に失敗します。 | | 4000002500003155 | 認証を必要とします。この組み込みでは、`authentication_not_handled` というコードで拒否されます。 | [テストカード](https://docs.stripe.com/testing.md)の全一覧をご覧ください。 ## カード認証を処理するために組み込みをアップグレードする 基本的なカード決済用の決済導入が完了しました。この導入は、**決済中に認証を必要とするカードを拒否する** ことにご注意ください。 ダッシュボードで決済が `Failed` としてリストされるようになった場合は、[連携をアップグレード](https://docs.stripe.com/payments/payment-intents/upgrade-to-handle-actions.md)する必要があります。Stripe グローバル導入は、決済を自動的に拒否するのではなく、これらの決済を処理します。