PAYATHON 2026

如何在 Angular 中调用第三方 ClearentSDK 函数

支付老李

结论

ClearentSDK 查找的是全局作用域中的 ClearentOnPaymentTypeChange。Angular component 的成员方法属于组件实例,不会自动挂载到 window。

因此,调用 ClearentSDK.init() 前,需要把回调函数显式注册到 window:

window.ClearentOnPaymentTypeChange = (paymentType) => {
  console.log('Payment type was changed to ', paymentType);
};

推荐实现

先补充 window 的 TypeScript 类型声明:

declare global {
  interface Window {
    ClearentOnPaymentTypeChange?: (paymentType: string) => void;
  }
}

然后在组件初始化 ClearentSDK 时注册回调:

import { Component, NgZone, OnDestroy } from '@angular/core';

declare const ClearentSDK: {
  init(config: {
    baseUrl: string;
    pk: string;
    enableAch: boolean;
  }): void;
};

declare global {
  interface Window {
    ClearentOnPaymentTypeChange?: (paymentType: string) => void;
  }
}

@Component({
  selector: 'app-payment',
  templateUrl: './payment.component.html'
})
export class PaymentComponent implements OnDestroy {
  isLoadingResults = false;

  constructor(private readonly ngZone: NgZone) {}

  setClearentToken(): void {
    this.isLoadingResults = false;

    // 必须在 ClearentSDK.init() 之前注册。
    window.ClearentOnPaymentTypeChange = (paymentType: string): void => {
      this.ngZone.run(() => {
        console.log('Payment type was changed to ', paymentType);

        // 如果需要,可以在这里更新 Angular 组件状态。
        // this.selectedPaymentType = paymentType;
      });
    };

    ClearentSDK.init({
      baseUrl: 'https://gateway-sb.clearent.net',
      pk: 'Your Public Key',
      enableAch: true
    });
  }

  ngOnDestroy(): void {
    delete window.ClearentOnPaymentTypeChange;
  }
}

如果回调只输出日志,不一定要使用 NgZone.run()。如果还需要修改组件字段并立即更新页面,则可以用它确保 Angular 执行变更检测。

复用组件方法

如果想保留原来的 component 方法,可以通过全局回调调用它:

ClearentOnPaymentTypeChange(paymentType: string): void {
  console.log('Payment type was changed to ', paymentType);
}

setClearentToken(): void {
  this.isLoadingResults = false;

  window.ClearentOnPaymentTypeChange = (
    paymentType: string
  ): void => {
    this.ClearentOnPaymentTypeChange(paymentType);
  };

  ClearentSDK.init({
    baseUrl: 'https://gateway-sb.clearent.net',
    pk: 'Your Public Key',
    enableAch: true
  });
}

这里要使用箭头函数,因为它会保留当前组件实例的 this,避免第三方 SDK 调用回调时丢失组件上下文。

如果不想扩展 Window 接口,也可以使用类型断言:

(window as any).ClearentOnPaymentTypeChange = (
  paymentType: string
): void => {
  console.log('Payment type was changed to ', paymentType);
};

这种写法更简短,但无法对该回调进行类型检查。

为什么组件方法不会被调用

下面的代码:

ClearentOnPaymentTypeChange(paymentType: string): void {
  console.log('Payment type was changed to ', paymentType);
}

声明的是 Angular component 的实例方法,只能通过组件实例访问。概念上相当于:

componentInstance.ClearentOnPaymentTypeChange(paymentType);

按照示例代码所体现的调用方式,ClearentSDK 很可能会在全局作用域中查找并调用:

window.ClearentOnPaymentTypeChange(paymentType);

这两个函数的位置不同。仅在 component 类中声明同名方法,SDK 仍然找不到它。

注意事项

  • 先注册 window.ClearentOnPaymentTypeChange,再调用 ClearentSDK.init()。
  • 函数名称和大小写必须完全一致。
  • 执行 init() 前,应确认 ClearentSDK 脚本已经加载完成。
  • 如果同一页面存在多个支付组件,全局回调可能相互覆盖,需要统一管理回调的注册和销毁。
  • 组件销毁时删除回调,防止 SDK 后续调用已经失效的组件实例。
  • pk 通常表示供前端使用的 public key,但具体含义仍应以 Clearent 的密钥说明为准。不要把 secret key 或其他服务端凭据写入 Angular 前端代码。
  • 以上方案的前提是当前 ClearentSDK 版本仍使用文档示例中的全局命名回调。如果该版本支持通过 init() 配置直接传入事件回调,应优先使用 SDK 明确提供的配置 API。

备注:内容仅供参考。