How to create a charge and a customer in Stripe (Rails)
All of this can be found in the excellent Ruby API Docs. There are a few steps involved, but it's not so hard. It may take a little experimentation to get it working in your application.
It looks as though you're trying to set the customer up on a Subscription Plan (use of plan: 1212
), so I'll explain how Subscription works. I'll also explain simple one-off charges, as well, in case that's what you were looking for.
Setup Stripe in your Application
Add Stripe keys to your config/secrets.yml
file:
development:
stripe_private_key: <%= ENV["STRIPE_PRIVATE_KEY"] %>
stripe_public_key: <%= ENV["STRIPE_PUBLIC_KEY"] %>
You can keep the STRIPE_PRIVATE_KEY and STRIPE_PUBLIC_KEY in your environment. Test and production environments would require similar configuration settings.
Next, add this code to your BillingController
, or wherever you plan to use the Stripe API:
require "stripe"
Stripe.api_key = Rails.application.secrets.stripe_private_key
Add a Migration to Add Stripe Customer ID to Customer
class AddUserStripeCustomerId < ActiveRecord::Migration
def change
change_table :users do |t|
t.string :stripe_customer_id, limit: 50, null: true
end
end
end
Create a Customer
When you're ready to begin the billing process for a customer, do this:
if !@user.stripe_customer_id
@user.stripe_customer_id = Stripe::Customer.create(
account_balance: 0,
email: @user.email_canonical
)
end
Make sure to save the customer ID in your User model. You'll need to make sure that you don't keep creating and overwriting your customer ID for a user, because this is your tie-in to the Stripe payments system for that user.
Create a Default Source
The customer must have a default source assigned for subscription charges to be made. This can be created from a token, like so:
customer.sources.create({source: token_id})
or assigned from a customer's existing cards, if you've already assigned cards to the user:
customer.default_source = customer.sources.retrieve(card_id)
Make a One-off Charge
You can charge the customer one time, without recurring, and you do that with this:
Stripe::Charge.create(
:amount => 1395, # <== Currency in 'cents'
:currency => "usd",
:source => customer.default_source, # <== from previous section
:description => "Fuzzy eyeglasses"
)
You should capture the charge ID, but you can always retrieve that from Stripe if you happen to need it later.
Create a Subscription Plan
You can easily create the Subscription Plan on the Stripe console, since this is typically a one-time activity; building out a UI to manage Subscription Plans is almost certainly overkill unless you have admin users that can manage subscription plans, but shouldn't have access to the Stripe console.
To programmatically create a Subscription Plan, try this:
Stripe::Plan.create(
:amount => 4200, #<== Amount is in cents, not dollars
:interval => "month",
:name => "Purple Plan",
:currency => "usd",
:id => "purple"
)
You can create as many plans as you like, and can subscribe the user to any that they like.
Create a Subscription for the Customer
At this point, you can create the subscription on the customer, and this will initiate the billing process.
Stripe::Subscription.create(
:customer => customer,
:plan => "purple"
)
Set up a Web Hook Receiver
For some reason, this documentation is in a different location (see Webhooks), but it's a very necessary part of the process. This will keep your application advised of the
def PaymentController
protect_from_forgery :except => :webhook
def webhook
# Capture the event information from the webhook params
event_id = params[:event]
# Verify that the event isn't forged to your Stripe account
event = Stripe::Event.retrieve(event_id)
# Record the event
PaymentEvents.create!(event)
# Handle the event in terms of your application
#...
end
end
The types of events sent from Stripe are documented at Types of Events. You may choose to capture and handle some, while letting others pass. However, in my applications, I've found it's better to capture and log all events, and then handle them as you need. This way, if you missed handling an event that later becomes important to have handled, you have the event to refer to and can deal with it post hoc.
Collect a Regular Payment
This is the easy part, and may best be done with your favorite cold beverage. All you need to do from this point is monitor the Stripe console and your bank account. No additional action required, because Stripe takes care of the rest.
How to charge a particular card on a customer with Stripe.com
I figured this out.
With existing card tokens you have to send in the customer token as well
charge = Stripe::Charge.create(
:amount => "#{@subscription.price}",
:currency => "usd",
:customer => current_user.stripe_customer_id,
:card => params[:existing_card_id],
:description => "Subscription for #{current_user.email}"
)
Stripe Payments - Add existing card to customer
When you create a customer with the source
parameter, it should be a token ID ("tok_..."
), not a card ID.
See this StackOverflow answer for more information: https://stackoverflow.com/a/34416413/5307473
Create Customer w/ simple Stripe Checkout
You're using the embedded form, where as you need to use custom forms and some server side code.
You would need first create a single use token which represents a customer card from your form
(Assuming your form contains credit card number, expiry date etc...)
Taken from the docs:
Form markup:
<form action="/customer" method="POST" id="payment-form">
<span class="payment-errors"></span>
<div class="form-row">
<label>
<span>Card Number</span>
<input type="text" size="20" data-stripe="number"/>
</label>
</div>
<div class="form-row">
<label>
<span>CVC</span>
<input type="text" size="4" data-stripe="cvc"/>
</label>
</div>
<div class="form-row">
<label>
<span>Expiration (MM/YYYY)</span>
<input type="text" size="2" data-stripe="exp-month"/>
</label>
<span> / </span>
<input type="text" size="4" data-stripe="exp-year"/>
</div>
<button type="submit">Submit Payment</button>
</form>
Javascript:
jQuery(function($) {
$('#payment-form').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
function stripeResponseHandler(status, response) {
var $form = $('#payment-form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// response contains id and card, which contains additional card details
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and submit
$form.get(0).submit();
}
};
This essentially takes your form, and adds a hidden field called stripeToken
before submitting
Notice the form action is /customer
I see you're using Ruby On Rails from your tag - so you would need to handle the customer POST with a controller
This is what you'll need to do:
https://stripe.com/docs/tutorials/charges#saving-credit-card-details-for-later
# Set your secret key: remember to change this to your live secret key in production
# See your keys here https://dashboard.stripe.com/account
Stripe.api_key = "sk_test_X9S2nHIxFy399uoNvakwJYSn"
# Get the credit card details submitted by the form
# notice stripeToken - this is the hidden field
token = params[:stripeToken]
# Create a Customer
customer = Stripe::Customer.create(
:card => token,
:description => "payinguser@example.com"
)
# Charge the Customer instead of the card
# ** I have commented this block out, as you say you do not want to charge the customer
# Stripe::Charge.create(
# :amount => 1000, # incents
# :currency => "gbp",
# :customer => customer.id
# )
# Save the customer ID in your database so you can use it later
save_stripe_customer_id(user, customer.id)
How to save customer card updates in Stripe, Rails?
You might also want to check out this SO answer How to create a charge and a customer in Stripe ( Rails) for more details on using Stripe in a Rails application.
For Ruby documentation, you can find great examples at on the Stripe Ruby API. In Stripe terminology, a card is called a source
for the customer. You can create a source
from a token
, but once it's created, you deal with source
and default_source
elements on the Customer object, and retrieve card
objects from the customer's source
. Also note that you should never try to use the token
beyond creating the source
(or for one-time charges).
The Stripe Ruby API for Customers shows that you can create a customer
and assign the source
at the same time:
customer = Stripe::Customer.create(
source: token,
email: current_user.email
)
You do not have to assign a source
to create a customer. However, if you set the customer up on a subscription, they will require a source
to be available, and the charges will be made to the customer's default_source
. If a customer has only one source
, it is automatically the default_source
.
The Stripe Ruby API for Cards, shows that you can also add a new card to an existing customer, using a token:
customer = Stripe::Customer.retrieve(customer_id)
customer.sources.create({source: token_id})
Once you have a card assigned to the customer, you can make it the default_source
, using this:
customer.default_source = customer.sources.retrieve(card_id)
And that's what it takes to get setup and ready to start charging customers. Happy billing!
Checking for a successful charge using Stripe for rails
Yes, that's all you need to do. If the charge succeeded, Stripe will return a Charge object, and you can check its paid
parameter. If the charge failed, we'd throw an exception.
Cheers,
Larry
PS I work on Support at Stripe.
Related Topics
Ruby Google_Drive Gem Oauth2 Saving
How Can One Set Property Values When Initializing an Object in Ruby
Execjs::Programerror in Welcome#Index Typeerror: Object Doesn't Support This Property or Method
Is This the Best Way to Grab Common Elements from a Hash of Arrays
How to Modify a Text File in Ruby
Ruby - Test Whether Database Connection Is Possible
Thor & Yaml Outputting as Binary
How to Run Rake with --Trace Within Capistrano
Exception_Notification for Delayed_Job
Paperclip File Not Found Error
Grouping Consecutive Numbers in an Array
Could Not Find Rake-10.1.0 in Any of the Sources
Generate Array of Numbers That Fit to a Probability Distribution in Ruby