August 23, 2016
In an earlier post I wrote about how to take a one off payment with Stripe from your Rails app. But it is likely to happen that there will be times when you will need to be able to take payment from your customer at a later time. Maybe you have a thing on back order, maybe you only charge when an item is shipped to your customer. However the tokens that are obtained from Stripe are made for immediate, one time use. So what do we do??
This is where the Stripe Customer object comes into play, and can very easily work with your existing Customer code in your system.
Assuming that you have a Customer class in your application, you are going to have to add a column to your customers table to be able to store what the customer id you get from stripe is. So you're going to need a database migration:
class AddStripeCustomerId < ActiveRecord::Migration def change add_column :customers, :stripe_customer_id, :string end end
The id that we get from Stripe is a string, so we'll get a string column added for when we create them with Stripe. The next part of what we need to do will depend on the flow of your application. I imagine that it belongs in a controller that takes care of your customers information. If you are capturing more stuff about the payment than just a stripe customer id, it may warrant it's own model and controller, but as all we are doing is storing that id, we can do it with a Customer Update action.
class CustomerProfilesController < ApplicationController def update @customer = Customer.find(params[:id]) if @customer.update(permitted_params) redirect_to profile_path(@customer) else render :edit end end end
This is a standard CRUD controller flow, and part of it would include a stripe card token obtained with Stripe.js like in my earlier post. As part of our update to our Customer object then, we want to create a Stripe Customer with a payment source.
class Customer < ActiveRecord::Base attr_accessor :payment_token before_save :create_stripe_customer, if: :card_supplied_and_stripe_customer_blank? before_save :update_stripe_payment_source, if: :card_supplied_and_stripe_customer_present? private def card_supplied_and_stripe_customer_blank payemt_token.present? && stripe_customer_id.blank? end def card_supplied_and_stripe_customer_present? payment_token.present? && stripe_customer_id.present? end end
Some simple callbacks here will allow us to decide if we need to do anything with Stripe, and what it is we need to do. When we are getting a payment_token from the Customers form and they do not have a stripe customer id, then we need to create a customer with Stripe that we can charge.
class Customer < ActiveRecord::Base ### omitted for brevity private def create_stripe_customer stripe_customer = Stripe::Customer.create( description: "This is a customer with email: #{email}", source: payment_token ) self.stripe_customer_id = stripe_customer.id end end
Pretty simple, create a Stripe customer object, take the id that it returns and assign it to our new field in the database. But about our second scenario. What if we already have a card and our customer supplies a card via their edit form. Then we need to update it with Stripe:
class Customer < ActiveRecord::Base ### omitted for brevity private def update_stripe_payment_source stripe_customer = Stripe::Customer.retrieve(stripe_customer_id) stripe_customer.source = payment_token stripe_customer.save end end
So all we had to do was call the customer that has been stored with Stripe, supply the new payment token as the source and save the new value with the customer.
Now that we have our stripe customer with a card attached to them, we can take a payment from them. This could be something as simple as our PurchasesController again, but now our customer would be part of the purchase, our customer could have many purchases:
class Customer < ActiveRecord::Base has_many :purchases end
So of course our Purchase will belong to a customer:
class Purchase belongs_to :customer end
And so now when we call our controller code to make a purchase:
class PurchasesController < ApplicationController def create @purchase = Purchase.new(purchase_params) if @purchase.save_and_make_payment redirect_to confirmation_path(@purchase) else render :new end end end
We would now have this in our Purchase class:
class Purchase < ActiveRecord::Base attr_accessor :payment_token def save_and_make_payment if valid? begin charge = Stripe::Charge.create( amount: price_in_cents, currency: currency, customer: customer.stripe_customer_id ) save rescue Stripe::CardError => e errors.add :credit_card, e.message false end end end end
So now instead of just providing a payment token that we obtained, we provide the stripe customer id that has got a token already associated with them on the Stripe system, and can be charged whenever they make a new purchase without having to provide their card details everytime, and, again, without you haing to go through the exhaustive and painful process of PCI compliance.
The sample code that I've used here to illustrate how these Stripe commands work are triggered with ActiveRecord Callbacks, which if used carelessly can certain create a bit of a mess if your classes are too big and too many of them are triggered. For instance, on this example Customer class, if there were more callbacks being called I would need to make sure that my stripe calls are last as I wouldn't want to bother trying to make them is if some other part of my callback chain failed as I'd end up updating my Stripe object, but not persisting that success to my database necessarily. There certainly would be other ways to manage the hookup with Stripe for these, possibly straight in the controller, or in a service object, but going into those were beyond the scope of what I was talking about.
Now you have the information you need to both charge for a purchase immediately, or now to provide your customers with the chance to pay you without entering their details on every purchase if they wish. Of course if you need more help with the, please let me know in the comments or send me an email.