我正在尝试通过自定义表单通过Stripe处理付款;但是,我反复遇到 Stripe :: InvalidRequestError您必须提供卡或客户ID 错误。我在SO here上引用了类似的错误消息,但我无法将其应用于我的代码。
根据我的日志,我发现问题出在Students
操作中的create
控制器中,但我可以弄清楚如何修复我的代码。非常感谢任何帮助。
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)
#@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
new.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 %>
的routes.rb
Registration::Application.routes.draw do
root 'students#index'
post "/students" => "students#create"
resources :students
resources :events
resources :schools
end
的console.log
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
布局/ application.html.erb
<!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>