Rails 4 and Stripe Card Processing Error - javascript

I'm new to Rails and I have spent a good chunk of today struggling with the following issue. I'm integrating Stripe into my Rails application. All was going well until I try to actually finish the order and I get the following error in my local host
Stripe::InvalidRequestError in OrdersController#create
You must supply either a card or a customer id
I have tried various fixes all to no avail including disabling turbolinks on the whole app. I will really appreciate any help I can get since I'm not sure how to proceed from here. I have attached the relevant code below
Orders Controller
def create
#order = Order.new(order_params)
#place = Place.find(params[:place_id])
#seller = #place.user
#order.place_id = #place.id
#order.buyer_id = current_user.id
#order.seller_id = #seller.id
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
puts "Token is #{token}"
begin
charge = Stripe::Charge.create(
:amount => (#place.rating * 100).floor,
:currency => "usd",
:card => token
)
flash[:notice] = "Thanks for ordering!"
rescue Stripe::CardError => e
flash[:danger] = e.message
end
respond_to do |format|
if #order.save
format.html { redirect_to root_url }
format.json { render :show, status: :created, location: #order }
else
format.html { render :new }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
# FURTHER DOWN BELOW
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:address, :city, :state, :card_number, :card_code, :'data-stripe' )
end
end
CoffeeScript
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
payment.setupForm()
payment =
setupForm: ->
$('#new_order').submit ->
$('input[type=submit]').attr('disabled', true)
Stripe.card.createToken($('#new_order'), payment.handleStripeResponse)
false
handleStripeResponse: (status, response) ->
if status == 200
$('#new_order').append($('<input-type="hidden" name="stripeToken"/>').val(response.id))
$('#new_order')[0].submit()
else
$('#stripe_error').text(response.error.message).show()
$('input[type=submit]').attr('disabled', false)
Orders View
<div class="form-group">
<div class="row">
<div class="col-md-8">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, {:name => nil, :'data-stripe' => "number" , class: "form-control" } %>
</div>
<div class="col-md-4">
<%= label_tag :card_code, "CVC" %>
<%= text_field_tag :card_code, nil, {:name => nil, :'data-stripe' => "cvc" , class: "form-control" } %>
</div>
</div>
</div>
<div class="form-group">
<%= label_tag nil, "Expiration Date" %>
<div class="row">
<div class="col-md-3">
<%= select_month nil, { use_two_digit_numbers: true }, { :name => nil, :'data-stripe' => "exp-month", class: "form-control"} %>
</div>
<div class="col-md-3">
<%= select_year nil, { start_year: Date.today.year, end_year: Date.today.year+10 }, { :name => nil, :'data-stripe' => "exp-year", class: "form-control"} %>
</div>
</div>
</div>
Also upon another recommendation, I added the following
puts "Token is #{token}"
to the controller and I get
Token is _____
So I get a blank space in the terminal next to where the token is. Is the token not passing through here or what is going on?
Can anyone please help me to solve this? I'm not sure what to do anymore and I have spent the better half of today on this problem. Thank you!

The createToken method requires a JS object with number and expiry date values. I don't believe you're sending those to it. Try passing those explicitly, and putting breakpoints after the method in your browser debugger to see what happens.

Related

Cannot Attach ajax:error handler to Form ID

I am having trouble binding an ajax:error response to a form ID. Can someone point me in the right direction to solve this problem?
Here is the code.
<%= form_for #person,
html: {
id: '#person_form',
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :first_name %>
</div>
<%= f.text_field :first_name,
:id => 'first_name',
class: 'js_new_person_frm_validate js_new_person_first_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:first_name).first if #person.errors[:first_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<div class='form-group-label'>
<%= f.label :last_name %>
</div>
<%= f.text_field :last_name,
:id => 'last_name',
class: 'js_new_person_frm_validate js_new_person_last_name' %>
<div class="text-error small">
<span>
<%= #person.errors.full_messages_for(:last_name).first if #person.errors[:last_name].any? %>
</span>
</div>
</div>
<div class="form-group">
<%= f.submit "Create", data: { disable_with: false } %>
</div>
<% end %>
Controller
class PeopleController < ApplicationController
......
def create
#person = Person.new(create_params)
if(#person.save)
flash[:success] = "person created successfully"
redirect_to root_path
else
respond_to do |format|
format.html { render :action => 'new' }
format.any(:js, :json) {
render :json => { :error => #person.errors }, :status => 422
}
end
end
end
.....
end
CoffeeScript
$ ->
$("#person_form").on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
The issue I cannot solve is this works as below when I use 'document', but I need this to be specific to my #person_form. And I get no response when I replace document with my form_id. Am I missing something simple here?
$ ->
$(document).on "ajax:error", (event, data, status, xhr) ->
alert "ajax:error!"
#do more stuff
Thank You!
I'm leaving this simple answer out here for anyone else who may run across this issue. Hopefully, it's this simple for the next person. It took me HOURS to track down the problem.
It turns out the error was happening because of a very simple mistake:
<%= form_for #person,
html: {
id: '#person_form', <= ERROR IS HERE!!
class: 'js_inline_validate'
},
data: { validate_url: validate_field_people_path },
remote: true,
url: people_path do |f| %>
The #person_form should have been person_form (excluding the pound sign). Just a very simple error in code I didn't catch when switching from script to ruby.
The global event handler would catch the ajax:error and execute the code properly. The pound sign in the identifier was preventing the proper registration of the local ajax event.

How do I add jquery validation on an ajax form that searches for the value in the database using Ruby on rails?

So I've recently implemented a phone/sim checker. The first form input requires the user to input their phone number. If the phone number exists in the database, render the phone number found message, otherwise replace the phone number form with the sim number form. Again if the sim number exists in the database, render the sim number found message, otherwise render the sim number not found message.
Is anybody able to show me an example on how I can use jquery validation on the user's input before the checkphone / checksim method is fired when the users clicks submit? Validations have been setup in my phone model (phone.rb)
Code below:
app/controllers/phones_controller.rb
class PhonesController < ApplicationController
def checkphone
#phone_number = Phone.where(phone_number: params[:phone][:phone_number])
respond_to do |format|
if #phone_number.exists?
format.js {render 'phone-found'}
elsif #phone_number.blank?
format.js {render 'phone-not-found'}
else
format.js {render 'errors'}
end
end
end
def checksim
#sim_number = Phone.where('sim_number = ?', params[:sim][:sim_number])
respond_to do |format|
if #sim_number.exists?
format.js {render 'sim-found'}
elsif #sim_number.blank?
format.js {render 'sim-not-found'}
else
format.js {render 'errors'}
end
end
end
private
def phone_params
params.require(:phone).permit(
:phone_number
)
end
def sim_params
params.require(:sim).permit(
:sim_number
)
end
end
app/models/phone.rb
class Phone < ActiveRecord::Base
validates :phone_number, length: {minimum: 11, maximum: 11}, allow_blank: false
validates :sim_number, length: {minimum: 12, maximum: 12}, allow_blank: false
end
app/views/phones/index.html.erb
<div id="phone-number-found"></div>
<div id="phone-number-not-found"></div>
<div id="error"></div>
<%= form_for :phone, :url => url_for(:action => 'checkphone', :controller => 'phones'), remote: true, html: { id: 'phone-number-form'} do |f| %>
<%= f.label "Phone Number:" %>
<%= f.number_field :phone_number %>
<%= submit_tag("Check") %>
<% end %>
app/views/phones/phone-found.js.erb
$('#phone-number-found').html('Phone Number Found!');
$('#phone-number-not-found').html('');
$('#error').html('');
$('#phone-number-form').hide();
app/views/phones/phone-not-found.js.erb
$('#phone-number-found').append("<%= j render(partial: 'sim') %>")
$('#phone-number-not-found').html('Phone Number Not Found!');
$('#error').html('');
$('#phone-number-form').hide();
app/views/phones/_sim.html.erb
<div id="sim-number-found"></div>
<div id="sim-number-not-found"></div>
<div id="error"></div>
<%= form_for :sim, :url => url_for(:action => 'checksim', :controller => 'phones'), remote: true, html: { id: 'sim-number-form'} do |f| %>
<%= f.label "Sim Number:" %>
<%= f.number_field :sim_number %>
<%= submit_tag("Check") %>
<% end %>
app/views/phones/sim-found.js.erb
$('#phone-number-found').html('Sim Found')
$('#phone-number-not-found').html('');
$('#phone-number-error').html('');
app/views/phones/sim-not-found.js.erb
$('#phone-number-found').html('');
$('#phone-number-not-found').html('Sim Number Not Found!');
$('#error').html('');
app/views/phones/errors.js.erb
$('#phone-number-found').html('');
$('#phone-number-not-found').html('');
$('#error').html('Error!');
config/routes.rb
post "/checkphone" => "phones#checkphone"
post "/checksim" => "phones#checksim"
resources :phones, path: '4g-promo'
Would be greatly appreciated if someone could show me how I can apply jquery validation according to my model validation rules before checkphone and checksim methods fires. Thanks!
Adding minlength, maxlength and required should do the trick. Then the sim partial will look thus:
app/views/phones/_sim.html.erb
<div id="sim-number-found"></div>
<div id="sim-number-not-found"></div>
<div id="error"></div>
<%= form_for :sim, :url => url_for(:action => 'checksim', :controller => 'phones'), remote: true, html: { id: 'sim-number-form'} do |f| %>
<%= f.label "Sim Number:" %>
<%= f.number_field :sim_number, minlength: 12, maxlength: 12, required: true %>
<%= submit_tag("Check") %>
<% end %>
User gem 'client_side_validations' that will use your server side validation for client side as well.

undefined method `item_path' while working with ajax

Im trying to update my create item action to work with Ajax but Im getting an error of undefined methoditem_path` which i wasn't getting before when it was responding in regular html format. The item is created and saved but ajax doesn't seem to work properly though.
Here is my _from partial :
<%= form_for [#user, item], remote: true do |f|%>
<div class="form-group">
<%= f.label :name, class: 'sr-only' %>
<%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
</div>
<%= f.submit "Submit Item", class: 'btn btn-primary pull-right' %>
<% end %>
item#create:
def create
#item = Item.new(item_params)
#item.user = current_user
if #item.save
flash[:notice] = 'Item saved successfully.'
else
flash[:alert] = 'Item not saved. Title is too short or missing. Please try again.'
end
respond_to do |format|
format.html
format.js
end
end
create.js.erb:
$('.js-items').prepend("<%= escape_javascript(render(#item)) %>");
$('.new-item').html("<%= escape_javascript(render partial: 'items/form', locals: {user: #user , item: #item }) %>");
User#show view
<div class='new_item'>
<%= render :partial => 'items/form', :locals =>{:item => Item.new , :user => #user} %>
</div>
<div class='js-items'>
<%= render #user.items %>
</div>
routes:
user_items GET /users/:user_id/items(.:format) items#index
POST /users/:user_id/items(.:format) items#create
new_user_item GET /users/:user_id/items/new(.:format) items#new
edit_user_item GET /users/:user_id/items/:id/edit(.:format) items#edit
user_item GET /users/:user_id/items/:id(.:format) items#show
PATCH /users/:user_id/items/:id(.:format) items#update
PUT /users/:user_id/items/:id(.:format) items#update
DELETE /users/:user_id/items/:id(.:format) items#destroy
The error im getting in rails s :
ActionView::Template::Error (undefined method `item_path' for #<#<Class:0x007fa4f0d30cd8>:0x007fa4f31b26b0>):
1: <%= form_for [#user, item], remote: true do |f|%>
2: <div class="form-group">
3: <%= f.label :name, class: 'sr-only' %>
4: <%= f.text_field :name , class: 'form-control', placeholder: "Enter a new item " %>
app/views/items/_form.html.erb:1:in `_app_views_items__form_html_erb__331698480542899910_70173200751480'
app/views/items/create.js.erb:2:in `_app_views_items_create_js_erb___3618987352886002527_70173200313760'
app/controllers/items_controller.rb:17:in `create'
Do something like that.
<%= form_for [#user, item], user_items, remote: true do |f|%>
If it doesn't work then run
rake routes
in terminal see what's your path.

Rails - refreshing page instead of partials when using AJAX [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Rails - AJAX to for new/create action
I have a timeline that has partials for events on it, so you can CRUD events directly on the timeline. I've got the delete part working fine, so that the delete partial and the timeline refresh each time an event gets deleted. However, I can't get it working when a new event is created. Instead of refreshing the form and the timeline, the whole page refreshes.
I'm assuming this is something to do with the controller? But I can't seem to fix it. Any help would be much appreciated, thanks :0)
events controller:
def create
#event = Event.new(params[:event])
respond_to do |format|
if #event.save
format.html { redirect_to #event.timeline, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
format.js
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
format.js
end
end
end
timeline/show:
<div id="new-event">
<%= render :partial => "new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) }, :remote => true %>
</div>
timeline/_new_event:
<br />
<h2>Add an event</h2>
<h4>Fill in the form and click 'Create Event' to add a new event to the timeline.</h4>
<%= form_for(event) do |f| %>
<% if event.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(event.errors.count, "error") %> prohibited this event from being saved:</h2>
<ul>
<% event.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%=f.hidden_field 'timeline_id', :value => current_user.timeline.id %>
<div class="field">
<%= f.label :date %><br />
<%= f.date_select :start_date, :order => [:day, :month, :year], :start_year => 1800 %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :headline, :size => 50 %>
</div>
<div class="field">
<%= f.label :event_description %><br />
<%= f.text_area :text, :size => "47x4" %>
</div>
<%= check_box_tag "blockCheck", :value => "1", :checked => false %>
<div class="field" id="media_box">
<%= f.label :media %> <span>Please paste a URL here</span><br />
<%= f.text_field :media, :size => 50 %>
</div>
<div class="field">
<%= f.label :media_description %><br />
<%= f.text_area :caption, :size => "47x3" %>
</div>
<div class="actions">
<%= f.submit 'Create Event', :class => "btn btn-success", :remote => true %>
</div>
<% end %>
events/create.js.erb:
$('#new-event').html('<%= escape_javascript( render :partial => "/timelines/new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) } ) %>');
$('.notice').html("<p>Event was successfully created.</p>");
$('.notice').show(300);
$('#my-timeline-box').html('<%= escape_javascript( render :partial => "/timelines/my_timeline" ) %>');
$('#show-timeline').html('<%= escape_javascript( render :partial => "/timelines/show_timeline" ) %>');
(The bottom two lines are to refresh the timeline iteself).
UPDATE:
Here is the error message:
Started POST "/events" for 127.0.0.1 at 2012-10-16 14:52:37 +0100
Processing by EventsController#create as JS
Parameters: {"utf8"=>"V", "authenticity_token"=>"i8oiRI7rOLsfb5o45QCK0te/hAsWv
BMTqpxU9KrbmNA=", "event"=>{"timeline_id"=>"1", "start_date(3i)"=>"16", "start_d
ate(2i)"=>"10", "start_date(1i)"=>"2012", "headline"=>"", "text"=>"", "media"=>"
", "caption"=>""}, "commit"=>"Create Event"}
←[1m←[35m (0.0ms)←[0m begin transaction
←[1m←[36mSQL (5.0ms)←[0m ←[1mINSERT INTO "events" ("caption", "created_at", "
credit", "end_date", "headline", "media", "start_date", "text", "thumbnail", "ti
meline_id", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)←[0m [["capti
on", ""], ["created_at", Tue, 16 Oct 2012 13:52:37 UTC +00:00], ["credit", nil],
["end_date", nil], ["headline", ""], ["media", ""], ["start_date", Tue, 16 Oct
2012], ["text", ""], ["thumbnail", nil], ["timeline_id", 1], ["updated_at", Tue,
16 Oct 2012 13:52:37 UTC +00:00]]
←[1m←[35m (88.0ms)←[0m commit transaction
Rendered events/create.js.erb (99.0ms)
Completed 500 Internal Server Error in 617ms
ActionView::Template::Error (Called id for nil, which would mistakenly be 4 -- i
f you really wanted the id of nil, use object_id):
1: $('#new-event').html('<%= escape_javascript( render :partial => "/timelin
es/new_event", :locals => { :event => Event.new(:timeline_id=>#timeline.id) } )
%>');
2: $('.notice').html("<p>Event was successfully created.</p>");
3: $('.notice').show(300);
4: $('#my-timeline-box').html('<%= escape_javascript( render :partial => "/t
imelines/my_timeline" ) %>');
app/views/events/create.js.erb:1:in `_app_views_events_create_js_erb___8626901
43_20024148'
app/controllers/events_controller.rb:59:in `create'
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/_trace.erb (5.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/_request_and_response.erb (2.0ms)
Rendered C:/Ruby193/lib/ruby/gems/1.9.1/gems/actionpack-3.2.4.rc1/lib/action_d
ispatch/middleware/templates/rescues/template_error.erb within rescues/layout (1
000.1ms)
You have :remote => true on the submit button. That's incorrect. It should be on the form:
<%= form_for(event, :remote => true) do |f| %>
You have not initialized #timeline in your controller code. Thus you get a nil action.
So, put in your Create code:
#timeline = current_user.timeline

Problems charging a card with Stripe in my Rails app

I'm building a Rails app that takes credit cards and I'm trying to use Stripe to do it. I'm having some issues passing the data from my app to Stripe in order to charge. That's what I'm hoping to get help with on this topic.
First, I have a standard form (with values instead of placeholders for quick submitting for testing purposes). The form successfully enters the name and email into the DB and the customer's "plan" is hardcoded in the controller for the time being:
<%= form_for #customer do |f| %>
<div class="payment-errors"></div>
<div class="name field">
<%= f.label :name %>
<%= f.text_field :name, :value => "Your name" %>
</div>
<div class="email field">
<%= f.label :email %>
<%= f.text_field :email, :value => "yourname#example.com" %>
</div>
<div class="cc_number field">
<%= label_tag 'cc_number' %>
<%= text_field_tag 'cc_number', nil, :value => "4242424242424242" %>
</div>
<div class="ccv field">
<%= label_tag 'ccv' %>
<%= text_field_tag 'ccv', nil, :value => "123" %>
</div>
<div class="cc_expiration field">
<%= label_tag 'cc_month', "Expiration date" %>
<%= text_field_tag 'cc_month', nil, :value => "12" %>
<%= text_field_tag 'cc_year', nil, :value => "2012" %>
</div>
<div class="actions">
<%= f.submit "Continue", :class => 'btn' %>
</div>
<% end %>
Also in my signups_view where the above code is, I have this JS, mostly provided by Stripe:
<script type="text/javascript">
// this identifies your website in the createToken call below
Stripe.setPublishableKey('<%= STRIPE['public'] %>');
function stripeResponseHandler(status, response) {
if (response.error) {
// show the errors on the form
$(".payment-errors").text(response.error.message);
$("input[type=submit]").removeAttr("disabled");
} else {
var form$ = $("form");
// token contains id, last4, and card type
var token = response['id'];
// insert the token into the form so it gets submitted to the server
form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");
// and submit
$('.cc_number.field, .ccv.field, .cc_expiration.field').remove();
form$.get(0).submit();
}
}
$(document).ready(function() {
$("form").submit(function(event) {
// disable the submit button to prevent repeated clicks
$('input[type=submit]').attr("disabled", "disabled");
Stripe.createToken({
number: $('#cc_number').val(),
cvc: $('#ccv').val(),
exp_month: $('#cc_month').val(),
exp_year: $('#cc_year').val()
}, stripeResponseHandler);
// prevent the form from submitting with the default action
return false;
});
});
</script>
There seems to be a problem with the line form$.append("<input type='hidden' name='customer[stripe_token]' id='stripeToken' value='" + token + "'/>");, as my Ruby app breaks when it gets to customer[stripe_token].
Finally, in my `customers_controller`, I have:
def create
#customer = Customer.new(params[:customer])
#customer.product =
if #customer.save
save_order
redirect_to #customer
else
render action: 'new'
end
def save_order
Stripe.api_key = STRIPE['secret']
charge = Stripe::Charge.create(
:amount => 20,
:currency => "usd",
:card => #customer.stripe_token,
:description => "Product 1"
)
end
Whenever I submit the form, it hits the else clause in the controller each time and after plenty of debugging, Googling around and stripping out this from and rebuilding from scratch, I'm still stumped.
Any help would be very very much appreciated.
Edit: Added the customer model
attr_accessible :name, :email, :stripe_token, :product
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, :presence => true,
:format => { :with => email_regex },
:length => { :minimum => 6, :maximum => 60 },
:uniqueness => { :case_sensitive => false }
validates :name, :length => {:minimum => 2, :maximum => 80 }
It would help to see your Customer model to get an idea of what's going on. If #customer.save returns false, it means that a validator is likely failing.
Also, do you have stripe_token as an accessible attribute on your model? Otherwise you won't be able to assign it form the form like you're doing. Note that the token should not be stored in the database, since it can only be used once.
class Customer
attr_accessor :stripe_token # do you have this?
end
One more note: you will probably want to store a Stripe ID field so that you can retrieve customer payments and cancel their account later.

Categories

Resources