Example of using Stripe Subscriptions to handle usage based billing for recurring payments
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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