如何基于 ajax 成功为 Stripe 令牌创建条件
How to create conditional for Stripe token based on ajax success
我正在使用 Stripe JS 和 Flask 在同一页面上创建和处理付款表单和优惠券表单。在提交付款表格之前,可选择通过 ajax 提交优惠券表格。如果优惠券提交成功,我想删除付款表格的付款部分,并提交不带 Stripe 的表格(因为我还有其他数据要收集和处理服务器端)。
我的优惠券代码表格如我所愿,我可以有条件地更改 DOM 以删除付款表格。但这会引发错误,因为 Stripe 已经在页面加载时创建了令牌。
但是我对 JS 的操作顺序感到困惑。如有任何帮助,我们将不胜感激!
我的 JS:
<script type="text/javascript">
Stripe.setPublishableKey('some_test_id');
var couponApplied;
var stripeResponseHandler = function(status, response) {
var $form = $('#purchase_form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('input').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
$form.append($('<input type="hidden" name="stripeToken">').val(token));
// and re-submit
$form.get(0).submit();
}
};
$(document).ready(function() {
$('#purchase_form').submit(function(e) {
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;
});
});
var csrftoken = $('meta[name=csrf-token]').attr('content');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
});
$('form#couponcode_form').submit(function() {
var code = $('input#coupon_code').val();
$.ajax({
data: JSON.stringify({
code: code
}),
url: '/code_validate',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function(json) {
console.log(json);
$(".ajax_response").text(json.response);
$(".code_redemption").text(json.price);
if (json.code_applied === true) {
var couponApplied = true;
$("#payment").remove();
} else {
var couponApplied = false;
}
console.log('Test coupon: ' + couponApplied);
},
error: function(request, errorType, errorMessage) {
console.log(errorType + ": " + errorMessage);
}
});
return false;
});
</script>
还有我 HTML 处理表格的一部分:
<form method='POST' action='/code_validate' id="couponcode_form">
{{ couponcode_form.csrf_token }}
{{ couponcode_form.coupon_code.label }} {{ couponcode_form.coupon_code(size=20) }}
{{ couponcode_form.submit }}
</form>
<form action="/buy" method="POST" id="purchase_form">
{{ form.csrf_token }}
{{ form.coupon_used }}
<div class="form_step">
<h2>1. Your Friend's Name</h2>
</div>
<div class="field_grouper" id="recipient">
<div class="form-group{% if form.recipient_name.errors %} has-error{% endif %}">
{{ form.recipient_name.label }}
{{ form.recipient_name(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.recipient_name.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.recipient_email.errors %} has-error{% endif %}">
{{ form.recipient_email.label }}
{{ form.recipient_email(class_='form-control', maxlength='100') }}
<span class="help_text">{{ form.recipient_email.description|safe }}</span>
</div>
</div>
<div class="form_step">
<h2>2. Your Friend's Address</h2>
</div>
<div class="field_grouper" id="recipient_address">
<div class="form-group{% if form.shipping_street_address_1.errors %} has-error{% endif %}">
{{ form.shipping_street_address_1.label }}
{{ form.shipping_street_address_1(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_street_address_1.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_street_address_2.errors %} has-error{% endif %}">
{{ form.shipping_street_address_2.label }}
{{ form.shipping_street_address_2(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_street_address_2.description|safe }}</span>
</div>
<div class="form-group{% if form.shipping_city.errors %} has-error{% endif %}">
{{ form.shipping_city.label }}
{{ form.shipping_city(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_city.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_state.errors %} has-error{% endif %}">
{{ form.shipping_state.label }}
{{ form.shipping_state(class_='form-control', maxlength='2') }}
<span class="help_text">{{ form.shipping_state.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_zip.errors %} has-error{% endif %}">
{{ form.shipping_zip.label }}
{{ form.shipping_zip(class_='form-control', maxlength='9') }}
<span class="help_text">{{ form.shipping_zip.description|safe }}</span> <span class="required">*</span>
</div>
</div>
<div class="form_step">
<h2>3. Add your message</h2>
</div>
{% block prefilled_messages %}
{% endblock %}
<div class="field_grouper" id="message">
<h3>Personalized Message:</h3>
<div class="form-group{% if form.personal_message.errors %} has-error{% endif %}">
{{ form.personal_message.label }}
{{ form.personal_message(class_='form-control', rows='10') }}
<span class="help_text">{{ form.personal_message.description|safe }}. You have <b><span id="charsleft"></span></b> characters left.</span><span class="required">*</span>
</div>
</div>
<div class="field_grouper" id="purchaser">
<h3>From:</h3>
<div class="form-group{% if form.purchaser_name.errors %} has-error{% endif %}">
{{ form.purchaser_name.label }}
{{ form.purchaser_name(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.purchaser_name.description|safe }}</span>
</div>
<div class="form-group{% if form.purchaser_email.errors %} has-error{% endif %}">
{{ form.purchaser_email.label }}
{{ form.purchaser_email(class_='form-control', maxLength='100') }}
<span class="help_text">{{ form.purchaser_email.description|safe }}</span> <span class="required">*</span>
</div>
</div>
<div class="form_step">
<h2>4. Pay</h2>
</div>
<span class="code_redemption"></span>
<div class="field_grouper" id="payment">
<span class="payment-errors"></span>
<h3>Credit card:</h3>
<div class="form-group">
<input type="text" size="20" data-stripe="number">
<span class="help_text">Card number</span> <span class="required">*</span>
</div>
<div class="form-group">
<input type="text" size="4" data-stripe="cvc">
<span class="help_text">CVC</span> <span class="required">*</span>
</div>
<div class="form-group">
<input type="text" size="2" data-stripe="exp-month">
<span> / </span>
<input type="text" size="4" data-stripe="exp-year">
<span class="help_text">Expiration month and year (MM/YYYY)</span> <span class="required">*</span>
</div>
</div>
<div class="field_grouper" id="submit">
<button type="submit">Submit Payment</button>
</div>
</form>
如果我正确理解流程,您应该能够将变量声明 couponApplied
移动到两个表单提交处理程序都可以访问的范围级别。
然后在购买提交处理程序中,如果 couponApplied
为真,您可以绕过 Stripe API,让表单提交而不是从提交处理程序返回 false。
$(document).ready(function () {
// declare variable with default false
var couponApplied = false;
$('#purchase_form').submit(function (e) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
if (!couponApplied) {
// only use stripe if no coupon
Stripe.card.createToken($form, stripeResponseHandler);
}
// return true/false by variable will determine if browser submit occurs
return couponApplied;
});
$('form#couponcode_form').submit(function () {
var code = $('input#coupon_code').val();
$.ajax({
//some options not shown for clarity
success: function (json) {
// don't use "var" here
couponApplied = json.code_applied;
/* other code */
}
});
});
});
我正在使用 Stripe JS 和 Flask 在同一页面上创建和处理付款表单和优惠券表单。在提交付款表格之前,可选择通过 ajax 提交优惠券表格。如果优惠券提交成功,我想删除付款表格的付款部分,并提交不带 Stripe 的表格(因为我还有其他数据要收集和处理服务器端)。
我的优惠券代码表格如我所愿,我可以有条件地更改 DOM 以删除付款表格。但这会引发错误,因为 Stripe 已经在页面加载时创建了令牌。
但是我对 JS 的操作顺序感到困惑。如有任何帮助,我们将不胜感激!
我的 JS:
<script type="text/javascript">
Stripe.setPublishableKey('some_test_id');
var couponApplied;
var stripeResponseHandler = function(status, response) {
var $form = $('#purchase_form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('input').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
$form.append($('<input type="hidden" name="stripeToken">').val(token));
// and re-submit
$form.get(0).submit();
}
};
$(document).ready(function() {
$('#purchase_form').submit(function(e) {
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;
});
});
var csrftoken = $('meta[name=csrf-token]').attr('content');
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken)
}
}
});
$('form#couponcode_form').submit(function() {
var code = $('input#coupon_code').val();
$.ajax({
data: JSON.stringify({
code: code
}),
url: '/code_validate',
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function(json) {
console.log(json);
$(".ajax_response").text(json.response);
$(".code_redemption").text(json.price);
if (json.code_applied === true) {
var couponApplied = true;
$("#payment").remove();
} else {
var couponApplied = false;
}
console.log('Test coupon: ' + couponApplied);
},
error: function(request, errorType, errorMessage) {
console.log(errorType + ": " + errorMessage);
}
});
return false;
});
</script>
还有我 HTML 处理表格的一部分:
<form method='POST' action='/code_validate' id="couponcode_form">
{{ couponcode_form.csrf_token }}
{{ couponcode_form.coupon_code.label }} {{ couponcode_form.coupon_code(size=20) }}
{{ couponcode_form.submit }}
</form>
<form action="/buy" method="POST" id="purchase_form">
{{ form.csrf_token }}
{{ form.coupon_used }}
<div class="form_step">
<h2>1. Your Friend's Name</h2>
</div>
<div class="field_grouper" id="recipient">
<div class="form-group{% if form.recipient_name.errors %} has-error{% endif %}">
{{ form.recipient_name.label }}
{{ form.recipient_name(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.recipient_name.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.recipient_email.errors %} has-error{% endif %}">
{{ form.recipient_email.label }}
{{ form.recipient_email(class_='form-control', maxlength='100') }}
<span class="help_text">{{ form.recipient_email.description|safe }}</span>
</div>
</div>
<div class="form_step">
<h2>2. Your Friend's Address</h2>
</div>
<div class="field_grouper" id="recipient_address">
<div class="form-group{% if form.shipping_street_address_1.errors %} has-error{% endif %}">
{{ form.shipping_street_address_1.label }}
{{ form.shipping_street_address_1(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_street_address_1.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_street_address_2.errors %} has-error{% endif %}">
{{ form.shipping_street_address_2.label }}
{{ form.shipping_street_address_2(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_street_address_2.description|safe }}</span>
</div>
<div class="form-group{% if form.shipping_city.errors %} has-error{% endif %}">
{{ form.shipping_city.label }}
{{ form.shipping_city(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.shipping_city.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_state.errors %} has-error{% endif %}">
{{ form.shipping_state.label }}
{{ form.shipping_state(class_='form-control', maxlength='2') }}
<span class="help_text">{{ form.shipping_state.description|safe }}</span> <span class="required">*</span>
</div>
<div class="form-group{% if form.shipping_zip.errors %} has-error{% endif %}">
{{ form.shipping_zip.label }}
{{ form.shipping_zip(class_='form-control', maxlength='9') }}
<span class="help_text">{{ form.shipping_zip.description|safe }}</span> <span class="required">*</span>
</div>
</div>
<div class="form_step">
<h2>3. Add your message</h2>
</div>
{% block prefilled_messages %}
{% endblock %}
<div class="field_grouper" id="message">
<h3>Personalized Message:</h3>
<div class="form-group{% if form.personal_message.errors %} has-error{% endif %}">
{{ form.personal_message.label }}
{{ form.personal_message(class_='form-control', rows='10') }}
<span class="help_text">{{ form.personal_message.description|safe }}. You have <b><span id="charsleft"></span></b> characters left.</span><span class="required">*</span>
</div>
</div>
<div class="field_grouper" id="purchaser">
<h3>From:</h3>
<div class="form-group{% if form.purchaser_name.errors %} has-error{% endif %}">
{{ form.purchaser_name.label }}
{{ form.purchaser_name(class_='form-control', maxlength='250') }}
<span class="help_text">{{ form.purchaser_name.description|safe }}</span>
</div>
<div class="form-group{% if form.purchaser_email.errors %} has-error{% endif %}">
{{ form.purchaser_email.label }}
{{ form.purchaser_email(class_='form-control', maxLength='100') }}
<span class="help_text">{{ form.purchaser_email.description|safe }}</span> <span class="required">*</span>
</div>
</div>
<div class="form_step">
<h2>4. Pay</h2>
</div>
<span class="code_redemption"></span>
<div class="field_grouper" id="payment">
<span class="payment-errors"></span>
<h3>Credit card:</h3>
<div class="form-group">
<input type="text" size="20" data-stripe="number">
<span class="help_text">Card number</span> <span class="required">*</span>
</div>
<div class="form-group">
<input type="text" size="4" data-stripe="cvc">
<span class="help_text">CVC</span> <span class="required">*</span>
</div>
<div class="form-group">
<input type="text" size="2" data-stripe="exp-month">
<span> / </span>
<input type="text" size="4" data-stripe="exp-year">
<span class="help_text">Expiration month and year (MM/YYYY)</span> <span class="required">*</span>
</div>
</div>
<div class="field_grouper" id="submit">
<button type="submit">Submit Payment</button>
</div>
</form>
如果我正确理解流程,您应该能够将变量声明 couponApplied
移动到两个表单提交处理程序都可以访问的范围级别。
然后在购买提交处理程序中,如果 couponApplied
为真,您可以绕过 Stripe API,让表单提交而不是从提交处理程序返回 false。
$(document).ready(function () {
// declare variable with default false
var couponApplied = false;
$('#purchase_form').submit(function (e) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
if (!couponApplied) {
// only use stripe if no coupon
Stripe.card.createToken($form, stripeResponseHandler);
}
// return true/false by variable will determine if browser submit occurs
return couponApplied;
});
$('form#couponcode_form').submit(function () {
var code = $('input#coupon_code').val();
$.ajax({
//some options not shown for clarity
success: function (json) {
// don't use "var" here
couponApplied = json.code_applied;
/* other code */
}
});
});
});