Stripe Payment Element 加载时间慢
Slow loading time of Stripe Payment Element
我有一个结帐页面,主要包含新的 Stripe Payment Element 和一个 PayPal 支付按钮(来自标准结帐集成)。按钮加载速度足够快,但通过 XAMPP 在本地加载时,支付元素的信用卡表单需要超过 5 秒,我想这同样适用于 Google Pay 和 Apple Pay 按钮,如果它们呈现的话在测试模式。我希望开发环境中的这种速度在快速连接下转化为至少 2-3 秒的生产环境,这仍然很慢。
假设这种加载速度对于 Stripe Payment Element 来说是正常的,我可以使用任何策略来使其加载更快吗?
无论如何,我想至少通过添加一个 spinner/preloader 来加快 感知的 加载速度,直到加载表单为止,这将还可以最大限度地减少当前加载表单时出现的不和谐 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 元素时,它并没有真正起作用,因此您必须滚动自己的微调器而不是 [=19= 】 直接。但这就是想法!
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");
我有一个结帐页面,主要包含新的 Stripe Payment Element 和一个 PayPal 支付按钮(来自标准结帐集成)。按钮加载速度足够快,但通过 XAMPP 在本地加载时,支付元素的信用卡表单需要超过 5 秒,我想这同样适用于 Google Pay 和 Apple Pay 按钮,如果它们呈现的话在测试模式。我希望开发环境中的这种速度在快速连接下转化为至少 2-3 秒的生产环境,这仍然很慢。
假设这种加载速度对于 Stripe Payment Element 来说是正常的,我可以使用任何策略来使其加载更快吗?
无论如何,我想至少通过添加一个 spinner/preloader 来加快 感知的 加载速度,直到加载表单为止,这将还可以最大限度地减少当前加载表单时出现的不和谐 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 元素时,它并没有真正起作用,因此您必须滚动自己的微调器而不是 [=19= 】 直接。但这就是想法!
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");