Ruby on rails 试图通过自定义表单处理单条付款

Ruby on rails 试图通过自定义表单处理单条付款,ruby-on-rails,ruby,ruby-on-rails-4,stripe-payments,Ruby On Rails,Ruby,Ruby On Rails 4,Stripe Payments,我正试图通过一个自定义表单通过Stripe处理付款;但是,我反复遇到一个Stripe::invalidRequester错误,即您必须提供卡或客户id错误。我在SO上引用了类似的错误消息,但我无法将其应用于我的代码 根据我的日志,我发现问题出在创建操作中的学生控制器中,但我可以找出如何修复代码。非常感谢您的帮助 学生\u控制器.rb: class StudentsController < ApplicationController def index @students = St

我正试图通过一个自定义表单通过Stripe处理付款;但是,我反复遇到一个Stripe::invalidRequester错误,即您必须提供卡或客户id错误。我在SO上引用了类似的错误消息,但我无法将其应用于我的代码

根据我的日志,我发现问题出在
创建
操作中的
学生
控制器中,但我可以找出如何修复代码。非常感谢您的帮助

学生\u控制器.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)
    #@payment = Payment.create

    Stripe.api_key = [STRIPE_KEY]

    token = params[:stripeToken]

    begin

      charge = 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, :rank, :school, :school_name, :art,
                                    :math, :science, :gym, :school_id,
                                    :country, :email, :stripeToken)
  end

  def total(student)

    total_events = 0

    if student.forms
        total_events = total_events + 1
    end

    if student.sparring
        total_events = total_events + 1
    end

    if student.weapons
        total_events = total_events + 1
    end

    if student.breaking
        total_events = total_events + 1
    end

    prices = {
        0 => 0,
        1 => 60,
        2 => 60,
        3 => 65,
        4 => 70
    }

    prices[total_events]

  end
end
控制台日志

Completed 500 Internal Server Error in 2555ms

Stripe::InvalidRequestError - You must supply either a card or a customer id:
  stripe (1.8.8) lib/stripe.rb:221:in `handle_api_error'
  stripe (1.8.8) lib/stripe.rb:115:in `rescue in request'
  stripe (1.8.8) lib/stripe.rb:101:in `request'
  stripe (1.8.8) lib/stripe/api_operations/create.rb:6:in `create'
  app/controllers/students_controller.rb:28:in `create'
  actionpack (4.0.0) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
  actionpack (4.0.0) lib/abstract_controller/base.rb:189:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/rendering.rb:10:in `process_action'
  actionpack (4.0.0) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
  activesupport (4.0.0) lib/active_support/callbacks.rb:403:in `_run__3015449183909972584__process_action__callbacks'
  activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
  actionpack (4.0.0) lib/abstract_controller/callbacks.rb:17:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/rescue.rb:29:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
  activesupport (4.0.0) lib/active_support/notifications.rb:159:in `block in instrument'
  activesupport (4.0.0) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
  activesupport (4.0.0) lib/active_support/notifications.rb:159:in `instrument'
  actionpack (4.0.0) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
  actionpack (4.0.0) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
  activerecord (4.0.0) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
  actionpack (4.0.0) lib/abstract_controller/base.rb:136:in `process'
  actionpack (4.0.0) lib/abstract_controller/rendering.rb:44:in `process'
  actionpack (4.0.0) lib/action_controller/metal.rb:195:in `dispatch'
  actionpack (4.0.0) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
  actionpack (4.0.0) lib/action_controller/metal.rb:231:in `block in action'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:80:in `dispatch'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:48:in `call'
  actionpack (4.0.0) lib/action_dispatch/journey/router.rb:71:in `block in call'
  actionpack (4.0.0) lib/action_dispatch/journey/router.rb:59:in `call'
  actionpack (4.0.0) lib/action_dispatch/routing/route_set.rb:655:in `call'
  rack (1.5.2) lib/rack/etag.rb:23:in `call'
  rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
  rack (1.5.2) lib/rack/head.rb:11:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/flash.rb:241:in `call'
  rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
  rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/cookies.rb:486:in `call'
  activerecord (4.0.0) lib/active_record/query_cache.rb:36:in `call'
  activerecord (4.0.0) lib/active_record/connection_adapters/abstract/connection_pool.rb:626:in `call'
  activerecord (4.0.0) lib/active_record/migration.rb:369:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
  activesupport (4.0.0) lib/active_support/callbacks.rb:373:in `_run__4145610644890293834__call__callbacks'
  activesupport (4.0.0) lib/active_support/callbacks.rb:80:in `run_callbacks'
  actionpack (4.0.0) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/reloader.rb:64:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
  better_errors (1.0.1) lib/better_errors/middleware.rb:84:in `protected_app_call'
  better_errors (1.0.1) lib/better_errors/middleware.rb:79:in `better_errors_call'
  better_errors (1.0.1) lib/better_errors/middleware.rb:56:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.0.0) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.0.0) lib/rails/rack/logger.rb:21:in `block in call'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `block in tagged'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:25:in `tagged'
  activesupport (4.0.0) lib/active_support/tagged_logging.rb:67:in `tagged'
  railties (4.0.0) lib/rails/rack/logger.rb:21:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
  rack (1.5.2) lib/rack/runtime.rb:17:in `call'
  activesupport (4.0.0) lib/active_support/cache/strategy/local_cache.rb:83:in `call'
  rack (1.5.2) lib/rack/lock.rb:17:in `call'
  actionpack (4.0.0) lib/action_dispatch/middleware/static.rb:64:in `call'
  railties (4.0.0) lib/rails/engine.rb:511:in `call'
  railties (4.0.0) lib/rails/application.rb:97:in `call'
  rack (1.5.2) lib/rack/lock.rb:17:in `call'
  rack (1.5.2) lib/rack/content_length.rb:14:in `call'
  rack (1.5.2) lib/rack/handler/webrick.rb:60:in `service'
  /Users/thomaskim/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/webrick/httpserver.rb:138:in `service'
  /Users/thomaskim/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/webrick/httpserver.rb:94:in `run'
  /Users/thomaskim/.rbenv/versions/2.0.0-p247/lib/ruby/2.0.0/webrick/server.rb:295:in `block in start_thread'


Started POST "/__better_errors/70109633489280/variables" for 127.0.0.1 at 2014-01-30     22:14:33 -0800
layouts/application.html.erb

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

<%= 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" %>
        <%= f.input :zip, label: "Zip/Postal", as: :string %>
        <%= f.input :country, priority: [ "United States" ] %>
        <%= f.input :email %>
        <%= f.input :phone, as: :string %>
        <%= f.input :age, collection: 5..90, prompt: "Select your age" %>
        <%= f.association :school, label_method: :school_name, value_method: :id, include_blank: false, label: "School Name" %>
        <%= f.input :art,    :input_html => { :class => "event" }, :as => :boolean %>
        <%= f.input :math, :input_html => { :class => "event" }, :as => :boolean %>
        <%= f.input :science,  :input_html => { :class => "event" }, :as => :boolean %>
        <%= f.input :gym, :input_html => { :class => "event" }, :as => :boolean %>
        <br>
    </p>

    <div id='bt_registration' class='btn btn-primary'>Submit</div>
</div>

<div id="cost">
    <h2>Total Price</h2>

    <br>
    <div>
        <form action="" method="POST" id="payment-form">
      <span class="payment-errors"></span>

      <div class="form-row">
        <label>
          <span>Cardholder Name</span>
          <input type="text" size="20" data-stripe="number"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>Card Number</span>
          <input type="text" size="20" data-stripe="number"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>CVC</span>
          <input type="text" size="4" data-stripe="cvc"/>
        </label>
      </div>

      <div class="form-row">
        <label>
          <span>Expiration (MM/YYYY)</span>
          <input type="text" size="2" data-stripe="exp-month"/>
        </label>
        <span> / </span>
        <input type="text" size="4" data-stripe="exp-year"/>
      </div>
      <br>
      <button type="submit">Submit Payment</button>
    </form> 
    </div>

    <div>
    <h3>Your total: $<span id="total"></span>.00</h3>
    </div>
    <p>

        <%= f.button :submit, "Register", class: 'btn btn-primary' %>
        <%= link_to "Cancel", students_path, class: 'btn btn-primary' %>
    </p>
</div>

<br>

<script>
$( document ).ready(hideTotal);

    $("input.event").click(updateTotal);

$("#bt_registration").click(function( event ) {
  event.preventDefault();
      showTotal();
});

    function hideTotal() {
  $("#cost").hide();
    }

    function showTotal() {
  $("#registration").hide();
  $("#cost").show();
    }

    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 %>
Registration::Application.routes.draw do

  root 'students#index'
  post "/students" => "students#create"

  resources :students
  resources :events
  resources :schools

end
<!DOCTYPE html>
<html>
<head>

  <title>Event Registration</title>
  <%= stylesheet_link_tag    "application", media: "all", "data-turbolinks-track" => true %>
  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>

  <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
  <script type="text/javascript">
    // This identifies your website in the createToken call below
    Stripe.setPublishableKey('STRIPE_KEY');

    jQuery(function($) {
      $('#payment-form').submit(function(event) {
        var $form = $(this);

        // Disable the submit button to prevent repeated clicks
        $form.find('button').prop('disabled', true);

        Stripe.card.createToken($form, stripeResponseHandler);

        // Prevent the form from submitting with the default action
        return false;
      });
    });

    var stripeResponseHandler = function(status, response) {
      var $form = $('#payment-form');

      if (response.error) {
        // Show the errors on the form
        $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>

  <div id="footer">
    <div class="container">
      <p class="text-muted credit">Event Registration</p>
    </div>
  </div>

</body>
</html>

活动登记
正确%>
正确%>
//这将在下面的createToken调用中标识您的网站
Stripe.setPublishableKey('Stripe_KEY');
jQuery(函数($){
$(“#付款单”)。提交(功能(事件){
var$form=$(此);
//禁用“提交”按钮以防止重复单击
$form.find('button').prop('disabled',true);
Stripe.card.createToken($form,stripeResponseHandler);
//阻止使用默认操作提交表单
返回false;
});
});
var stripeResponseHandler=函数(状态、响应){
var$form=$(“#付款单”);
if(response.error){
//在表单上显示错误
$form.find('.payment errors').text(response.error.message);
$form.find('button').prop('disabled',false);
}否则{
//令牌包含id、last4和卡类型
var token=response.id;
//将令牌插入表单,以便将其提交到服务器
$form.append($('').val(标记));
//并提交
$form.get(0.submit();
}
};
事件注册


参数[:stripeToken]应该来自哪里?我在您的表单中没有看到它,通常会有一些(Java | Coffee)脚本将卡的详细信息发送到Stripe并取回令牌。很抱歉,我遗漏了
application.html.erb
layout文件。现在已经添加了。我只是把回调脚本放在这里,我认为这不是问题。您检查了
create
调用的请求日志了吗?它应该告诉您
params
中的真正内容。是的,除了
stripeToken
之外,所有内容都被传递到
params
。这就是让我发疯的原因。Stripe的令牌调用脚本在那里,但我不知道为什么它不起作用。我正在使用更好的错误gem,错误发生在'charge=Stripe::charge.create(`在我的控制器中。您确定提交的
与您的JavaScript所认为的一样吗?请注意,这里有两个