Stripeについて

無料トライアルを開始すると、Webhookのcustomer.subscription.created
が開始される。
stripeEvent.data.object
をcustomerSubscriptionCreated
として定義すると、
customerSubscriptionCreated.status === "trialing"
となり、そのitems.data
に購入している商品の情報が格納されている。

無料トライアルをそのまま完了した場合
無料トライアル期間が終了した際に、Webhookのcustomer.subscription.updated
が開始される。
stripeEvent.data.object
をcustomerSubscriptionUpdated
として定義すると、
customerSubscriptionUpdated.status === "active"
で判断できる。

サブスクリプションがキャンセルされると、customer.subscription.deleted
が実行される。

課金が発生した場合は、invoice.payment_succeeded
を使うのがよさそう。

サブスクリプションの請求が失敗したことが分かるWebhookは、invoice.payment_failedです

サブスクリプションの請求が失敗すると、Stripeは複数回自動的に請求を試みます。試行回数の上限に達すると、サブスクリプションのステータスが past_due に変更されます。past_due ステータスのサブスクリプションがある場合、顧客には指定された期限までに請求を支払うように通知されます。期限を過ぎると、サブスクリプションのステータスが unpaid に変更されます。unpaid ステータスの場合、顧客にはサブスクリプションがキャンセルされることが通知されます。

past_due になった時には customer.subscription.updated が走り、該当サブスクリプションの status が past_due に更新される。
また、subscription_items と latest_invoice に含まれる情報を参照することで、該当のイベントを判別することができる。

サブスクリプションの作成(無料トライアル有)
サブスクリプションが作成されたときにcustomer.subscription.created
が実行される。
statusがtrialling
になっている。その際に、サービスに購入されたプランと有効期限を記録する。
サブスクリプションが有料ステータスに移行
invoice.paid
の状態をみて、サービスの有効期限を更新する。
invoice.paid
をもとにサービスの有効期限を更新し、customer.subscription.updated
をもとにサービスのプランの状態を更新する。
無料トライアル期間中にプランを変更
無料期間中にプランを変更した場合は、customer.subscription.updated
をもとにプランを更新する。
invoice.paid
の状態をみて、サービスの有効期限を更新する。
サブスクリプションが有料ステータスに移行した場合と、やることは変わらない。
毎月のサブスクリプションを請求(成功)
invoice.paid
状態を見て、サービスの有効期限を更新する。
プランの変更
customer.subscription.updated
をもとにサービスのプランの状態を更新する。
毎月のサブスクリプションを請求(失敗)

customer idから、アクティブなサブスクリプションを全て削除する
import Stripe from 'stripe';
const stripe = new Stripe('ストライプのシークレットキー', {
apiVersion: '2020-08-27',
});
const cancelActiveSubscriptions = async (customerId: string) => {
try {
// 顧客情報を取得する
const customer = await stripe.customers.retrieve(customerId, {
expand: ['subscriptions.data'],
});
// アクティブなサブスクリプションをキャンセルする
const cancelSubscriptionPromises = customer.subscriptions.data
.filter((subscription) => subscription.status === 'active')
.map((subscription) => stripe.subscriptions.del(subscription.id));
const results = await Promise.all(cancelSubscriptionPromises);
console.log(`Canceled ${results.length} active subscriptions for customer ${customerId}`);
} catch (err) {
console.error(err);
}
};

StripeのSubscriptionのstatus
- trialing
- active
- past_due
- unpaid
- canceled
- incomplete
- incomplete_expired

StripeのカスタマーIDから、従量課金のsubscriptionIdを取得する方法。
const subscriptions = await stripe.subscriptions.list({ customer: customerId });
const subscriptionItems = subscriptions.data.find(
(subscriptionData) =>
subscriptionData.status === 'active' || subscriptionData.status === 'trialing',
)?.items.data;
const payPerUnitItem = subscriptionItems?.find(
(subscriptionItem) => subscriptionItem.plan.billing_scheme === 'tiered',
);

subscriptionIdを指定して、使用料を更新する方法
await stripe.subscriptionItems.createUsageRecord(subscriptionItemId, {
quantity,
timestamp,
action: 'set',
});

顧客IDを指定して、次回の請求予定金額を取得する方法
const upcomingInvoice = await stripe.invoices.retrieveUpcoming({
customer: customerId,
});
// 次回請求金額
const amountDue = upcomingInvoice.amount_due;

顧客IDから、次回の請求予定日を取得する方法
const nextBillingDate = subscriptions.data.find(
(subscriptionData) =>
subscriptionData.status === 'active' || subscriptionData.status === 'trialing',
)?.current_period_end;