Stripe Custom Checkout Issue with Rails - javascript

I'm currently creating a job board where when a customer posts a job board they pay for it in one form and it will then post the job and charge there card all at once.
First, I used the standard Stripe Checkout button along with my listings form and it submitted both my form and took payment.
Then I tried customizing the Stripe Checkout button using the custom docs found here but I can't seem to understand what I'm missing.
Now when I click on the button it pops up like normal but when I submit the button my Rails form doesn't create nor does it charge Stripe.
listings_controller.rb
def create
p #listing = Listing.new(listing_params)
#categories = Category.all.map{|c| [ c.title, c.id ] }
charge_error = nil
p #listing.valid?
p #listing.errors
if #listing.valid?
begin
customer = Stripe::Customer.create(
:email => params[:stripeEmail],
:card => params[:stripeToken]
)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => #amount,
:description => 'New Job Posting',
:currency => 'usd'
)
rescue Stripe::CardError => e
p 'rescue'
p e
charge_error = e.message
end
if charge_error
p 'change error not nil'
p charge_error
flash[:error] = charge_error
render :new
else
p 'trying to save listing'
p #listing.save
redirect_to #listing
end
else
p 'listing not valid'
flash[:error] = 'one or more errors in your orders'
render :new
end
end
listings/_form.html.erb
//Top of the page //
<script src="https://checkout.stripe.com/checkout.js"></script>
<button class='btn btn-block btn-primary' id='customButton'>
Pay and Post Your Job Posting!
</button>
<% end %>
<script>
var handler = StripeCheckout.configure({
key: "pk_test_iSItYFJUx04fB9Ax6yGQjRDP",
image: "https://stripe.com/img/documentation/checkout/marketplace.png",
name: "Example Name",
description: "Pro Subscription ($29 per month)",
panelLabel: "Subscribe",
allowRememberMe: false,
locale: 'auto',
token: function(token) {
token.id
}
});
document.getElementById('customButton').addEventListener('click', function(e) {
handler.open({
name: 'Example Name #2',
description: 'Subscripe ($99/monthly)',
amount: 2000
});
e.preventDefault();
});
// Close Checkout on page navigation:
window.addEventListener('popstate', function() {
handler.close();
});
</script>
If you need any other info please ask. Thank you!

Related

Get attribute from model of selected option

I have an employee dropdown that lists all the employees. I want to be able to select an employee and get the address of the employee from the model so that I may display it. the following is the code of my collection_select.
<div class="form-group col-md-2 field">
<%= form.label :employee_id %>
<%= form.collection_select :employee_id, Employee.all, :id, :full_name,{:prompt=>"Select Employee"},{:id=>"emp_select",class:"form-control",:onchange=>"getEmployee();"} %>
</div>
Next is the code I am using to grab the value of the employee that was selected and it does work.
function getEmployee() {
var selectedVal=$('#emp_select option:selected').val();}
From here what do I do to get the address of the employee that was selected?
You will have to retrieve the employee's address via ajax call. Here are the steps:
Define an action in your rails app to return employee's address by json.
Make an ajax request to that action and get the info needed.
Render result into view.
For more information, take a look at this link:
https://guides.rubyonrails.org/working_with_javascript_in_rails.html
routes.rb
controller :ajax do
get 'ajax/get_employee_address/:employee_id', action: :get_employee_address, as: :get_employee_address
end
ajax_controller.rb
class AjaxController < ActionController::Base
def get_employee_address
employee = Employee.find(params[:employee_id])
render json: employee.address.to_json
rescue ActiveRecord::RecordNotFound
render json: 'Employee not found', status: 422
end
end
Your js code
function getEmployee() {
var selectedVal=$('#emp_select option:selected').val();
$.ajax({
url: '/ajax/get_employee_address/' + selectedVal,
success: function (address) {
// Render your address to view
},
error: function () {
// Handle error here or just return nothing
return null;
}
})
}
Note: This ajax endpoint will expose your employee address to outside so be sure to make authentication to prevent leaking info.
Add address to option data-attribute:
<%= form.select :employee_id,
options_for_select(Employee.all.map {
|e| [e. full_name, e.id, { 'data-address' => e.address }]
}),
{ prompt: "Select Employee" },
{ id: "emp_select", class: "form-control", onchange: "getEmployee();" } %>
On change get it with js:
function getEmployee() {
var selectedVal=$('#emp_select option:selected').data("address");}
And insert it to needed place

Dynamic button values from javascript?

I have a page that does a search, using javascript, and I want to take the list of users that it comes up with, and send that as a submit to the next page. What I have, is:
.search_client_users
= form_tag admin_clients_path, method: "get" , class: "search_form" do
= label_tag 'search_term', 'Old domain name:'
= text_field_tag 'search_term', nil, autocomplete: "off", size: "50"
.main_form.client_emails
= simple_form_for(:domainNameSwap, url: { action: "update" }, html: { method: :put }) do |f|
.input-row
= f.hidden_field :users, value: #clients
.submit-row
.row
.col-xs-5
.submit
= f.submit "Update domains", id: "submit", :class => "btn btn-primary submit"
.client_list
- content_for :javascript do
= javascript_include_tag 'admin/search_client_users'
[some of the formatting may not be quite right due to cut and paste, sorry]
The admin/search_client_users creates an #clients, I'm pretty sure, at least, with:
class App.ClientUserList
constructor: ->
#incrementalSearchAttempts = 0
search: (searchTerm, completeCallback) =>
handleResponseWithOrderAwareness = (attemptNumber, response) =>
if attemptNumber >= #incrementalSearchAttempts
completeCallback(response)
#incrementalSearchAttempts++
onComplete = _.partial(handleResponseWithOrderAwareness, #incrementalSearchAttempts)
$.get('/admin/manage_clients/client_list', { search_term: searchTerm }).complete(onComplete)
class App.Views.SearchClientUsers extends Backbone.View
events:
"keyup input[name='search_term']": "search",
"click .profile_attribute": "showClientUserProfile"
initialize: =>
#clientUserList = new App.ClientUserList()
search: =>
searchTerm = $('.search_form input[name=search_term]').val()
#clientUserList.search(searchTerm, #render)
showClientUserProfile: (event) =>
window.location = $(event.currentTarget).closest('tr').data('client-path')
render: (response) =>
#$el.find('.client_list').html(response.responseText)
$ ->
new App.Views.SearchClientUsers(el: $('.search_client_users')).search()
so, I'm trying to take the list of clients, and send it to the update method in the controller. However, due to when javascript and ruby take place, it doesn't seem to be working... is there a way to do this? or do I have to figure out how to do this in Ajax?
ETA: An alternative idea is, I suppose to just turn the initial text_field into a form, so that the text field is used both for the javascript, and THEN submitted to the form, and then the update can re-do the search... My dataset is small enough that doing the search twice is not a huge problem I suppose...
But I'm not quite sure exactly how to merge the two forms...

Rails Stripe integration no active card error

Trying to charge a customer for a product registration. I've been following this tutorial upskillcourses.com. Which sets up a subscription. I' just trying to create a charge for a product.
I keep getting this error:
Stripe::CardError in Roadregistrations::RegistrationsController#create
Cannot charge a customer that has no active card
I've setup the stripe.js file:
app/assets/javascripts/
/* global $, Stripe */
//Document ready.
$(document).on('turbolinks:load', function(){
var theForm = $('#payment-form');
var submitBtn = $('#form-submit-btn');
//Set Stripe public key.
Stripe.setPublishableKey( $('meta[name="stripe-key"]').attr('content') );
//When user clicks form submit btn,
submitBtn.click(function(event){
//prevent default submission behavior.
event.preventDefault();
submitBtn.val("Processing").prop('disabled', true);
//Collect the credit card fields.
var ccNum = $('#card_number').val(),
cvcNum = $('#card_code').val(),
expMonth = $('#card_month').val(),
expYear = $('#card_year').val();
//Use Stripe JS library to check for card errors.
var error = false;
//Validate card number.
if(!Stripe.card.validateCardNumber(ccNum)) {
error = true;
alert('The credit card number appears to be invalid');
}
//Validate CVC number.
if(!Stripe.card.validateCVC(cvcNum)) {
error = true;
alert('The CVC number appears to be invalid');
}
//Validate expiration date.
if(!Stripe.card.validateExpiry(expMonth, expYear)) {
error = true;
alert('The expiration date appears to be invalid');
}
if (error) {
//If there are card errors, don't send to Stripe.
submitBtn.prop('disabled', false).val("Register and Pay");
} else {
//Send the card info to Stripe.
Stripe.createToken({
number: ccNum,
cvc: cvcNum,
exp_month: expMonth,
exp_year: expYear
}, stripeResponseHandler);
}
return false;
});
//Stripe will return a card token.
function stripeResponseHandler(status, response) {
//Get the token from the response.
var token = response.id;
//Inject the card token in a hidden field.
theForm.append($('<input type="hidden" name="user[stripe_card_token]">').val(token));
//Submit form to our Rails app.
theForm.get(0).submit();
}
});
Which it seems like the token is not being submitted with the form.
Not sure if I need both of these in my users_controller.rb:
# Only allow a trusted parameter "white list" through.
def roadregistration_params
params.require(:user).permit(:first_name, :last_name, :company, :street, :city, :state, :zip, :email, :phone, :roadshowcity, :stripe_card_token, :comments)
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) { |u| u.permit(:stripe_card_token, :password, :password_confirmation, :email, :first_name, :last_name, :company, :street, :city, :state, :zip, :phone, :roadshowcity, :comments) }
end
Then I have this in my user model:
attr_accessor :stripe_card_token
# If user passes validations (email, pass, etc.),
# Call stripe and tell stripe to set up a subscription
def save_with_registration
if valid?
#product_price = Objective.find(objective_id)
customer = Stripe::Customer.create(email: email, card: stripe_card_token, description: stripe_card_token.to_s)
charge = Stripe::Charge.create(
:customer => customer.id,
:amount => 9500,
:currency => "usd",
:description => "Roadshow Registration"
)
self.stripe_customer_token = customer.id
save!
end
end
customer = Stripe::Customer.create(email: 'example#gma.com')
=> #<Stripe::Customer:0x3ffd3a10e024 id=cus_A5CWbyto5ugmju> JSON: {
"id": "cus_A5CWbyto5ugmju",
"object": "customer",
"account_balance": 0,
"created": 1486585998,
"currency": null,
"default_source": null,
"delinquent": false,
"description": null,
"discount": null,
"email": "example#gma.com",
"livemode": false,
"metadata": {},
"shipping": null,
"sources": {"object":"list","data":[],"has_more":false,"total_count":0,"url":"/v1/customers/cus_A5CWbyto5ugmju/sources"},
"subscriptions": {"object":"list","data":[],"has_more":false,"total_count":0,"url":"/v1/customers/cus_A5CWbyto5ugmju/subscriptions"}
}
You just have to link card to the customer after creating the customer on stripe and before charging him:
customer = Stripe::Customer.create(email: email)
customer.sources.create(card: stripe_card_token) # <-- this
charge = Stripe::Charge.create(..
And I would advice to not send stripe_card_token in the customer object.
If you are on a version older than 2015-02-18 API version replace sources with cards.
Turbolinks was not being loaded in the app/assets/javascripts/application.js file. Fixing that issue allowed the stripe javascript to run and passed the stripe_card_token along.

Stripe RailsJS, Cannot charge a customer that has no active card

I keep getting the "Cannot charge a user that has no active card" error when trying to bill a test user.
The app works so that a user gets charged $10 on sign up after they input their CC credentials.
I know the customers are being created but the charges aren't being sent
Here is the Stripe error
My credit_card_form.js file which is what collects the credit card info and sends it to stripe without it hitting my database.
$(document).ready(function(){
var show_error, stripeResponseHandler, submitHandler;
submitHandler = function (event) {
var $form = $(event.target);
$form.find("input[type=submit]").prop("disabled", true);
//If Stripe was initialized correctly this will create a token using the credit card info
if(Stripe){
Stripe.card.createToken($form, stripeResponseHandler);
show_error("CC token generated")
} else {
show_error("Failed to load credit card processing functionality. Please reload this page in your browser.")
}
return false;
};
// calling the SUBMIT
$(".cc_form").on('submit', submitHandler);
// RESPONSE HANDLER
stripeResponseHandler = function (status, response) {
var token, $form;
$form = $('.cc_form');
if (response.error) {
console.log(response.error.message);
show_error(response.error.message);
$form.find("input[type=submit]").prop("disabled", false);
} else {
token = response.id;
$form.append($("<input type=\"hidden\" name=\"payment[token]\" />").val(token));
$("[data-stripe=number]").remove();
$("[data-stripe=cvv]").remove();
$("[data-stripe=exp-year]").remove();
$("[data-stripe=exp-month]").remove();
$("[data-stripe=label]").remove();
$form.get(0).submit();
}
return false;
};
//ERROR HANDLING
show_error = function (message) {
if($("#flash-messages").size() < 1){
$('div.container.main div:first').prepend("<div id='flash-messages'></div>")
}
$("#flash-messages").html('<div class="alert alert-warning"><a class="close" data-dismiss="alert">×</a><div id="flash_alert">' + message + '</div></div>');
$('.alert').delay(5000).fadeOut(3000);
return false;
};
});
And payment.rb
class Payment < ApplicationRecord
attr_accessor :card_number, :card_cvv, :card_expires_month, :card_expires_year
belongs_to :user
def self.month_options
Date::MONTHNAMES.compact.each_with_index.map{|name,i| ["#{i+1} - #{name}", i+1]}
end
def self.year_options
(Date.today.year..(Date.today.year+10)).to_a
end
def process_payment
customer = Stripe::Customer.create email:email, card:token
Stripe::Charge.create customer:customer.id, amount: 1000, description: "Premium", currency: "usd"
end
end
And a snippet of the devise registrations new.html.erb which is where the user will be charged from
<div class="col-md-3">
<%=p .select :card_expires_month, options_for_select(Payment.month_options), {include_blank: "Month"}, "data-stripe"=>"exp-month", class: "form-control", required: true%>
</div>
<div class="col-md-3">
<%=p .select :card_expires_year, options_for_select(Payment.year_options.push), {include_blank: "Year"}, class: "form-control", data: {stripe: "exp-year"}, required: true%>
</div>
I know that the customers are being created but I have no clue why my customers aren't paying when I use the test credit card numbers. No answers on stack overflow have helped me as of yet.
Jack and I had a chat and discovered that Stripe.js wasn't loading, so the token wasn't being sent in the request.
The issue was <%= javascript_include_tag 'https://js/stripe.com/v2' %> being a mistyped js link in application.html.erb
The fix was making it <%= javascript_include_tag 'https://js.stripe.com/v2/' %>

Stripe checkout.js - passing custom params to token callback

I'm following this example integration from Stripe Docs (slightly modified in order to be able to add click handlers to more than one button:
<script src="https://checkout.stripe.com/checkout.js"></script>
<button id="customButton">Purchase</button>
<script>
var handler = StripeCheckout.configure({
key: 'pk_test_jPVRpCB1MLjWu2P71eTvXBZD',
image: '/square-image.png',
token: function(token) {
// Use the token to create the charge with a server-side script.
// You can access the token ID with `token.id`
}
});
$('.pay-deposit').click( function(e) {
// Open Checkout with further options
handler.open({
name: 'Demo Site',
description: '2 widgets ($20.00)',
amount: 2000
});
e.preventDefault();
});
In my particular case I have a few buttons like:
<button class='pay-deposit' booking-id='3455'>Pay Deposit</button>
<button class='pay-deposit' booking-id='335'>Pay Deposit</button>
<button class='pay-deposit' booking-id='34'>Pay Deposit</button>
... and obviously I'd like to pass a booking-id of clicked button somehow to token callback. Couldn't find any example or explanation covering this seemingly simple case... any help much appreciated. thanks!
This is a little bit late, but maybe it will help someone else. This is modified from a Rails example:
# HTML file
<script src="https://checkout.stripe.com/checkout.js"></script>
<button class='pay-deposit' data-booking-id='3455'>Pay Deposit</button>
<button class='pay-deposit' data-booking-id='335'>Pay Deposit</button>
<button class='pay-deposit' data-booking-id='34'>Pay Deposit</button>
# JS file
$('.pay-deposit').on('click', function(event) {
event.preventDefault();
// Get booking information from database
var booking_id = $(this).data('booking-id');
$.getJSON("/bookings/"+booking_id, function(data) {
// Open Checkout with further options
handler = stripe_checkout(booking_id);
handler.open({
name: "My Bookings",
description: data["description"],
amount: data["amount"],
email: data["email"],
});
// Close Checkout on page navigation
$(window).on('popstate', function() {
handler.close();
});
});
});
function stripe_checkout(booking_id) {
var handler = StripeCheckout.configure({
key: 'pk_test_jPVRpCB1MLjWu2P71eTvXBZD',
token: function(token) {
// Send the charge through
$.post("/charges/create",
{ token: token.id, booking_id: booking_id }, function(data) {
if (data["status"] == "ok") {
window.location = "/some-url";
} else {
// Deal with error
alert(data["message"]);
}
});
}
});
return handler;
}
# Bookings controller
class BookingsController < ApplicationController
def show
#booking = Booking.find(params[:id])
attrs = #booking.attributes
attrs.merge!("email" => current_user.email)
respond_to do |format|
format.json { render json: attrs.to_json }
end
end
end
# Charges controller
class ChargesController < ApplicationController
def create
booking = Booking.find(params[:booking_id])
customer = Stripe::Customer.create(card: params[:token])
charge = Stripe::Charge.create(
customer: customer.id,
amount: booking.amount,
description: booking.description,
currency: 'usd'
)
if charge.paid
# Do some things for successful charge
respond_to do |format|
format.json { render json: {status: "ok"}.to_json }
end
else
respond_to do |format|
format.json { render json: {status: "fail", message: "Error with processing payment. Please contact support."}.to_json }
end
end
end
end
Move your token initializer from configure to open.
var handler = StripeCheckout.configure({
key: 'pk_test_jPVRpCB1MLjWu2P71eTvXBZD',
image: '/square-image.png'
});
$('.pay-deposit').click( function(e) {
var data = $(this).data('booking-id');
// Open Checkout with further options
handler.open({
name: 'Demo Site',
description: '2 widgets ($20.00)',
amount: 2000,
token: function(token) {
// here you go!
alert(data);
}
});
e.preventDefault();
});
And switch to:
<button class='pay-deposit' data-booking-id='3455'>Pay Deposit</button>
<button class='pay-deposit' data-booking-id='335'>Pay Deposit</button>
<button class='pay-deposit' data-booking-id='34'>Pay Deposit</button>

Categories

Resources