如何在 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。
备注:内容仅供参考。
