Question

For some reason, my form is not displaying validation errors when trying to process a payment via Stripe. I'm expecting validation errors such as "Your card number is invalid" when testing, but I get nothing. When I check the logs, there's nothing.

Any help would be appreciated. Thanks.

layouts/application.html.erb

<!DOCTYPE html>
<html>
<head>

  <title>Event Registration</title>
  <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
  <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
  <script type="text/javascript">

    Stripe.setPublishableKey('TESTKEY');
    jQuery(function($) {

      $('#new_student').submit(function(event) {
        var $form = $(this);

        $form.find('button').prop('disabled', true);

        Stripe.card.createToken({
           name: $('#cardholder-name').val(),
           number: $('#card-number').val(),
           cvc: $('#card-cvc').val(),
           exp_month: $('#card-expiry-month').val(),
           exp_year: $('#card-expiry-year').val()
        }, stripeResponseHandler);

        return false;
      });
    });

    var stripeResponseHandler = function(status, response) {

      var $form = $('#new_student');

      if (response.error) {
        $form.find('.payment-errors').text(response.error.message);
        $form.find('button').prop('disabled', false);
      } else {
        // 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="stripeToken" />').val(token));
        // and submit
        $form.get(0).submit();
      }
    };
  </script>

</head>
<body>

    <div class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
      <div class="  navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <a class="navbar-brand" href="/students">Event Registration</a>
      </div>
      <div class="collapse navbar-collapse">
        <ul class="nav navbar-nav">
          <li class="active"><a href="/students">Home</a></li>
          <li><a href="/details">Details</a></li>
          <li><a href="/contact">Contact</a></li>
        </ul>
      </div><!--/.nav-collapse -->
    </div>
  </div>

  <div id="wrap">
        <div class="container">
            <%= yield %>
        </div>
    </div>

</body>
</html>

student.rb file:

class Student < ActiveRecord::Base
    validates :first_name, :last_name, :gender, :address1, :city, :state,
                        :zip, :phone, :age, :school, :email, :email_confirmation,
                        presence: true

    validates :email, confirmation: true
    validates_confirmation_of :email, message: "Email addresses should match each other"

    attr_accessor :stripeToken

end

students/new.html.erb file

<div id="registration">
    <h2>Tournament Registration:</h2>

    <%#= Unsure if I should add id: "payment-form" to the :html hash?%>
    <%= simple_form_for(@student, :html => {:class => 'form-horizontal'}) do |f| %>
        <p id="input">

            <%= f.input :first_name, :input_html => { :class => 'span6'} %>
            <%= f.input :last_name %>
            <%= f.input :gender, as: :radio_buttons, collection: ["Male", "Female"] %>
            <%= f.input :address1 %>
            <%= f.input :city %>
            <%= f.input :state, label: "State/Province", :include_blank => false, collection:[["AK", "Alaska"], 
        ["AL", "Alabama"], 
        ["RI", "Rhode Island"], 
        ["SC", "South Carolina"]] %>
            <%= f.input :zip, label: "Zip/Postal", as: :string %>
            <%= f.input :country, priority: [ "United States" ] %>
            <%= f.input :phone, as: :string %>
            <%= f.input :age, collection: 5..90, prompt: "Select your age" %>
            <%= f.input :school, label: "School Name", :include_blank => false, collection:
                ["Britton Location",
                "Mahogony Location",
                "Johnson Location",] %> 
      <%= f.input :forms,    label: "Dance (click, if Yes)", :input_html => { :class => "event" }, :as => :boolean %>
      <%= f.input :sparring, label: "Music (click, if Yes)", :input_html => { :class => "event" }, :as => :boolean %>
      <%= f.input :weapons,  label: "Painting (click, if Yes)", :input_html => { :class => "event" }, :as => :boolean %>
      <%= f.input :breaking, label: "Drawing (click, if Yes)", :input_html => { :class => "event" }, :as => :boolean %>
            <br>
        </p>
        <!-- <div id='bt_registration' class="btn btn-primary">Next</div> -->
    </div>

    <div id="cost">
        <h2>Payment Information:</h2>
        <br>
        <div>
            <form action="" method="POST" id="new_student">
          <span class="payment-errors"></span>
          <div class="form-row">
            <label>
                <span>Email</span>
                    <%= f.text_field :email %>
              </label>
          </div>
          <div class="form-row">
            <label>
                <span>Email Confirmation</span>
                    <%= f.text_field :email_confirmation %>
              </label>
          </div>  
          <div class="form-row">
            <label>
              <span>Cardholder Name</span>
              <input type="text" size="20" data-stripe="number" id="cardholder-name"/>
            </label>
          </div>
          <div class="form-row">
            <label>
              <span>Card Number</span>
              <input type="text" size="20" data-stripe="number" id="card-number"/>
            </label>
          </div>
          <div class="form-row">
            <label>
              <span>CVC</span>
              <input type="text" size="4" data-stripe="cvc" id="card-cvc"/>
            </label>
          </div>
          <div class="form-row">
                <%= label_tag :card_month, "Card Expiration" %>
                <%= select_month nil, {add_month_numbers_true: true}, {name: nil, id: "card-expiry-month"}%>
            <%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card-expiry-year"}%>
          </div>
          <br>
          <div>
        <h3>Your total: $<span id="total"></span>.00</h3>
            </div>
            <br>
          <button type="submit", class="btn btn-success">Submit Payment</button>
          <%= link_to "Cancel", students_path, class: 'btn btn-primary', color: 'Blue' %>
            </form> 
        </div>
    </div>
    <br>
    <script>
    $( document ).ready(updateTotal);

  $("input.event").click(updateTotal);
      function updateTotal() {
        var prices = {
          0: 0,
          1: 60,
          2: 60,
          3: 65,
          4: 75
        },
        numberOfEvents = $("input.event:checked").length,
        total = prices[numberOfEvents];

        $("#total").text(total);
      }
    </script>
    <% end %>

students_controller.rb

class StudentsController < ApplicationController

    def index
        @students = Student.all
    end

    def show
        @student = Student.find(params[:id])
    end

    def new
        @student = Student.new
    end

    def create
        @student = Student.create(student_params)

        Stripe.api_key = "TESTKEY"

        token = params[:stripeToken]

        begin
        Stripe::Charge.create( 
        amount:      total(@student),
        currency:    "usd",
        card:        token,
        description: student_params[:email]
        )

        redirect_to @student, :notice => "Thank you for registering!"

    rescue Stripe::CardError => e
        The card has been declined or some other error has occured
        @error = e
        render :new
        end

    end


    private 

    def student_params
        params.require(:student).permit(:first_name, :last_name, 
                                                        :gender, :address1, :city, :state, 
                                                        :zip, :phone, :age, :school,
                                                        :school_name, :dance, :music,  
                                                        :drawing, :painting, :school_id, :country,
                                                        :email, :email_confirmation,
                                                        :stripeToken)
    end
Was it helpful?

Solution

Try changing your jQuery in your head from this:

jQuery(function($) {

  $('#new_student').submit(function(event) {
    var $form = $(this);

    $form.find('button').prop('disabled', true);

    Stripe.card.createToken({
       name: $('#cardholder-name').val(),
       number: $('#card-number').val(),
       cvc: $('#card-cvc').val(),
       exp_month: $('#card-expiry-month').val(),
       exp_year: $('#card-expiry-year').val()
    }, stripeResponseHandler);

    return false;
  });
});

To this:

jQuery(function($){
    $('#new_student').submit(function(e) {
        var $form = $(this);

        $form.find('button').prop('disabled', true);

        Stripe.createToken($form, stripeResponseHandler);

        return false;
        });
    });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top