You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular/TypeScript集成Stripe支付页面初始化及提交报错求助

Angular/TypeScript 信用卡保存页面Stripe集成错误解决

错误详情

1. 初始化阶段错误

Uncaught TypeError: Cannot read properties of undefined (reading 'queuedMessages')
at value (https://js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:452741)
at (https://js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:451881)
value @ js.stripe.com/v3/fingerprinted/js/controller-803e2f3ecfca23afd889cd24f93bdf22.js:1:452741

2. 提交阶段错误

ERROR IntegrationError: 请使用创建此Element时所用的同一Stripe实例来创建Source或Token。
at Ii (/Users/mysite/client:1:350323)
at e._handleMessage (/Users/mysite/client:1:355676)
at e._handleMessage (/Users/mysite/client:1:152157)
at /Users/mysite/client:1:353245
at _ZoneDelegate.invokeTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:406:1)
at Object.onInvokeTask (/Users/mysite/client/node_modules/@angular/core/fesm2015/core.mjs:25535:1)
at _ZoneDelegate.invokeTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:405:1)
at Zone.runTask (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:178:1)
at ZoneTask.invokeTask [as invoke] (/Users/mysite/client/node_modules/zone.js/fesm2015/zone.js:487:1)
at invokeTask (https://localhost:4200/polyfills.js:4776:18) {message: '请使用创建此Element时所用的同一Stripe实例来创建Source或Token。', name: 'IntegrationError', stack: 'IntegrationError: 请使用创建此Element时所用的同一Stripe实例来创建Source或Token。\n at Ii (...'}

问题分析

  1. 初始化错误:Stripe脚本未完全加载就执行初始化代码,或存在重复加载Stripe脚本的情况,导致全局对象状态异常。
  2. 提交错误:调用createToken时使用的Stripe实例与创建Card Element时的实例不一致。可能是组件重新渲染时重复创建实例,或变量作用域问题导致实例被覆盖。

代码还存在其他潜在问题:

  • 直接declare const Stripe: any缺乏类型支持,无法保证脚本加载时机
  • ngAfterViewInit中有多余的});语法错误
  • 事件监听函数未绑定组件上下文,导致this指向异常

解决方案

步骤1:规范Stripe依赖引入

使用官方@stripe/stripe-js包管理Stripe加载与实例化,确保脚本就绪后再初始化:

npm install @stripe/stripe-js

组件中导入并预加载Stripe:

import { loadStripe } from '@stripe/stripe-js';

// 组件类内定义
private stripePromise: Promise<Stripe | null>;

ngOnInit() {
  // 提前加载Stripe,避免初始化时脚本未就绪
  this.stripePromise = loadStripe('pk_test_fTrh6B1...');
}

步骤2:确保Stripe实例单例化

在ngAfterViewInit中等待Stripe加载完成后,仅初始化一次实例:

async ngAfterViewInit() {
  const style = {
    // 你的样式配置
  };

  this.stripe = await this.stripePromise;
  if (!this.stripe) return;

  this.stripeElements = this.stripe.elements();

  // 创建并挂载Card Number Element
  this.cardNumber = this.stripeElements.create('cardNumber', { style });
  this.cardNumber.mount(this.cardNumberElement.nativeElement);
  // 绑定组件上下文,避免this指向异常
  this.cardNumber.addEventListener('change', (event) => this.cardNumberHandler(event));

  // 创建并挂载Card Expiry Element
  this.cardExpiry = this.stripeElements.create('cardExpiry', { style });
  this.cardExpiry.mount(this.cardExpiryElement.nativeElement);
  this.cardExpiry.addEventListener('change', (event) => this.cardExpiryHandler(event));

  // 创建并挂载Card CVC Element
  this.cardCvc = this.stripeElements.create('cardCvc', { style });
  this.cardCvc.mount(this.cardCvcElement.nativeElement);
  this.cardCvc.addEventListener('change', (event) => this.cardCvcHandler(event));
}

步骤3:修正提交逻辑

确保createToken使用初始化时的同一Stripe实例:

submitCard() {
  if (!this.stripe || !this.cardNumber) return;

  this.loadingPayment = true;
  const cardData = { name: this.nameOnCard.value };

  from(this.stripe.createToken(this.cardNumber, cardData)).pipe(take(1)).subscribe((result: any) => {
    this.loadingPayment = false;
    if (result.error) {
      this.alertService.danger(result.error.message);
      return;
    }

    const allowedBrands = ['Visa', 'MasterCard', 'Discover', 'American Express'];
    if (allowedBrands.includes(result.token.card.brand)) {
      this.accountService.saveCard({ token: result.token.id }).subscribe({
        next: () => {
          this.router.navigate(['/account/cards']);
          this.alertService.success('卡片添加成功');
        },
        error: (err) => console.log(err)
      });
    } else {
      this.alertService.info('仅接受Visa、MasterCard、Discover或American Express卡');
    }
  });
}

步骤4:修正HTML模板拼写错误

将模板中Expirtion改为正确的Expiration:

<label for="floatingExpiration">Expiration</label>

关键注意事项

  • 组件生命周期内仅初始化一次Stripe实例,禁止重复创建
  • 调用createToken/createPaymentMethod时,必须使用创建Element的同一Stripe实例
  • 确保Stripe脚本加载完成后再执行初始化逻辑,避免因脚本未就绪导致的异常

内容的提问来源于stack exchange,提问作者chuckd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 13:40:43