I implement Stripe in a Rails application and get an Invalid Token error when loading an input form - I have not submitted client data yet. I mainly followed http://railscasts.com/episodes/288-billing-with-stripe . I made a few changes because it was somewhat incomplete.
books / show.html.erb is the page on which I link to the form:
<b>Title:</b> <%= @book.title %> </p> <b>Author:</b> <% authorid = @book.author %></p> <%= @book.id %> <%= link_to "Buy Now", new_purchase_path(:book_id => @book.id) %>
purchase / new.html.erb is where the user fills in the information. When this loads, I get an Invalid Token error:
<%= form_for @purchase do |f| %> <% if @purchase.errors.any? %> <%= pluralize(@purchase.errors.count, "error") %> prohibited this purchase from being saved. <% @purchase.errors.full_messages.each do |msg| %> <%= msg %> <% end %> <% end %> <%= f.hidden_field :stripe_card_token %> <% if @purchase.stripe_card_token.present? %> Credit card has been provided. <% else %> <%= label_tag :card_number, "Credit Card Number" %> <%= text_field_tag :card_number, nil, name: nil %><p> <%= label_tag :card_code, "Security Code on Card (CVV)" %> <%= text_field_tag :card_code, nil, name: nil %><p> <%= label_tag :card_month, "Card Expiration" %> <%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %> <%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"} %> <% end %> <div id="stripe_error"> <noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript> </div> <%= f.submit "Purchase" %> <% end %>
purchase.js.coffee is almost the same as in the tutorial. I have added some warnings. The status according to my Stripe dashboard is 402. This is a POST / v1 / tokens and Body Response error:
error: type: "card_error" message: "This card number looks invalid" param: "number"
purchases.js.coffee:
jQuery -> Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content')) purchase.setupForm() purchase = setupForm: -> $('#new_purchase').submit -> $('input[type=submit]').attr('disabled', true) if $('#card_number').length purchase.processCard() false else true processCard: -> card = number: $('#card_number').val() cvc: $('#card_code').val() expMonth: $('#card_month').val() expYear: $('#card_year').val() Stripe.createToken(card, purchase.handleStripeResponse) handleStripeResponse: (status, response) -> if status == 200 alert('This token can still be charged.') alert(response.id) $('#purchase_stripe_card_token').val(response.id) $('#new_purchase')[0].submit() else alert(response.error.message) alert('The token was invalid, or has been used.') $('#stripe_error').text(response.error.message) $('input[type=submit]').attr('disabled', false)
I tried several versions of my purchase.rb model, for example, commenting on the Stripe :: Charge function, but still get a Token 402 error. However, creating the Client is successful (code 200).
class Purchase < ActiveRecord::Base attr_accessible :stripe_customer_token, :author_id, :book_id attr_accessor :stripe_card_token belongs_to :book def save_with_payment if valid? customer = Stripe::Customer.create( :description => "customer email", :card => stripe_card_token ) self.stripe_customer_token = customer.id # charge = Stripe::Charge.create( - this code doesn't work either # :amount => 1000, # :currency => "usd", # :card => stripe_card_token, # :description => "book title" # ) save! end rescue Stripe::InvalidRequestError => e logger.error "Stripe error while creating customer: #{e.message}" errors.add :base, "There was a problem with your credit card." false end end
The error I get if I uncomment the code Stripe :: Charge: Stripe :: CardError in PurchaseController # create You cannot charge a client that does not have an active card
And, the create method in my purchases_controller.rb
def create @purchase = Purchase.new(params[:purchase]) if @purchase.save_with_payment redirect_to @purchase, :notice => "Thank you for purchasing this book!" else render :new end end
Here is my new method in purchase_controller.rb:
def new
book = Book.find(params[:book_id]) @purchase = book.purchases.build
end
BUT, if I click the "Back" button after submitting the purchase (to return to the purchase page /new.html.erb), the SECOND "purchase" and the code for this POST token in my log 200 (pass) band will be entered into my database !!!
Here's the javascript compiled from coffeescript:
(function () {
buying var;
jQuery (function () {
Stripe.setPublishableKey ($ ('meta [name = "strip-key"]') atr ('content').);
return purchase.setupForm ();
});
buy = {
setupForm: function () {
$('#new_purchase').submit(function() { return $('input[type=submit]').attr('disabled', true); }); if ($('#card_number').length) { purchase.processCard(); return false; } else { return true; }
},
processCard: function () {
var card; card = { number: $('#card_number').val(), cvc: $('#card_code').val(), expMonth: $('#card_month').val(), expYear: $('#card_year').val() }; return Stripe.createToken(card, purchase.handleStripeResponse);
},
handleStripeResponse: function (status, response) {
if (status === 200) { alert('This token can still be charged.'); alert(response.id); $('#purchase_stripe_card_token').val(response.id); return $('#new_purchase')[0].submit(); } else { alert(response.error.message); alert('The token was invalid, or has been used.'); $('#stripe_error').text(response.error.message); return $('input[type=submit]').attr('disabled', false); }
}
};
}) call (this) ;.