# Bancontact による支払いの受け付け ベルギーで一般的な支払い方法である Bancontact を受け付ける方法をご紹介します。 # ダイレクト API Bancontact は [1 回限りの使用](https://docs.stripe.com/payments/payment-methods.md#usage)の決済手段であり、顧客は支払いの[認証](https://docs.stripe.com/payments/payment-methods.md#customer-actions)を求められます。Bancontact を使用して支払う場合、*顧客* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments)はアプリからリダイレクトされ、支払いを承認するとアプリに戻されます。ここで、お客様は支払いが成功したか失敗したかに関する[即時通知](https://docs.stripe.com/payments/payment-methods.md#payment-notification)を受け取ります。 > Bancontact のご利用にあたっては、[Bancontact 利用規約](https://stripe.com/bancontact/legal)に従う必要があります。 ## Stripe を設定する [サーバー側] まず、Stripe アカウントが必要です。[今すぐご登録ください](https://dashboard.stripe.com/register)。 アプリケーションから Stripe API にアクセスするには、Stripe の公式ライブラリを使用します。 #### 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' ``` ## PaymentIntent を作成する [サーバー側] [PaymentIntent (支払いインテント)](https://docs.stripe.com/api/payment_intents/object.md) は、顧客から支払いを回収する意図を表すオブジェクトで、決済プロセスのライフサイクルの各段階を追跡します。 Create a `PaymentIntent` on your server and specify the amount to collect and the `eur` currency (Bancontact doesn’t support other currencies). If you have an existing [Payment Intents](https://docs.stripe.com/payments/payment-intents.md) integration, eligible payment methods display automatically based on the currency and other parameters you provide. ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=eur \ -d "automatic_payment_methods[enabled]=true" ``` Bancontact オーソリページのデフォルト言語は英語 (`en`) に設定されています。`preferred_language` を `fr`、`nl`、または `de` に設定し、顧客の希望言語に合わせることもできます。 ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=eur \ -d "automatic_payment_methods[enabled]=true" \ -d "payment_method_options[bancontact][preferred_language]=fr" ``` ### client secret を取得する PaymentIntent には、*client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) が含まれています。これは、支払いプロセスを安全に完了するためにクライアント側で使用されます。client secret をクライアント側に渡す際は、いくつかの方法を使用できます。 #### 1 ページのアプリケーション ブラウザーの `fetch` 関数を使用して、サーバーのエンドポイントから client secret を取得します。この方法は、クライアント側が 1 ページのアプリケーションで、特に React などの最新のフロントエンドフレームワークで構築されている場合に最適です。client secret を処理するサーバーのエンドポイントを作成します。 #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end ``` その後、クライアント側で JavaScript を使用して client secret を取得します。 ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### サーバ側のレンダリング サーバーからクライアントに client secret を渡します。この方法は、アプリケーションがブラウザーへの送信前に静的なコンテンツをサーバーで生成する場合に最適です。 決済フォームに [client_secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) を追加します。サーバー側のコードで、PaymentIntent から client secret を取得します。 #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ## 支払い方法の詳細を収集する [クライアント側] #### HTML + JS クライアントで決済フォームを作成し、必要な請求先情報を顧客から収集します。 | フィールド | 値 | | ------ | ------ | | `name` | 顧客の氏名。 | ```html
``` #### React #### npm npm パブリックレジストリーから [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) と [Stripe.js ローダー](https://www.npmjs.com/package/@stripe/stripe-js)をインストールします。 ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` #### umd Stripe は npm やモジュールを使用しないサイト向けに UMD ビルドも提供しています。 グローバルな `Stripe` 機能をエクスポートする Stripe.js スクリプトと、グローバルな `ReactStripe` オブジェクトをエクスポートする React Stripe.js の UMD ビルドを含めてください。常に **js.stripe.com** から Stripe.js スクリプトを直接読み込むことにより、PCI への準拠が維持されます。スクリプトをバンドルに含めたり、そのコピーを自身でホストすることがないようにしてください。 ```html ``` > [CodeSandbox でのデモ](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark)を使用すると、新しいプロジェクトを作成することなく、React Stripe.js を試してみることができます。 ### お客様のページへの Stripe.js および Elements の追加 Element コンポーネントを使用するには、決済ページコンポーネントを [Elements プロバイダー](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider)でラップします。公開キーを使用して `loadStripe` を呼び出し、返された `Promise` を `Elements` プロバイダーに渡します。 ```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')); ``` ## Stripe に支払いを送信する [クライアント側] `PaymentIntent` の [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) を使用し、クライアント側で決済を作成します。client secret は、Stripe API リクエストを認証する API キーとは異なります。client secret は決済を完了できるため、慎重に取り扱う必要があります。ログに記録したり、URL に埋め込んだり、当該の顧客以外に公開したりしないでください。 #### HTML + JS 顧客が Bancontact での支払いをクリックしたときに、Stripe.js を使用してその支払いを Stripe に送信します。[Stripe.js](https://docs.stripe.com/payments/elements.md) は、決済フローを構築するための基本的な JavaScript ライブラリです。このライブラリにより、以下で説明するリダイレクトなどの複雑な処理が自動的に行われ、他の決済手段にも対応できるように実装を拡張できます。Stripe.js スクリプトを決済ページに含めるには、HTML ファイルの `head` にこのスクリプトを追加します。 ```html Checkout ``` 決済ページで以下の JavaScript を使用して、Stripe.js のインスタンスを作成します。 ```javascript // Set your publishable key. Remember to change this to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe('<>'); ``` [stripe.confirmBancontactPayment](https://docs.stripe.com/js/payment_intents/confirm_bancontact_payment) を呼び出し、顧客を Bancontact のウェブサイトまたはアプリにリダイレクトして支払いを完了します。支払い完了後に顧客をリダイレクトする `return_url` を含めてください。また、顧客の氏名を `billing_details` に指定する必要もあります。 ```javascript var stripe = Stripe('<>'); // Redirects away from the client const {error} = await stripe.confirmBancontactPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { name: "Jenny Rosen" } }, return_url: 'https://example.com/checkout/complete', } ); if (error) { // Inform the customer that there was an error. } ``` #### React [stripe.confirmBancontactPayment](https://docs.stripe.com/js/payment_intents/confirm_bancontact_payment) を使用して、お客様のページからのリダイレクトを処理して支払いを完了します。この機能に [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) を追加して、ユーザーが各自の銀行のウェブサイトまたはモバイルアプリで支払いを完了した後に Stripe がユーザーをリダイレクトする場所を指示します。 支払いフォームコンポーネントから `stripe.confirmBancontactPayment` を呼び出すには、[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} 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(); if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } // For brevity, this example is using uncontrolled components for // the accountholder's name. In a real world app you will // probably want to use controlled components. // https://reactjs.org/docs/uncontrolled-components.html // https://reactjs.org/docs/forms.html#controlled-components const accountholderName = event.target['accountholder-name']; const {error} = await stripe.confirmBancontactPayment('{CLIENT_SECRET}', { payment_method: { billing_details: { name: accountholderName.value, }, }, return_url: 'https://example.com/checkout/complete', }); if (error) { // Show error to your customer. console.log(error.message); } // Otherwise the customer will be redirected away from your // page to complete the payment with their bank. }; return (
); } ``` #### クラスコンポーネント ```jsx import React from 'react'; import {ElementsConsumer} from '@stripe/react-stripe-js'; class CheckoutForm extends React.Component { handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); const {stripe, elements} = this.props if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } // For brevity, this example is using uncontrolled components for // the accountholder's name. In a real world app you will // probably want to use controlled components. // https://reactjs.org/docs/uncontrolled-components.html // https://reactjs.org/docs/forms.html#controlled-components const accountholderName = event.target['accountholder-name']; const {error} = await stripe.confirmBancontactPayment('{CLIENT_SECRET}', { payment_method: { billing_details: { name: accountholderName.value, }, }, return_url: 'https://example.com/checkout/complete', }); if (error) { // Show error to your customer. console.log(error.message); } // Otherwise the customer will be redirected away from your // page to complete the payment with their bank. }; render() { const {stripe} = this.props; return (
); } } export default function InjectedCheckoutForm() { return ( {({stripe, elements}) => ( )} ); } ``` ### リダイレクトを処理する Stripe が顧客を `return_url` にリダイレクトする際に、以下の URL クエリパラメータが提供されます。 | パラメータ | 説明 | | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | `PaymentIntent` の一意の識別子。 | | `payment_intent_client_secret` | `PaymentIntent` オブジェクトの [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret)。 | `return_url` を指定する際に、独自のクエリパラメータを追加することもできます。このクエリパラメータは、リダイレクトプロセスの始めから終わりまで存続します。`return_url` は、決済のステータスを提供するウェブサイトのページと一致している必要があります。戻りページをレンダリングするときに、`PaymentIntent` のステータスを確認してください。確認するには、Stripe.js の `retrievePaymentIntent` 関数を使用し、`payment_intent_client_secret` を渡します。 ```javascript (async () => { const url = new URL(window.location); const clientSecret = url.searchParams.get('payment_intent_client_secret'); const {paymentIntent, error} = await stripe.retrievePaymentIntent(clientSecret); if (error) { // Handle error } else if (paymentIntent && paymentIntent.status === 'succeeded') { // Handle successful payment } })(); ``` ### 銀行口座の詳細 顧客が支払いの実行に使用した銀行口座の詳細は、結果として生じた支払いの [payment_method_details (支払い方法詳細)](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-bancontact) で確認できます。 #### Json ```json { "charges": { "data": [ {"payment_method_details": { "bancontact": { "bank_code": "VAPE", "bank_name": "VAN DE PUT & CO", "bics": "VAPEBE22", "iban_last4": "7061", "preferred_language": "en", "verified_name": "Jenny Rosen" }, "type": "bancontact" }, "id": "src_16xhynE8WzK49JbAs9M21jaR", "object": "source", "amount": 1099, "client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU", "created": 1445277809, "currency": "eur", "flow": "redirect", "livemode": true, "statement_descriptor": null, "status": "pending", "type": "bancontact", "usage": "single_use" } ], "object": "list", "has_more": false, "url": "/v1/charges?payment_intent=pi_1G1sgdKi6xqXeNtkldRRE6HT" }, "payment_method_options": { "bancontact": { "preferred_language": "en" } }, "payment_method_types": [ "bancontact" ], "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", "amount": 1099, "client_secret": "pi_1G1sgdKi6xqXeNtkldRRE6HT_secret_h9B56ObhTN72fQiBAuzcVPb2E", "confirmation_method": "automatic", "created": 1579259303, "currency": "eur", "livemode": true, "next_action": null } ``` ## Optional: 支払い後のイベントを処理する 支払いが完了すると、Stripe は [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) イベントを送信します。ダッシュボード、カスタム *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests)、またはパートナーソリューションを使用してこれらのイベントを受信し、また、顧客への注文確認メールの送信、データベースでの売上の記録、配送ワークフローの開始などのアクションを実行します。 クライアントからのコールバックを待つのではなく、これらのイベントをリッスンします。クライアント側では、コールバックが実行される前に顧客がブラウザーのウィンドウを閉じたり、アプリを終了したりする可能性があります。また、悪意を持つクライアントがレスポンスを不正操作する恐れもあります。非同期型のイベントをリッスンするよう構築済みのシステムを設定することで、これ以降はより多くの決済手段を簡単に受け付けられるようになります。[サポートされているすべての決済手段の違い](https://stripe.com/payments/payment-methods-guide)をご確認ください。 - **ダッシュボードでイベントを手動で処理する** ダッシュボードを使用して、テスト決済を[ダッシュボードで表示](https://dashboard.stripe.com/test/payments)したり、メール領収書を送信したり、入金を処理したり、失敗した決済を再試行したりできます。 - **Custom Webhook を構築する** [カスタム webhook](https://docs.stripe.com/webhooks/handling-payment-events.md#build-your-own-webhook) ハンドラを構築して、イベントをリッスンし、カスタムの非同期決済フローを構築できます。Stripe CLI を使用すると、ローカルで webhook 連携をテストしてデバッグできます。 - **構築済みアプリを導入する** パートナーアプリケーションを統合することで、[自動化](https://stripe.partners/?f_category=automation)や[マーケティング/セールス](https://stripe.partners/?f_category=marketing-and-sales)などの一般的なビジネスイベントを処理します。 ## Optional: Bancontact リダイレクトを手動で処理する クライアント側で `confirmBancontactPayment` を使用して Bancontact のリダイレクトおよび支払いを処理するには、Stripe.js を使用することをお勧めします。Stripe.js を使用すると、他の決済手段にも対応するように実装を拡張できます。ただし、以下の手順に従って、お客様のサーバーに顧客を手動でリダイレクトすることもできます。 1. タイプが `bancontact` の PaymentIntent を作成し、*確定* (Confirming an intent indicates that the customer intends to use the current or provided payment method. Upon confirmation, the intent attempts to initiate the portions of the flow that have real-world side effects)します。顧客から収集する必要がある `payment_method_data.billing_details.name` プロパティを提供する必要があります。`payment_method_data` を指定すると、PaymentMethod が作成され、この PaymentIntent でただちに使用されることに注意してください。 また、顧客が決済を完了した後にリダイレクトされる先の URL を `return_url` フィールドに指定する必要があります。オプションで、独自のクエリパラメータをこの URL に指定することもできます。これらのパラメータは、リダイレクトフロー完了時の最終的な URL に含められます。 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') payment_intent = client.v1.payment_intents.create({ confirm: true, amount: 1099, currency: 'eur', payment_method_types: ['bancontact'], payment_method_data: { type: 'bancontact', billing_details: { name: 'Jenny Rosen', }, }, return_url: 'https://example.com/checkout/complete', }) ``` 1. `PaymentIntent` のステータスが `requires_action` であることと、`next_action` のタイプが `redirect_to_url` であることを確認します。 #### Json ```json {"status": "requires_action", "next_action": { "type": "redirect_to_url", "redirect_to_url": { "url": "https://hooks.stripe.com/...", "return_url": "https://example.com/checkout/complete" } }, "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", ... } ``` 1. `next_action.redirect_to_url.url` プロパティで指定された URL に顧客をリダイレクトします。ここでのコード例はおおまかなものであり、リダイレクト方法は、お客様のウェブフレームワークによって異なることがあります。 #### Ruby ```ruby if payment_intent.status == 'requires_action' && payment_intent.next_action.type == 'redirect_to_url' url = payment_intent.next_action.redirect_to_url.url redirect(url) end ``` 支払いプロセスが完了すると、顧客は `return_url` にリダイレクトされます。`payment_intent` および `payment_intent_client_secret` URL クエリパラメーターは、お客様独自のクエリパラメーターと併せて含まれています。支払いのステータスをプログラムで確認するために、[Webhook エンドポイント](https://docs.stripe.com/payments/payment-intents/verifying-status.md#webhooks)を設定することをお勧めします。