我正在关注Rails演员以实现订阅结算。就在这里:
http://railscasts.com/episodes/288-billing-with-stripe
我的代码几乎完全相同,但我将一些额外的字段传递给Stripe。问题是,javascript中的错误消息总是在提交按钮被点击时显示错误消息...即使成功收费。我不确定Strip是否会返回触发错误的内容,或者是否存在JS问题。
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
subscription.setupForm()
subscription =
setupForm: ->
$('#new_membership').submit ->
$('input[type=submit]').attr('disabled', true)
if $('#card_number').length
subscription.processCard()
false
else
true
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
$('#membership_stripe_card_token').val(response.id)
$('#new_membership')[0].submit()
else
$('#stripe_error').text(response.error.message)
$('input[type=submit]').attr('disabled', false)
这是用于错误处理的示例条带。他们首先翻转过程并测试错误:
function stripeResponseHandler(status, response) {
if (response.error) {
...
//show the errors on the form
$(".payment-errors").html(response.error.message);
} else {
var form$ = $("#payment-form");
// token contains id, last4, and card type
var token = response['id'];
// insert the token into the form so it gets submitted to the server
form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
// and submit
form$.get(0).submit();
}
}
更新:所以我可以告诉你发生了什么,但不知道为什么或如何修复它。
我添加了一个控制台日志语句,现在可以看到handleStripeResponse
被调用两次,一次当用户点击提交时,它返回一个200
,然后它再次出现(可能是因为表单然后必须发布到Rails应用程序进行实际处理?它返回一个0
,它会启动错误消息。但是 - 因为Rails现在处理处理服务器端,所以费用会通过。
这是编译后的JS,如果有帮助:
(function() {
var subscription;
jQuery(function() {
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'));
return subscription.setupForm();
});
subscription = {
setupForm: function() {
return $('#new_membership').submit(function() {
$('input[type=submit]').attr('disabled', true);
if ($('#card_number').length) {
subscription.processCard();
return false;
} else {
return true;
}
});
},
processCard: function() {
var card;
card = {
number: $('#card_number').val(),
cvc: $('#card_code').val(),
expMonth: $('#card_month').val(),
expYear: $('#card_year').val()
};
return Stripe.createToken(card, subscription.handleStripeResponse);
},
handleStripeResponse: function(status, response) {
if (status === 200) {
$('#membership_stripe_card_token').val(response.id);
return $('#new_membership')[0].submit();
} else {
$('#stripe_error').text(response.error.message);
return $('input[type=submit]').attr('disabled', false);
}
}
};
}).call(this);
答案 0 :(得分:5)
我遇到了同样的问题。我不知不觉地两次调用javascript。
一次(明确地)在页面上:
= javascript_include_tag 'stripe'
然后(无意中)在application.js
中//= require_tree .
结果是jQuery文档就绪函数被调用两次,导致所有侦听器被设置两次。
根据您的应用程序设置方式,您应该删除一个或另一个包含。对于我的应用程序,最好从我的application.js中删除该行。
棘手的资产管道!
答案 1 :(得分:1)
有同样的问题。简单地拿了jQuery - &gt;在存储条带代码的coffeescript文件的顶部之外,并且双提交已停止。得到了Nathan Colgate上面的提示。
答案 2 :(得分:0)
所以,到目前为止我的hacky解决方案是这样做的,因为第二次通过回调它一直返回0。
else if status == 0
$('#stripe_error').text('Processing...')
至少这样,用户不会收到错误消息,并且不会重新激活提交按钮。
答案 3 :(得分:0)
我遇到了同样的问题。仍然不确定是什么导致它。我找到的解决方案是为coffeescript添加不同的验证:
subscription =
setupForm: ->
$('#new_subscription').submit ->
$('input[type=submit]').attr('disabled', true)
if $('#subscription_stripe_card_token').val
true
else
subscription.processCard()
false
请注意,对于'if'语句,而不是检查:
if $('#card_number').length
而是我检查了一下:
if $('#subscription_stripe_card_token').val
这样,当表单第一次提交时,它会成功返回'stripe_card_token'的值,因此它不会再次提交表单。我还不知道为什么使用railscast中的card_number.length方法无效。我认为@subscription对象可能有问题,因为它没有识别它现在有一个stripe_card_token值,因此没有删除card_number字段......但我不知道
<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<% if @subscription.stripe_card_token %>
Credit card has been provided
<% else %>
<div class="field">
<%= label_tag :card_number, "Credit Card Number " %>
<%= text_field_tag :card_number, nil, name: nil %>
希望这有助于在这里找到最终答案!
答案 4 :(得分:0)
对于阅读此内容的人:如果您遇到类似问题,我建议您查看&#34;查看页面来源&#34;或者相当于看看是否包含了两次javascripts。
我正在关注相同的Railscast并遇到同样的问题。我花了很长时间才愿意承认这一点,但我的问题是在困倦的时候复制粘贴了一行来自轨道广播的笔记。原因是应用程序javascripts被包含两次,一次是自动生成的rails包含在application.html.erb中:
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
并第二次复制粘贴来自railscast的线条:
<%= javascript_include_tag "https://js.stripe.com/v1/", "application" %>
因此包括&#34;申请&#34;两次。我只是通过移除其中一个来解决它。
答案 5 :(得分:0)
所以今天在工作中我们遇到了类似的问题:
Stripe希望通过与Stripe自己的域进行Ajax处理来首先提交表单,然后返回结果时,它希望使用其响应数据填充表单中的某些隐藏字段。发生这种情况后,Stripe希望我们像往常一样提交表单。
对于我们来说,存在一个冲突,即Rails和Stripe都对表单提交做出了反应,并且没有进行协调。由于我们无法轻松更改jquery-ujs.js,因此我们研究了它们如何编码其全局表单“提交”事件处理程序。
事实证明,一个Rails对象作为jQuery插件公开,其中有一个防止jquery-ujs.js处理程序处理任何事件的功能-整洁!
所以对我们来说,解决方法是致电...
$.rails.stopEverything(event);
...在Stripe提交事件处理程序内(这是我们项目的特殊情况)
以下是Stripe事件处理程序的代码,用于其他上下文:
// Create a token or display an error when the form is submitted.
var form = document.getElementById('payment-form');
form.addEventListener('submit', function (event)
{
$.rails.stopEverything(event); // Dont let Rails' global form submit handler handle this event (in jquery-ujs.js)
event.preventDefault();
stripe.createToken(card).then(function(result)
{
if (result.error)
{
// Inform the user if there was an error
var errorElement = document.getElementById('card-errors');
errorElement.textContent = result.error.message;
$('#stripe-btn').prop('disabled', false)
$('.fa-spin').remove()
}
else
{
// Send the token to your server
stripeTokenHandler(result.token);
}
});
});