Stripe/JavaScript:如何获取已创建的Payment Element对象
解决Stripe Elements跨方法访问问题
核心问题原因
MountStripeElement里的stripe和elements都是函数内部的局部变量,CreateStripeSubscription无法直接访问,导致调用时出现elements未定义的错误。
可行解决方案
方案1:将实例提升到共享作用域
把stripe和elements变量声明在两个函数的外部(模块级作用域),让两个方法共享同一个实例:
// 模块级共享变量 let stripe; let elements; export function MountStripeElement() { stripe = Stripe("pk_test..."); const options = { mode: 'subscription', amount: 1099, currency: 'usd', appearance: {/*...*/ }, }; elements = stripe.elements(options); const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element'); } export async function CreateStripeSubscription(event) { event.preventDefault(); const submitBtn = document.getElementById('submit'); const handleError = (error) => { const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; submitBtn.disabled = false; } submitBtn.disabled = true; // 直接使用共享的elements实例 const { error: submitError } = await elements.submit(); if (submitError) { handleError(submitError); return; } const paymentElement = elements.getElement('payment'); const { error } = await stripe.confirmPayment({ paymentElement, clientSecret, confirmParams: { return_url: 'https://www.google.co.uk/', }, }); if (error) { handleError(error); } else { // 处理成功逻辑 } }
方案2:使用闭包封装(更模块化)
把两个方法封装在同一个闭包内,确保stripe和elements在闭包内部共享,避免污染全局作用域:
const StripeSubscriptionModule = (() => { let stripe; let elements; function mount() { stripe = Stripe("pk_test..."); const options = { mode: 'subscription', amount: 1099, currency: 'usd', appearance: {/*...*/ }, }; elements = stripe.elements(options); const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element'); } async function create(event) { event.preventDefault(); const submitBtn = document.getElementById('submit'); const handleError = (error) => { const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; submitBtn.disabled = false; } submitBtn.disabled = true; const { error: submitError } = await elements.submit(); if (submitError) { handleError(submitError); return; } const paymentElement = elements.getElement('payment'); const { error } = await stripe.confirmPayment({ paymentElement, clientSecret, confirmParams: { return_url: 'https://www.google.co.uk/', }, }); if (error) { handleError(error); } else { // 处理成功逻辑 } } return { MountStripeElement: mount, CreateStripeSubscription: create }; })(); export const { MountStripeElement, CreateStripeSubscription } = StripeSubscriptionModule;
方案3:DOM节点绑定实例(应急方案)
把elements实例挂载到已挂载的Payment Element的DOM节点上,后续通过DOM获取(不推荐长期使用,可能引发DOM属性冲突):
export function MountStripeElement() { const stripe = Stripe("pk_test..."); const options = { mode: 'subscription', amount: 1099, currency: 'usd', appearance: {/*...*/ }, }; const elements = stripe.elements(options); const paymentElement = elements.create('payment'); paymentElement.mount('#payment-element'); // 将elements实例绑定到DOM节点的自定义属性 document.getElementById('payment-element')._stripeElements = elements; } export async function CreateStripeSubscription(event) { event.preventDefault(); const submitBtn = document.getElementById('submit'); const stripe = Stripe("pk_test..."); const handleError = (error) => { const messageContainer = document.querySelector('#error-message'); messageContainer.textContent = error.message; submitBtn.disabled = false; } submitBtn.disabled = true; // 从DOM节点获取elements实例 const elements = document.getElementById('payment-element')._stripeElements; if (!elements) { handleError(new Error('Stripe Elements未初始化')); return; } const { error: submitError } = await elements.submit(); if (submitError) { handleError(submitError); return; } const paymentElement = elements.getElement('payment'); const { error } = await stripe.confirmPayment({ paymentElement, clientSecret, confirmParams: { return_url: 'https://www.google.co.uk/', }, }); if (error) { handleError(error); } else { // 处理成功逻辑 } }
关键注意事项
- 不要重复初始化
Stripe实例,多次调用Stripe("pk_test...")会创建独立实例,无法关联已创建的Elements。 - 优先选择方案1或方案2,这两种方式更符合模块化规范,代码可维护性更高。
内容的提问来源于stack exchange,提问作者JsonStatham
相关产品推荐
相关产品推荐

