防止 Stripe confirmPayment 在自定义输入字段无效时进行重定向。

huangapple go评论149阅读模式
英文:

Prevent Stripe confirmPayment from redirecting when custom input field is invalid

问题

我在同一结账页面上使用了自定义字段来填写姓名和电子邮件,与Stripe的支付元素一起。我已将这些字段与支付元素的表单关联,使用了form属性:

<input type="text" form="payment-form" id="name" ... required>
<input type="email" form="payment-form" id="email" ... required>

我在表单上设置了novalidate以禁用默认浏览器验证,并启用Bootstrap自己的验证:

<div class="stripe-container">
    <form id="payment-form" novalidate>
    {{csrf_field()}}
    <div id="payment-element">
    <!-- Stripe.js injects the Payment Element here-->
    </div>
    <div class="loading-spinner"></div>
    <button id="submit">
    <div class="spinner hidden" id="spinner"></div>
    <span id="button-text">Pay now</span>
    </button>
    <div id="payment-message" class="hidden"></div>
    </form>
</div>

并修改了支付元素的JS以在单击“Pay now”时触发验证:

async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);

    // Added JS to trigger Bootstrap validation for custom fields
    paymentInputs = document.querySelectorAll(".payment-input");
    Array.prototype.slice.call(paymentInputs).forEach(function (paymentInput) {
        paymentInput.classList.remove("is-invalid");
        if (!paymentInput.checkValidity()) {
            paymentInput.classList.add("is-invalid");
            setLoading(false);
        }
    });

    const { error } = await stripe.confirmPayment({
        elements,
        confirmParams: {
            return_url: process.env.MIX_APP_URL + "/success",
        },
    });

    // ...
}

所有这些都完美地用于显示我的自定义字段的验证错误,甚至在Stripe字段之一未通过验证时阻止提交。问题是,当所有Stripe字段都有效时,单击付款按钮会触发我的自定义字段的验证失败,如预期的那样,但几秒钟后会简单地重定向到return_url,这可能是因为confirmPayment成功解决。

如何防止confirmPayment在我的自定义字段验证失败时解决?我确定这与异步函数和Promise的工作方式有关,但我对它们不够熟悉,不知道该怎么做。

英文:

I have custom fields for name and email on the same checkout page as Stripe's Payment Element. I've linked these fields to the form for the Payment Element using the form attribute:

&lt;input type=&quot;text&quot; form=&quot;payment-form&quot; id=&quot;name&quot; ... required&gt;
&lt;input type=&quot;email&quot; form=&quot;payment-form&quot; id=&quot;email&quot; ... required&gt;

I set novalidate on the form to disable default browser validation and enable Bootstrap's own validation:

        &lt;div class=&quot;stripe-container&quot;&gt;
        &lt;form id=&quot;payment-form&quot; novalidate&gt;
        {{csrf_field()}}
        &lt;div id=&quot;payment-element&quot;&gt;
        &lt;!-- Stripe.js injects the Payment Element here--&gt;
        &lt;/div&gt;
        &lt;div class=&quot;loading-spinner&quot;&gt;&lt;/div&gt;
        &lt;button id=&quot;submit&quot;&gt;
        &lt;div class=&quot;spinner hidden&quot; id=&quot;spinner&quot;&gt;&lt;/div&gt;
        &lt;span id=&quot;button-text&quot;&gt;Pay now&lt;/span&gt;
        &lt;/button&gt;
        &lt;div id=&quot;payment-message&quot; class=&quot;hidden&quot;&gt;&lt;/div&gt;
        &lt;/form&gt;
        &lt;/div&gt;

And modified the Payment Element's JS to trigger the validation when "Pay now" is clicked:

async function handleSubmit(e) {
    e.preventDefault();
    setLoading(true);

    // Added JS to trigger Bootstrap validation for custom fields
    paymentInputs = document.querySelectorAll(&quot;.payment-input&quot;);
    Array.prototype.slice.call(paymentInputs).forEach(function (paymentInput) {
        paymentInput.classList.remove(&quot;is-invalid&quot;);
        if (!paymentInput.checkValidity()) {
            paymentInput.classList.add(&quot;is-invalid&quot;);
            setLoading(false);
        }
    });

    const { error } = await stripe.confirmPayment({
        elements,
        confirmParams: {
            return_url: process.env.MIX_APP_URL + &quot;/success&quot;,
        },
    });

    ...

All this works perfectly to show validation errors for my custom fields, and even prevent the submit when one of the Stripe fields fails validation. The problem is when all of the Stripe fields are valid, clicking the payment button triggers the failed validation for my custom fields as expected, but a few seconds later simply redirects to the return_url, likely because of confirmPayment resolving successfully.

How do I prevent confirmPayment from resolving when my custom fields fail validation? I'm sure this has something to do with how asynchronous functions and Promises work, but I'm not familiar enough with them to know what.

答案1

得分: 2

你可以避免调用 stripe.confirmPayment 如果你的附加输入字段无效。

let isInvalid = false;
Array.prototype.slice.call(paymentInputs).forEach(function (paymentInput) {
    paymentInput.classList.remove("is-invalid");
    if (!paymentInput.checkValidity()) {
        paymentInput.classList.add("is-invalid");
        setLoading(false);
        isInvalid = true;
    }
});

if (isInvalid) {
  return;
} 

// Only gets here if other inputs are valid
const { error } = await stripe.confirmPayment({
    elements,
    confirmParams: {
        return_url: process.env.MIX_APP_URL + "/success",
    },
});
英文:

You can avoid calling stripe.confirmPayment if your additional input fields are invalid.

let isInvalid = false;
Array.prototype.slice.call(paymentInputs).forEach(function (paymentInput) {
    paymentInput.classList.remove(&quot;is-invalid&quot;);
    if (!paymentInput.checkValidity()) {
        paymentInput.classList.add(&quot;is-invalid&quot;);
        setLoading(false);
        isInvalid = true;
    }
});

if (isInvalid) {
  return;
} 

// Only gets here if other inputs are valid
const { error } = await stripe.confirmPayment({
    elements,
    confirmParams: {
        return_url: process.env.MIX_APP_URL + &quot;/success&quot;,
    },
});

huangapple
  • 本文由 发表于 2023年6月12日 23:46:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76458281.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定