PAYATHON 2026

支付 API tradePay 失败回调是否包含参数,TypeScript 如何定义?

支付小周

明确结论

tradePay 的 fail 回调在运行时可以接收失败结果对象。文档示例中的回调参数就是实际调用方式。如果 mini-types 将其声明为 fail?: () => void,通常是因为类型声明不完整、版本较旧,或遗漏了回调参数,并不表示运行时不会传参。

失败对象的字段应以当前平台文档和真机返回结果为准。常见字段可能有 error、errorMessage,但客户端版本、支付渠道和失败场景不同,返回结构也可能不同。未经确认的字段不要全部声明为必填。

推荐写法

可以在业务代码中定义一个本地类型,将不稳定的字段设为可选:

interface TradePayFailResult {
  error?: number | string;
  errorMessage?: string;
  [key: string]: unknown;
}

type TradePayFailCallback = (result: TradePayFailResult) => void;

调用时:

my.tradePay({
  tradeNO: 'your_trade_no',

  success(result) {
    console.log('支付成功:', result);
  },

  fail: ((result: TradePayFailResult) => {
    console.error('支付失败:', result);
    console.error('错误码:', result.error);
    console.error('错误信息:', result.errorMessage);
  }) as unknown as () => void,
});

这里的类型转换只是为了兼容 mini-types 中错误或不完整的 () => void 声明,不会影响运行时行为。

更稳妥的封装方式

如果不想在每次调用时都写类型转换,可以增加一层封装:

interface TradePayFailResult {
  error?: number | string;
  errorMessage?: string;
  [key: string]: unknown;
}

interface TradePayOptions {
  tradeNO: string;
  success?: (result: unknown) => void;
  fail?: (result: TradePayFailResult) => void;
  complete?: (result: unknown) => void;
}

function tradePay(options: TradePayOptions): void {
  my.tradePay(options as unknown as Parameters<typeof my.tradePay>[0]);
}

业务代码:

tradePay({
  tradeNO: 'your_trade_no',

  success(result) {
    console.log('支付成功:', result);
  },

  fail(result) {
    console.error(result.error, result.errorMessage);
  },
});

这样可以把类型兼容逻辑集中在一处。以后官方类型修正后,只需修改封装层。

为什么不能直接写带参数的回调

假设 mini-types 当前的声明是:

fail?: () => void;

开启严格类型检查后,下面的代码可能报错:

my.tradePay({
  tradeNO: 'your_trade_no',

  fail(result: TradePayFailResult) {
    console.error(result);
  },
});

类型定义表明调用方可以不传参数,而你的函数要求必须接收一个参数,因此 TypeScript 会认为两者不完全兼容。这个报错只能说明声明文件与代码存在冲突,不能证明运行时没有回调参数。

也可以修正声明文件

如果已经确认项目使用的 mini-types 版本和接口名称,也可以通过声明合并修正类型:

interface TradePayFailResult {
  error?: number | string;
  errorMessage?: string;
  [key: string]: unknown;
}

再根据 mini-types 实际暴露的模块、命名空间和参数接口进行扩展,将 fail 改为:

fail?: (result: TradePayFailResult) => void;

声明合并代码必须与当前安装包中的真实模块名和接口名一致,不能靠猜测。如果原接口已经将 fail 声明为 () => void,TypeScript 的属性声明合并可能不允许用不同类型重新声明。遇到这种情况,本地封装通常更省事。

注意事项

  • 优先升级到与当前开发工具和运行环境匹配的最新版 mini-types,确认类型差异是否已经修复。
  • 不要根据某一次失败结果,就把所有观察到的字段都声明为必填。
  • error 的实际类型可能受 SDK 版本影响。如果当前官方文档无法确认,使用 number | string 比限定为单一类型更稳妥。
  • fail 表示接口调用或支付流程失败。支付业务的最终状态仍需通过服务端查询或异步通知确认,不能只依赖客户端回调。
  • as unknown as () => void 只用于绕过已知的类型声明缺陷,不适合作为常规类型设计。项目中的相关调用较多时,建议统一封装。

备注:内容仅供参考。