error when signing up users on production
macoughl opened this issue · comments
Hi Daniel,
Thank you for these tutorials. As a Rails newbie I've run through a lot of tutorials over the last few months and this has definitely been one of the most helpful.
About a month ago I successfully completed your tutorial as the base for a project I'm working on. I've been slowly customizing it and implementing your updates as you've added to the tutorial. It was working perfectly on my local machine and on production.
However, I am now experiencing an error on production (heroku) when signing up new users that I've spent days trying to fix and am now hoping you can maybe point me in the right direction.
The app works fine on my local machine. Admin works as it should and I can sign up new users as long as they have @gmail.com as their email address.
Due to the following in user.rb:
return if email.include?('@gmail.com') and not Rails.env.production?
On production, the admin works fine but after submitting the form for a new user, I land on the /users URL and see the error msg "We're Sorry But Something Went Wrong" in red.
After running heroku logs it looks like it gives me the RuntimeError (Stripe token not present. Can't create account.) and it references app/models/user.rg:51:in 'update_stripe' which I will paste now:
class User < ActiveRecord::Base rolify # Include default devise modules. Others available are: # :token_authenticatable, :confirmable, # :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable # Setup accessible (or protected) attributes for your model attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :stripe_token attr_accessor :stripe_token before_save :update_stripe before_destroy :cancel_subscription def update_plan(role) self.remove_role(self.roles.first.name) self.add_role(role.name) unless customer_id.nil? customer = Stripe::Customer.retrieve(customer_id) customer.update_subscription(:plan => role.name) end end def update_stripe return if email.include? (ENV['ADMIN_EMAIL']) return if email.include?('@gmail.com') and not Rails.env.production? if customer_id.nil? if !stripe_token.present? raise "Stripe token not present. Can't create account." end customer = Stripe::Customer.create( :email => email, :description => name, :card => stripe_token, :plan => roles.first.name ) else customer = Stripe::Customer.retrieve(customer_id) if stripe_token.present? customer.card = stripe_token end customer.email = email customer.description = name customer.save end self.last_4_digits = customer.active_card.last4 self.customer_id = customer.id self.stripe_token = nil rescue Stripe::StripeError => e logger.error e.message errors.add :base, "Unable to create your subscription. #{e.message}" stripe_token = nil false end def cancel_subscription unless customer_id.nil? customer = Stripe::Customer.retrieve(customer_id) if (!customer.nil?) && (customer.subscription.status == 'active') customer.cancel_subscription end end rescue Stripe::StripeError => e logger.error e.message errors.add :base, "Unable to cancel your subscription. #{e.message}" false end def expire UserMailer.expire_email(self).deliver destroy end end
When I run heroku config it has all my live key variables and everything looks correct.
Any direction you can give me would greatly appreciated!
From your description, it sounds like the stripe token might not be getting passed back to the server. You can verify by checking your heroku logs. You should see something similar to where the "Parameters:" line includes the "stripe_token" attribute.
2013-01-24 05:16:19+00:00 app web.1 - - Started POST "/users" for n.n.n.n at 2013-01-24 05:16:19 +0000
2013-01-24 05:16:19+00:00 app web.1 - - Processing by RegistrationsController#create as HTML
2013-01-24 05:16:19+00:00 app web.1 - - Parameters: ...
If there is a value there for the token, then you are getting a token and probably have an issue with your RegistrationsController or User model. If there is no value, then take a look at app/assets/javascripts/registrations.js and app/views/devise/registrations/new.html.erb. Make sure that your form in new.html.erb has the class "card_form" that matches the jquery used in registrations.js. Also make sure there is a hidden field for the stripe_token in the form so the javascript can set it. Your new.html.erb page should also have your public stripe API key in a meta tag. You can verify this by viewing your heroku-hosted sign up page with Firefox and View Page Source (or use the excellent Firebug add-on).
Thanks for the response billvieux!
I see your first line in the logs but its not followed by either of the other two. The only time "Stripe Token" is referenced is in a few lines after the first one you said to look for and it is that runtime error I mentioned
RuntimeError (Stripe token not present. Can't create account.) app/models/user.rb:51:in 'update_stripe'
I've looked in the files you referenced and I believe I have everything as it should be. The only difference being that I do not have my public stripe key in a meta tag. That is fairly new to the tutorial and it used to set an ENV variable there, which was before the app used figaro and since I'm on a PC I just hard coded my pk_live Stripe key in. I have updated and added Figaro, have tried using the ENV variable there but currently have it hard coded. The proper variables are set in Heroku as I do use the ENV variables in my initializers/stripe.rb
registrations.js.erb
$('.registrations').ready(function() { $.externalScript('https://js.stripe.com/v1/').done(function(script, textStatus) { Stripe.setPublishableKey('pk_live_my-live-key-here'); var subscription = { setupForm: function() { return $('.card_form').submit(function() { $('input[type=submit]').prop('disabled', true); if ($('#card_number').length) { subscription.processCard(); return false; } else { return true; } }); }, processCard: function() { var card; card = { name: $('#user_name').val(), number: $('#card_number').val(), cvc: $('#card_code').val(), expMonth: $('#card_month').val(), expYear: $('#card_year').val() }; return Stripe.createToken(card, subscription.handleStripeResponse); }, handleStripeResponse: function(status, response) { if (status === 200) { $('#user_stripe_token').val(response.id) $('.card_form')[0].submit() } else { $('#stripe_error').text(response.error.message).show(); return $('input[type=submit]').prop('disabled', false); } } }; return subscription.setupForm(); }); });
The line from new.html.erb utilizing the card_form class
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'card_form form-vertical' }) do |f| %>
I forgot, I put
config.logger = Logger.new(STDOUT)
around line 40 of my config/environments/production.rb so I get a little more logging on the server-side.
You can also troubleshoot this from the client-side. I would recommend using Firefox. Under the web developer menu, open the web console. You should select the "Log Request and Response Bodies" option to capture network traffic. Then you can verify that your form is executing the javascript, calling stripe servers for token, and POSTing to your site with the token in the expected location in the form values.
So it is client-side issue. Verify that you see a call to the stripe api server before your POST to /users (see my screenshot). If that isn't there, look to see if there are any javascript errors in the console to point you in the right direction. You can also add console.log calls into your registrations.js to help trace the issue or attach a javascript debugger to the browser.
Not sure if you added any other gems to your application. I've been bitten before by not specifying the version number of a gem in my Gemfile. Locally I was running one version, but heroku had an updated version that behaved differently.
Fixed it!
Thank you for all the help! It was a javascript error I believe was caused by an bootstrap theme .js file.
I had removed the theme and the only calls to the .js file were on the homepage but I'm thinking that since the .js file was still in the /javascripts folder the asset pipeline was hitting it and causing an error.
Regardless, its working now. Thanks again!