【问题标题】:Stripe with Rails 4 Error "The Customer has no payment source" using stripe.jsStripe with Rails 4 错误“客户没有付款来源”使用 stripe.js
【发布时间】:2016-01-11 19:11:03
【问题描述】:

尝试使用 stripe.js 提交自定义付款表单(由 subscription#new 操作呈现)时,我收到以下错误消息:“客户没有付款来源”

我提交的表格是:

<% unless @subscription.errors.blank? %>
  <%= @subscription.errors.full_messages.to_sentence %>
<% end %>

<h2>Subscribing to <%= @plan.name %></h2>

<%= form_for [:student, @subscription], html: { id: 'payment-form' } do |f| %>
  <input type="hidden" name="plan_id" value="<%= @plan.id %>" />
  <span class="payment-errors"></span>

  <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>

  <button type="submit">Pay Now</button>
<% end %>

我的订阅控制器如下所示:

class Student::SubscriptionsController < StudentApplicationController
  skip_before_filter :authenticate_user!, except: [:update]
  before_filter :load_plans 
  before_filter :find_plan, except: [:index]

  def index
  end

  def new
    @subscription = Subscription.new
  end

  def create
    if current_user.stripe_customer_id.blank?
      @subscription = CreateSubscription.call(
        @plan,
        current_user.email,
        params[:stripeToken]
        )
        if @subscription.errors.blank?
          flash[:notice] = 'Thank you for your purchase!' +
          'Please click the link in the email we just sent ' +
          'you to get started.'
          redirect_to '/'
        else
          render :new, notice: "Oops something went wrong"
        end
    else
      redirect_to new_student_subscription_path, notice: "You cannot create two subscriptions"
    end

  end

  def edit
  end

  def update
    @plan = Plan.find(params[:plan_id])
    @old_subscription = Subscription.find(current_user.subscription.id)
    @updated_subscription = ChangePlan.call(@old_subscription, @plan)
    if @updated_subscription.errors.blank?
      flash[:notice] = "You are now subscribed to the #{current_user.subscription.plan.name}"
      redirect_to '/'
    else
      render :new, notice: "Oops something went wrong"
    end
  end

  protected

    def load_plans
      @plans = Plan.all.order('amount')
    end

    def find_plan
      @plan = Plan.find(params[:plan_id])
    end

end

创建动作中使用的服务对象是:

class CreateSubscription
  def self.call(plan, email_address, token)
    user, raw_token = CreateUser.call(email_address)

    subscription = Subscription.new(
      plan: plan,
      user: user
    )

    begin
      stripe_sub = nil
      customer = Stripe::Customer.create(
        source: token,
        email: user.email,
        plan: plan.stripe_id,
      )
      user.stripe_customer_id = customer.id
      user.save!
      stripe_sub = customer.subscriptions.first

      subscription.stripe_id = stripe_sub.id
      subscription.expiry = Date.today + 1.month

      subscription.save!
    rescue Stripe::StripeError => e
      subscription.errors[:base] << e.message
    end

    subscription
  end 
end

在 /app/assets/javascripts/students/subscriptions.js 我有:

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;
  });
});

function stripeResponseHandler(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 {
    // response contains id and card, which contains additional card details
    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();
  }
};

提交自定义支付表单时,params[:stripeToken]的值为nil,所以我不确定上面的jQuery代码是否有错误。

在 app/views/layouts/application.html.erb 我有:

<head>
  <title>OnlinePlatform</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">
  $(function(){
    Stripe.setPublishableKey('<%= Rails.configuration.stripe[:publishable_key] %>');
  });
  </script>
</head>

谁能帮我确定为什么我会从 Stripe 收到错误消息?

谢谢

【问题讨论】:

  • 这听起来绝对是您的 javascript 的问题。您是否熟悉 javascript 和/或 jquery 以及如何使用浏览器的 javascript 调试器?
  • 回答您的最后一个问题,您会看到该错误,因为您尝试为其创建订阅的客户没有任何卡片保存到他们的条带帐户中。由于没有提供支付来源,也没有默认来源可以依赖(即客户至少保存了一张卡),Stripe 会返回您看到的错误。要解决这个问题,你必须弄清楚为什么params[:stripeToken] 为nil(可能没有通过)。一旦你解决了这个问题,你就可以开始了。
  • 不知道你有没有类似的问题:stackoverflow.com/questions/31014977/…你用的是什么版本的jQuery?
  • 似乎我在 Javascript 代码的第 11 行收到错误,其中引发了以下异常:“参考错误:未定义条纹”
  • 欢迎您在这里与我聊天:chat.stackoverflow.com/rooms/92336/33112756

标签: javascript jquery ruby-on-rails stripe-payments


【解决方案1】:

好的,首先,您的表单在没有令牌的情况下提交,因为在返回 false 之前发生错误,因此它继续使用默认行为。我会添加event.preventDefault(); 作为提交处理程序的第一行,以阻止这种情况发生。接下来,您需要弄清楚为什么没有在 window 对象中定义 Stripe。我怀疑涡轮链接可能在其中发挥作用。暂时禁用 turbolinks 以将其作为变量消除,然后检查页面上是否存在该脚本,并使用浏览器的 javascript 控制台定义 window.Stripe

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-13
    • 2019-01-26
    • 2018-11-07
    • 2018-12-13
    • 2016-05-22
    • 1970-01-01
    • 2016-05-21
    相关资源
    最近更新 更多