Stripe 不接受付款,收费一直失败。我收到此错误:
Started POST "/charges" for 127.0.0.1 at 2014-06-09 06:30:58 -0700
Processing by ChargesController#create as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"9bqk2Q6NEM1ehHDJPgncNQ3gnP0X1hQK6y6ENm3Yb1g=", "c
harge"=>{"contest_id"=>"36", "user_id"=>"", "amount"=>"12", "stripe_card_token"=>""}, "card_number"=
>"4242 4242 4242 4242", "card_code"=>"478", "button"=>""}
Stripe error while creating customer: You passed an empty string for 'card'. We assume empty values
are an attempt to unset a parameter; however 'card' cannot be unset. You should remove 'card' from y
our request or supply a non-empty value
Redirected to http://localhost:3000/
Completed 302 Found in 477ms (ActiveRecord: 0.0ms)
看起来好像它可能没有创建条纹令牌?这是怎么回事?
这是我的表格:
<% content_for :head do %>
<%= tag :meta, :name => "stripe-key", :content => STRIPE_PUBLIC_KEY %>
<% end %>
<%= form_for @charge, :html => { :class => 'form' } do |f| %>
<div class="form-inputs">
<div class="row">
<%= f.hidden_field :contest_id, value: @contest.id %>
<%= f.hidden_field :user_id %>
<%= f.hidden_field :amount %>
<!-- TODO CHANGE THIS ACCORDINGLY -->
<%= f.hidden_field :stripe_card_token %>
<div class="small-12 medium-6 large-2 columns">
<%= f.label "Amount:", class: "text-right" %>
</div>
<div class="small-12 medium-6 large-10 columns" style="margin-bottom: 0.5rem; margin-top: 0.5rem;">
<%= number_to_currency(@charge.amount, :unit => "$") %>
</div>
<% if @charge.stripe_card_token.present? %>
Credit card has been provided.
<% else %>
<div class="small-12 medium-6 large-2 columns">
<%= label_tag :card_number, "Credit Card Number:", class: "text-right" %>
</div>
<div class="small-12 medium-6 large-10 columns">
<%= text_field_tag :card_number %>
</div>
<div class="small-12 medium-6 large-2 columns">
<%= label_tag :card_code, "Security Code on Card (CVV):", class: "text-right" %>
</div>
<div class="small-12 medium-6 large-10 columns end">
<%= text_field_tag :card_code %>
</div>
<div class="small-12 medium-6 large-2 columns">
<%= label_tag :card_month, "Card Expiration:", class: "text-right" %>
</div>
<div class="small-6 medium-3 columns">
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %>
</div>
<div class="small-6 medium-3 columns">
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"} %>
</div>
<% end %>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
</div>
<div class="row">
<div class="form-actions small-9 small-offset-2 columns">
<%= button_tag :type => "button", :class => "radius" do %>
<%= link_to "Back", @contest, :style => "color: white" %>
<% end %>
<%= f.button :Donate, :class => "radius" %>
</div>
</div>
</div>
<% end %>
<% content_for :js do %>
<%= javascript_include_tag "https://js.stripe.com/v1", "application" %>
<%= javascript_include_tag asset_path("stripe/stripe.js"), "application" %>
<% end %>
这是我的收费控制器:
class ChargesController < ApplicationController
def new
@contest = Contest.find(params[:id])
@charge = Charge.new(amount: params[:amount])
end
def create
@charge = Charge.new(charges_params)
if @charge.save_with_payment(@charge)
redirect_to root_path, :notice => "Contribution was recorded succesfully!"
else
redirect_to root_path, :notice => "Transaction was not able to be recorded"
end
end
def charges_params
params.require(:charge).permit(:stripe_card_token, :contest_id, :user_id, :amount)
end
end
我的收费模式:
class Charge < ActiveRecord::Base
attr_accessor :stripe_card_token
belongs_to :contest
belongs_to :user
def save_with_payment(charge)
if valid?
Stripe::Charge.create(
:amount => (charge.amount.to_i)*100,
:currency => "usd",
:card => stripe_card_token);
save
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
end
很可能看起来 stripe_card_token 是空白的
:card => stripe_card_token
尝试将其更改为
:card => charge.stripe_card_token
与
stripe_card_token
为空无关,您的服务器当前位于 PCI 范围内,因为它正在接收卡号和 CVV 代码。如果您使用 Stripe,这可能不是您想要的。
来自 Stripe 入门文档:
注意输入字段如何表示敏感卡数据(号码、CVC、 到期月份和年份)没有“名称”属性。这 提交表单时防止他们访问您的服务器。
Rails 标签助手默认生成一个 name 属性。在这种情况下这是不可取的。
您可以通过为
name
和 value
传递 nil 并定义某种标识符来覆盖此行为:
<%= text_field_tag nil, nil, 'data-stripe' => 'card_number' %>
这里我使用了 Stripe 当前推荐的
data-stripe
,但您也可以使用 id
属性(正如他们的旧教程推荐的那样)。
回到原来的问题,问题出在您的 Charge 模型中,您在其中覆盖 Active Record 并屏蔽数据库中的数据:
class Charge < ActiveRecord::Base
attr_accessor :stripe_card_token # Don't do this!
attr_accessor
切勿在数据库列上使用。 Active Record 提供了自己的访问器,以便从数据库中提取数据;通过在此处声明访问器,您将用 Ruby 的基本功能替换 Active Record 的功能:
irb(main):001:0> Charge.first
Charge Load (0.3ms) SELECT "charges".* FROM "charges" ORDER BY "charges"."id" ASC LIMIT 1
=> #<Charge id: 1, stripe_card_token: "0xdeadbeef", created_at: "2014-06-11 14:27:40", updated_at: "2014-06-11 14:27:40">
irb(main):002:0> c.stripe_card_token
=> nil
话虽如此,您开始使用的 Railscast 已经有近三年的历史了,到处都违反了最佳实践,并且使用了早已过时的 API 端点。一旦你纠正了你的模型,你仍然最好开始你的表单和 JavaScript,而不是使用 Stripe 的当前教程和文档。
我遇到了同样的问题。
我的subscription.js.coffee:
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
subscription.setupForm()
subscription =
setupForm: ->
$('#new_subscription').submit (e) ->
$('input[type=submit]').attr('disabled', true)
subscription.processCard()
return false
processCard: ->
card =
number: $('#card_number').val()
cvc: $('#card_code').val()
expMonth: $('#card_month').val()
expYear: $('#card_year').val()
Stripe.createToken(card, subscription.handleStripeResponse)
handleStripeResponse: (status, response) ->
if status == 200
$('#subscription_stripe_card_token').val(response.id)
$('#new_subscription')[0].submit()
else
$('#stripe_error').text(response.error.message)
$('input[type=submit]').attr('disabled', false)
false
正如您所看到的,当用户按下
submit
按钮时,功能 $('#new_subscription').submit (e)
会升起。几乎所有的条纹魔法都在提交函数中。
在我的情况下,有时不会引发提交函数,因此空的
stripe_card_toke
参数会发送到您的服务器。
奇怪的行为是由 Rails Turbolinks 设施引起的。
我是这样解决的:
gem 'jquery-turbolinks'
//= require jquery.turbolinks
//= require jquery //= require jquery.turbolinks //= require jquery_ujs //= require turbolinks //= require bootstrap //= require jquery_nested_form //= require_tree .