Skip to main content

Blog

Stripe Billingの従量課金をNode.js (TypeScript)で実装する

Posted over 2 years ago
この記事をシェア:

Stripe Billingではクラウドサービスのような「使った分だけ請求する」従量課金が作れます。「ユーザー1人につき100円」のようなこともできます。

今回はNode.js(TypeScript)でこのあたりの諸々を実装する方法をまとめました。

プランを作る

まずは従量課金のプランを作ります。

今回作るプランは、「1単位10円の月額プラン」とします。

import * as Stripe from 'stripe'

const stripe = new Stripe(process.env.STRIPE_DEV_KEY as string)

stripe.plans.create({
  amount: 10,
  currency: 'jpy',
  interval: 'month',
  interval_count: 1,
  product: {
    name: 'metor plan'
  },
  nickname: 'test',
  aggregate_usage: 'max',
  billing_scheme: 'per_unit',
  usage_type: 'metered',
})
  .then(data => console.log(data))
  .catch(err => console.log(err))

段階的に価格を変えたい場合については、QiitaにRubyで実装した記事がありますのでそちらを御覧ください。

作成に成功すれば、Stripeのダッシュボードからプランが確認できます。

余談ですが、現状従量課金プランはCheckout使えないみたいですね

従量課金プランをsubscribeする

続いて作ったプランを顧客に契約してもらいましょう。

必要なのはcustomer idとplan idの2つです。

stripe.subscriptions.create({
  customer: 'cus_xxxxx',
  plan: 'plan_xxxxx',
}).then(data => console.log(data))
.catch(err => console.log(err))

これでOKです。ただし従量課金の場合、これだけでは1円も課金されません。なぜなら使用量をStripeに伝える必要があるからです。

初期状態は0単位ですので1円も課金されません。

使用量をStripeに伝える

先程作成したsubscriptionに対して、usageRecords APIを使うことで使用量を伝えることができます。

import * as Stripe from 'stripe'
import moment from 'moment'

const stripe = new Stripe(process.env.STRIPE_DEV_KEY as string)

// 従量課金プランかどうかを判定するヘルパー関数
const isMeteredPlan = (plan: Stripe.plans.IPlan): boolean => plan.usage_type === 'metered'

// 従量課金プランをピックアップするヘルパー関数
const findMeteredSubscriptionItem = (subscriptionItems: Stripe.subscriptionItems.ISubscriptionItem[]): Stripe.subscriptionItems.ISubscriptionItem | undefined => {
  return subscriptionItems.find(({plan}) => isMeteredPlan(plan))
}


const setUsage = async (subscriptionId: string, usage: number) => {
  // subscribeしているアイテムを取得
  const si = await stripe.subscriptionItems.list({
    subscription: subscriptionId
  })
  const subscriptionItems = si.data || []
  if (subscriptionItems.length < 0) throw new Error('No such subscription')

  // 従量課金プランをピックアップ
  const autoChargeSubscription = findMeteredSubscriptionItem(subscriptionItems)
  if (!autoChargeSubscription) throw new Error('No metered plan')

  // 使用量をセットする
  const result = await stripe.usageRecords.create(
    autoChargeSubscription.id,
    {
      timestamp: moment().unix(),
      quantity: usage,
      action: 'set'
    })
  
  // 使用状況を確認する
  const history = await stripe.usageRecordSummaries.list(autoChargeSubscription.id)
  console.log(history.data)
}

setUsage(subscriptionId, 6)

ポイントはsubscriptionのidではなく、subscription itemのidが必要ということです。「定額プラン」+「従量課金のオプション」のようなsubscription体系になることもありますので、subscribeしているitemをちゃんと指定してねということでしょう。

ちなみに上のサンプルは従量課金プランが1つであることを前提に作ってあります。なので複数の従量課金プランをsubscribeさせている場合は、findMeteredSubscriptionItem関数の判定文を「従量課金かどうか」+「追加したいplanかどうか」という判定になるように調整してください。

Tools to Support Stripe Development

We provide helpful tools to extend the Stripe Dashboard and streamline development and testing.

View All Tools

Support This Project

If you find this content helpful, consider supporting the project through GitHub Sponsors. Your support helps maintain and improve these tools.