Stripeでは、一回切りの決済でも定期課金でも商品・料金データをDashboardで登録して利用します。
Checkoutのサンプルコードでも、料金IDを引数に設定していますね。
const sesssion = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{
price: 'price_xx',
quantity: 1
}]
...
})
そのため、ECやSaaSなどで、複数の商品・料金をユーザーが選んで決済できるシステムを作りたい場合には、料金データのリストを取得して表示させる実装が便利です。
ただし、提供する製品やサービスによっては、「取得したい料金」と「除外したい料金」が発生します。
ここでは、料金データをStripeのAPIから取得する方法を6種類紹介します。
基本: Price APIのListメソッドを利用して取得する
まず基本の形として、Price APIでListメソッドを利用する方法を紹介します。
const prices = await stripe.prices.list();
引数を何も設定していない場合、有効化されている料金データを先頭10件分取得できます。
一部の方法を除いて、基本的にはこのAPIに引数を渡して、料金データを検索します。
検索方法1: 通貨や有効化ステータス、支払いサイクルで検索する
List APIでは、通貨や有効化ステータス・支払いサイクルでの検索ができます。
そのため、「日本円の定期課金料金を30件」や「月額の定期課金データを最大100件」のような、検索が可能です。
日本円の料金データのみ取得する
await stripe.prices.list({
currency: 'jpy',
});
月額のサブスクリプション料金のみ取得する
await stripe.prices.list({
recurring: {
interval: 'month',
},
type: 'recurring',
});
検索方法2: 特定の商品に紐付けされた料金データを取得する
List APIには、「どの商品に紐付けされた料金か」を検索するためのオプションも含まれています。
product
パラメーターに対象の商品IDを入れることで、その商品に設定された料金のみが取得できます。
const prices = await stripe.prices.list({
product: 'prod_xxx',
});
また、その他のパラメーターと組み合わせることもできますので、「prod_xxx
の日本円での買い切り料金のみ取得」などの検索も可能です。
const prices = await stripe.prices.list({
product: 'prod_xxx',
currency: 'jpy',
type: 'one_time',
});
方法3: [検索キー]を利用して、必要な料金データのみ取得する
「表示させたい料金があまり多くない」かつ「一部の料金は、価格改訂を行う可能性がある」ケースでは、「検索キー(Lookup Key)」を利用することもできます。
lookup_keys
引数で取得したい料金の検索キーを列挙することで、対応する検索キーが設定されている料金データのみを取得できます。
const result = await stripe.prices.list({
lookup_keys: ['membership_free', 'membership_bronze', 'membership_silver']
})
検索キーを利用すると、価格改訂で新しい料金データを表示させたい場合の作業量を減らすことができます。
transfer_lookup_key
を利用したCreateまたはUpdateのAPIリクエストを実行するだけで、取得・検索側の実装を変更せずに料金データを差し替えることができます。
await stripe.prices.update('price_xxxx', {
transfer_lookup_key: true,
lookup_key: 'monthly_membership_bronze',
})
現時点では、取得したいキーを明示的に指定する必要があります。
そのため、Connectを利用したマーケットプレイスなど、料金データが増減しやすいシステムでは実装にすこし工夫が必要です。
検索キーの使い方についてはこちらの記事へ
方法4: Search APIを利用する
検索キーやList APIのパラメーターだけでは検索しきれないケースでは、Search APIを利用することもできます。
このAPIでは、List APIの引数に加えてmetadataの内容についても検索対象に含めることができます。
const prices = await stripe.prices.search({
query: "metadata['service']:'awesome_food_service'"
});
また、Search APIではAND
またはOR
を利用してクエリを組み立てることも可能です。
ただし、AND
とOR
の併用はできませんのでご注意ください。
const prices = await stripe.prices.search({
query: "metadata['service']:'awesome_food_service' AND metadata['class']:'bronze' AND currency:'jpy'"
});
TypeScriptであれば、以下のようなクエリービルダー関数を用意することも可能です。
const createPriceSearchQuery = (query : {
[key: string]: string | {
[metadataName: string]: string;
};
}, operator: 'AND' | 'OR' = 'AND'): string => {
const queries = Object.entries(query).map(([key, value]) => {
if (typeof value === 'string') {
return `${key}: "${value}"`;
}
return Object.entries(value).map(([metadataKey, metadataValue]) => {
return `${key}["${metadataKey}"]: "${metadataValue}"`;
}).join(` ${operator} `);
})
return queries.join(` ${operator} `);
};
ビルダー関数を用意することで、オブジェクト形式でクエリを定義することができます。
const prices = await stripe.prices.search({
query: createPriceSearchQuery({
metadata: {
service: 'awesome_food_service',
class: 'bronze',
},
currency: 'jpy',
})
});
Search APIは、2022年4月に登場した新しいAPIです。
もしmetadataを利用した検索で対応できる要件であれば、List API呼び出し後にフィルターしている処理をSearch APIに切り替えてみてもよいかもしれません。
方法5: Search APIで商品データを検索してから料金データを取得する
Search APIは料金以外のデータに対しても利用できます。
そのため、商品のデータに対してSearchを行うことで、取得したい料金データの種類を絞り込むことも可能です。
const products = await stripe.products.search({
query: 'active: "true" AND description~"food"'
});
const prices = await Promise.all(
products.data.map(
async product => {
return stripe.prices.list({
product: product.id,
});
})
);
ただし、取得した商品データの件数分PriceのList APIを呼び出すため、レスポンスが遅くなる可能性があることにご注意ください。
方法6: Webhookを利用して、別途検索インデックスを作成する
これまでの5つの方法でも難しい要件の場合、別途検索用のAPIを外部に作ることも検討できます。
その場合、Priceに関係するWebhookイベントをListenし、検索インデックスの追加・変更・削除を自動化できるようにしましょう。
switch (event.type) {
case 'price.created': {
// 検索用DBにアイテムを追加する処理
break;
}
case 'price.deleted': {
// 検索用DBからアイテムを削除する処理
break;
}
case 'price.updated': {
// 検索用DBのアイテムを更新する処理
break;
}
default:
break;
}
Webhookと検索APIそれぞれのメンテナンスが必要になります。
ですが、AlgoliaやElasticsearch / Opensearchなどを利用することで、ユーザーが利用する商品検索画面にも利用できます。
おわりに
Stripeの料金データを検索・取得する方法を6種類紹介しました。
実装のシンプルさや取得したいデータの種類、ユーザーに提供したい画面・機能に応じて、どの方法が向いていそうかの検討に役立てば幸いです。
[PR] Stripe開発者向け情報をQiitaにて配信中!
- [Stripe Updates]:開発者向けStripeアップデート紹介・解説
- ユースケース別のStripe製品や実装サンプルの紹介
- Stripeと外部サービス・OSSとの連携方法やTipsの紹介
- 初心者向けのチュートリアル(予定)
など、Stripeを利用してオンラインビジネスを始める方法について週に2〜3本ペースで更新中です。