#Stripe API で 未来のスケジュール登録を更新して、サブスクリプションにキャンセル日を登録する。

# Points

- まだ開始していない、アクティブでないスケジュールでは、フェーズの start_date / end_date を自由に指定し直すことが出来そうだけ。
- SubscriptionSchedule の end_behaviour で cancel を指定すると、まだ開始していないサブスクリプションにキャンセル日、すなわち終了日を設定することができそうだ。デフォルトの挙動である end_behaviour = release だと、end_date   = 終了日はあくまで各フェーズの最後としてだけ扱われるのか、サブスクリクション自体の終了日とはならず、サイクル請求はずっと続いていくように見えた。
- end_behaviour で cancel を指定した場合も、まだサブスクリプション自体が作成されているわけではないため、サブスクリプションに対する cancel_at の登録は起こらないというか、起こり得ないように思えた。SubscriptionScheduleの状態自体をStripeが判断して、サブスクリプションの開始日・終了日を判断しているように思えたが、どうだろう。
- このサブスクリプションのスケジュール登録では、そもそも各フェーズの始まりと終わりは、サブスクリプションの開始日時・終了日時とはそんなに関係ないというか、1個フェーズの最後をトリガーにして、次のフェーズを開始するためのものっぽい。end_behaviour の指定も、あくまで最後のフェーズが終了した時の振る舞いの指定のようだ。1個のフェーズだけを扱う場合と、複数のフェーズを扱う場合も振る舞いが違ってきそうな気がするので、注意したい。
- 日割計算の扱いがどうなっているかはまだ確認していない。

# Guide

>Transitioning to the next phase
>
>Subscription schedules automatically transition from one phase to the next based on the cancel at attribute. This doesn’t cancel the subscription, it’s just the timestamp that triggers the transition to the next phase. When a phase starts, Stripe updates the subscription based on the next phase’s attributes. You can optionally enable proration to credit the user for unused items or time on the plan.

>Completing a schedule
>
>A subscription schedule is completed after the last phase is finished. When this happens, the subscription is released from the schedule and it behaves the same as it did before the schedule was applied. If you want to cancel a subscription after the last phase of a schedule is complete, you can set end_behavior to cancel.

Subscriptions Schedules API | Stripe Billing
https://stripe.com/docs/billing/subscriptions/subscription-schedules

各フェーズの終わりにそれぞれ、サブスクリプションを終了させることはできないのだろうか？もしくはできるけれど、自分が気づいていないだけなのだろうか？

* 気になったので本記事にも動作確認のサンプルを追記した。

この仕組みを考えると、フェーズが1個だけであることをベースとして、スケジュール登録の仕組みでサブスクリプションのキャンセルまで予約することは、なんだかいまいちにも思えてくる。まあ、取り扱いの方針として、そもそも複数のフェーズを扱わなければ良いのかな。

# Code

```rb
# Docs

# https://stripe.com/docs/billing/subscriptions/subscription-schedules
# https://stripe.com/docs/billing/subscriptions/subscription-schedules/use-cases
#
# https://stripe.com/docs/api/subscription_schedules/release
# https://support.stripe.com/questions/create-update-and-schedule-subscriptions

# Code

require 'stripe'

Stripe::api_key = ENV['STRIPE_SECRET_KEY']

product1 = Stripe::Product.create(name: "Gold plan #{rand(9999999999)}")
plan1 = Stripe::Plan.create(interval: 'day', currency: 'jpy', amount: 5000, product: product1.id, usage_type: 'licensed')

tax_rate = Stripe::TaxRate.create(display_name: 'Tax Rate', percentage: 10.0, inclusive: false)
customer = Stripe::Customer.create
payment_method = Stripe::PaymentMethod.create(type: 'card', card: { number: '4242424242424242', exp_year: 2030, exp_month: 01})
customer_payment_method = Stripe::PaymentMethod.attach(payment_method.id, customer: customer.id)

def put_subscription_schedule(subscription_schedule, message)
  puts '-' * 100
  puts "Subscription Schedule"
  puts message
  puts '-' * 100
  puts subscription_schedule
  puts '-' * 100
  puts "https://dashboard.stripe.com/test/subscription_schedules/#{subscription_schedule.id}"
end

# https://stripe.com/docs/api/subscription_schedules/create
subscription_schedule = Stripe::SubscriptionSchedule.create(
  {
    customer: customer.id,
    start_date: Time.now.to_i + (24*60*60),
    default_settings: {
      default_payment_method: customer_payment_method.id,
    },
    phases: [
      {
        plans:
          [
            { plan: plan1.id, quantity: 1 },
          ],
          default_tax_rates: [tax_rate],
      }
    ],
  }
)
put_subscription_schedule(subscription_schedule, 'CREATED')

phase_start_date = subscription_schedule.phases[0].start_date - (12*60*60)
phase_end_date = subscription_schedule.phases[0].start_date + (30*12*60*60)

# Example
# If set end_date and "relase" behaviour
updated_subscription_schedule = Stripe::SubscriptionSchedule.update(
  subscription_schedule.id,
  {
    end_behavior: 'release',
    phases: [
      {
        plans:
          [
            { plan: plan1.id, quantity: 1 },
          ],
          default_tax_rates: [tax_rate],
          start_date: phase_start_date,
          end_date: phase_end_date
      },
    ]
  }
)
put_subscription_schedule(updated_subscription_schedule, 'UPDATED')

# <Stripe::SubscriptionSchedule:0x3fe0871c7d64 id=sub_sched_1Fw3jGCmti5jpytUUEx777Uw> JSON: {
#   "id": "sub_sched_1Fw3jGCmti5jpytUUEx777Uw",
#   "object": "subscription_schedule",
#   "canceled_at": null,
#   "completed_at": null,
#   "created": 1577871782,
#   "current_phase": null,
#   "customer": "cus_GSzieHd4SaZVwT",
#   "default_settings": {"billing_thresholds":null,"collection_method":"charge_automatically","default_payment_method":"pm_1Fw3jFCmti5jpytULIdFmhNG","default_source":null,"invoice_settings":{"days_until_due":null}},
#   "end_behavior": "release",
#   "livemode": false,
#   "metadata": {},
#   "phases": [
#     {"application_fee_percent":null,"billing_thresholds":null,"collection_method":null,"coupon":null,"default_payment_method":null,"default_tax_rates":[{"id":"txr_1Fw3jFCmti5jpytUP1Oxsrtz","object":"tax_rate","active":true,"created":1577871781,"description":null,"display_name":"Tax Rate","inclusive":false,"jurisdiction":null,"livemode":false,"metadata":{},"percentage":10.0}],"end_date":1579254182,"invoice_settings":null,"plans":[{"billing_thresholds":null,"plan":"plan_GSziwVjn9dBHSj","quantity":1,"tax_rates":[]}],"prorate":true,"start_date":1577914982,"tax_percent":10.0,"trial_end":null}
#   ],
#   "released_at": null,
#   "released_subscription": null,
#   "renewal_interval": null,
#   "revision": "sub_sched_rev_1Fw40FCmti5jpytUHLyhkRAl",
#   "status": "not_started",
#   "subscription": null
#}

# If set end_date and "cancel" behaviour with single phase
updated_subscription_schedule = Stripe::SubscriptionSchedule.update(
  subscription_schedule.id,
  {
    end_behavior: 'cancel',
    phases: [
      {
        plans:
          [
            { plan: plan1.id, quantity: 1 },
          ],
          default_tax_rates: [tax_rate],
          start_date: phase_start_date,
          end_date: phase_end_date
      },
    ]
  }
)

# <Stripe::SubscriptionSchedule:0x3fe0871a6510 id=sub_sched_1Fw3jGCmti5jpytUUEx777Uw> JSON: {
#   "id": "sub_sched_1Fw3jGCmti5jpytUUEx777Uw",
#   "object": "subscription_schedule",
#   "canceled_at": null,
#   "completed_at": null,
#   "created": 1577871782,
#   "current_phase": null,
#   "customer": "cus_GSzieHd4SaZVwT",
#   "default_settings": {"billing_thresholds":null,"collection_method":"charge_automatically","default_payment_method":"pm_1Fw3jFCmti5jpytULIdFmhNG","default_source":null,"invoice_settings":{"days_until_due":null}},
#   "end_behavior": "cancel",
#   "livemode": false,
#   "metadata": {},
#   "phases": [
#     {"application_fee_percent":null,"billing_thresholds":null,"collection_method":null,"coupon":null,"default_payment_method":null,"default_tax_rates":[{"id":"txr_1Fw3jFCmti5jpytUP1Oxsrtz","object":"tax_rate","active":true,"created":1577871781,"description":null,"display_name":"Tax Rate","inclusive":false,"jurisdiction":null,"livemode":false,"metadata":{},"percentage":10.0}],"end_date":1579254182,"invoice_settings":null,"plans":[{"billing_thresholds":null,"plan":"plan_GSziwVjn9dBHSj","quantity":1,"tax_rates":[]}],"prorate":true,"start_date":1577914982,"tax_percent":10.0,"trial_end":null}
#   ],
#   "released_at": null,
#   "released_subscription": null,
#   "renewal_interval": null,
#   "revision": "sub_sched_rev_1Fw40eCmti5jpytUbsy70Mht",
#   "status": "not_started",
#   "subscription": null
# }

put_subscription_schedule(updated_subscription_schedule, 'UPDATED')


# If set end_date and "cancel" behaviour with multiple phases
updated_subscription_schedule = Stripe::SubscriptionSchedule.update(
  subscription_schedule.id,
  {
    end_behavior: 'cancel',
    phases: [
      {
        plans:
          [
            { plan: plan1.id, quantity: 1 },
          ],
          default_tax_rates: [tax_rate],
          start_date: phase_start_date,
          end_date: phase_end_date
      },
      {
        plans:
          [
            { plan: plan1.id, quantity: 1 },
          ],
          default_tax_rates: [tax_rate],
          iterations: 3
      },
    ]
  }
)

put_subscription_schedule(updated_subscription_schedule, 'UPDATED')

# <Stripe::SubscriptionSchedule:0x3fce690d5224 id=sub_sched_1Fw4UqCmti5jpytUEUBuMWRm> JSON: {
#   "id": "sub_sched_1Fw4UqCmti5jpytUEUBuMWRm",
#   "object": "subscription_schedule",
#   "canceled_at": null,
#   "completed_at": null,
#   "created": 1577874732,
#   "current_phase": null,
#   "customer": "cus_GT0VlSwXWmmxbL",
#   "default_settings": {"billing_thresholds":null,"collection_method":"charge_automatically","default_payment_method":"pm_1Fw4UpCmti5jpytU9RefgCDT","default_source":null,"invoice_settings":{"days_until_due":null}},
#   "end_behavior": "cancel",
#   "livemode": false,
#   "metadata": {},
#   "phases": [
#     {"application_fee_percent":null,"billing_thresholds":null,"collection_method":null,"coupon":null,"default_payment_method":null,"default_tax_rates":[{"id":"txr_1Fw4UoCmti5jpytUIvY4dds0","object":"tax_rate","active":true,"created":1577874730,"description":null,"display_name":"Tax Rate","inclusive":false,"jurisdiction":null,"livemode":false,"metadata":{},"percentage":10.0}],"end_date":1579257132,"invoice_settings":null,"plans":[{"billing_thresholds":null,"plan":"plan_GT0VyGHcQ7u6vp","quantity":1,"tax_rates":[]}],"prorate":true,"start_date":1577917932,"tax_percent":10.0,"trial_end":null},
#     {"application_fee_percent":null,"billing_thresholds":null,"collection_method":null,"coupon":null,"default_payment_method":null,"default_tax_rates":[{"id":"txr_1Fw4UoCmti5jpytUIvY4dds0","object":"tax_rate","active":true,"created":1577874730,"description":null,"display_name":"Tax Rate","inclusive":false,"jurisdiction":null,"livemode":false,"metadata":{},"percentage":10.0}],"end_date":1579516332,"invoice_settings":null,"plans":[{"billing_thresholds":null,"plan":"plan_GT0VyGHcQ7u6vp","quantity":1,"tax_rates":[]}],"prorate":true,"start_date":1579257132,"tax_percent":10.0,"trial_end":null}
#   ],
#   "released_at": null,
#   "released_subscription": null,
#   "renewal_interval": null,
#   "revision": "sub_sched_rev_1Fw4XXCmti5jpytUazXmVcw2",
#   "status": "not_started",
#   "subscription": null
# }


```

# Dashboard  - Release behaviour

リリースを設定した場合は、サブスクリプションは開始はするが終了はしないようだ。

![image](https://user-images.githubusercontent.com/13635059/71640229-6901dd80-2cc9-11ea-97c4-317c6082e7f9.png)


# Dashboard - Cancel behaviour

キャンセルを指定した場合は、サブスクリプションは開始して、end_date で終了するようだ。

![image](https://user-images.githubusercontent.com/13635059/71640211-e4af5a80-2cc8-11ea-9a05-0acea8be5f29.png)


# Dashboad - events

未来のスケジュールに対して何をしても、イベントはスケジュール変更以外には何も起こっていないことが分かるだろう。


![image](https://user-images.githubusercontent.com/13635059/71640285-9e5afb00-2cca-11ea-9544-34bde52a6ed0.png)


# Cancel behaviour and multiple phases

```
This update doesn't change anything about this subscription.
```

と表記されている。複数フェーズの場合は、各フェーズの終わりでサブスクリプションがキャンセル、終了するわけではないようだ。

![image](https://user-images.githubusercontent.com/13635059/71640451-9d779880-2ccd-11ea-8efe-deee75e42d4b.png)




# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2907








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->