# InboundTransfer オブジェクトを使用した資金移動

お持ちの他の口座から金融口座への送金方法をご紹介します。

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

インバウンド送金は、ACH ネットワークを使用して外部のアメリカの銀行口座から金融口座に資金を移動します。このような送金は、[InboundTransfer](https://docs.stripe.com/api/treasury/inbound_transfers.md) オブジェクトで開始されます。

インバウンド送金は、即日 ACH 機能をご利用の場合を除き、完了までに 2 〜 4 営業日かかります。詳しくは、[資金移動のタイムライン](https://docs.stripe.com/treasury/connect/legacy/v1/money-movement/timelines.md#inboundtransfer-transactions)ガイドをご覧ください。

> インバウンド送金を使用すると、金融口座所有者の銀行口座から資金を移動できます。インバウンド送金は、サードパーティの外部口座から資金を移動することには対応していません。サードパーティの外部口座から金融口座に資金を入れるには、[ACH Debit](https://docs.stripe.com/payments/ach-direct-debit/accept-a-payment.md) を使用して決済残高に資金を追加し、その後[金融口座への入金](https://docs.stripe.com/treasury/connect/legacy/v1/moving-money/payouts.md)を行います。

## InboundTransfer を作成する

`POST /v1/treasury/inbound_transfers` を使用して `InboundTransfer` オブジェクトを作成します。これは、お客様が保有する外部口座から自身の金融口座への引き出しベースの送金を表します。言い換えると、`InboundTransfer` を作成し、外部のアメリカの銀行口座から引き落としを行い、金融口座に資金を移動します。このリクエストには、以下のパラメーターを含める必要があります。

- `amount`: 金融口座に送金されるセント単位での金額。
- `currency`: 3 文字の ISO 通貨コード (サポートされている値は、現在 `usd` のみ)。
- `financial_account`: 送金を受け取る金融口座の ID。
- `origin_payment_method`: インバウンド送金の資金源です。まず、インバウンドフロー用の口座に関連付けられた決済手段を設定し、[SetupIntent](https://docs.stripe.com/api/setup_intents.md) を使用して銀行口座を確認する必要があります。または、確認済みの [ExternalAccount](https://docs.stripe.com/api/external_accounts.md) として以前設定した既存の [BankAccount](https://docs.stripe.com/api/customer_bank_accounts.md) を使用することもできます。決済手段と銀行口座のどちらを使用する場合でも、口座から資金を引き落とすには、[アカウント所有者の許可](https://docs.stripe.com/treasury/connect/legacy/v1/moving-money/working-with-bankaccount-objects.md)を得てください。

以下の JSON は、リクエストの本文に含めることができるデータを示します。 

```json
{
  // The source PaymentMethod or BankAccount. Funds are pulled from this account.
  "origin_payment_method": "{{PAYMENT_METHOD_ID}}" | "{{BANK_ACCOUNT_ID}}",
  // The destination FinancialAccount. Funds arrive in this account.
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
  // The amount to debit. 10.00 USD in this case.
  "amount": 1000,
  "currency": "usd",
  // An optional, internal description for the InboundTransfer.
  "description": "Funds for vendor payment payment_234281",
  // An optional descriptor for the InboundTransfer to send
  // to the network with the debit request. Max 10 characters
  "statement_descriptor": "payment_1",
  // Stripe doesn't support updating InboundTransfers after creation.
  // You can only set metadata at creation time.
  "metadata": null | {{Hash}}
}
```

以下のリクエストは、アカウントに関連付けられた支払い方法を使用して 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` が含まれ、お客様のプラットフォームのアカウント所有者が取引詳細にアクセスできるようにします。

```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",
    ...
}
```

> まれに、 Stripeがさまざまなリスク要因により InboundTransfer リクエストをキャンセルすることがあります。これらのシナリオでは、 API リクエストがレスポンスコード 402 でエラーになります。エラーメッセージには、エラーにつながったリスク要因の詳細が表示されています。

### 同日の ACH

Same-day ACH により、インバウンド振込の決済が迅速化され、資金は同営業日中に利用可能になります。

> Same-day ACH は、限定提供のプレビュー段階です。アクセスをリクエストするには、[treasury-support@stripe.com](mailto:treasury-support@stripe.com) までメールでお問い合わせください。アクセスが付与されるまで、Same-day ACH パラメーターを含む API コールはエラーを返します。

即日 ACH を使用すると、`InboundTransfer` が [cutoff time](https://docs.stripe.com/treasury/connect/legacy/v1/money-movement/timelines.md#bank-partner-timelines--inbound) 前に成功した場合、資金は同じ営業日に送金元の金融口座に到着します。そうでない場合、資金は翌営業日に到着します。`origin_payment_method_options.us_bank_account.ach.submission` パラメーターを `same_day` に設定します。

#### 当日 ACH の提供による不正利用リスク

当日中決済の ACH インバウンド送金は迅速に処理されるため、標準的な ACH インバウンド送金に比べて、プラットフォーム側の財務リスクが高まる恐れがあります。たとえば、連結アカウントが開始したインバウンド送金が、送金元口座の資金不足により返送されるケースが挙げられます。決済が当日中に行われると、資金が返送される前に金融口座から資金が引き落とされる時間的余裕が生じることになります。連結アカウントが資金を引き落とした後に返送が発生し、金融口座の残高がマイナスになった場合、[プラットフォーム側でその責任を負うことになります](https://docs.stripe.com/treasury/connect/legacy/v1/account-management/working-with-balances-and-transactions.md#overdrafts)。

Stripe の不正利用防止システムがインバウンド送金を高リスクのアクティビティと見なした場合、作成リクエストはエラーで失敗します。

```json
{
  "error": {
    "type": "invalid_request_error",
    "message_code": "inbound_transfer_not_same_day_eligible",
    "message": "This transaction is not eligible for same-day availability at this time. Please try again with `standard` ACH submission."
  }
}
```

`inbound_transfer_not_same_day_eligible` メッセージコードのエラーが発生した場合は、`origin_payment_method_options.us_bank_account.ach.submission` パラメーターを `standard` に設定してリクエストを再試行します。

## InboundTransfer を取得する

`GET /v1/treasury/inbound_transfers/{{INBOUND_TRANSFER_ID}}` を使用し、関連付けられた ID の `InboundTransfer` オブジェクトを取得します。

以下の JSON は、リクエストの本文に含めることができるデータを示します。 レスポンスの一部のパラメーターには、`expand[]` パラメーターに値として追加した場合にのみ返される追加情報があります。次のレスポンス例で、拡張できるフィールドには、「Expandable」コメントが付いています。オブジェクトレスポンスの拡張の詳細については、[レスポンスを拡張する](https://docs.stripe.com/api/expanding_objects.md)をご覧ください。

```json
{
  "id": "{{INBOUND_TRANSFER_ID}}",
  "object": "inbound_transfer",
  "livemode": false,
  "created": "{{Timestamp}}",
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}", // Expandable
  "amount": 1000,
  "currency": "usd",
  // The only current valid PaymentMethod type for InboundTransfers is us_bank_account
  "origin_payment_method": "{{PAYMENT_METHOD_ID}}",
  "origin_payment_method_details": {
    "type": "us_bank_account",
    "billing_details": {
      "name": "{{String}}",
      "address": {},
      "phone": "{{String}}",
      "email": "{{String}}"
    },
  },
  "description": "Funds for vendor payment payment_234281",
  "statement_descriptor": "payment_1",
  // See the following InboundTransfer state machine section
  "status": "processing" | "succeeded" | "failed",
  "status_transitions": {
    "succeeded_at": null | "{{Timestamp}}",
    "failed_at": null | "{{Timestamp}}"
  },
  // If the InboundTransfer fails, this field includes reasons for the failure
  "failure_details": {
    "code": "account_closed" |
            "account_frozen" |
            "bank_account_restricted" |
            "bank_ownership_changed" |
            "could_not_process" | // Generic fallback code
            "invalid_account_number" |
            "incorrect_account_holder_name" |
            "invalid_currency" |
            "no_account"
  },
  // Transaction representing balance impact of the InboundTransfer, created
  // upon success. If the InboundTransfer fails, no transaction
  // is created
  "transaction": "{{TRANSACTION_ID}}", // Expandable
  "hosted_regulatory_receipt_url": "https://stripe.com/unique-receipt-url",
  // If the InboundTransfer was returned after succeeding, `returned` is
  // set to True, and a ReceivedDebit is added to the linked_flows hash
  "returned": "{{Boolean}}",
  "linked_flows": {
    "return": nil | "{{RETURN_ID}}", // Expandable
  },
  "metadata": {},
}
```

次のリクエストは、`id` 値が `{{INBOUND_TRANSFER_ID}}` の `InboundTransfer` を取得します。本文の `expand[]` 配列に `transaction` を含めると、該当する情報が展開されて返されます。

```curl
curl -G https://api.stripe.com/v1/treasury/inbound_transfers/{{INBOUND_TRANSFER_ID}} \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "expand[]=financial_account"
```

成功すると、拡張された情報を持つ `InboundTransfer` オブジェクトがレスポンスで返されます。

```json
{
    "id": "{{INBOUND_TRANSFER_ID}}",
    "object": "inbound_transfer",
    "amount": 20000,
    "created": 1648071297,
    "currency": "usd",
    "description": "Inbound transfer",
    "failure_details": null,
    "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
    "hosted_regulatory_receipt_url": "https://payments.stripe.com/regulatory-receipt/{{INBOUND_TRANSFER_ID}}",
    "linked_flows": null,
    "livemode": false,
    "metadata": {},
    "origin_payment_method": "{{PAYMENT_METHOD_ID}}",
    "origin_payment_method_details": {
        "billing_details": {
            "address": {
                "city": "city",
                "country": "US",
                "line1": "Test line1",
                "line2": null,
                "postal_code": "12345",
                "state": "CA"
            },
            "email": "success@example.com",
            "name": "Created from ...",
            "phone": null
        },
        "type": "us_bank_account",
        "us_bank_account": {
            "account_holder_type": "individual",
            "account_type": "checking",
            "bank_name": "STRIPE TEST BANK",
            "fingerprint": "9k4N3QBuYSZOQY08",
            "last4": "6789",
            "network": "ach",
            "routing_number": "110000000"
        }
    },
    "returned": false,
    "statement_descriptor": "test payme",
    "status": "succeeded",
    "status_transitions": {
        "failed_at": null,
        "succeeded_at": 1648071306
    },
    "transaction": {
        "id": "{{TRANSACTION_ID}}",
        "object": "transaction",
        "amount": 20000,
        "balance_impact": {
            "cash": {
                "available": 20000,
                "inbound_pending": 0,
                "outbound_pending": 0
            },
            "credit": null,
            "current": 20000,
            "type": "cash"
        },
        "created": 1648071304,
        "currency": "usd",
        "description": "Created from ...",
        "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
        "financial_account_type": "treasury",
        "flow": "{{INBOUND_TRANSFER_ID}}",
        "flow_type": "inbound_transfer",
        "livemode": false,
        "status": "posted",
        "status_transitions": {
            "posted_at": 1648071304,
            "voided_at": null
        },
        "treasury": {
            "regulatory_receipt_url": "https://payments.stripe.com/treasury/receipt/{{TRANSACTION_ID}}"
        }
    }
}
```

## InboundTransfer を一覧表示する

`GET /v1/treasury/inbound_transfers` を使用し、関連付けられた ID の金融口座のすべての `InboundTransfers` を取得します。標準のリストパラメーターまたは `status` でリストをフィルタリングできます。

```
{
  // Standard list parameters
  "limit", "starting_after", "ending_before",
  // Filter by status
  "status": "processing" | "succeeded" | "failed",
  // Filter by FinancialAccount (Required)
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}", // Required
}
```

以下のリクエストは、ID `{{CONNECTED_ACCOUNT_ID}}` の連結アカウントに関連付けらた、ID `{{FINANCIAL_ACCOUNT_ID}}` の金融口座について、ステータスが `succeeded` のインバウンド送金をすべて取得します。

```curl
curl -G https://api.stripe.com/v1/treasury/inbound_transfers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "financial_account={{TREASURYFINANCIALACCOUNT_ID}}" \
  -d status=succeeded
```

## InboundTransfers を手動で確認する

銀行パートナーへの送金を遅らせるか、売上を長期間保留することで、送金のリスクを軽減できます。この保留により、不審なアクティビティを確認するための時間が増える可能性があります。`inbound_transfers.ach.platform_review` の機能への[アクセスをリクエスト](https://support.stripe.com/contact)すると、ステータスが `requires_confirmation` のインバウンド送金を、この機能が有効になっている金融口座ですべて受け取れるようになります。

以下は、新しい金融口座でこの機能を設定する例です。他の機能を追加することもできます。

```curl
curl https://api.stripe.com/v1/treasury/financial_accounts \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "supported_currencies[]=usd" \
  -d "inbound_transfers[ach][requested]=true" \
  -d "inbound_transfers[ach][platform_review][requested]=true"
```

以下は、既存の金融口座でこの機能を設定する例です。

```curl
curl https://api.stripe.com/v1/treasury/financial_accounts/fa_xxx/features \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "supported_currencies[]=usd" \
  -d "inbound_transfers[ach][requested]=true" \
  -d "inbound_transfers[ach][platform_review][requested]=true"
```

通常、インバウンド送金は作成時に自動的に銀行に送金されます。ただし、ステータスが `requires_confirmation` のインバウンド送金では、銀行パートナーに送金を送信する前に `/v1/treasury/inbound_transfers/{id}/confirm` エンドポイントでユーザーの明示的な確認を取る必要があります。送金を確定またはキャンセルする前に、インバウンド送金の詳細とリスクシグナルを確認できます。ステータスが `requires_confirmation` のインバウンド送金は、5 営業日以内に確定またはキャンセルしてください。5 営業日を過ぎると、送金は自動的にキャンセルされます。たとえば、金曜日に作成された `requires_confirmation` のインバウンド送金は、翌週の金曜日までに確定させる必要があります (アメリカで祝日がない場合)。

`confirm` エンドポイントで `funds_availability_delay` パラメーターを使用して、目的の金融口座に資金をリリースするまでの遅延時間 (秒単位) を指定します。これにより、追加の遅延を利用して、送金を手動で確認できます。また、このフィールドを使用して、ACH の差戻し期間を過ぎても資金を保持し、元の銀行が遅延後に資金を取り消すことができないようにすることもできます。`funds_availability_delay` を 432,000 に設定して、差戻し期間後に資金がリリースされるようにすると、さらにセキュリティが高まります。

以下は、可用性の遅延なしで `confirm` エンドポイントを呼び出す例です。

```curl
curl -X POST https://api.stripe.com/v1/treasury/inbound_transfers/ibt_xxx/confirm \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}"
```

以下は、可用性の遅延を指定して `confirm` エンドポイントを呼び出す例です。

```curl
curl https://api.stripe.com/v1/treasury/inbound_transfers/ibt_xxx/confirm \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d funds_availability_delay=432000
```

## InboundTransfer の状態

以下の表は、各ステータスと可能な移行状態について説明したものです。

| ステータス | 説明 | 状態の移行 |
| --- | --- | --- |
| `processing` | `InboundTransfer` の作成に成功しました。Stripe はネットワークでの売上の送金を指示します。 | `failed`、`canceled`、`succeeded`、`requires_confirmation` |
| `requires_confirmation` | `InboundTransfer` は保留状態で作成されます。Stripe がネットワーク上で資金の移動を開始していないときは、ユーザーは `/v1/treasury/inbound_transfers/:ID/confirm` エンドポイントを使用してこのインバウンド送金をトリガーする意図を明示する必要があります。 | `processing`、`canceled` |
| `failed` (最終状態) | `InboundTransfer` の確定に失敗しました。取引は作成されず、`payment_method` は引き落としされていません。 | 該当なし |
| `canceled` (最終状態) | `InboundTransfer` はネットワークへの送信前にキャンセルされました。Stripe は取引を無効化し、売上を外部の銀行口座から移動しません。 | 該当なし |
| `succeeded` (最終状態) | `InboundTransfer` が成功し、資金がアカウントに入金されました。取引が作成されました。外部の口座が資金を引き出した場合、InboundTransfer は成功した後で返金されることがあります。これは、関連付けられた ReceivedDebit によって表されます。 | 該当なし |

## InboundTransfer をテストする

実装をエンドツーエンドでテストするには、test [SetupIntents requests](https://docs.stripe.com/api/setup_intents.md) を使用して `PaymentMethod` を作成し、その `PaymentMethod` を `InboundTransfer` 作成リクエストに渡します。`PaymentMethods` が有効であれば `InboundTransfers` は成功し、無効な `PaymentMethods` が無効であれば (サポートされていないタイプ、未確認の銀行口座を含む、インバウンドフロー用に設定されていない、など) 本番環境と同じエラーをスローします。

## InboundTransfer の状態をテストする

Stripe では、テスト用の `PaymentMethod` トークンのセットも用意しています。これを使用すると、次のような特定の状態の移行をトリガーできます。

| PAYMENT_METHOD の値 | 結果 |
| --- | --- |
| `pm_usBankAccount` | `processing` から `succeeded` に移行する `InboundTransfer`。 |
| `pm_usBankAccount_processing` | `processing` 状態のままの `InboundTransfer`。 |
| `pm_usBankAccount_internalFailure` | `processing` から `failed` に移行する `InboundTransfer`。 |

さまざまなエッジケースをより迅速にテストするために、`PaymentMethod` のトークンは以下の特定の失敗タイプをシミュレーションします。

| PAYMENT_METHOD の値 | 結果 |
| --- | --- |
| `pm_usBankAccount_noAccount` | `failure_details.code= "no_account"` で失敗に移行する `InboundTransfer`。 |
| `pm_usBankAccount_accountClosed` | `failure_details.code= "account_closed"` で `failed` に移行する `InboundTransfer`。 |
| `pm_usBankAccount_invalidAccountNumber` | `failure_details.code= "invalid_account_number"` で失敗に移行する `InboundTransfer`。 |
| `pm_usBankAccount_insufficientFunds` | `failure_details.code= "insufficient_funds"` で失敗に移行する `InboundTransfer`。 |
| `pm_usBankAccount_debitNotAuthorized` | `failure_details.code= "debit_not_authorized"` で失敗に移行する `InboundTransfer`。 |
| `pm_usBankAccount_dispute` | `processing` から `succeeded` に移行し、後で不審請求の申請が行われる `InboundTransfer`。`inbound_transfer.returned` が `true` になり、関連付けられた `ReceivedDebit` が作成されます |

上記のすべてのケースで、`InboundTransfer` のレスポンスは `processing` 状態で始まります。関連する状態へと移行するたびに [Webhook イベント](https://docs.stripe.com/webhooks.md)が受信され、作成後に `InboundTransfer` を取得すると、想定された状態が返されます。

`PaymentMethod` として `pm_usBankAccount_sameDayACHIneligible` トークンを渡すことでも、エラー状態をテストすることができます。これにより、`InboundTransfer` (同日の ACH 送信を伴う) の作成がトリガーされ、エラーが返されます。

## InboundTransfer テストヘルパーエンドポイント

Stripe では、さまざまな状態の `InboundTransfers` をテストできるエンドポイントも提供しています。`InboundTransfer` を作成し、以下の手順に従います。

- Use the [Succeed an InboundTransfer](https://docs.stripe.com/api/treasury/inbound_transfers/test_mode_succeed.md) test helper to move the transfer with the associated ID directly into the `succeeded` state.

  `POST /v1/test_helpers/treasury/inbound_transfers/{{INBOUND_TRANSFER_ID}}/succeed`

- [テスト用の fail エンドポイント](https://docs.stripe.com/api/treasury/inbound_transfers/test_mode_fail.md) を使用し、関連付けられた ID の送金を直接 `failed` の状態に移行します。

  `POST /v1/test_helpers/treasury/inbound_transfers/{{INBOUND_TRANSFER_ID}}/fail`

これらのエンドポイントは、返品などのエラーシナリオをテストするために特に便利です。こういったエンドポイントがなければ、InboundTransfer が資金を引き出していた外部の口座からのアクションが必要になります。

本文にオプションの `failure_details.code` パラメーターを含め、送金が失敗した理由を示します。この情報が提供されない場合には、送金はデフォルトの `could_not_process` 失敗コードで失敗します。

```json
{
  "failure_details": {
    "code": "account_closed" |
          "account_frozen" |
          "bank_account_restricted" |
          "bank_ownership_changed" |
          "could_not_process" | // Generic fallback code
          "invalid_account_number" |
          "incorrect_account_holder_name" |
          "invalid_currency" |
          "no_account"
  }
}
```

プラットフォーム向け Stripe Treasury では、成功したものの後で返却される InboundTransfer をシミュレートするための `return` エンドポイントも提供しています。

[テスト用の return エンドポイント](https://docs.stripe.com/api/treasury/inbound_transfers/test_mode_return.md) を使用し、関連付けられた ID の `InboundTransfer` で返金のシミュレーションを開始します。

`POST /v1/test_helpers/treasury/inbound_transfers/{{INBOUND_TRANSFER_ID}}/return`

すべてのテスト用エンドポイントは、該当するそれぞれの状態の移行に対して [Webhooks](https://docs.stripe.com/webhooks.md) をトリガーします。移行後に `InboundTransfer` を取得すると、想定される状態が返されます。

## InboundTransfer Webhook

Stripe は、[Webhook](https://docs.stripe.com/webhooks.md) エンドポイントに以下の `InboundTransfer` イベントを送信します。

- `InboundTransfer` 作成時の `treasury.inbound_transfer.created`。
- `InboundTransfer` のステータスが変化した際の `treasury.inbound_transfer.{{new_status}}`。ステータス値のオプションには以下が含まれます。
  - `treasury.inbound_transfer.succeeded`
  - `treasury.inbound_transfer.failed`
