Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
How to issue a refund and clear the account balance when downgrading a Stripe plan
# Michael Bianco <>
# Description: Issue a refund and clear the account balance when downgrading a Stripe plan
# Usage:
# export STRIPE_KEY=sk_test
# gem install stripe
# ruby stripe_customized_plan_changes.rb
require 'stripe'
Stripe.api_key = ENV['STRIPE_KEY']
uid =
high_plan = Stripe::Plan.create(
amount: 200_00,
interval: 'month',
currency: 'usd',
name: 'A High Plan',
id: "high_#{uid}",
low_plan = Stripe::Plan.create(
amount: 100_00,
interval: 'month',
currency: 'usd',
name: 'A Low Plan',
id: "low_#{uid}",
# There's a bunch more options available to customize how subscriptions are created:
customer = Stripe::Customer.create(email: "customer+#{uid}")
customer.sources.create(card: 'tok_visa')
subscription = customer.subscriptions.create(plan:
# NOTE in this case the initial balance will always be empty; in the real-world the
# customer could have a balance from another subscription, etc
initial_account_balance = customer.account_balance * -1
# switch to a lower-cost plan
subscription.plan =
# normally an invoice would only be created at the beginning of the next billing cycle (next month)
# here we force an invoice to be created in order to simulate the beginning of the next billing cycle
invoice = Stripe::Invoice.create(customer:, subscription:
# Issue a refund for the unused time and clear the customer balance
# the unused time on the original payment for the higher-cost plan is pushed into the account balance
current_account_balance = customer.account_balance * -1
prorated_unused_time = current_account_balance - initial_account_balance
# find the previous invoice created for this subscription so we can issue a refund
last_invoice = customer.
reject { |i| == || i.subscription != }.
max_by { |i| }
charge = Stripe::Charge.retrieve(last_invoice.charge)
refund = charge.refunds.create(amount: prorated_unused_time)
# clear the account balance
customer.account_balance = initial_account_balance * -1
puts "Customer: #{}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment