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

金融口座から外部口座への送金方法をご紹介します。

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

`OutboundTransfer` オブジェクトは、金融口座からの送金を円滑にします。`OutboundTransfer` を使用して、ACH ネットワーク、または国内の電信送金を通じて、連結アカウントが所有する外部の銀行口座に資金を送金できます。

アウトバウンド送金は通常、電信送金または ACH のどちらを使用したかに応じて、同日から 2 営業日後に受け取り側の銀行に到着します。

> (Multi FA ベータ) Multi FA ベータに登録している場合、`OutboundTransfer` を使用して、同じ連結アカウントに関連付けられている別の金融口座に `stripe` ネットワーク経由で資金を送金できます。資金は、宛先の金融口座に数分以内で入金されます。

詳しくは、[資金移動のタイムライン](https://docs.stripe.com/treasury/connect/legacy/v1/money-movement/timelines.md#outboundpayment-and-outboundtransfer-transactions)ガイドを参照してください。

`OutboundTransfer` は、決済手段のタイプとして `us_bank_account` をサポートしています。または、事業者の既存の [BankAccount](https://docs.stripe.com/payments/ach-direct-debit/migrating-from-charges.md) を [ExternalAccount](https://docs.stripe.com/api/external_accounts.md) として使用することもできます。

## OutboundTransfer を作成する

`POST /v1/treasury/outbound_transfers` を使用し、関連付けられた ID の金融口座に対して [OutboundTransfer](https://docs.stripe.com/api/treasury/outbound_transfers/create.md) を作成します。リクエストに使用可能なパラメーターのうち、4 つが必須です。

- `amount`: セント単位での送金額。
- `currency`: 3 文字の ISO 通貨コード。
- `financial_account`: 資金を引き出す元となる金融口座 ID。
- `destination_payment_method`: 送金先の `PaymentMethod` ID、または資金を受け取る `BankAccount` ID。
- `destination_payment_method_data`: 資金を受け取る金融口座。

```json
{
  // The source financial account to pull funds from.
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
  // The amount to send. 10.00 USD in this case.
  "amount": 1000,
  "currency": "usd",
  // The destination PaymentMethod or BankAccount.
  // This should be nil if destination_payment_method is set.
  "destination_payment_method_data": {
    "type": "financial_account", // us_bank_account is not supported
    "financial_account": "{{FINANCIAL_ACCOUNT_ID}}"
  },

  // This should be nil if destination_payment_method_data is set.
  "destination_payment_method": "{{PAYMENT_METHOD_ID}}"  | "{{BANK_ACCOUNT_ID}}",
  // Optionally, to explicitly specify a network, override the `network` value
  // This should be nil if destination_payment_method_data is set.
  "destination_payment_method_options": {
    "us_bank_account": {
      "network": "ach" | "us_domestic_wire"
    }
  },
  // A description visible on the external bank statement.
  "statement_descriptor": "Bank xfer",
  // An optional internal description to identify this OutboundTransfer
  "description": "Transfer to my external account",
  // Stripe doesn't support updating originated transfers after creation.
  // You can only set metadata at creation.
  "metadata": nil | Hash,
}
```

以下のリクエストは、アカウントに関連付けされた `PaymentMethod` に、送金元が特定された金融口座となる `OutboundTransfer` を作成します。

```curl
curl https://api.stripe.com/v1/treasury/outbound_transfers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "financial_account={{TREASURYFINANCIALACCOUNT_ID}}" \
  -d amount=1000 \
  -d currency=usd \
  -d "destination_payment_method={{PAYMENTMETHOD_ID}}" \
  -d "statement_descriptor=Test xfer" \
  -d "destination_payment_method_options[us_bank_account][network]=ach"
```

成功すると、新しく作成された `OutboundTransfer` オブジェクトがレスポンスで返されます。

```json
{
    "id": "{{OUTBOUND_TRANSFER_ID}}",
    "object": "outbound_transfer",
    "amount": 1000,
    "cancelable": true,
    "created": 1648479987,
    "currency": "usd",
    "description": null,
    "destination_payment_method": "{{PAYMENT_METHOD_ID}}" | null,
    "destination_payment_method_details": {
        "billing_details": {
            "address": {
                "city": null,
                "country": null,
                "line1": null,
                "line2": null,
                "postal_code": null,
                "state": null
            },
            "email": null,
            "name": null,
            "phone": null
        },
        "type": "financial_account",
        "financial_account": {
          "id": "{{FINANCIAL_ACCOUNT_ID}}",
          "network": "stripe",
        },
    },
    "expected_arrival_date": 1648512000,
    "financial_account": "{{FINANCIAL_ACCOUNT_ID}}",
    "hosted_regulatory_receipt_url": "https://payments.stripe.com/regulatory-receipt/{{URL_ID}}",
    "livemode": false,
    "metadata": {},
    "returned_details": null,
    "statement_descriptor": "Test xfer",
    "status": "processing",
    "status_transitions": {
        "canceled_at": null,
        "failed_at": null,
        "posted_at": null,
        "returned_at": null
    },
    "transaction": "{{TRANSACTION_ID}}"
}
```

### 同日の ACH

Same-day ACH により、アウトバウンド送金の決済が迅速化され、資金は同じ営業日に到着します。

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

同日 ACH を使用すると、`OutboundTransfer` の呼び出しが[締切時間](https://docs.stripe.com/treasury/connect/legacy/v1/money-movement/timelines.md#bank-partner-timelines--outbound)前に正常に完了した場合、同日中に到着する資金を送信できます。同日 ACH を使用するには、`destination_payment_method_options.us_bank_account.network` パラメーターを `ach` に設定し、`destination_payment_method_options.us_bank_account.ach.submission` パラメーターを `same_day` に設定します。

### 電信送金: 金融番号

一部の銀行では、ACH とは異なる別の電信送金の金融番号を使用することがあります。このため、支払い方法の金融番号が電信送金をサポートしていない場合、電信送金の作成時にエラーが発生することがあります。このエラーを受信した場合には、銀行の電信送金用の金融番号を指定して新しい支払い方法を追加する必要があります。

### 電信送金: 受取人の住所

電信送金には ACH メタデータのほかに、受取人名と請求先住所が必要です。住所は銀行の住所ではなく、電信送金を受け取るアカウント所有者の住所です。

支払い方法の `billing_details.address` を入力する際は、すべての住所フィールドに入力する必要があります。 `billing_details.address` に不完全なフィールドがある状態で電信送金しようとすると、エラーが発生します。

> `OutboundTransfer` を使用して電信送金を行う際、住所フィールドに入力しない場合は、デフォルトで Stripe アカウント所有者を代表する法人に設定されます。

## OutboundTransfer を取得する

`GET /v1/treasury/outbound_transfers/{{OUTBOUND_TRANSFER_ID}}` を使用して、関連付けられた ID の `OutboundTransfer` の詳細を取得します。

以下のリクエストは、関連付けられた ID の `OutboundTransfer` を取得し、`Transaction` の詳細を展開します。

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

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

#### JSON (コメント付き)

```json
{
  "id": "{{OUTBOUND_TRANSFER_ID}}",
  "object": "outbound_transfer",
  "livemode": Boolean,
  "created": Timestamp,
  "financial_account": "{{FINANCIAL_ACCOUNT_ID}}", // Expandable
  "amount": 1000,
  "currency": "usd",
  "destination_payment_method": "{{PAYMENT_METHOD_ID}}",
  "description": "Transfer to my external account",
  "statement_descriptor": "Bank xfer",
  // For more information about status, see [OutboundTransfer states](#outbound-transfer-states)
  "status": "processing" | "failed" | "posted" | "returned" | "canceled",
  "status_transitions": {
    "canceled_at": nil | Timestamp,
    "failed_at": nil | Timestamp,
    "posted_at": nil | Timestamp,
    "returned_at": nil | Timestamp,
  },
  // The local date when funds are expected to arrive in the
  // destination account
  // Set when the status is processing
  // Can change after being set (for example, due to a partner delay) - Stripe fires a
  // `treasury.outbound_transfer.expected_arrival_date_updated` webhook when it does
  "expected_arrival_date": Timestamp,
  // Transaction representing balance impact of the OutboundTransfer, created
  // synchronously with the OutboundTransfer
  // OutboundTransfer always have a Transaction from creation (the funds are
  // held immediately).
  // If the OutboundTransfer fails, the Transaction will be voided
  // If the OutboundTransfer is returned, its Transaction remains posted
  // Funds are returned to the balance with returned_details.transaction
  "transaction": "{{TRANSACTION_ID}}", // Expandable
  // A unique, Stripe-hosted direct link to the regulatory receipt for this OutboundTransfer
  "hosted_regulatory_receipt_url": Url,
  "destination_payment_method_details": nil | {
    "type": "us_bank_acount",
    "billing_details": {
      "name": nil | String,
      "phone": nil | String,
      "email": nil | String,
      "address": nil | {
        "line1": nil | String,
        "line2": nil | String,
        "city": nil | String,
        "state": nil | String,
        "postal_code": nil | String,
        "country": nil | String
      }
    }
  },
  // If the OutboundTransfer hasn't yet been sent, this field is `true`, indicating
  // that the user may still cancel through the cancel endpoint (POST v1/outbound_transfers/obt_123/cancel)
  "cancelable": Boolean,
  // If the OutboundTransfer has been returned, this field will be included with more
  // information about the return, including the transaction that returns the funds
  // The possible return codes and messages are listed below
  // See the "Handling Returned Funds" section below for more details on Returns.
  "returned_details": {
    "code": "account_closed" |
            "account_frozen" |
            "bank_account_restricted" |
            "bank_ownership_changed" |
            "could_not_process" |
            "invalid_account_number" |
            "incorrect_account_holder_name" |
            "invalid_currency" |
            "no_account" |
            "declined" // Generic fallback code
    // Human readable reason for the return. This message is geared towards the
    // end user, to help them determine next steps.
    "message": "The destination has been closed." |
               "The destination has been frozen." |
               "The destination bank account has restrictions on either the type or number of transfers allowed. This normally indicates that the bank account is a savings or other non-checking account." |
               "The destination bank account is no longer valid because its branch has changed ownership." |
               "The destination could not process this OutboundTransfer." |
               "The destination bank account details on file are probably incorrect. The routing number seems correct, but the account number is invalid." |
               "The destination bank account details on file may be incorrect." |
               "The destination was unable to process this OutboundTransfer because of its currency." |
               "The details of the destination may be incorrect." |
               "The destination has declined this OutboundTransfer."
    "transaction": "{{TRANSACTION_ID}}" // Expandable
  },
  // If available, this field shows network-specific tracking information.
  // Tracking details can appear anytime after the object is no longer cancelable.
  // Stripe sends the `treasury.outbound_transfer.tracking_details_updated` event
  // when this field is updated.
  "tracking_details": nil | {
    "type": "ach" | "us_domestic_wire",
    // Only set for ACH transfers
    "ach": nil | {
      "trace_id": "12345678901234"
    },
    // Only set for wire transfers
    "us_domestic_wire": nil | {
      "imad": "20230101MMQFMPD1001234",
      "omad": "20230101MMQFMPD1002345"
    }
  },
  "metadata": {},
}
```

## OutboundTransfer をキャンセルする

`POST /v1/treasury/outbound_transfers/{{OUTBOUND_TRANSFER_ID}}/cancel` を使用し、関連付けられた ID の `OutboundTransfer` をキャンセルします。 `OutboundTransfer` オブジェクトには、送金をキャンセルできるかどうかを示すブール値を含む `cancelable` パラメーターが含まれます。`OutboundTransfer` がネットワークに送信されると、`cancelable` 値が `false` になり、このエンドポイントからの送金に対するエラーが受信されます。

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

成功すると、ステータスが `canceled` の `OutboundTransfer` オブジェクトがレスポンスで返されます。

```json
{
    "id": "{{OUTBOUND_TRANSFER_ID}} ",
    "object": "outbound_transfer",
    "amount": 1000,
    "cancelable": false,
    "created": 1648487177,
    "currency": "usd",
    ...
    "status": "canceled",
    "status_transitions": {
        "canceled_at": 1648487198,
        "failed_at": null,
        "posted_at": null,
        "returned_at": null
    },
    "transaction": "{{TRANSACTION_ID}}"
}
```

## OutboundTransfer を一覧表示する

`GET /v1/treasury/outbound_transfers` を使用し、`financial_account` パラメーターの ID の金融口座から送信された `OutboundTransfers` をリストします。標準のリストパラメーターや `status` でリストをフィルタリングできます。

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

以下のリクエストは、特定された金融口座からの `OutboundTransfers` を取得します。含まれたパラメーターにより、レスポンスは、指定された ID の `OutboundTransfer` の後の最初の 3 件の送金に制限されます。

```curl
curl -G https://api.stripe.com/v1/treasury/outbound_transfers \
  -u "<<YOUR_SECRET_KEY>>:" \
  -H "Stripe-Account: {{CONNECTEDACCOUNT_ID}}" \
  -d "financial_account={{TREASURYFINANCIALACCOUNT_ID}}" \
  -d limit=3 \
  -d starting_after={{OUTBOUND_TRANSFER_ID}}
```

成功すると、フィルター条件を満たす [OutboundTransfer オブジェクト](https://docs.stripe.com/api/treasury/outbound_transfers/object.md) のリストがレスポンスで返されます。

## OutboundTransfer の状態

以下の表は、`OutboundTransfers` の 各 `status` と可能な移行状態について説明したものです。

| ステータス | 説明 | 状態の移行 |
| --- | --- | --- |
| `processing` | `OutboundTransfer` の開始状態。資金は、保留中の取引に割り当てられます (ただし、引き続き現在の残高に含まれています)。`cancelable` パラメーターの値が `true` の間は 、ユーザーは `OutboundTransfer` をキャンセルできます。 | `posted`、`canceled`、`failed` |
| `canceled` (最終状態) | ユーザーが、転記前に `OutboundTransfer` をキャンセルしました。Stripe は、保留中の取引を無効にし、資金をユーザーに返金します。 | 該当なし |
| `posted` | Stripe は金融口座の残高を調整し、`OutboundTransfer` が返金される可能性は低いと判断しました。 | `returned` |
| `returned` (最終状態) | `OutboundTransfer` は、送金先に正常に入金されませんでした (口座詳細に誤りがあった場合など)。Stripe は、`returned_details[transaction]` を指定して資金をユーザーに返金します。 | 該当なし |
| `failed` (最終状態) | `OutboundTransfer` がネットワークに送信されませんでした。Stripe は保留中の取引を無効にし、資金をユーザーに返金します。Stripe は、この状態を使用して内部エラーを通知する場合があります。 | 該当なし |

## OutboundTransfer をテストする

テスト環境では、テスト用決済手段として `destination_payment_method` を指定できます。独自のテスト用の [PaymentMethods](https://docs.stripe.com/api/payment_methods.md) を作成するか、実装のテスト時にテスト用 ID を使用できます。

| タイプ | 結果 | 決済手段 |
| --- | --- | --- |
| `us_bank_account` | デフォルトは `posted` に移行します。 | `pm_usBankAccount` |
| `us_bank_account` | `posted` に移行し、元の `expected_arrival_date` に 1 日追加します。 | `pm_usBankAccount_expectedArrivalDateUpdated` |
| `us_bank_account` | `processing` のままになります。 | `pm_usBankAccount_processing` |
| `us_bank_account` | `canceled` に移行します。 | `pm_usBankAccount_canceledByUser` |
| `us_bank_account` | `failed` に移行します。 | `pm_usBankAccount_internalFailure` |
| `us_bank_account` | `returned_details.code="no_account"` で `returned` に移行します。 | `pm_usBankAccount_noAccount` |
| `us_bank_account` | `returned_details.code="account_closed"` で `returned` に移行します。 | `pm_usBankAccount_accountClosed` |
| `us_bank_account` | `returned_details.code="invalid_account_number"` で `returned` に移行します。 | `pm_usBankAccount_invalidAccountNumber` |

いずれの場合も、`OutboundTransfer` のレスポンスは `processing` の状態です。Stripe は、該当する状態の移行に対して [Webhook](https://docs.stripe.com/webhooks.md) をトリガーします。`OutboundTransfer` を作成後に取得すると、想定された状態が返されます。

### OutboundTransfer のテスト用ヘルパーエンドポイント

Stripe は、さまざまな状態の `OutboundTransfers` をテストできるエンドポイントを提供しています。`OutboundTransfer` を作成した後、これらのエンドポイントを使用して、`OutboundTransfer` を `posted`、`failed`、`canceled`、または `returned` などの新しい状態に直接移行します。

- [テスト用の post エンドポイント](https://docs.stripe.com/api/treasury/outbound_transfers/test_mode_post.md)を使用して、特定された `OutboundTransfer` を `processing` から `posted` に移行します。

  `POST /v1/test_helpers/treasury/outbound_transfers/{{OUTBOUND_TRANSFER_ID}}/post`

- [テスト用の fail エンドポイント](https://docs.stripe.com/api/treasury/outbound_transfers/test_mode_fail.md)を使用して、特定された `OutboundTransfer` を `processing` から `failed` に移行します。

  `POST /v1/test_helpers/treasury/outbound_transfers/{{OUTBOUND_TRANSFER_ID}}/fail`

- [テスト用の return エンドポイント](https://docs.stripe.com/api/treasury/outbound_transfers/test_mode_return.md)を使用して、特定された `OutboundTransfer` を `posted` から `returned` に移行します。

  `POST /v1/test_helpers/treasury/outbound_transfers/{{OUTBOUND_TRANSFER_ID}}/return`

これらのエンドポイントは、返品などのエラーシナリオをテストするために特に便利です。これらがなければ、外部でのアクションが必要になります。

`return` エンドポイントでは、オプションの `returned_details.code` パラメーターを本文に含め、返金理由を示します。この情報が提供されない場合、送金にはデフォルトの `declined` 返金コードが適用されます。

```json
{
  "returned_details": {
    "code": "account_closed" |
          "account_frozen" |
          "bank_account_restricted" |
          "bank_ownership_changed" |
          "could_not_process" |
          "invalid_account_number" |
          "incorrect_account_holder_name" |
          "invalid_currency" |
          "no_account" |
          "declined"
  }
}
```

また、テスト用の `Outbound Transfer` で追跡詳細の転記をシミュレートするための、[テスト用更新エンドポイント](https://docs.stripe.com/api/treasury/outbound_transfers/test_mode_update.md)も提供しています。`tracking_details` フィールドは、テスト用オブジェクトにのみ設定できます。

いずれのケースでも、Stripe は、該当するそれぞれの状態の移行に対して [Webhooks](https://docs.stripe.com/webhooks.md) をトリガーします。移行後に `OutboundTransfer` を取得すると、想定される状態が返されます。

## OutboundTransfer Webhook

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

- OutboundTransfer 作成時の `treasury.outbound_transfer.created`。
- OutboundTransfer のステータスが変化した際の `treasury.outbound_transfer.{{new_status}}`。ステータス値のオプションには以下が含まれます。
  - `treasury.outbound_transfer.posted`
  - `treasury.outbound_transfer.failed`
  - `treasury.outbound_transfer.returned`
  - `treasury.outbound_transfer.canceled`
- OutboundTransfer の `expected_arrival_date` が変化した際の `treasury.outbound_transfer.expected_arrival_date_updated`。
- `OutboundTransfer` の追跡の詳細情報が更新された際の `treasury.outbound_transfer.tracking_details_updated`。
