javascript - Stripe Payment Element 加载时间慢

标签 javascript php ajax laravel stripe-payments

我有一个结帐页面,主要包含新的 Stripe Payment Element和一个 PayPal 支付按钮(来自 Standard Checkout 集成)。按钮加载速度足够快,但通过 XAMPP 在本地加载时,支付元素的信用卡表单需要超过 5 秒,我想如果 Google Pay 和 Apple Pay 按钮在测试模式下呈现,这同样适用于它们。我希望开发环境中的这种速度在快速连接上转化为至少 2-3 秒的生产环境,这仍然非常慢。

假设这种加载速度对于 Stripe Payment Element 来说是正常的,我是否可以使用任何策略来使其加载速度更快?

无论如何,我想至少通过添加一个微调器/预加载器来加快感知的加载速度,该微调器/预加载器在加载表单之前一直显示,这也可以最大程度地减少不和谐content jump当前在加载表单时发生(老实说,我很惊讶 Stripe 一开始就适合这个 UX)。我如何将这样的微调器集成到 Stripe 的客户端代码中?

这是 checkout.js 中有问题的客户端代码,仅从 Stripe 的 Quickstart guide 中略微改编而来:

const stripe = Stripe(<PK_TEST_KEY>);

const fonts = [
    {
        cssSrc:
            "https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap",
    },
];

const appearance = {
    theme: "stripe",
    labels: "floating",
    variables: {
        colorPrimary: "#000",
        colorPrimaryText: "#fff",
        colorText: "#fff",
        fontFamily: "Open Sans, Segoe UI, sans-serif",
        borderRadius: "4px",
        fontSizeBase: "1em",
        fontSizeXs: "0.7em",
        fontWeightNormal: "400",
        fontWeightMedium: "400",
        fontWeightLight: "400",
    },
};
   
let elements;

initialize();
checkStatus();

document
    .querySelector("#payment-form")
    .addEventListener("submit", handleSubmit);

// Fetches a payment intent and captures the client secret
async function initialize() {
    const { clientSecret } = await fetch("/payment/stripe", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
            "X-CSRF-TOKEN": document.querySelector('input[name="_token"]').value,
        },
    }).then((r) => r.json());

    elements = stripe.elements({ fonts, appearance, clientSecret });

    const paymentElement = elements.create("payment");
    paymentElement.mount("#payment-element");
}

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

    const { error } = await stripe.confirmPayment({
        elements,
        confirmParams: {
            // Make sure to change this to your payment completion page
            return_url: "http://localhost/success",
        },
    });

    // This point will only be reached if there is an immediate error when
    // confirming the payment. Otherwise, your customer will be redirected to
    // your `return_url`. For some payment methods like iDEAL, your customer will
    // be redirected to an intermediate site first to authorize the payment, then
    // redirected to the `return_url`.
    if (error.type === "card_error" || error.type === "validation_error") {
        showMessage(error.message);
    } else {
        showMessage("An unexpected error occured.");
    }

    setLoading(false);
}

// Fetches the payment intent status after payment submission
async function checkStatus() {
    const clientSecret = new URLSearchParams(window.location.search).get(
        "payment_intent_client_secret"
    );

    if (!clientSecret) {
        return;
    }

    const { paymentIntent } = await stripe.retrievePaymentIntent(clientSecret);

    switch (paymentIntent.status) {
        case "succeeded":
            showMessage("Payment succeeded!");
            break;
        case "processing":
            showMessage("Your payment is processing.");
            break;
        case "requires_payment_method":
            showMessage("Your payment was not successful, please try again.");
            break;
        default:
            showMessage("Something went wrong.");
            break;
    }
}

// ------- UI helpers -------

function showMessage(messageText) {
    const messageContainer = document.querySelector("#payment-message");

    messageContainer.classList.remove("hidden");
    messageContainer.textContent = messageText;

    setTimeout(function () {
        messageContainer.classList.add("hidden");
        messageText.textContent = "";
    }, 10000);
}

// Show a spinner on payment submission
function setLoading(isLoading) {
    if (isLoading) {
        // Disable the button and show a spinner
        document.querySelector("#submit").disabled = true;
        document.querySelector("#spinner").classList.remove("hidden");
        document.querySelector("#button-text").classList.add("hidden");
    } else {
        document.querySelector("#submit").disabled = false;
        document.querySelector("#spinner").classList.add("hidden");
        document.querySelector("#button-text").classList.remove("hidden");
    }
}

最佳答案

实现加载微调器的主要方法是在 initialize() 函数开始时启动一个加载微调器的动画,然后监听 PaymentElement 的“就绪”事件以确定何时隐藏

Stripe 的示例代码有一个用于提交按钮的微调器,但不幸的是,当应用于其他 DOM 元素时它并没有真正起作用,因此您必须滚动自己的微调器而不是直接重新使用它。但这就是想法!

https://stripe.com/docs/js/element/events/on_ready

async function initialize() {
  loaderOn(); // start showing a spinner and maybe apply `hidden` to the payment-element div
  const response = await fetch("/create-payment-intent", {
  ...
  ...

  const paymentElement = elements.create("payment");
  paymentElement.on("ready", function(){
    loaderOff(); // hide the spinner and maybe remove `hidden` from the payment-element div
  })
  paymentElement.mount("#payment-element"); 

关于javascript - Stripe Payment Element 加载时间慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71324848/

相关文章:

javascript - 如果绑定(bind)在 KnockoutJS 中不起作用,则为无容器

php - RecursiveFilterIterator 在 RecursiveIteratorIterator 中重新实例化?

javascript - 页面上有多个视频需要自动播放单击的按钮之一

php - 在安全 API 通信中使用请求签名时防止重放攻击?

javascript - JSF Richfaces 自动完成问题 - 使用..anything 发送隐藏参数

php - HTML 站点的复制安全性

javascript - Set.has() 方法 O(1) 和 Array.indexOf O(n) 是吗?

javascript - 结合 JSON 和 GCAL 的 jQuery FullCalendar

javascript - 使用链接防止默认选择输入行为

javascript - 使用外部 URL 中的变量填充文本框,无需提交表单