PAYATHON 2026

my.ix.startapp 唤起刷脸支付失败时为何无提示?

支付老李

结论

两种收银模式采用了不同的兜底策略,这并不表示刷脸设备没有检测到失败。

个人收银模式使用蜻蜓内置的完整收银流程。刷脸不可用或支付失败时,系统可以直接切换到支付宝扫码支付,因此会主动显示扫码提示。

在小程序模式中,my.ix.startapp 主要用于唤起收银台应用。支付流程如何处理异常、是否切换到扫码支付,通常由接入方的小程序决定。用户关闭“到店刷脸支付”后,如果业务代码没有处理失败回调、取消结果或超时,页面就可能持续显示失败,也不给出任何提示。系统一般不会代替小程序发起其他支付方式,以免改变商户设定的支付流程或引发重复支付。

回调字段和错误码可能因设备系统、收银台应用及 SDK 版本而异,请以当前接入版本的官方文档和真机返回结果为准。

为什么个人收银模式会自动提示扫码

蜻蜓出厂自带的个人收银是一套预置的闭环产品,刷脸和扫码都属于内置收银流程。系统掌握当前订单状态,也能控制后续使用哪种付款方式,所以刷脸不可用时,可以引导用户出示付款码或扫描二维码。

小程序调用 my.ix.startapp 时,系统只能确认小程序请求启动了目标应用,却未必能代替业务方决定以下事项:

  • 是否允许从刷脸切换为扫码;
  • 应展示付款码还是收款二维码;
  • 原订单能否继续使用;
  • 失败后是否需要取消订单或重新创建订单;
  • 当前结果属于支付失败、用户取消,还是应用启动失败。

所以,个人收银模式中的自动降级提示并不是 my.ix.startapp 的通用能力。

解决方法

小程序需要自行补充刷脸支付失败后的兜底流程:

  1. 处理 my.ix.startapp 的成功、失败和完成回调。
  2. 接收收银台返回的最终支付结果,不能把“应用唤起成功”当成“支付成功”。
  3. 遇到刷脸失败、用户取消或返回结果不明确时,向用户显示清楚的提示。
  4. 提供“改用支付宝扫码支付”按钮,并接入相应的扫码支付能力。
  5. 设置合理的等待超时,避免收银台没有返回结果时,页面长时间没有响应。
  6. 切换支付方式前查询订单状态,防止刷脸已经完成扣款,但前端没有及时收到结果。

如果当前版本只能收到“唤起成功”,无法获取刷脸失败的原因,就需要结合收银台结果通知、订单查询接口或服务端支付状态作出判断。

代码示例

下面的代码只展示异常处理结构。appId、启动参数、结果字段和扫码支付方法都需要替换为项目实际使用的接口定义,不能把示例字段直接当作固定协议。

let finished = false;

const timer = setTimeout(async () => {
  if (finished) return;

  const paid = await queryOrderStatus();

  if (paid) {
    handlePaymentSuccess();
    return;
  }

  showScanFallback('刷脸支付暂未完成,可改用支付宝扫码支付');
}, 30000);

my.ix.startapp({
  appId: CASHIER_APP_ID,
  params: cashierParams,

  success(res) {
    // 此处通常只表示目标应用已被成功唤起,
    // 是否代表支付成功必须以当前接口文档和实际返回协议为准。
    console.log('cashier started', res);
  },

  fail(err) {
    finished = true;
    clearTimeout(timer);

    console.error('failed to start cashier', err);
    showScanFallback('无法使用刷脸支付,请改用支付宝扫码支付');
  },

  complete() {
    // complete 只表示本次 API 调用结束,不等同于付款完成。
  }
});

function showScanFallback(message) {
  my.confirm({
    title: '刷脸支付未完成',
    content: message,
    confirmButtonText: '扫码支付',
    cancelButtonText: '取消',

    async success(result) {
      if (!result.confirm) return;

      // 切换前再次核对订单,避免重复支付。
      const paid = await queryOrderStatus();

      if (paid) {
        handlePaymentSuccess();
        return;
      }

      startAlipayScanPayment();
    }
  });
}

如果收银台通过页面事件或业务回调返回支付结果,还要在对应入口统一清理超时定时器:

async function handleCashierResult(result) {
  finished = true;
  clearTimeout(timer);

  if (result.status === 'SUCCESS') {
    handlePaymentSuccess();
    return;
  }

  const paid = await queryOrderStatus();

  if (paid) {
    handlePaymentSuccess();
  } else {
    showScanFallback('刷脸支付失败或已取消,可改用支付宝扫码支付');
  }
}

这里的 result.status 只是用来说明处理思路,并不表示 my.ix.startapp 一定会返回该字段。具体判断条件必须以设备的实际返回协议为准。

注意事项

  • 手机支付宝关闭“到店刷脸支付”后,改变的是用户侧的能力或授权状态,小程序未必能直接读取这个开关。
  • 不要只根据前端回调判断付款结果,最终应以服务端订单状态或支付结果通知为准。
  • 超时并不等于支付失败。提示用户扫码前,必须查询原订单状态,避免同一笔交易重复支付。
  • 如果不同设备或系统版本的表现不一致,应记录设备型号、系统版本、收银台版本及 my.ix.startapp 的完整返回内容,再对照相应版本的接口文档排查。
  • 如果官方文档明确说明某个版本会自动提供扫码兜底,但真机没有出现,更可能是版本兼容或收银台配置问题,需要向设备或支付服务提供方确认。

备注:内容仅供参考。