创建客户时出现条带错误:您为“卡”传递了一个空字符串

Posted

技术标签:

【中文标题】创建客户时出现条带错误:您为“卡”传递了一个空字符串【英文标题】:Stripe error while creating customer: You passed an empty string for 'card' 【发布时间】:2014-07-30 01:47:33 【问题描述】:

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

【问题讨论】:

你在什么时候看到这个?是不是看到“已提供信用卡”后。然后点击捐赠? @Baloo 这是在我输入信用卡信息并点击捐赠后发生的 它是空白的,因为如果它存在则执行此操作,否则输入信用卡数据,此时您不会传递条带卡令牌。从您的模型来看,您似乎正在做任何事情来生成一个。 如何取消空白?有什么我想念的吗? 【参考方案1】:

stripe_card_token 很可能是空白的

:card => stripe_card_token

尝试将其更改为

:card =&gt; charge.stripe_card_token

【讨论】:

因为他在模型中stripe_card_token 会工作。 charge.stripe_card_token 不会,因为它会给出一个错误,说没有收费之类的东西。【参考方案2】:

stripe_card_token 为空白无关,您的服务器目前在 PCI 范围内,因为它正在接收卡号和 CVV 代码。如果您使用的是 Stripe,这可能不是您想要的。

来自Stripe Getting Started docs:

注意输入字段如何表示敏感卡数据(数字、CVC、 到期月份和年份)没有“名称”属性。这 防止他们在提交表单时访问您的服务器。

Rails 标签助手默认生成名称属性。在这种情况下,这是不可取的。

您可以通过为 namevalue 传递 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 提供了自己的访问器,以便从数据库中提取数据;通过在此处声明访问器,您将 Active Record 的功能替换为 Ruby 的基本功能:

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 当前的教程和文档。

【讨论】:

感谢这有很大帮助!我仍然无法弄清楚如何取消 stripe_card_token 的空白... @user3597950 查看链接到的文档 colnm 中的第 2 步 我已经这样做了,这是我刚刚发布的所有代码的新问题,包括我创建令牌的 js.coffee 文件。 ***.com/questions/24157833/…如果你能发现我的错误,请告诉我! @user3597950 再看一眼就找到了。更新了答案。 如果我取出 attr_accessor 我得到(未定义的方法 `stripe_card_token' for #<0x3f1ff20>【参考方案3】:

我遇到了同样的问题。 我的 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 设施引起的。 我是这样解决的:

    Gemfile中添加一行:gem 'jquery-turbolinks' 在清单application.js中添加一行://= require jquery.turbolinks 所以我的 application.js 看起来像:
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require turbolinks
//= require bootstrap
//= require jquery_nested_form
//= require_tree .

【讨论】:

以上是关于创建客户时出现条带错误:您为“卡”传递了一个空字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 Stripe.com 向客户收取特定卡的费用

无需储蓄卡即可进行条带支付

将字符串引用作为参数传递时出现错误的 Ptr

尝试接受具有大文件的模型时出现 .net API 错误

将字符串的 2darray 作为参数传递时出现“错误:类型的数组值”

为啥将字符串作为文件名而不是 char* 传递时出现错误?