如何使用带有 rails 的自定义表格使用 stripe v2 进行充电?

How to charge using stripe v2 with custom form with rails?

我不断收到

Stripe::InvalidRequestError in ChargesController#create Customer cus_8fqEmSUxnGEO6g does not have a linked source with ID tok_18OUXYLM1r6OYriq1WcKNB79.

我不确定是什么原因造成的。

这是我的表格:

 <%= form_tag charges_path, id:"payment-form" do %>
    <article>
      <label class="amount">
        <span>Price: <%= number_to_currency @booking.price %></span>
      </label>
    </article>
    <%= hidden_field_tag 'booking_id', @booking.id %>
    <div class="form-group">
      <%= label_tag :card_number, "Credit Card Number" %>
      <%= text_field_tag :card_number, nil, name: nil, data: {stripe: "number"}, value:"4242 4242 4242 4242", class:"form-control" %>
    </div>
    <div class="form-group">
      <%= label_tag :card_code, "Security Code on Card (CVC)" %>
      <%= text_field_tag :card_code, nil, name: nil, data: {stripe: "cvc"}, value:"123", class:"form-control" %>
    </div>
    <div class="form-group">
      <%= label_tag :card_month, "Card Expiration" %>
      <%= text_field_tag :card_month, nil, name: nil, data: {stripe: "exp"}, value:"12 / 17", class:"form-control" %>
    </div>
    <div class="card-errors">
    </div>
    <%= submit_tag 'Submit', class: "button round", id: "pay_now", class:"btn btn-success" %>

  <% end %>

这是我的控制器:

    class ChargesController < ApplicationController
      before_action :authenticate_user!

      def create
         token = params[:stripeToken]
         # Amount in cents
         @amount = (current_booking.price * 100).to_i

         customer = Stripe::Customer.create(
         :email => params[:stripeEmail]
         )

         charge = Stripe::Charge.create(
         :customer    => customer.id,
         :amount      => @amount,
         :description => 'Content',
         :currency    => 'usd',
         :source      => token
         )

         redirect_to booking_path(current_booking), notice:"Thanks, your  purchase was successful!"
         rescue Stripe::CardError => e
         flash[:error] = e.message
         redirect_to "/bookings/new/?space_listing_id=#{@current_booking.space_listing_id}"
         end

          private

          def current_booking
            @current_booking ||= Booking.find(params[:booking_id])
          end
        end

这是我的 jQuery:

jQuery(function($) {
  $('#payment-form').submit(function(event) {
    var $form = $(this);
// Disable the submit button to prevent repeated clicks
    $form.find('#pay_now').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) {
    $("div.card-errors").text(response.error.message);
    $form.find('#pay_now').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();
   }
};

为客户创建费用时,source 参数将代表一张已链接到该客户对象的卡: https://stripe.com/docs/api/#create_charge-source

在这种情况下,您正试图传递尚未与该客户相关联的令牌(这是正确的失败)。相反,您需要在尝试进行收费之前使用该来源创建或更新客户对象。要解决此问题,您实际上只需要将 :source => token 从创建费用尝试移至客户:

customer = Stripe::Customer.create(
  :email => params[:stripeEmail],
  :source => token.id
)

Stripe 网站上有一份指南对此进行了更详细的介绍: https://stripe.com/docs/charges#saving-credit-card-details-for-later