Example of using Stripe Subscriptions to handle usage based billing for recurring payments
# Mike Bianco <mike@suitesync.io> | |
# Description: Example of using Stripe's subscription billing to add usage based billing | |
# information to the customer's recurring invoice | |
require 'stripe' | |
require 'sinatra' | |
Stripe.api_key = ENV['STRIPE_KEY'] | |
# This example uses sinatra to listen for webhooks. You can easily use rails, or any other framework/language. | |
# Listen to Stripe events using webhooks | |
# | |
# - https://stripe.com/docs/webhooks | |
# - https://dashboard.stripe.com/account/webhooks | |
# | |
# In order to test this example out, you'll need to bind Stripe's webhooks to this local server: | |
# | |
# 1. Create a server to forward requests locally: `ngrok http 8081` | |
# 2. Setup the resulting ngrok domain in Stripe: https://dashboard.stripe.com/account/webhooks | |
# 3. Set your Stripe key: `export STRIPE_KEY=sk_test` | |
# 4. Run `ruby stripe_usage_based_billing_with_subscriptions.rb` to start the local server | |
# 5. Visit http://localhost:8081/example to trigger an example | |
# set port & host explicitly to match ngrok so Stripe can send us webhooks | |
set :port, 8081 | |
set :bind, 'localhost' | |
def generate_example_plan | |
plan = (Stripe::Plan.retrieve('example-usage-plan') rescue nil) | |
return plan if plan | |
Stripe::Plan.create( | |
id: 'example-usage-plan', | |
name: 'Example Usage Based Billing Plan', | |
amount: 10_00, | |
interval: 'month', | |
currency: 'usd', | |
) | |
end | |
post "/" do | |
event_json = JSON.parse(request.body.read) | |
# https://stripe.com/docs/api#list_events | |
# invoice.created is fired an hour or so before the invoice is paid | |
if event_json['type'] == 'invoice.created' | |
invoice_id = event_json['data']['object']['id'] | |
customer_id = event_json['data']['object']['customer'] | |
# initial invoices are always paid immediately; we only want to run usage based billing | |
# after the initial billing period | |
is_invoice_paid = event_json['data']['object']['paid'] | |
if is_invoice_paid | |
status 200 | |
return | |
end | |
puts "adding invoice item to invoice: #{invoice_id}" | |
# the line item can be mapped to a NetSuite item based on the name, or a direct | |
# reference to a NetSuite item: https://dashboard.suitesync.io/docs/invoices#standalone-invoice-items | |
invoice_item = Stripe::InvoiceItem.create( | |
customer: customer_id, | |
invoice: invoice_id, | |
amount: (rand * 100).round, | |
currency: 'usd', | |
description: 'Usage Based Billing', | |
# add custom information about the charge | |
# metadata: { } | |
) | |
end | |
status 200 | |
end | |
get '/example' do | |
plan = generate_example_plan | |
customer = Stripe::Customer.create | |
customer.sources.create(source: 'tok_visa') | |
customer.subscriptions.create( | |
plan: plan.id, | |
trial_end: Time.now.to_i + 5 | |
) | |
puts customer.id | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment