LoginSignup
4
3

More than 1 year has passed since last update.

Stripeの料金データを通貨やmetadataなどで検索・取得する6つの方法

Posted at

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を利用してクエリを組み立てることも可能です。
ただし、ANDORの併用はできませんのでご注意ください。

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本ペースで更新中です。

-> Stripe Organizationsをフォローして最新情報をQiitaで受け取る

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3