These notes are meant to answer some basic questions about using Stripe for billing, and also to answer some questions about implementation which are not covered in the Stripe documentation and forums. This is not a comprehensive overview by any means. If you find errors, please let me know and I will fix them. The examples will use the stripe-ruby gem (v1.7.0). A list of basic operations can be found in Stripe's documentation.
Stripe recommends downloading the gem over SSL from the mirror at https://code.stripe.com.
sudo gem install --source https://code.stripe.com stripe
Here is a list of resources which I have found useful:
- Railscasts episode 288
- Stripe sample checkout form
- https://answers.stripe.com/
- https://stripe.com/docs/testing
Creating Subscription Plans
Plans can be created through the Stripe Dashboard or the API. Since plans will not change often, it’s easy to create them through the Dashboard and retrieve them from the application via the API.
Stripe::Plan.create(
:amount => 999,
:interval => 'month',
:name => 'My Basic Plan',
:currency => 'usd',
:id => 'basic'
)
Create Token with Stripe.js
Stripe provides a javascript library which sends encrypted credit card and cardholder data to Stripe’s servers from the browser. Card info is sent (along with the accounts public key) directly to Stripe and is never handled by host application.
// https://gist.github.com/1750368
Stripe.setPublishableKey('pk_YOUR_PUBLISHABLE_KEY');
Stripe.createToken({
number: $('.card-number').val(),
cvc: $('.card-cvc').val(),
exp_month: $('.card-expiry-month').val(),
exp_year: $('.card-expiry-year').val()
}, stripeResponseHandler);
The response includes the ID of the created card token if successful, and relevant error messages otherwise. The token represents a valid credit card stored by Stripe’s servers. Card tokens do not represent charges of any kind.
Token Object
A The host server can retrieve information about the card by retrieving the token referenced by the token ID. The response will contain basic card details including the last four digits of the card, instead of the entire number.
Stripe::Token.retrieve("tok_00000000000000")
Create Customer
The card token ID can then be submitted to the host server. Card tokens can be used to create a one-time charge or to create a customer with a subscription. The relationship between a customer and a plan is described by a subscription. Subscriptions can be updated or canceled through the customer object.
Stripe::Customer.create(
:description => "Customer for jim@example.com",
:plan => "basic",
:card => "tok_00000000000000" # obtained with Stripe.js
)
Many applications will offer a free plan. Stripe will allow plans to have an amount of 0 (zero). Customers can be subscribed to a free plan without providing credit card information. Subscribing free users to a free plan could make the upgrade process simpler, since a customer record will already exist. Providing a card token is optional when creating a customer with a subscription to a free account.
Stripe::Customer.create(
:description => "Customer for jim@example.com",
:plan => "my_free_plan_id"
)
Updating Customer Subscription
It’s likely that a host application will allow users to change to a different plan. In this case, the relevant customer object can be retrieved and updated. Updates can optionally be prorated.
c = Stripe::Customer.retrieve("cus_00000000000000")
c.update_subscription(:plan => "enterprise", :prorate => true)
Customers can only be updated from a free plan to a paid plan if a valid card token is provided with the request.
c = Stripe::Customer.retrieve("cus_00000000000000")
c.update_subscription(:plan => "pro", :card => "tok_00000000000000" ,:prorate => true)
Customers can be updated from a paid plan to a free plan without providing a card token. In this case Stripe will still have the user’s active card on file; so if the user switches back to a paid plan, it is optional to include a card token with the update request.
At this time, Stripe does not offer a way to remove an active card from a customer which is subscribed to a free plan.
Cancel Customer Subscription
When a user deletes their account or their customer record is no longer needed, the customer object can be retrieved and deleted.
c = Stripe::Customer.retrieve("cus_00000000000000")
c.delete
Webhook Authentication
It is critical to properly authenticate webhooks. There are two methods of authentication recommended by Stripe. The first (and simplest) method is to retrieve the event using the id parameter of the webhook request.
# in a Rails controller
def my_webhook_action
# this will raise InvalidRequestError (status 404) if the event does not exist
event = Stripe::Event.retrieve(params[:id])
# safe to use the returned event object
# ...
rescue Stripe::InvalidRequestError => e
logger.error "Unable to authenticate webhook request: #{e.message}"
# 401 Unauthorized response
end
The second method for authenticating webhooks is to use HTTP basic authentication. When setting the webhook url in the Stripe Dashboard, provide a username and password. See Railscasts episode 82 for details on implementing HTTP basic authentication in a Rails app.
Testing
If you are implementing your system in Ruby, I highly recommend the VCR gem. For a good overview of VCR and it capabilities, watch Railscasts episode 291 *.
It is important not to commit your secret api key to the repo. Use the filter_sensitive_data configuration option to redact your private key from the recordings.
VCR.configure do |c|
# ...
c.filter_sensitive_data('[secret_key]') { Stripe.api_key }
end
Appendix
* Please note that some of the configuration syntax has changed in newer versions of the VCR gem:
# VCR.config do |c| # outdated
VCR.configure do |c| # new
# ...
# c.stub_with :fakeweb # outdated
c.hook_into :fakeweb # new
end
