0
0

More than 1 year has passed since last update.

#Stripe API / サブスクリプションのスケジュール登録が開始済みでも予約中でも SubscriptionSchedule を Update してキャンセル登録する例 / #Ruby

Last updated at Posted at 2020-01-03

points

  • 1ヶ月サイクルのプラン1個だけをスケジュール登録して、あとから end_date = キャンセル日を登録する場合
  • Subscription に対してであれば Update で cance_at を登録すれば良いのだが、SubscriptionSchedule が開始していない場合は、そもそも Subscription が発生していないため、できない
  • どちらの場合も SubscriptionSchedule への update で APIリクエストを完結させたいが、SubscriptionSchedule はちょっと癖があるやつ
  • SubscriptionSchedule が active = 開始している場合は、 current_phase.start_date を起点に、そこから数ヶ月後の end_date をぴったりと指定する。なぜなら中途半端な日時を指定すると、日割り計算的な請求が発生してしまうから。
  • SubscriptionSchedule が not_started= 開始していない場合は、 未来に開始される最初のフェーズ = phasse の start_date を起点に、そこから数ヶ月後の end_date をぴったりと指定する。なぜなら中途半端な日時を指定すると、日割り計算的な請求が発生してしまうから。ちなみに現在フェーズの期間 ( current_phase ) はサブスクリプションの請求サイクルとは異なる。
  • SubscriptionSchedule Update で phase 単位で iterations を指定することもできるだろうが、start_date / end_date を明確に与えてあげたほうが、場合によってはやりやすそうだ。いや、やりやすい方でお願いします。

Docs

参考 - Stripeの基本

日本正式リリースしたStripeを使ってサブスクリプション型決済システムを実装する - Qiita
https://qiita.com/tady/items/7617e62b2a5402ebd0fb

Stripe Billing 101 - Qiita
https://qiita.com/y_toku/items/235b5e7ee00792edcbbf

Stripe初心者のための基本的な使い方(Rails編) - Qiita
https://qiita.com/ryouzi/items/6ee8f277471aa3b02f7b

Docs

Code

# 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

require 'active_support/core_ext'
require 'stripe'

Stripe::api_key = ENV['STRIPE_SECRET_KEY']

[1.month, 3.months].each do |end_at_from|
  product1 = Stripe::Product.create(name: "Gold plan #{rand(9999999999)}")
  plan1 = Stripe::Plan.create(interval: 'month', 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
  soon_start_subscription_schedule = Stripe::SubscriptionSchedule.create(
    {
      customer: customer.id,
      start_date: Time.now.to_i + 5,
      default_settings: {
        default_payment_method: customer_payment_method.id,
      },
      phases: [
        {
          plans:
            [
              { plan: plan1.id, quantity: 1 },
            ],
          prorate: false,
          default_tax_rates: [tax_rate],
        },
      ],
    }
  )

  puts '-' * 100
  puts "Wait until subscription schedule starts"
  puts '-' * 100
  until soon_start_subscription_schedule.status == 'active' do
    soon_start_subscription_schedule = Stripe::SubscriptionSchedule.retrieve(soon_start_subscription_schedule.id)
    puts soon_start_subscription_schedule.status
    sleep 2
  end

  started_subscription_schedule = Stripe::SubscriptionSchedule.retrieve(id: soon_start_subscription_schedule.id, expand: ['subscription'])

  future_subscription_schedule = Stripe::SubscriptionSchedule.create(
    {
      customer: customer.id,
      start_date: Time.now.to_i + 100*24*60*60,
      default_settings: {
        default_payment_method: customer_payment_method.id,
      },
      phases: [
        {
          plans:
            [
              { plan: plan1.id, quantity: 1 },
            ],
          prorate: false,
          default_tax_rates: [tax_rate],
        },
      ],
    }
  )

  # current_phase.start_date is not subscription cycle start_date
  def update_subscription_schedule(base_subscription_schedule)
    if base_subscription_schedule.status == 'active'
      start_date = base_subscription_schedule.current_phase.start_date
    elsif base_subscription_schedule.status == 'not_started'
      start_date = base_subscription_schedule.phases[0].start_date
    else
      raise
    end

    end_date = Time.at(start_date).since(3.months).to_i

    Stripe::SubscriptionSchedule.update(
      base_subscription_schedule.id,
      {
        # Set "cancel" not "releasse"
        end_behavior: 'cancel',
        phases: [
          {
            plans:
              [
                {
                  plan:     base_subscription_schedule.phases[0].plans[0].plan,
                  quantity: base_subscription_schedule.phases[0].plans[0].quantity
                },
              ],
            # prorate does not effect to Subscription or SubscriptionSchedule Canceling
            # prorate: true / false,
            default_tax_rates: base_subscription_schedule.phases[0].default_tax_rates.map(&:id),
            # For Update You must set start_date in first phase not in subscription schedule directly
            start_date: start_date,
            # If you do not want to get upcoming invoice on Subscription
            # Then you must specify end_date with Subscription natural cycle interval
            end_date: end_date
          },
        ]
      }
    )
  end

  updated_started_subscription_schedule = update_subscription_schedule(started_subscription_schedule)
  updated_future_subscription_schedule = update_subscription_schedule(future_subscription_schedule)

  put_subscription_schedule(updated_started_subscription_schedule, 'UPDATED')
  put_subscription_schedule(updated_future_subscription_schedule, 'UPDATED')
end

# NOTE
# SubscriptionSchedule current_phase is not same as Subscription cycle
# it is "phase" start_date and end_date
#
# If phase end_date is 3.months after then ...
#
# Time.at(updated_started_subscription_schedule.current_phase.start_date)
# => 2020-01-02 17:44:23 +0900
# Time.at(updated_started_subscription_schedule.current_phase.end_date)
# => 2020-04-02 17:44:23 +0900

Started Subscription - cancel at current phase

Upcoming invoice leaves from dashboard

image

Not Started Subscription - cancel at first phase

Theres Starts Ends in both in future
Theres upcoming invoice becauce Schedule will start in future
Not current invoice because Schedule not started

image

Started Subscription - cancel at future phase

Change end_date in code and run Case

image

Not Started Subscription - cancel at not first phase

Change end_date in code and run Case

image

Result

  • This is run code resutls example but not correctly same as Image capture images in this article.
----------------------------------------------------------------------------------------------------
Wait until subscription schedule starts
----------------------------------------------------------------------------------------------------
not_started
not_started
not_started
not_started
not_started
not_started
active
----------------------------------------------------------------------------------------------------
Subscription Schedule
CREATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPNZCmti5jpytUe3xhuCdN",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577955005,
  "current_phase": null,
  "customer": "cus_GTM5yQ0vRozYUW",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNHCmti5jpytURUDXSKtE",
    "default_source": null,
    "invoice_settings": 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_1FwPNHCmti5jpytUA4yh9gmW",
          "object": "tax_rate",
          "active": true,
          "created": 1577954987,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1589187005,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5XKzi7c1qy8",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": false,
      "start_date": 1586595005,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPNZCmti5jpytUWUBqK4lG",
  "status": "not_started",
  "subscription": null
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPNZCmti5jpytUe3xhuCdN
----------------------------------------------------------------------------------------------------
Subscription Schedule
UPDATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPNJCmti5jpytU8hFkMssH",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577954989,
  "current_phase": {
    "end_date": 1585817393,
    "start_date": 1577954993
  },
  "customer": "cus_GTM5yQ0vRozYUW",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNHCmti5jpytURUDXSKtE",
    "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_1FwPNHCmti5jpytUA4yh9gmW",
          "object": "tax_rate",
          "active": true,
          "created": 1577954987,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1585817393,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5XKzi7c1qy8",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": true,
      "start_date": 1577954993,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPNZCmti5jpytUoCQuoPaf",
  "status": "active",
  "subscription": "sub_GTM59xT4BS5E3j"
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPNJCmti5jpytU8hFkMssH
----------------------------------------------------------------------------------------------------
Subscription Schedule
UPDATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPNZCmti5jpytUe3xhuCdN",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577955005,
  "current_phase": null,
  "customer": "cus_GTM5yQ0vRozYUW",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNHCmti5jpytURUDXSKtE",
    "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_1FwPNHCmti5jpytUA4yh9gmW",
          "object": "tax_rate",
          "active": true,
          "created": 1577954987,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1594457405,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5XKzi7c1qy8",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": true,
      "start_date": 1586595005,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPNaCmti5jpytUnlvLBTke",
  "status": "not_started",
  "subscription": null
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPNZCmti5jpytUe3xhuCdN
----------------------------------------------------------------------------------------------------
Wait until subscription schedule starts
----------------------------------------------------------------------------------------------------
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
not_started
active
----------------------------------------------------------------------------------------------------
Subscription Schedule
CREATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPOZCmti5jpytUqLGjGd5a",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577955067,
  "current_phase": null,
  "customer": "cus_GTM5Wlau0N9HHj",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNcCmti5jpytUPG6hdjRk",
    "default_source": null,
    "invoice_settings": 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_1FwPNbCmti5jpytUOMYY1jCE",
          "object": "tax_rate",
          "active": true,
          "created": 1577955007,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1589187067,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5akDaPHCKOr",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": false,
      "start_date": 1586595067,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPOZCmti5jpytUsHM0JqYJ",
  "status": "not_started",
  "subscription": null
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPOZCmti5jpytUqLGjGd5a
----------------------------------------------------------------------------------------------------
Subscription Schedule
UPDATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPNdCmti5jpytUnvii1fUR",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577955009,
  "current_phase": {
    "end_date": 1585817414,
    "start_date": 1577955014
  },
  "customer": "cus_GTM5Wlau0N9HHj",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNcCmti5jpytUPG6hdjRk",
    "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_1FwPNbCmti5jpytUOMYY1jCE",
          "object": "tax_rate",
          "active": true,
          "created": 1577955007,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1585817414,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5akDaPHCKOr",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": true,
      "start_date": 1577955014,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPOaCmti5jpytU2OqMiUUC",
  "status": "active",
  "subscription": "sub_GTM64npF4L1rop"
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPNdCmti5jpytUnvii1fUR
----------------------------------------------------------------------------------------------------
Subscription Schedule
UPDATED
----------------------------------------------------------------------------------------------------
{
  "id": "sub_sched_1FwPOZCmti5jpytUqLGjGd5a",
  "object": "subscription_schedule",
  "canceled_at": null,
  "completed_at": null,
  "created": 1577955067,
  "current_phase": null,
  "customer": "cus_GTM5Wlau0N9HHj",
  "default_settings": {
    "billing_thresholds": null,
    "collection_method": "charge_automatically",
    "default_payment_method": "pm_1FwPNcCmti5jpytUPG6hdjRk",
    "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_1FwPNbCmti5jpytUOMYY1jCE",
          "object": "tax_rate",
          "active": true,
          "created": 1577955007,
          "description": null,
          "display_name": "Tax Rate",
          "inclusive": false,
          "jurisdiction": null,
          "livemode": false,
          "metadata": {
          },
          "percentage": 10.0
        }
      ],
      "end_date": 1594457467,
      "invoice_settings": null,
      "plans": [
        {
          "billing_thresholds": null,
          "plan": "plan_GTM5akDaPHCKOr",
          "quantity": 1,
          "tax_rates": [

          ]
        }
      ],
      "prorate": true,
      "start_date": 1586595067,
      "tax_percent": 10.0,
      "trial_end": null
    }
  ],
  "released_at": null,
  "released_subscription": null,
  "renewal_interval": null,
  "revision": "sub_sched_rev_1FwPObCmti5jpytU5eKvVg9W",
  "status": "not_started",
  "subscription": null
}
----------------------------------------------------------------------------------------------------
https://dashboard.stripe.com/test/subscription_schedules/sub_sched_1FwPOZCmti5jpytUqLGjGd5a


Original by Github issue

チャットメンバー募集

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

Twitter

0
0
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
0
0