my.ix.startapp 唤起刷脸支付失败时为何无提示?
结论
两种收银模式采用了不同的兜底策略,这并不表示刷脸设备没有检测到失败。
个人收银模式使用蜻蜓内置的完整收银流程。刷脸不可用或支付失败时,系统可以直接切换到支付宝扫码支付,因此会主动显示扫码提示。
在小程序模式中,my.ix.startapp 主要用于唤起收银台应用。支付流程如何处理异常、是否切换到扫码支付,通常由接入方的小程序决定。用户关闭“到店刷脸支付”后,如果业务代码没有处理失败回调、取消结果或超时,页面就可能持续显示失败,也不给出任何提示。系统一般不会代替小程序发起其他支付方式,以免改变商户设定的支付流程或引发重复支付。
回调字段和错误码可能因设备系统、收银台应用及 SDK 版本而异,请以当前接入版本的官方文档和真机返回结果为准。
为什么个人收银模式会自动提示扫码
蜻蜓出厂自带的个人收银是一套预置的闭环产品,刷脸和扫码都属于内置收银流程。系统掌握当前订单状态,也能控制后续使用哪种付款方式,所以刷脸不可用时,可以引导用户出示付款码或扫描二维码。
小程序调用 my.ix.startapp 时,系统只能确认小程序请求启动了目标应用,却未必能代替业务方决定以下事项:
- 是否允许从刷脸切换为扫码;
- 应展示付款码还是收款二维码;
- 原订单能否继续使用;
- 失败后是否需要取消订单或重新创建订单;
- 当前结果属于支付失败、用户取消,还是应用启动失败。
所以,个人收银模式中的自动降级提示并不是 my.ix.startapp 的通用能力。
解决方法
小程序需要自行补充刷脸支付失败后的兜底流程:
- 处理
my.ix.startapp的成功、失败和完成回调。 - 接收收银台返回的最终支付结果,不能把“应用唤起成功”当成“支付成功”。
- 遇到刷脸失败、用户取消或返回结果不明确时,向用户显示清楚的提示。
- 提供“改用支付宝扫码支付”按钮,并接入相应的扫码支付能力。
- 设置合理的等待超时,避免收银台没有返回结果时,页面长时间没有响应。
- 切换支付方式前查询订单状态,防止刷脸已经完成扣款,但前端没有及时收到结果。
如果当前版本只能收到“唤起成功”,无法获取刷脸失败的原因,就需要结合收银台结果通知、订单查询接口或服务端支付状态作出判断。
代码示例
下面的代码只展示异常处理结构。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的完整返回内容,再对照相应版本的接口文档排查。 - 如果官方文档明确说明某个版本会自动提供扫码兜底,但真机没有出现,更可能是版本兼容或收银台配置问题,需要向设备或支付服务提供方确认。
备注:内容仅供参考。
