我已在我们的应用中部署了自定义条纹付款表单,97%的时间它运行得很好。有时候,我发现Stripe报告了一次尝试付款的错误。
POST /v1/customers
error:
type: "invalid_request_error"
message: "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 your request or supply a non-empty value"
param: "card"
使用应该从javascript生成的Stripe令牌创建客户时会引发此问题:
sale = current_user.sales.create(
plan_id: plan.id,
amount: plan.price_in_cents,
stripe_token: params[:stripeToken]
)
经过多次故障排除后,我确认发生了这种情况,因为首先没有调用Stripe来创建令牌。换句话说,这不是传递params的问题,其中令牌生成但是根本没有传递给控制器。出于某种原因,javascript中的某些内容没有运行,因此表单只是在没有调用Stripe的情况下提交。
再次记住97%的时间没有发生此问题。当它确实发生时,它一次又一次地发生在同一个用户身上。我没有找到任何浏览器模式(它发生在Chrome,IE,Firefox上)。此外,最终面临此问题的用户可以使用相同的浏览器成功付款,无需任何设置调整。这让我觉得我的服务器环境可能存在一些问题,而不是客户端。
这是我的完整javascript:
subscription.js
var stripeResponseHandler = function(status, response) {
var $form = $('#paid_subscription');
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
$('#stripe_card_token').val(token);
//$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and submit
$form.get(0).submit();
}
};
jQuery(function($) {
$('#card_number').payment('formatCardNumber')
$('#paid_subscription').submit(function(event) {
// var expiration = $("#card-expiry").payment("cardExpiryVal")
// $('#card-exp-month').val(expiration.month);
// $('#card-exp-year').val(expiration.year);
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;
});
});
以下是控制器代码,以防万一:
电荷#创建
def create
token = params[:stripeToken]
bundle = Bundle.find_by_id(params[:bundle_id])
if bundle
process_bundle_sale(bundle, token)
else
plan = Plan.find(params[:plan_id])
begin
sale = current_user.sales.create(
plan_id: plan.id,
amount: plan.price_in_cents,
stripe_token: params[:stripeToken]
)
sale.process!
if sale.finished?
if current_user.subscribe_with_referer({plan_id: plan.id}, session[:http_referer])
TrackSubscriptions.track_paid_subscription(cookies, plan, sale)
flash[:success] = "Success! You now have full access to \"#{plan.title}\""
redirect_to plan_path(plan)
else
flash[:alert] = "Oops something went wrong. Please contact support and we'll get to the bottom of it."
redirect_to plan_path(plan)
end
else
flash[:alert] = sale.error
redirect_to new_plan_subscription_path(plan.slug)
#redirect_to plan_path(plan)
end
end
end
end
最后这是表格代码:
<%= simple_form_for @charge = Sale.new, :url => charges_path, :method => :post, html: { id: :paid_subscription } do |f| %>
<fieldset class = "inputWrapper">
<h2 class="sub-header">Payment</h2>
<span class="payment-errors"></span>
<%= hidden_field_tag :plan_id, @plan.id %>
<%= hidden_field_tag :stripeToken, nil,id: :stripe_card_token %>
<div class="payment-fields">
<div class="field card-number-field">
<label class="control-label">Card Number</label>
<%= text_field_tag :card_number, nil, name: nil, placeholder: "4444 1234 1234 1234",:data => {:stripe => 'number' } %>
</div>
<div class="field security-code-field">
<label class="control-label">Security Code</label>
<%= text_field_tag :card_code, nil, name: nil, placeholder: "123", :data => {:stripe => 'cvc' } %>
</div>
<div class="field expiry-field">
<label class="control-label">Exp (MM/YYYY)</label>
<div class="month-field">
<%= text_field_tag :exp_month, nil, name: nil, placeholder: "10", id: "card-exp-month", maxlength: 2, data: { stripe: "exp-month" } %>
<span class="slash"> / </span>
</div>
<div class="year-field">
<%= text_field_tag :exp_year, nil, name: nil, placeholder: "2016", id: "card-exp-year", maxlength: 4, data: { stripe: "exp-year" } %>
</div>
</div>
<div style="clear:both"></div>
</div>
<%= render 'end_form', :plan => @plan %>
<div class="submit-button">
<%= f.submit 'Register for Course', :class => "button greenButton", :error => false %>
</div>
</fieldset>
<% end %>