Reputation: 11
I have been trying to get Stripe to return a token to my rails app but I keep getting this error:
Stripe::InvalidRequestError in Users::RegistrationsController#create No such token: undefined
Chrome highlights this line:
customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
I have also tried changing "card" to "source" and still it comes back as token undefined:
{"utf8"=>"✓",
"authenticity_token"=>"returns a token :)",
"plan"=>"2",
"user"=>{"email"=>"sljkdfhgvbdlvb@ae;klfgjbearfgvkujb.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"stripe_card_token"=>"undefined"}}
I also get a 'block in create' & 'create' in the application trace
app/models/user.rb:11:in save_with_payment'
app/controllers/users/registrations_controller.rb:8:in
block in create'
app/controllers/users/registrations_controller.rb:4:in `create'
registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController #given to us by Devise
#creating a class Users and inheriting devise
def create #When the user submits their form
super do |resource| #importing to create action code that is inside the devise gem
if params[:plan] #when user submits basic or pro form
resource.plan_id = params[:plan] #were going to cath that form and see if param :plan was submitted and if yes then we save to resource.plan_id
if resource.plan_id == 2 # if User.first_plan.id = 2
resource.save_with_payment # if id does = 2 then we save_with_payment defined in models/user.rb otherwise
else #if id = 1
resource.save #just do a regular save to resources
end
end
end
end
end
I tried restarting the server I tried a bundle update Here are some posts I've read:
Stripe Integration - Dynamically adding attr value in to the hidden_field
https://github.com/tyler-johnson/stripe-meteor/issues/25
I've also tried 4 different card #'s according to
https://stripe.com/docs/testing
Any help would be greatly appreciated :)
FOR REFERENCE:
application.yml
stripe_api_key: test key
stripe_publishable_key: pk test key
#
production:
stripe_api_key: test key
stripe_publishable_key: pk test key
users.js
/* global $ */
$(document).ready(function() { //The .ready just means that the document will get loaded before teh JS runs
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content')); //Lets grab generic meta tag contents. We can use it because we loaded the JS Stripe file
// Watch for a form submission:
$("#form-submit-btn").click(function(event) { //When the user clicks on submit, we add an event listener to "next line"
event.preventDefault(); //Dont send anything to the server just yet
$('input[type=submit]').prop('disabled', true); //This disables the button
var error = false; //establishing a variable false
var ccNum = $('#card-number').val(), //storing variables
cvcNum = $('#card_code').val(),
expMonth = $('#card_month').val(),
expYear = $('#card_year').val();
if (!error) { //if there are no errors
//Get the Stripe token:
Stripe.createToken({ //Ship off the data entered to STRIPE
number: ccNum,
cvc: cvcNum,
exp_month: expMonth,
exp_year: expYear
}, stripeResponseHandler); //Once stripe returns TOKEN
}
return false;
}); //form submission
function stripeResponseHandler(status, response) { //response coming back from server
//Get a reference to the form:
var f = $("#new_user"); //Lets use this form we made
//Get the token from the response:
var token = response.id; //coming from response above and gives us card TOKEN
//Add the token to the form:
f.append('<input type="hidden" name="user[stripe_card_token]" value="' + token + '" />'); //and append the value for the field
//Submit the form:
f.get(0).submit(); //f.get(0) means we only want to the first forn incase there are multiple forms returned and submit
}
});
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
belongs_to :plan
attr_accessor :stripe_card_token #stripe_card_token hidden field value
def save_with_payment #method used in /app/controllers/users/registrations_controller.rb
if valid? #If user filled out form properly
customer = Stripe::Customer.create(description: email, plan: plan_id, source: stripe_card_token)
self.stripe_customer_token = customer.id #setting property of user to user id returned from stripe
save! #saving entire user object to database by creating new migration file
end
end
end
stripe.rb
Stripe.api_key = ENV["stripe_api_key"]
STRIPE_PUBLIC_KEY = ENV["stripe_publishable_key"] #The ENV comes from the figaro file
migration file (rails generated)
class AddStripeCustomerTokenToUsers < ActiveRecord::Migration
def change
add_column :users, :stripe_customer_token, :string
end #add a column to the user database and call it stripe ciutomer token as a string
end #bundle exec rake db:migrate after you created this
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>DevMatch</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag "https://js.stripe.com/v2/", type: 'text/javascript' %>
<%= javascript_include_tag 'application'%>
<%= tag :meta, :name => "stripe-key", :content => STRIPE_PUBLIC_KEY %>
<%= csrf_meta_tags %>
</head>
<body>
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class='container'>
<div class='navbar-header'>
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#main-nav-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<%= link_to root_path, class: 'navbar-brand' do %>
<i class="fa fa-users"></i>
DevMatch
<% end %>
</div>
<div class="collapse navbar-collapse" id="main-nav-collapse">
<div class="navbar-nav navbar-right">
<% if current_user %>
<%= button_to "Sign Out", destroy_user_session_path, method: :delete, class: 'btn btn-primary navbar-btn' %>
<% else %>
<%= link_to "Log In", new_user_session_path, class: 'btn btn-primary navbar-btn', method: :get %>
</div>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "About", about_path %></li>
<li><%= link_to "New Contact", new_contact_path %></li>
</ul>
</div><!-- /.navbar-collapse -->
</div>
</nav>
<div class="container">
<% flash.each do |key, value| %>
<%= content_tag :div, value, class: "alert alert-#{key}" %>
<% end %>
<%= yield %>
<% end %>
</div>
</body>
</html>
Upvotes: 1
Views: 872
Reputation: 649
Your error is probably caused by an invalid card number.
Comment out your f.get(0).submit
and use
console.log(`status: ${status}, response: ${response}`);
At the beginning of stripeResponseHandler
function to get the actual error being sent from Stripe. An error code will be returned in status.
Just lookup stripe error YOUR_ERROR_CODE
and you'll find a solution.
A pretty common one is 402
, which means your card number is invalid. Here is a list of some stripe errors.
Upvotes: 0
Reputation: 1923
It appears that we were working on a similar project because I had this same issue using the method you are using. After trying the same fixes that you did (and still getting the same error), I finally discovered a small error in the directions that we both may have used to set up Stripe. The first clue is to look at the variable values in your users.js
file. I noticed a typo right off the bat in yours. You have
var ccNum = $('#card-number').val(), //storing variables
cvcNum = $('#card_code').val(),
expMonth = $('#card_month').val(),
expYear = $('#card_year').val();
Notice that you have #card-number
when it should be #card_number
(with an _ not a -). While you don't have it listed, you also need to check the _pro_form.html.erb
file, or it's equivalent. In my case, I had
<%= label_tag :card_code, "Credit Card Number" %>
when it should have been
<%= label_tag :card_number, "Credit Card Number" %>
Make sure, that those values in the _pro_form.html.erb
(or equivalent) file are matching to those in the users.js
file. Hope that helps.
Upvotes: 1