# プラットフォーム向け Treasury を使用した資金移動

SetupIntents と PaymentMethods の使用方法と、プラットフォームの Treasury で銀行口座を確認する方法をご紹介します。

> #### 従来の実装
> 
> Treasury for platforms の v1 は従来の実装であり、[Treasury for platforms v2](https://docs.stripe.com/treasury/connect.md) で導入された機能の多くをサポートしていません。新しい v1 の実装を構築しないでください。

Homebox は架空の業種特化型 SaaS で、HVAC、清掃業者、配管工などのホームサービス会社向けのソフトウェアを構築しています。この導入例では、[Stripe API](https://docs.stripe.com/api.md) の Treasury エンドポイントを使用した基本的な資金移動について説明します。この会社がどのように金融口座を設定し、決済カードを発行するかについては、[Treasury for platforms を使用した金融口座とカードの設定](https://docs.stripe.com/treasury/connect/legacy/v1/examples/financial-accounts.md)をご覧ください。

## 外部の銀行口座の使用

プラットフォーム向け Treasury は、連結アカウントの資金の保管、管理、移動を支援する、アカウント作成および資金移動の API エンドポイント一式をプラットフォームに提供します。プラットフォームは金融口座に資金を追加し、金融口座と外部銀行口座の間で資金を移動できます。

Stripe API は、`InboundTransfer` と `OutboundTransfer` を提供し、連結アカウントの外部銀行口座と金融口座間の資金移動を容易にします。Stripe API はまた、`OutboundPayment` を提供し、連結アカウントの金融口座からサードパーティーの外部銀行口座への資金の移動を容易にします。これらのオブジェクトはすべて、`PaymentMethods` を使用して、金融番号や口座番号などの外部銀行口座の詳細を保管できます。

## PaymentMethods の説明

Stripe API では、`PaymentMethod` オブジェクトを使用して、支払い方法の情報を保存できます。たとえば、Homebox は、ベンダーのアカウントを `PaymentMethods` として保存すると、情報を再入力して収集する必要なしに、資金を送金できます。

外部銀行口座情報を含む `PaymentMethods` は、顧客 (サードパーティーに送金するため) または Stripe アカウント (Stripe アカウント所有者に属する外部銀行口座から資金を引き出すため、またはその口座に資金を送金するため) に関連付けることができます。「顧客」とは、Stripe API の `Customer` オブジェクトを指し、任意のサードパーティーを定義します。プラットフォーム向け Treasury の用途では、顧客は通常、Stripe アカウント所有者に決済する側ではなく、Stripe アカウント所有者から決済を受け取るベンダーです。顧客に関連付けられたものとアカウントに関連付けられたものの両方の `PaymentMethod` オブジェクトを設定するには、`SetupIntent` オブジェクトを使用します。

`PaymentMethod` で使用できる関連 API オブジェクトは、その関連付けの方法によって異なります。

- 顧客に関連付け: `OutboundPayments` を使用します。
- アカウントに関連付け: `InboundTransfers` および `OutboundTransfers` を使用します。
![フローチャート。左側の外部銀行口座からの矢印が SetupIntent、さらに PaymentMethod につながり、顧客またはアカウントに関連付けられている。](https://b.stripecdn.com/docs-statics-srv/assets/paymentmethods.f429ec4e87b87636c0e2b34c26a69c83.png)

PaymentMethod のフロー

## InboundTransfers および OutboundTransfers の概要

`InboundTransfer` を使用して Stripe アカウントの外部銀行口座から資金を引き出し、`OutboundTransfer` を使用して同じ所有者の外部銀行口座に資金を追加できます。

`InboundTransfer` を使用して資金を金融口座に移動するには、Stripe アカウント所有者が外部口座を確認する必要があります。`OutboundTransfer` を使用して金融口座から資金を送信する際に使用される銀行口座を確認する必要はありません。

外部の銀行口座が `InboundTransfers` または `OutboundTransfers` に使用される場合、対応する `PaymentMethod` を Stripe アカウント (顧客ではなく) にアタッチする必要があります。これを行うには、`SetupIntent` を使用して `PaymentMethod` を作成するときに、`customer` パラメーターではなく、`attach_to_self=true` パラメーターを使用します。
![フローチャート。左側の外部銀行口座からの矢印が SetupIntent、さらに PaymentMethod につながり、Stripe アカウントに関連付けられている。](https://b.stripecdn.com/docs-statics-srv/assets/iot.38c049d39deca401a3341b34d72189fe.png)

InboundTransfers および OutboundTransfers のフロー。

## OutboundPayments

プラットフォームは `OutboundPayment` API を使用して、金融口座から第三者が所有する外部銀行口座に資金を送金します。

`OutboundPayments` で使用するには、`PaymentMethods` を顧客にアタッチする必要があります。`OutboundPayments` に使用する銀行口座を確認する必要はありません。
![](https://b.stripecdn.com/docs-statics-srv/assets/iot-customer.5476c499693c606ead280fbae61ebe4a.png)

`OutboundPayments` のフロー

## 外部の銀行口座を追加

Homebox は、顧客保有の外部銀行口座をそれぞれの金融口座にリンクしようと考えています。Homebox の連結アカウントは、すべてのビジネス資金を金融口座に保管し、インバウンド送金を使用して外部の口座から金融口座に資金を引き出すことを望んでいます。連結アカウントが外部の口座との間で資金を送金できるようにするために、Homebox は、必要なパラメーターを指定して `SetupIntent` を作成し、アカウントにアタッチされた `PaymentMethod` に関連付けます。

```curl
curl https://api.stripe.com/v1/setup_intents \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d attach_to_self=true \
  -d "flow_directions[]=inbound" \
  -d "flow_directions[]=outbound" \
  -d "allowed_payment_method_types[]=us_bank_account" \
  -d "payment_method_data[type]=us_bank_account" \
  -d "payment_method_data[us_bank_account][routing_number]=110000000" \
  -d "payment_method_data[us_bank_account][account_number]=000123456789" \
  -d "payment_method_data[us_bank_account][account_holder_type]=company" \
  -d "payment_method_data[billing_details][name]=Company Corp" \
  -d confirm=true \
  -d "mandate_data[customer_acceptance][type]=online" \
  -d "mandate_data[customer_acceptance][online][ip_address]=123.123.123.123" \
  --data-urlencode "mandate_data[customer_acceptance][online][user_agent]=curl/1.2.3"
```

`OutboundTransfers` または `InboundTransfers` を使用して資金の送受金を行うために、Homebox は、`payment_method_data[us_bank_account]` パラメーターで外部の銀行口座を指定する必要があります。本番環境の外部銀行口座リンクを作成する前に、Homebox は、Stripe が提供する[テスト用口座番号](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md?platform=web&payment-ui=stripe-hosted#test-account-numbers)を使用してフローをテストします。

上記の例のように、Homebox は、外部の銀行口座 (`payment_method_data[us_bank_account]`) を定義して、`attach_to_self` を `true` に設定しました。これにより、銀行口座情報を Stripe アカウント所有者 (サードパーティーではない) に関連付けることができます。プラットフォームがリクエストを送信すると、API は `SetupIntent` で応答します。

```json
{
  "id": "{{SETUP_INTENT_ID}}",
  "object": "setup_intent",
  "application": "{{APPLICATION_ID}}",
  "attach_to_self": true,
  "cancellation_reason": null,
  "client_secret": "{{SETUP_INTENT_SECRET}}",
  "created": 1642520861,
  "customer": null,
  "description": null,
  "flow_directions": [
    "inbound",
    "outbound"
  ],
  "last_setup_error": null,
  "latest_attempt": "{{ATTEMPT_ID}}",
  "livemode": false,
  "mandate": "{{MANDATE_ID}}",
  "metadata": {
  },
  "next_action": {
    "type": "verify_with_microdeposits",
    "verify_with_microdeposits": {
      "arrival_date": 1642579200,
      "hosted_verification_url": "https://payments.stripe.com/microdeposit/sacs_test_xxx",
      "microdeposit_type": "amounts"
    }
  },
  "on_behalf_of": null,
  "payment_method": "{{PAYMENT_METHOD_ID}}",
  "payment_method_options": {
    "us_bank_account": {
      "verification_method": "automatic"
    }
  },
  "payment_method_types": [
    "us_bank_account"
  ],
  "single_use_mandate": null,
  "status": "requires_confirmation",
  "usage": "off_session"
}

```

## 外部の銀行口座の確認

前のセクションで、Homebox は外部の銀行口座を登録しました。Homebox がこれを `InboundTransfers` に使用するには、事前に銀行口座を検証する必要があります。銀行口座の検証により、アカウントのオーナーは外部の銀行口座の所有権を確認できます。検証にあたり、Homebox は [Stripe Financial Connections](https://docs.stripe.com/treasury/connect/legacy/v1/examples/moving-money.md#connections) を使用して即座に検証するか、[マイクロデポジット](https://docs.stripe.com/treasury/connect/legacy/v1/examples/moving-money.md#microdeposits) (さらに時間がかかります) を使用できます。

### Stripe Financial Connections

[Financial Connections](https://docs.stripe.com/financial-connections.md) を使用して、所有する銀行口座を即時に確認できます。Financial Connections は、Stripe がホストするフローであり、アプリケーションのクライアント側とサーバー側に実装されます。

Homebox が Financial Connections で銀行口座情報を収集して確認するために必要な 3 つのステップ:

1. `customer_id` プロパティーの代わりに `attach_to_self` プロパティーを指定し、`verification_method` プロパティーの値に `instant`を指定して `SetupIntent` を作成します。

2. フロントエンドアプリケーションに `client_secret` を提供して `stripe.collectBankAccountForSetup` を使用し、銀行口座の詳細を収集し、`PaymentMethod` を作成して、`PaymentMethod` を `SetupIntent` にアタッチします。

   > `billing_details` パラメーターのアカウント所有者の名前は、アメリカの銀行口座の`PaymentMethod` を作成するために必要です。

3. 同意書の規約を表示して、`PaymentMethod` を使用する許可を収集うします。

ステップ 1 では、Homebox は以下のコードを生成してサーバー側で `SetupIntent` を作成し、handlebars.js テンプレートに情報を渡します。このコードは、アプリケーションには Stripe にログインしているユーザーがいて、Stripe `アカウント` ID を [Session](https://docs.stripe.com/api/financial_connections/sessions/object.md) オブジェクト (`req.session.accountId`) の一部として渡すことを想定します。

```javascript
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY);
router.get('/add_bank_account', async (req, res) => {
  const account = await stripe.accounts.retrieve(req.session.accountId);
  const setupIntent = await stripe.setupIntents.create({
    attach_to_self: true,
    flow_directions: ['inbound', 'outbound'],
    allowed_payment_method_types: ['us_bank_account'],
    payment_method_options: {us_bank_account: {verification_method: "automatic"}}
  },{
    stripeAccount: account.id,
  });
  let client_secret= setupIntent.client_secret;
  res.render('add_bank_account', { account: account, client_secret: client_secret, stripe_pk: process.env.STRIPE_PUBLISHABLE_KEY });
});
```

ステップ 2 は、Homebox が以下のデータを render 関数に渡すと開始します。

- Stripe アカウント ID。
- ID として使用される `SetupIntent` から取得した client secret。
- プラットフォームの公開可能な API キー。

この例では、クライアント側のページに、Financial Connections を使用して銀行口座を確認するためのボタンがレンダリングされます。
![「銀行口座を追加する」モーダルのスクリーンショットに、「支払い情報の保存」ボタンを表示。](https://b.stripecdn.com/docs-statics-srv/assets/add-bank-account-modal.0b727f65d3c6691f3bef211c1a45cb83.png)

銀行口座を追加するためのモーダル

Homebox は、前述のボタンの背後にあるロジックを動作させるために、以下のコードを作成します。

```javascript
const getBankAccount = async e => {
  paymentMethodButton.setAttribute("disabled", "disabled");
  // Calling this method triggers the Financial Connections modal to display.
  const response = await stripe.collectBankAccountForSetup("{{ client_secret }}", {
    billing_details: {
      name: "John Doe",
      email: "test@test.com",
    },
  });
  if (response.error)
  {
    console.error(response.error);
  }
  if (response.status == "requires_confirmation")
  {
    //Show confirmation modal
    AcceptBankAccountModal.classList.remove("hidden");
  }
};
```

このコード例では、スクリプトは `collectUsBankAccountForSetup` メソッドを呼び出し、`SetupIntent` から取得した `client_secret` を渡します。アプリケーションのダイアログは、銀行口座を登録する手順をユーザーに示します。
![銀行口座を追加するワークフローを実行中のモーダルのスクリーンショット。モーダルの最初の段階では「同意する」ボタンでの承認ステップ、次の段階では口座を関連付けるためのボタンを表示し、口座を強調表示。](https://b.stripecdn.com/docs-statics-srv/assets/add-account-flow.cfd2209695ca186cd617f682319e564c.png)

銀行口座を追加するためのワークフロー

ステップ 3 は、前のワークフローが正常に完了し、`SetupIntent` のステータスが `requires_confirmation` に変わり、ユーザーが確認するための[オーソリメッセージ](https://docs.stripe.com/payments/ach-direct-debit/set-up-payment.md?payment-ui=elements#web-collect-mandate-and-submit)がモーダルに表示されると開始されます。
![承認の確定に関する文言が表示されているモーダルのスクリーンショット。下部には「同意する」ボタン、左上にはキャンセルするための x を表示。](https://b.stripecdn.com/docs-statics-srv/assets/accept-modal.6db14c686b9ec87ff471a18d2f9d2abf.png)

承認メッセージ

ユーザーが**同意する**をクリックすると、コードは `confirmUsBankAccountSetup` メソッドを呼び出し、銀行口座が確認済みとして保管されます。これで、銀行口座を `InboundTransfers` に使用できます。

```javascript
const acceptBankAccount = async e => {
  acceptButton.setAttribute("disabled", "disabled");
  const response = await stripe.confirmUsBankAccountSetup("{{ client_secret }}");
  if (response.setupIntent.status == "requires_payment_method") {
    // Confirmation failed. Attempt again with a different payment method.
    console.log("Requires payment method")
  } else if (response.setupIntent.status == "succeeded") {
    // Confirmation succeeded! The account is now saved.
    // Display a message to customer.
    AcceptBankAccountModal.classList.add("hidden");
    console.log("Account added");
  } else if (response.setupIntent.next_action?.type == "verify_with_microdeposits") {
    // The account needs to be verified through microdeposits.
    // Display a message to consumer with next steps (consumer waits for
    // microdeposits, then enters an amount on a page sent to them through email).
    console.log("The account needs to be verified with microdeposits")
  }
};
```

### 少額入金

少額入金は、Stripe が外部の銀行口座に入金する少額 (通常は本の少額の USD) の資金です。口座の所有者は、こうした入金の正確な金額を確認することにより、口座の所有権を確認できます。

Homebox が前のセクションで作成した `SetupIntent` オブジェクトには、`PaymentMethod` ID が含まれています。

```json
{
  "id": "{{SETUP_INTENT_ID}}",
  …
  "on_behalf_of": null,
  "payment_method": "{{PAYMENT_METHOD_ID}}",
  "payment_method_options": {
…
 }
}

```

`SetupIntent` には、`hosted_verification_url` 値で URL が定義された `next_action` オブジェクトも含まれています。

```json
{
  "id": "{{SETUP_INTENT_ID}}",
…
   "next_action": {
    "type": "verify_with_microdeposits",
    "verify_with_microdeposits": {
      "arrival_date": 1642579200,
      "hosted_verification_url": "https://payments.stripe.com/microdeposit/sacs_test_xxx",
      "microdeposit_type": "amounts"
    }
…
 }
```

Homebox は、確認を完了するために、連結アカウントの所有者に URL を提供します。所有者は URL をたどり、対象の少額入金の記述子コード (テスト環境では、値 `SM11AA` を使用) を入力して受領を確認する必要があります。
![アカウントへの 1 セントの入金を示す、少額入金の確認ダイアログで、明細書表記コードの入力と確認ボタンのクリックを促す表示。](https://b.stripecdn.com/docs-statics-srv/assets/microdeposits.0b67c00bb4028265c9ed9dbe300f5b81.png)

少額入金確認

## PaymentMethods を InboundTransfers で使用する

Homebox では、前述のいずれかの方法で確認済みの銀行口座を使用して `InboundTransfers` の作成を開始できます。

以下のリクエストは、アカウントに関連付けられた支払い方法を使用して 200 USD を指定された ID の金融口座に送金します。`Stripe-Account` ヘッダー値は、金融アカウントと支払い方法の両方を所有する Stripe アカウントを識別します。

```curl
curl https://api.stripe.com/v1/treasury/inbound_transfers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "origin_payment_method={{PAYMENTMETHOD_ID}}" \
  -d "financial_account={{TREASURYFINANCIALACCOUNT_ID}}" \
  -d amount=20000 \
  -d currency=usd \
  -d "description=Funds for repair" \
  -d "statement_descriptor=Invoice 12"
```

成功すると、レスポンスで `InboundTransfer` オブジェクトが提供されます。このオブジェクトには、`hosted_regulatory_receipt_url` が含まれ、Homeboxプラットフォームのアカウント所有者が取引詳細にアクセスできるようにします。

```json
{
    "id": "{{INBOUND_TRANSFER_ID}}",
    "object": "inbound_transfer",
    "amount": 20000,
    "created": 1648071297,
    "currency": "usd",
    "description": "Funds for repair",
    "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
    "hosted_regulatory_receipt_url": "https://payments.stripe.com/regulatory-receipt/{{IBT_URL}}",
    "linked_flows": null,
    "livemode": false,
    "metadata": {},
    "origin_payment_method": "{{PAYMENT_METHOD_ID}}",
    ...
    "statement_descriptor": "Invoice 12",
    "status": "processing",
    ...
}
```

## PaymentMethods を OutboundPayments で使用する

また `PaymentMethod` を使用し、`OutboundPayment` オブジェクトを使用して、サードパーティーが保有する外部の銀行口座に資金を送金することもできます。

Homebox は、用品に対する支払いのために、連結アカウントのベンダー 1 社に継続的に送金する必要があります。そのためには、プラットフォームは、最初に `Customers` エンドポイントを使用して顧客 ID を取得する必要があります。

```curl
curl https://api.stripe.com/v1/customers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "description=Test Customer"
```

レスポンスには、関連する連結アカウントの顧客が示されます。Homebox は、適正な顧客を確認して、ID を記録します。

```json
{
  "id": "{{CUSTOMER_ID}}",
  "object": "customer",
  "address": null,
  "balance": 0,
  "created": 1642523420,
  "currency": null,
  "default_source": null,
  "delinquent": false,
  "description": "Test Customer",
  "discount": null,
  "email": null,
  "invoice_prefix": "96A50A92",
  "invoice_settings": {
    "custom_fields": null,
    "default_payment_method": null,
    "footer": null
  },
  "livemode": false,
  "metadata": {
  },
  "name": null,
  "next_invoice_sequence": 1,
  "phone": null,
  "preferred_locales": [

  ],
  "shipping": null,
  "tax_exempt": "none"
}

```

次に、Homebox は、ID を使用して `SetupIntent` を作成します。サードパーティーへのアウトバウンドの資金のフローでは `OutboundPayments` が使用されるため、Homebox は `customer` を指定する代わりに `flow_directions` を `outbound` に設定し、`attach_to_self` を使用する必要があります。

```curl
curl https://api.stripe.com/v1/setup_intents \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "customer={{CUSTOMER_ID}}" \
  -d "flow_directions[]=outbound" \
  -d "allowed_payment_method_types[]=us_bank_account" \
  -d "payment_method_data[type]=us_bank_account" \
  -d "payment_method_data[us_bank_account][routing_number]=110000000" \
  -d "payment_method_data[us_bank_account][account_number]=000123456789" \
  -d "payment_method_data[us_bank_account][account_holder_type]=individual" \
  -d "payment_method_data[billing_details][name]=John doe" \
  -d confirm=true
```

呼び出しが成功すると、`PaymentMethod` が顧客に正常に関連付けられたことを示す次のオブジェクトが返されます。

```json
{
  "id": "{{SETUP_INTENT_ID}}",
  "object": "setup_intent",
  "application": "{{APPLICATION_ID}}",
  "cancellation_reason": null,
  "client_secret": "{{SETUP_INTENT_SECRET}}",
  "created": 1642528487,
  "customer": "{{CUSTOMER_ID}}",
  "description": null,
  "flow_directions": [
    "outbound"
  ],
  "last_setup_error": null,
  "latest_attempt": null,
  "livemode": false,
  "mandate": null,
  "metadata": {
  },
  "next_action": null,
  "on_behalf_of": null,
  "payment_method": "{{PAYMENT_METHOD_ID}}",
  "payment_method_options": {
  },
  "payment_method_types": [
    "us_bank_account"
  ],
  "single_use_mandate": null,
  "status": "succeeded",
  "usage": "off_session"
}
```

## PaymentMethod なしで OutboundPayment を作成する

1 回限りの支払いと同様に受取人の銀行口座を保存する必要がない場合、`OutboundPayments` を送信または使用するときに `PaymentMethods` は必要ありません。

Homebox は、消耗品の費用として 50 USD をベンダーに支払う必要がありました。ベンダーに支払うために、プラットフォームは、外部銀行口座情報を指定して `OutboundPayments` を呼び出します。

```curl
curl https://api.stripe.com/v1/treasury/outbound_payments \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "destination_payment_method_data[type]=us_bank_account" \
  -d "destination_payment_method_data[us_bank_account][routing_number]=110000000" \
  -d "destination_payment_method_data[us_bank_account][account_number]=000123456789" \
  -d "destination_payment_method_data[us_bank_account][account_holder_type]=individual" \
  -d "destination_payment_method_data[billing_details][name]=John Doe" \
  -d "financial_account={{TREASURYFINANCIALACCOUNT_ID}}" \
  -d statement_descriptor=payment_1 \
  -d amount=5000 \
  -d currency=usd
```

呼び出しが成功すると、次のオブジェクトが返されます。

```json
{
  "id": "{{OUTBOUNDPAYMENT_ID}}",
  "object": "treasury.outbound_payment",
  "amount": 5000,
  "cancelable": true,
  "created": 1643033124,
  "currency": "usd",
  "customer": null,
  "description": null,
  "destination_payment_method": null,
  "destination_payment_method_details": {
    "billing_details": {
      "address": {
        "city": null,
        "country": null,
        "line1": null,
        "line2": null,
        "postal_code": null,
        "state": null
      },
      "email": null,
      "name": "John Doe",
      "phone": null
    },
    "type": "us_bank_account",
    "us_bank_account": {
      "account_holder_type": "individual",
      "bank_name": "STRIPE TEST BANK",
      "fingerprint": "SzrMIps1gg91aVKG",
      "last4": "6789",
      "network": "ach",
      "routing_number": "110000000"
    }
  },
  "end_user_details": {
    "present": false,
    "ip_address": null
  },
  "expected_arrival_date": 1643068800,
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
  "hosted_regulatory_receipt_url": "https://payments.stripe.com/regulatory-receipt/bot_test_xxx",
  "livemode": false,
  "metadata": {
  },
  "statement_descriptor": "payment_1",
  "status": "processing",
  "status_transitions": {
    "canceled_at": null,
    "failed_at": null,
    "posted_at": null,
    "processing_at": 1643033124,
    "returned_at": null
  },
  "transaction": "{{TRANSACTION_ID}}"
}
```

## See also

- [Treasury for platforms を使用した金融口座とカードの設定](https://docs.stripe.com/treasury/connect/legacy/v1/examples/financial-accounts.md)
- [API リファレンス](https://docs.stripe.com/api/treasury/financial_accounts.md)
