Stripe Checkoutで、複数の通貨表示に対応した決済ページを作成する

グローバルにサービスを提供している場合、商品・サービスを日本円以外の通貨で購入・契約してもらうケースが発生します。

Stripeでは、顧客に応じた通貨で決済したのち、アカウントオーナーの設定した通貨に両替してから入金を行います。

![スクリーンショット 2022-09-07 14.51.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/7146a264-057b-2c64-6379-b6d7efaef398.png)

## 為替レートに影響されない価格をグローバルに設定する方法

上記の方法では、顧客への請求金額または売上高が為替レートに影響されます。

このリスクを避けるため、「日本円では1,000円、アメリカドルでは7USD」のように複数の価格を設定することがあります。

Stripeでは、このような通貨ごとの値段設定もノーコード・API両方で可能です。

## 複数の通貨で価格を設定する

サブスクリプションや請求書では、事前に商品と価格をStripeに登録します。

料金を登録する際、[価格]フィールドの下部に[通貨を選択してください]が表示されます。

![スクリーンショット 2022-09-07 14.58.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/f536637b-6a0f-bae2-2280-f929bb78cb28.png)

ここで価格を設定したい通貨を選びましょう。

![スクリーンショット 2022-09-07 14.59.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/5e4a6b03-4557-6d68-b493-2fa2d65a101c.png)

### 現時点での為替レートを参考に価格を設定する

通貨を選択すると、すでに数字が入力された状態でフィールドが追加されます。

![スクリーンショット 2022-09-07 15.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/ed6294c8-715c-9d91-ebcb-5216cf92bb79.png)

これは現在の為替レートに応じてStripeが自動で価格を提案する機能です。
ただし提案のために為替レートを利用しているだけのため、**為替レートに応じて価格が変わることはない**点にご注意ください。

設定する金額が決まれば、通貨ごとのフィールドを更新しましょう。

![スクリーンショット 2022-09-07 15.02.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/3a947210-7a3b-c4ba-f6df-79b8810092ae.png)

### Taxの設定（外税・内税）もお忘れなく

Taxを有効化している場合、登録する料金が外税・内税どちらかを指定します。

これは[価格に税金を含める]チェックボックスのオンオフだけで設定できます。

![スクリーンショット 2022-09-07 14.57.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/5278cacf-9287-5eb3-0caf-fddc230d46b5.png)

### APIで価格を登録する方法

APIから登録する場合、Prices APIを利用します。
日本円で700円かつ7USD, 7EURで月額のサブスクリプションを提供したい場合、以下のようなコードを使います。

```js
    const price = await stripe.prices.create({
      product: 'prod_xxxx',
      currency: 'jpy',
      unit_amount: 7,
      currency_options: {
        usd: {
          unit_amount: 700,
        },
        eur: {
          unit_amount: 700,
        }
      },
      recurring: {
        interval: 'month'
      }
    })
```

`currency_options`パラメータに、`[通貨単位（英字３文字）]: Price`形式でデータを登録します。

段階的な料金(`tiers`)や顧客が金額を変更できる料金`custom_unit_amount`もサポートしています。

https://stripe.com/docs/api/prices/create#create_price-currency_options

#### 通貨によって単位が異なることに注意！

日本円では設定した数値がそのまま円になります。が、**ドルなどの一部通貨では、100倍した数値を設定**する必要があります。

ドルの場合、最小単位がドルではなくセントで設定されています。

そのため、日本円と同じ数値を入力すると、セントで換算されてしまい、金額が1/100になります。

### 設定した料金は、料金詳細ページから確認可能

商品ページなどでは、デフォルトの通貨で設定した価格のみ表示されます。

その他の通貨については、ダッシュボードの価格詳細ページにある[通貨]セクションを確認しましょう。

![スクリーンショット 2022-09-07 15.05.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/b6772d53-a967-ee3e-3139-f684ccded279.png)

## Checkoutで通貨別料金を確認する

設定した通貨別価格を、実際に決済画面で使用してみましょう。

Stripe Checkoutを利用する場合、セッション作成時のパラメータに`currency`オプションを追加します。

```diff_javascript
    const session = await stripe.checkout.sessions.create({
      line_items: [{
        price: 'price_1xxxxx',
        quantity: 1
      }, {
        price: 'price_1xxxx',
        quantity: 1
      }],
+      currency: 'usd',
      mode: 'subscription',
      success_url: 'https://example.com',
      cancel_url: 'https://example.com',
    })
```

通貨を指定すると、`line_items`で指定した料金に設定された通貨別価格が決済ページに表示されます。

![スクリーンショット 2022-09-07 15.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/e066526d-f043-9612-00af-cdc7d7c8cda4.png)

### 注意1: 設定していない通貨は指定できません

料金に登録されていない通貨を指定すると、以下のようなエラーが発生します。

```
The price specified supports currencies of `eur`, `usd`, `jpy` which doesn't include the expected currency of `cad`.
```

### 注意2: 2022/09時点では、１顧客に複数通貨のサブスクリプションは設定できません

すでに日本円でサブスクリプションを開始している顧客では、USDやEURのサブスクリプションを開始することは現状できません。

そのため、異なる通貨のサブスクリプションを開始するためのCheckoutセッションを作ろうとすると、以下のエラーが発生します。

```
You cannot combine currencies on a single customer. This customer has had a subscription, coupon, or invoice item with currency jpy
```


## 設定した通貨別料金をAPIから取得する

Checkoutを利用せず、独自のUIを構築したい場合には、Price APIからデータを取得します。

ただし、デフォルトのレスポンスには`currency_options`は含まれていません。

`currency_options`を取得するには、`expand`を指定します。

```js
    const price = await stripe.prices.retrieve('price_xxx', {
      expand: ['currency_options']
    })
```

### Lookup Key / Search APIを利用している場合

Lookup keyやSearch APIで料金データを取得している場合、`expand`の値が少し変わります。

```js
    const prices = await stripe.prices.list({
      lookup_keys: ['multi_currency'],
      expand: ['data.currency_options']
    })
```

---

## [PR] Stripe開発者向け情報をQiitaにて配信中！

- [Stripe Updates]：開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)

など、Stripeを利用してオンラインビジネスを始める方法について週に２〜３本ペースで更新中です。

-> [Stripe Organizationsをフォローして最新情報をQiitaで受け取る](https://qiita.com/organizations/stripe)