Stripe CheckoutやPayment Linksで「宛名書き」や「カスタマイズのオプション」などのカスタムフィールドを追加する方法

商品を販売する際、顧客に追加の情報入力を求めたいケースがあります。

例えばギフト商品を販売するECでは、「熨斗紙の宛名書き」の入力フォームを追加したくなります。

![スクリーンショット 2023-05-22 17.57.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/96f78ba8-ce72-5e44-ec0e-bf9351eeaa96.png)

またコーヒー豆を販売する際には、「焙煎度合い」や「挽きの細かさ」などを顧客が選べると、顧客の満足度が高まる可能性が上がります。

![スクリーンショット 2023-05-22 18.02.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/c4dfe1c1-bab2-4ebc-3c48-3b4afac22fa1.png)

## Stripeで「カスタムフィールド」を設定する

Stripeでは、リンク型(Payment Links)やリダイレクト型（Checkout）の決済フォームで簡単にカスタムフィールドを追加できます。

https://stripe.com/docs/payments/checkout/custom-fields

### テキストフィールドを追加する

「熨斗紙の宛名」など、顧客にテキスト入力を求めたい場合は、`type: 'text'`でフィールドを指定します。

```diff_javascript
	const session = await stripe.checkout.sessions.create({
		mode: 'payment',
		success_url: 'https://example.com/success',
		cancel_url: 'https://example.com/cancel',
		line_items: [{
			price: 'price_xxxx',
			quantity: 1
		}],
+		custom_fields: [
+		  {
+			key: 'noshigami',
+			label: {
+				type: 'custom',
+				custom: '熨斗紙の宛名(オプション)'
+			},
+			optional: true,
+			type: 'text',
+		  },
+		],
	})
```

### 選択式のフィールドを追加する

焙煎度合いなど、こちらが提示した選択肢を選んでもらう場合には、`type: 'dropdown'`を指定しましょう。

```diff_javascript

	const session = await stripe.checkout.sessions.create({
		mode: 'payment',
		success_url: 'https://example.com/success',
		cancel_url: 'https://example.com/cancel',
		line_items: [{
			price: 'price_xxx',
			quantity: 1
		}],
+		custom_fields: [
+		  {
+			key: 'roasing',
+			label: {
+				type: 'custom',
+				custom: '焙煎度合い'
+			},
+			dropdown: {
+				options:[{
+					label: '浅煎り',
+					value: 'light'
+				}, {
+					label: '中煎り',
+					value: 'midium',
+				}, {
+					label: '深煎り',
+					value: 'city'
+				}]
+			},
+			type: 'dropdown',
+		  }
+		],
	})
```

### 一度に登録できるフィールドは、２つまで

`custom_fields`の配列には、２つまでフィールドを設定できます。

```javascript

	const s = await stripe.checkout.sessions.create({
		mode: 'payment',
		success_url: 'https://example.com/success',
		cancel_url: 'https://example.com/cancel',
		line_items: [{
			price: 'price_xxx',
			quantity: 1
		}],
		custom_fields: [
		  {
			key: 'roasing',
			label: {
				type: 'custom',
				custom: '焙煎度合い'
			},
			dropdown: {
				options:[{
					label: '浅煎り',
					value: 'light'
				}, {
					label: '中煎り',
					value: 'midium',
				}, {
					label: '深煎り',
					value: 'city'
				}]
			},
			type: 'dropdown',
		  }, {
			key: 'grind',
			label: {
				type: 'custom',
				custom: '挽き方'
			},
			dropdown: {
				options: [{
					label: '細挽き',
					value: 'light'
				}, {
					label: '中挽き',
					value: 'midium',
				}, {
					label: '粗挽き',
					value: 'city'
				}]
			},
			type: 'dropdown'
		  }
		],
	})
```

:::note
`dropdown`のオプションは、２００個まで指定できます。

https://stripe.com/docs/api/checkout/sessions/create#create_checkout_session-custom_fields-dropdown-options

また、オプションごとのラベルは、100文字まで設定できます。
101文字を超えると、`Invalid string: xxx; must be at most 100 characters`のように、エラーが発生しますのでご注意ください。
:::

## Payment Linksでの設定方法

Payment Linksでカスタムフィールドを設定するには、ダッシュボードの設定画面を利用します。

[オプション]に[カスタムフィールドを追加]がありますので、オンにしましょう。

![スクリーンショット 2023-05-22 18.12.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/d82453b8-1e12-bae5-455a-4cbc8ce22b9e.png)

フィールドのラベルやオプションなどを設定すれば、追加完了です。

![スクリーンショット 2023-05-22 18.13.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/b0e0c8b5-db67-dc3c-8e5c-9339cf148ef5.png)

APIを利用する場合は、Checkout同様`custom_fields`パラメータを設定しましょう。

```diff_javascript
	const pl = await stripe.paymentLinks.create({
		line_items: [{
			price: 'price_xxxxxx',
			quantity: 1
		}],
+		custom_fields: [
+		  {
+			key: 'noshigami',
+			label: {
+				type: 'custom',
+				custom: '熨斗紙の宛名(オプション)'
+			},
+			optional: true,
+			type: 'text',
+		  },
+		],
	})
```

## 入力した情報の確認方法

入力されたカスタムフィールドの情報は、ダッシュボードやAPI・Webhookから取得できます。

### ダッシュボードでは、[支払い]ページから

もっとも簡単に確認できるのは、ダッシュボードです。

Checkoutでの決済履歴は、[支払い]ページから確認できます。

詳細ページに移動して、[Checkoutサマリー]を表示させましょう。

![スクリーンショット 2023-05-22 18.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/1ec93393-3f91-cd27-5a35-31250b16ed08.png)

顧客情報に加えて、カスタムフィールドの項目が表示されています。

### APIからカスタムフィールドを取得する

Checkout　Sessionのデータから、カスタムフィールドの情報を取得できます。

#### １回きりの注文では、`checkout.sessions.retrieve`を使う

CheckoutのセッションIDから、カスタムフィールドの情報を取得できます。

```ts
	const result = await stripe.checkout.sessions.retrieve('cs_test_xxx')
    const custom_fields = result.custom_fields
    console.log(custom_fields)
```

#### サブスクリプションでは、`checkout.sessions.list`を使う

サブスクリプションでは、`checkout.sessions.list`で**サブスクリプションIDから情報を取得**しましょう。

```ts
	const result = await stripe.checkout.sessions.list({
		subscription: 'sub_xxxx'
	})
    const custom_fields = result.data[0].custom_fields
    console.log(custom_fields)
```

#### [Appendix] 必要な情報だけ抽出する方法

選択肢の情報なども含まれていますので、「キー」と「選択された値」だけを取得したい場合には次のような処理を追加します。

```ts
	const customFieldData: {
		[key: string]: string;
	} = {}
	custom_fields.forEach((field) => {
		const { key, type } = field
		switch (type) {
			case 'dropdown': {
				if (field.dropdown?.value) {
					customFieldData[key] = field.dropdown?.value
				}
				return
			}
			case 'text': {
				if (field.text?.value) {
					customFieldData[key] = field.text?.value
				}
				return
			}
			default:
				return
		}
	})
```

### Webhookでは、`checkout.session.completed`イベントを利用する

発送システムやCRMなどと連携する場合は、Webhookでデータを連携しましょう。

`checkout.session.completed`イベントを利用すると、次のようなデータが送信されます。

```json
{
  "id": "evt_1Ep24XHssDVaQm2PpwS19Yt0",
  "object": "event",
  "api_version": "2022-11-15",
  "created": 1664928000,
  "data": {
    "object": {
      "id": "cs_test_MlZAaTXUMHjWZ7DcXjusJnDU4MxPalbtL5eYrmS2GKxqscDtpJq8QM0k",
      "object": "checkout.session",
      "cancel_url": "https://example.com/cancel",
      "custom_fields": [{
        "key": "engraving",
        "label": {
          "type": "custom",
          "custom": "Personalized engraving"
        },
        "optional": false,
        "type": "text",
        "text": {
          "value": "Jane",
        }
      }],
      "mode": "payment",
      "success_url": "https://example.com/success"
    }
  },
  "livemode": false,
  "pending_webhooks": 1,
  "request": {
    "id": null,
    "idempotency_key": null
  },
  "type": "checkout.session.completed"
}
```

## まとめ

Stripeが提供するリダイレクト型決済フォームのCheckoutやPayment Linksを利用することで、カスタムな情報を顧客に入力してもらうことも簡単にできます。

ただし在庫管理や商品画像のバリエーションに応じた変更などができませんので、SKUを持つ商品バリエーションなどに使うことは要注意です。

## 関連ドキュメント

https://stripe.com/docs/payments/checkout/custom-fields

https://stripe.com/docs/api/checkout/sessions/create