こんにちは、サイオステクノロジーの佐藤 陽です。
今回は Subscription Schedule のちょっとした Tips をご紹介します。
ニッチな部分ではありますが、誰かに刺さることを願って書きたいと思います。
- Subscription Schedule 使いこなしたい!
- Subscription Schedule の更新がうまくいかない。
という人は是非最後までご覧ください。
はじめに
Subscription Schedule は、Subscription の変更をあらかじめ設定しておき
指定したタイミングで、自動で Subscriptionの内容を切り替えたり、キャンセルするといった便利機能です。
非常に便利な機能なのですが、その分使いこなすのもやや難しい印象です。
今回は以下のようなケースの実装例を紹介したいと思います。
- 既に Subscription が存在する(Schedule なし)
- この Subscription に対して Schedule を追加し、即座にプランの変更を実施する
ポイントとしては「即座にプランの変更を実施する」です。
イメージとしてはこのような感じです。
準備
サブスクリプションを扱うにあたり
- 商品・価格オブジェクト
- 支払いカード割り当て済みの顧客オブジェクト
については、作成してあるものとして話を進めていきます。
今回は、商品に関して
- STANDARD(10,000 円/月)
- PREMIUM(20,000 円/月)
の2種類を作成しました。
要件(スケジュール)
組みたい要件(スケジュール)としては以下の通りです。
- STANDARDを新規契約する
~ 一定時間経過 ~ - PREMIUM への変更と同時に、以下のSchedule追加する
・ 1 Iteration分だけ PREMIUM を利用後、STANDARD に戻す(今回であれば 1 ヵ月) - その後 Schedule を Release する。
(あんまりよくわからない要件ですが、そこは目をつむってください。)
環境
APIバージョンは2023-08-16を利用します。
APIのコールにはcurlを利用していきます。
各言語SDKでも同じことができると思うので、パラメータを参考にして実装してみてください。
実装
以下の流れで実装していきます。
- 新規にサブスクリプション作成
- 既存のサブスクリプションを元に Schedule を作成
- Schedule の内容を更新
それでは進めていきましょう。
新規にサブスクリプション作成
まずはサブスクリプションを作成していきます。
STANDARDの商品を一つ契約する Subscription を作成します。
STRIPE_SECRET_KEY=""
curl https://api.stripe.com/v1/subscriptions \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'customer=cus_OdiWVHTctWeyRI' \
-d 'items[0]price=price_1NqQlgE7qHO17eJUQnSUd7ru' #STANDARD priceId
作成が完了したら、レスポンスに含まれるSubscriptionId を控えておきましょう。(sub_1NqRATE7qHO17eJURAJwAorV)
既存の Subscription に対して Schedule を作成
作成したサブスクリプションに対して Schedule を作成していきます。
CreateSubscriptionSchedule に from_subscriptionというパラメータが存在するため、こちらを利用します。
このパラメータの説明には以下のように書かれています。
Migrate an existing subscription to be managed by a subscription schedule. If this parameter is set, a subscription schedule will be created using the subscription’s item(s), set to auto-renew using the subscription’s interval. When using this parameter, other parameters (such as phase values) cannot be set. To create a subscription schedule with other modifications, we recommend making two separate API calls.
from_subscriptionを使った場合は、Phase などのパラメータは使えませんよって書いてあります。
つまり、既存のサブスクリプションに対して Schedule を追加し、なおかつ Schedule の内容を変更することを一回のコールでは許容してないようです。
なのでここではひとまず、Schedule を追加するだけのリクエストを送ってみます。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules' \
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'from_subscription=sub_1NqRATE7qHO17eJURAJwAorV' #先ほど作成したSubscriptionId
レスポンスとしては以下の内容が返ってきました。
{
"id": "sub_sched_1NqRNeE7qHO17eJUmno71IQy",
"object": "subscription_schedule",
"application": null,
"canceled_at": null,
"completed_at": null,
"created": 1694743418,
"current_phase": {
"end_date": 1697334601,
"start_date": 1694742601
}
(略)
"end_behavior": "release",
(略)
}
Subscription Schedule Idは、改めて使うので控えておきましょう(sub_sched_1NqRNeE7qHO17eJUmno71IQy)
またこの時、レスポンスから
- end_behaviorが”release”である
- start_dateとend_dateが1 Iteration分である
- Phaseが1つしか含まれていない
ということが分るため、
from_subscriptionでScheduleを追加した場合は、 1 Iteration分だけのScheduleが組まれるようです。
Schedule の内容を更新
次に、この Schedule の Phase の内容を切り替えていきます。
※Phaseというのは、スケジュール内における塊の単位です。
各Phaseに対して、どのPriceを適用するのか、どの長さにするのか、等を設定できます。
繰り返しになりますが、要件としては
- STANDARD をすぐに PREMIUM に変更し
- 1か月経過した後にSTANDARDへ変更
です。
最初、以下の内容で Schedule を Update すればいいのでは?と考えました。
phase[0]:PREMIUM
phase[1]:STANDARD
一度この内容で、UpdateSchedule のリクエスト作成し、送ってみます。
※少し話が逸れますが、1つポイントとして、start_dateに”now”というパラメータを設定しています。
これはStripe側で自動で現在時刻を設定してくれるものであり、
テストクロックを利用した場合も、その時間軸での現在時刻を設定してくれます。
なので、アプリ上で現在時刻を値として与えるのではなく、”now”を使う事を推奨します。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules/sub_sched_1NqRNeE7qHO17eJUmno71IQy' \ # 先ほど作成したSchedule
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'phases[0][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ #STANDARDのpriceId
-d 'phases[0][items][0][quantity]=1' \
-d 'phases[0][start_date]=now' \
-d 'phases[0][iterations]=1' \
-d 'phases[1][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \ #PREMIUMのpriceId
-d 'phases[1][items][0][quantity]=1' \
-d 'phases[1][iterations]=1'
以下のレスポンスが返ってきました。
{
"error": {
"message": "You can not modify the start date of the current phase.",
"request_log_url": "https://dashboard.stripe.com/test/logs/req_6yPP3HqTApLXUC?t=1694746189",
"type": "invalid_request_error"
}
}
なるほど!
currentPhase の start_date は変更できないようです。
もう始まってしまっている部分のパラメータは変えられないようですね。
なので、以下のようにリクエスト内容を変えてやりました。
処理の内容としては、
- 現在の Phase (STANDARD)を即時終了させる
- PREMIUM の Phase を 1 Iteration 分追加する
- STANDARD の Phase を 1 Iteration 分追加する
という流れです。(下図(A))
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules/sub_sched_1NqRNeE7qHO17eJUmno71IQy' \ # 先ほど作成したSchedule
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'phases[0][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \ #STANDARDのpriceId
-d 'phases[0][items][0][quantity]=1' \
-d 'phases[0][start_date]=1694742601' \ #Schedule作成時のレスポンスからstart_dateを取得
-d 'phases[0][end_date]=now' \ #CurrentPhaseを即時終了させる
-d 'phases[1][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ #PREMIUMのpriceId
-d 'phases[1][items][0][quantity]=1' \
-d 'phases[1][iterations]=1' \
-d 'phases[2][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \ #STANDARDのpriceId
-d 'phases[2][items][0][quantity]=1' \
-d 'phases[2][iterations]=1'
これを実行すると、即座に PREMIUMプランに更新され
なおかつ 1 Iteration 分だけ PREMIUMプランを利用した後、STANDARD に戻る Schedule が作成されました!
また、こういった書き方もできるかな?と思いました。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules/sub_sched_1NqRNeE7qHO17eJUmno71IQy' \ # 先ほど作成したSchedule
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'phases[0][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \ #PREMIUMのpriceId
-d 'phases[0][items][0][quantity]=1' \
-d 'phases[0][start_date]=1694746172' \ #Schedule作成時のレスポンスからstart_dateを取得
-d 'phases[0][iterations]=1' \
-d 'phases[1][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \ #STANDARDのpriceId
-d 'phases[1][items][0][quantity]=1' \
-d 'phases[1][iterations]=1'
これはCurrent Phase上書きパターンですね。(下図(B))
ただ、こうしたときに注意が必要なのは、プレミアムプランが1 Iteration分続かない事です。
あくまでPhaseのIterationが1なので、Schedule作成時から1 Iteration分の期間が経過すると、自動的にStandardプランに戻ってしまいます。
なのでPREMIUMプランが1か月続かないことから、今回の要件には適しませんね。
このあたり、end_dateとのパラメータの設定でも調整できると思いますので
ビジネス要件に合わせて柔軟に設定してみてください。
支払請求日について
また、ここでひとつ注意したいのが、支払い請求日とPhaseの変更日は別物である事です。
もしScheduleのPhase変更タイミングに支払い請求日も変更したい場合は
Phaseのbilling_cycle_anchorをphase_startに設定する必要があります。
(A)のパターンでPREMIUMへの変更時に支払い請求日を変更したい場合は
phases[1][billing_cycle_anchor]=phase_start
を利用し、以下のように変更します。
STRIPE_SECRET_KEY=""
curl -L 'https://api.stripe.com/v1/subscription_schedules/sub_sched_1NqRNeE7qHO17eJUmno71IQy' \ # 先ほど作成したSchedule
-H "Authorization: Bearer ${STRIPE_SECRET_KEY}" \
-d 'phases[0][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \
-d 'phases[0][items][0][quantity]=1' \
-d 'phases[0][start_date]=1694742601' \ #Schedule作成時のレスポンスからstart_dateを取得
-d 'phases[0][end_date]=now' \ #CurrentPhaseを即時終了させる
-d 'phases[1][items][0][price]=price_1NqQlgE7qHO17eJUDIF2tl6f' \
-d 'phases[1][items][0][quantity]=1' \
-d 'phases[1][start_date]=now' \
-d 'phases[1][iterations]=1' \
-d 'phases[1][billing_cycle_anchor]=phase_start' \ #支払い請求日をPhaseの開始日に合わせる
-d 'phases[2][items][0][price]=price_1NqQlgE7qHO17eJUQnSUd7ru' \
-d 'phases[2][items][0][quantity]=1' \
-d 'phases[2][iterations]=1'
まとめ
今回は既存のSubscriptionにScheduleを追加し、なおかつその内容を更新する流れについて触れてみました。
Subscription Scheduleの扱いに関しては、パラメータも多く難しい部分もありますが、使いこなしていきたいところです。
自分も書いている間に混乱しがちだったので、
もっとシンプルに実装できるよ!ここ間違えてるよ!!
なんて事があればぜひぜひコメントお願いします。
ではまた!