payment-channel-select 前置支付组件
收藏我的收藏
组件用于将支付渠道内嵌到小程序页面,免去拉起收银台步骤,缩短交易链路,提升交易转化。
前提条件 | |
业务背景 | 开发者可将此组件引入提单页或充值面 板页,提前为用户展示支付列表,当用户点击立即支付时,将直接拉起支付而不再需要唤起收银台。 |
使用限制 |
|
注意事项 |
|
相关教程 | 无 |
效果示例
使用流程
正常流程:
渲染出错:
支付出错:
属性说明
属性名 | 类型 | 默认值 | 必填 | 说明 |
scene | string | 'cash' | 条件选填 (在iOS情况下必填) | 组件支付场景,有现金支付和钻石支付两种。 枚举说明: cash - 现金支付; diamond - 钻石支付 注意:
|
sku-list | SkuList[] SkuList 说明见下文 | 无 | 是 | 用户选择的商品信息 注意:目前只支持传入一项 |
merchant-uid | string | 无 | 否 | 开发者自定义收款商户号, 若使用默认收款商户号可忽略该参数 |
limit-pay-way-list | number[] | 无 | 否 | 以订单维度指定屏蔽的支付方式。如: [1,2] 表示该笔订单屏蔽微信和支付宝 。枚举说明: 1 - 微信 2 - 支付宝 注意: scene=diamond时,该参数无效 |
custom-style | object | 无 | 否 | 自定义样式 详见下文说明 |
bind:requestorder | EventHandle | 无 | 是 | 用户点击立即支付触发 详见 bind:requestorder 说明 |
bind:getpaymentresult | EventHandle | 无 | 否 | 获取支付结果,支付成功和失败都会触发 详见 bind:getpaymentresult 说明 |
bind:error | EventHandle | 无 | 否 | 组件传入属性异常、组件内部发生异常时触发 详见 bind:error 说明 |
sku-list 说明
object 类型,属性如下:
属性名 | 类型 | 默认值 | 必填 | 说明 |
skuId | string | 无 | 是 | 外部商品id,如:号卡商品id、会员充值套餐id、某类服务id、付费工具id等 |
price | number | 无 | 是 | 商品价格
注意:
|
title | string | 无 | 是 | 商品标题,长度 <= 256字节 |
type | number | 无 | 是 | 商品类型,详细查看 |
tagGroupId | string | 无 | 是 | 注意:
|
custom-style 说明
属性名 | 类型 | 默认值 | 必填 | 说明 |
backgroundColor | string | 无 | 否 | 组件背景颜色 |
fontSize | string | 无 | 否 | 组件文字大小 |
retryTextColor | string | 无 | 否 | 重试文字颜色 |
buttonBackgroundColor | string | 无 | 否 | 支付按钮背景颜色 |
buttonColor | string | 无 | 否 | 支付按钮文字颜色 |
payChannelCell | object | 无 | 否 | 支付方式栏样式配置 详见下文说明 |
payTagCell | object | 无 | 否 | 交易保障栏样式配置 详见下文说明 |
payDiscountCell | object | 无 | 否 | 支付优惠栏样式配置 详见下文说明 |
payChannelCell, payTagCell, payDiscountCell 配置说明:
属性名 | 类型 | 默认值 | 必填 | 说明 |
titleColor | string | 无 | 否 | 左侧标题文字颜色 |
textColor | string | 无 | 否 | 右侧内容文字颜色 |
bind:requestorder 说明
需要返回 promise ,将 data 和 byteAuthorization 传入 resolve 函数 。(data、byteAuthorization 与原 tt.requestOrder 的参数一致)。
使用示例:
// bind:requestorder 使用示例 handleRequestOrder(event) { // 开发者服务端下单 // 返回一个 promise return new Promise(resolve => { resolve({ data, byteAuthorization }); }); }
bind:getpaymentresult 说明
使用示例:
// bind:getpaymentresult 使用示例 handleGetPaymenResult(event) { const { status, result } = event.detail; if (status === 'success') { const { code } = result; if (code === 0) { // 支付成功 } else { // 支付失败、超时、取消、关闭 } } else { // 支付失败 } }
事件对象的 event.detail 为 object 类型,属性如下:result 属性说明:
- •当 status 为 success 时:
属性名 | 类型 | 说明 |
code | number |
|
orderId | string | 抖音交易系统内部交易订单号
|
- •当 status 为 fail 时:
属性名 | 类型 | 说明 |
errMsg | string | 错误信息 |
errNo | number | 错误码 |
bind:error报错信息
// bind:error 使用示例 handleError(event){ const { errNo , errMsg } = event.detail // errNo(错误码,对应某种具体报错原因) // errMsg(报错信息) }
组件初始化错误
errNo | errMsg | 说明 |
20000 | skuList.skuId should be string, but got undefined | skuList.skuId 未传。其他字段 skuList 校验失败也会有类似错误信息 |
20000 | bindrequestorder should be function, but got undefined | 未绑定 bindrequestorder |
10601 | not login | 用户未登录,组件无渲染 |
169006 | render multiple components | 一个页面同时渲染多个支付前置组件,组件无渲染 |
169007 | component init fail | 组件初始化失败 |
169008 | fail to get cashier info | 获取组件渲染数据失败 |
169009 | unable to use component | 无法使用组件,组件无渲染 |
169021 | unknown scene: ${scene} | 未知 scene,目前仅支持 cash 和 diamond。 |
默认情况下,当组件初始化失败时会给用户重试按钮,用户可点击重试。
为保证支付链路稳定性,当出现以下错误时,建议使用 tt:if 隐藏组件,并回退到 tt.requestOrder + tt.getOrderPayment 支付,errNo 如下:20000、169006、169007、169009。
支付错误
errNo | errMsg | 说明 |
169015 | bind:requestorder method call error | 调用开发者 bind:requestorder 报错 |
169016 | server error, no "sdkInfo" in response | 支付失败,服务端错误 |
169017 | payment failed | 支付失败,组件内部错误 |
169018 | component price is different from the bind:requestorder totalAmount | 传入组件的 skuList price 和 bind:requestorder 返回的 totalAmount 不一致 |
169019 | component tagGroupId is different from the bind:requestorder tagGroupId | 传入组件的 skuList tagGroupId 和 bind:requestorder 返回的 tagGroupId 不一致 |
169020 | bind:requestorder data or byteAuthorization validate error | bind:requestorder 返回值中的 data 或 byteAuthorization 校验失败 |
10000 | 参数错误 | 参数错误 |
商品不符合行业要求 | ||
iOS前置支付组件仅支持钻石场景 | iOS使用payment-channel-select组件仅支持钻石,该报错原因在于bind:requestorder中开发者传入的下单参数data未指定使用钻石下单 | |
10401 | internal error | 请求异常,可重试或升级APP |
11004 | 签名参数异常 | 请开发者自行检查byteAuthorization的格式是否满足此要求 |
签名校验异常 | ||
11001 | 访问未授权 | 该JSAPI依赖用户登录,使用前请确保用户已经完成登录 |
12002 | 账号行为异常 | 账号行为异常 |
13000 | 系统错误 | 系统错误 |
21012 | 创建订单失败,请稍后重试 | 创建订单失败,请稍后重试 |
21016 | 外部单号已存在 | 外部单号已存在 |
21046 | 订单收款商户号不合法 | 订单收款商户号不合法 |
21550 | not login | 请用真机调试或者参考常见问题 |
26001 | 当前订单状态不可支付 | 当前订单状态不可支付 |
26003 | 小程序违规,支付能力被封禁 | 小程序违规,支付能力被封禁 |
26005 | 无可用支付方式 | 无可用支付方式 |
26006 | 商户号与小程序的支付产品不一致 | 商户号与小程序的支付产品不一致 |
为保证支付链路的稳定性,当出现支付相关错误时,建议回退到 tt.requestOrder + tt.getOrderPayment 支付方式,errorNo 如下:169015、169016、169017、169018、169019、169020。
代码示例
- 1.在页面 json 文件中引入组件。
{ "usingComponents": { "payment-channel-select": "ext://industry/payment-channel-select" } }
- 2.在 ttml 文件中引入组件。
- a.传入 sku-list 和相应处理回调,当商品变更时,需重新传递商品信息 sku-list 给 payment-channel-select 组件。
- b.开发者可通过 tt.canIUse('payment-channel-select') 判断是否支持组件。
<!-- 传递商品信息和绑定回调 --> <payment-channel-select tt:if="{{showPaymentChannelSelect}}" sku-list="{{skuList}}" bind:requestorder="handleRequestOrder" bind:getpaymentresult="handleGetpaymentresult" bind:error="handleError" > </payment-channel-select>
- 3.实现 bind:requestorder 回调,在回调中返回下单参数,参数与tt.requestOrder 保持一致。
// bind:requestorder 使用示例 handleRequestOrder(event) { // 开发者服务端下单 // 返回一个 promise return new Promise(resolve => { resolve({ data, byteAuthorization }); }); }
- 4.实现 bind:getpaymentresult 回调,在支付成功或者支付失败时,通过浮层提示用户,在 code 为 9 时,自行查询订单状态。
// bind:getpaymentresult 使用示例 handleGetPaymenResult(event) { const { status, result } = event.detail; if (status === 'success') { const { code } = result; if (code === 0) { tt.showToast({ icon: 'success', title: '支付成功', }); } else if( code === 9) { // code 为 9,开发者自行查询订单状态 } else { // 支付失败、超时、取消、关闭 tt.showToast({ icon: 'success', title: '支付失败', }); } } else { // 支付失败 tt.showToast({ icon: 'success', title: '支付失败', }); } }
- 5.实现 bind:error 回调,在出现错误时,回退到 tt.requestOrder + tt.getOrderPayment 支付
// bind:error 使用示例 handleError(event){ // errNo(错误码,对应某种具体报错原因) // errMsg(报错信息) const { errNo, errMsg } = event.detail const componentInitError = [169007, 20000] const payError = [169015, 169016, 169017, 169018, 169019, 169020] if (componentInitError.includes(errNo)) { this.setData({ showPaymentChannelSelect: false }) } else if(payError.includes(errNo)) { // 使用 tt.requestOrder + tt.getOrderPayment } }
index.js文件完整代码示例如下:
Page({ data: {}, handleRequestOrder(event) { // 开发者服务端下单 // 返回一个 promise return new Promise((resolve) => { resolve({ data, byteAuthorization, }); }); }, // bind:getpaymentresult 使用示例 handleGetPaymenResult(event) { const { status, result } = event.detail; if (status === "success") { const { code } = result; if (code === 0) { tt.showToast({ icon: "success", title: "支付成功", }); } else if (code === 9) { // code 为 9,开发者自行查询订单状态 } else { // 支付失败、超时、取消、关闭 tt.showToast({ icon: "success", title: "支付失败", }); } } else { // 支付失败 tt.showToast({ icon: "success", title: "支付失败", }); } }, // bind:error 使用示例 handleError(event) { // errNo(错误码,对应某种具体报错原因) // errMsg(报错信息) const { errNo, errMsg } = event.detail; const componentInitError = [169007, 20000]; const payError = [169015, 169016, 169017, 169018, 169019, 169020]; if (componentInitError.includes(errNo)) { this.setData({ showPaymentChannelSelect: false }); } else if (payError.includes(errNo)) { // 使用 tt.requestOrder + tt.getOrderPayment } }, });
Bug & Tip
暂无。
常见问题
使用 uniapp 脚手架时,接入组件时出现报错: bind:requestorder data or byteAuthorization validate error
原因:bind:requestorder 要求绑定函数的返回值,但是 uniapp 处理的时候,会把这个函数给吞掉,具体可参考:https://ask.dcloud.net.cn/question/189088。
解决方案:
// 在 template 中, 将 @requestorder 改写成 bind:requestorder <payment-channel-select ... bind:requestorder="handleRequestOrder" /> // 在 js 中,在小程序容器上挂上 vue 实例 export default { //... created: { this.$scope.handleReqeustOrder = this.handleReqeustOrder.bind(this) }, methods: { handleReqeustOrder: function handleReqeustOrder() { return new Promise(resolve => { resolve(...) }) } } }
组件返回异常 unable to use component