交易系统组件开发指南
收藏
我的收藏通过插件的形式,我们预先实现了一些页面模板,例如退款页模板,小程序开发者只需要直接引入相应插件,并且遵循插件约定的规范,与插件之间实现相互通信,即可完成相应的页面,从而提高开发效率。
注:提单页即用户点击下单后进入的页面,也叫下单页
方案1:行业 SDK 交易组件接入指南(推荐使用)
- 1.使用 pay-button 需要行业sdk支持, 可以通过以下方法判断。
// 判断是否支持行业sdk 的 pay-button 组件 if (tt.canIUse("industrySDK.pay-button")) { // do something }
- 2.另外在使用组件时需要在页面 json 文件中进行引入。
// index.json { "usingComponents": { "pay-button-sdk": "ext://industry/pay-button" } }
这样,在页面的 ttml 中就可以像使用自定义组件一样使用行业sdk组件。
<pay-button-sdk mode="{{2}}" goods-type="{{1}}" goods-id="xxxx" bind:getgoodsinfo="getGoodsInfo" bind:placeorder="userLogin" bind:pay="onPay" />
- 3.行业sdk pay-button 对路由逻辑进行了优化,小程序开发者无需主动引入插件页面(即无需修改小程序全局配置文件 package.json 和 app.json),也可实现跳转相应的页面,从而提高开发效率。
- 4.直播间直跳场景支持营销能力
- 5.暂不支持在 IDE 上调试,请以真机调试为准。
方案2:交易组件接入指南(旧版组件使用方式,不建议使用)
使用限制
使用交易模版页面需要基础库支持,可以通过以下方法判断。
// 判断是否支持交易模版2.0 和 pay-button 组件 if (tt.canIUse("microapp-trade-plugin")) { // do something }
第一步:在小程序中引入插件
修改小程序全局配置文件 package.json 和 app.json。
- •package.json:
{ "ttPlugins": { "dependencies": { // 配置插件名,版本等信息 "microapp-trade-plugin": { "version": "1.1.2", "isDynamic": true } } } }
- •app.json:
{ "pages": [ "pages/index/index", // 提单页 "ext://microapp-trade-plugin/order-confirm", // 退款申请页配置 "ext://microapp-trade-plugin/refund-apply", // 退款详情页 "ext://microapp-trade-plugin/refund-detail" ] }
说明:在插件页面(提单页、申请退款页、退款详情页)想跳转到小程序页面时,需要在页面路径前加
usr://
tt.navigateTo({ url: "usr://pages/index/index", });
第二步:使用组件
前端模板提供了一个入口组件
pay-button
,该组件是小程序基础库内置组件,可直接使用。第三步:挂载 app 方法(可选)
除了引入插件及使用
pay-button
组件之外,开发者还需要在 app 上挂载以下两个方法,挂载的方法会在不同的特定时机下被前端模板调用。getThemeConfig
在前端模板的页面中,我们面向 开发者开放了主题色配置,包括了前端模板内按钮的圆角大小、背景色、文字颜色。若开发者不定义此方法,将使用交易系统默认主题色。
| | |
通过修改 app.js 文件,在该方法中定义主题色。
// app.js /** * desc: 主题色配置 * borderRadius:按钮圆角大小,默认 8rpx * backgroundColor:按钮背景色 + 退款原因选中背景色,默认 #FE2C55 * fontColor:按钮字体颜色,默认 #ffffff */ getThemeConfig() { return { borderRadius: '8rpx', // string backgroundColor: '#FE2C55', // string fontColor: '#ffffff', // string } }
getPhoneNumber
为了保证「一键填写」按钮可用,开发者需传入此方法。
在提单页中,有一个「一键填写」的按钮,该按钮调用了小程序获取手机号的开放能力,在模板中的实现大致如下:
<button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber"> 使用本机号码 </button> /** * desc: 获取手机号 * encryptedData: 包括敏感数据在内的完整用户信息的加密数据 * iv:加密算法的初始向量 */ getPhoneNumber(e) { const { iv, encryptedData } = e.detail; ... }
当用户在提单页点击该按钮时,会弹出手机号授权弹窗,用户允许授权后,模板会将
iv
、encryptedData
传递给开发者,开发者需要通过解密后得到手机号,然后以回调的方式通知前端模板,模板收到后将手机号传入输入框。注意
- •开发者需要先申请获取手机号的权限,申请说明请参见获取用户手机号开通规范。
- •
iv
、encryptedData
的含义及解密说明请参考获取手机号。// app.js /** * desc: 获取手机号 * params:加密数据 * success:成功回调 * fail: 失败回调 */ getPhoneNumber({ params, success, fail }) { const { iv, encryptedData } = params; // ... // 开发者服务端解密 encryptedData,得到手机号 // ... const result = { phoneNumber: '13580006666', } // 回调前端模板 success(result) }
第四步:提单页直跳(可选)
在直播间&短视频场景下,部分开发商希望用户能够直接进入提单页面,无需进入商详页,实现用户下单功能,为实现该功能需要对商品库商品信息及小程序代码进行相关改造。若无相关需求,可暂时不进行相关改造。
支持提单页直跳的抖音版本为 19.7,安卓、iOS 可下载最新线上版本即可测试。
低版本(低于抖音 19.7)用户不支持提单页直跳时,会跳转至 trade_url 配置的地址。
在行业sdk的提单页,直跳场景支持使用营销能力,支持的抖音版本为 27.0(使用行业sdk提单页,需要联系运营配置白名单)。
商品库商品信息配置 trade_url
直播间&短视频商品若需实现点击抢购直跳,需要给商品库配置 trade_url 相关信息,需要在 trade_url 的 params 中增加新的字段。注意:该功能并不能免除配置 trade_url 的工作,如果要直播,该值必填。( trade_url数据格式参考:https://bytedance.larkoffice.com/docx/doxcncpgP3vi7QtK4CPX7Ark1sd)
字段名 | 类型 | 默认值 | 必传 | 说明 |
use_template | boolean | 无 | 否 | 当前商品是否需要直跳功能
|
is_phone_necessary | boolean | true | 否 | 当前商品手机号为必填 |
min_limits | number | 1 | 否 | 最小起购份数 |
const demoData = { product: { account_name: "提单页作为首页", attr_key_value_map: { appointment: '{"need_appointment":true, "ahead_time_type":2, "ahead_hour_num":5,"external_link":"urlxxx", "order_appointment_time_url":"urlxxx"}', auto_renew: "true", bring_out_meal: "false", can_no_use_date: '{"enable": true,"days_of_week": [7, 1, 2, 3, 4],"holidays": [1, 2, 3, 4, 5],"date_list": ["2022-03-08", "2022-03-09"],"holiday_dates": {"1": "2022.01.01-2022.01.03"}}', customer_reserved_info: '{"allow":false}', description_rich_text: '[{"note_type":1,"content":"其他说明信息-美食团购"}]', detail_image_list: '[{"uri":"aweme-upload-image/7038504987084734508"}]', dishes_image_list: '[{"uri":"aweme-upload-image/7038504987084734508"}]', EntryType: "2", environment_image_list: '[{"uri":"aweme-upload-image/7038504987084734508"}]', free_pack: "true", FrontCategoryTag: '["美食套餐"]', image_list: '[{"uri":"aweme-upload-image/7038505021658382380"},{"uri":"aweme-upload-image/7038505050439696428"}]', IsConfirmImme: "true", Notification: '[{"title":"标题","content":"内容美食1.1"}]', private_room: "true", real_name_info: '{"enable":false,"scene":0}', RecommendWord: "推荐语", rec_person_num: "99", rec_person_num_max: "999", RefundPolicy: "2", refund_need_merchant_confirm: "true", show_channel: "2", SortWeight: "0", superimposed_discounts: "true", TagList: "标签列表-待填写", trade_url: '{"app_id":"ttcfdbb96650e33350","params":"{\\"use_template\\":true,\\"is_phone_necessary\\":true,\\"min_limits\\":1,\\"goodsId\\":\\"123456\\"}","path":"page/detail/detail"}', use_date: '{"use_date_type":1,"use_start_date":"2021-12-06","use_end_date":"2033-03-03"}', use_time: '{"use_time_type":1}', }, biz_line: 5, out_url: '{"app_id":"ttcfdbb96650e33350","params":"{\\"productId\\":\\"1\\",\\"packageId\\":2,\\"channelLinkId\\":3}","path":"page/detail/detail"}', category_id: 1001001, out_id: "lmc-life-app-006", poi_list: [ { supplier_ext_id: "DXQPOI-supplier_ext_id-002", }, ], product_name: "提单页作为首页-提单页补充参数没有的商品", product_type: 1, sold_end_time: 1745607528, sold_start_time: 1646724999, telephone: ["1234-4321"], }, sku: { actual_amount: 996, attr_key_value_map: { code_source_type: "1", commodity: '[{"group_name":"测试0001","total_count":1,"option_count":1,"item_list":[{"name":"可乐","price":1998,"count":1,"unit":"份"}]}]', limit_rule: '{"is_limit":true,"total_buy_num":999999}', market_price: "900", settle_type: "1", use_type: "1", }, origin_amount: 1399, sku_name: "测试", status: 1, stock: { limit_type: 0, stock_qty: 500, }, }, };
直跳提单页下需挂载的 app 方法
由于直跳场景下,无 pay-button 组件前置挂载,无法触发 bindgetgoodsinfo、bindpay 等方法,所以需要在 app 的 TradingSystem 对象上挂载相关方法获取相关数据及触发回调。
userLogin
由于下单时需要用户在小程序中处于登录态,与 bindplaceorder 方法类似,可复用相关代码,所以提供该回调供小程序校验及提醒用户进行登录,代码示例见下方。
getExtraInfo
部分开发者在下单时会透传 extra 信息,直跳场景下会通过 getExtraInfo 获取相关透传数据,与 bindgetgoodsinfo 方法类似,可复用相关代码,代码示例见下方。
pay
用户支付成功或取消后相关回调,与 bindpay 方法类似,可复用相关代码,代码示例见下方。
error
错误发生时的相关回调,与 binderror 方法类似,可复用相关代码,代码示例见下方。
代码示例
App({ getPhoneNumber({ success }) { // 获取手机号 }, getThemeConfig() { // 获取主题色 }, TradingSystem: { userLogin(event) { const { goodsId, goodsType } = event.detail; return new Promise((resolve, reject) => { tt.login({ success() { // 用户登录成功并获取信息,用户可正常下单 resolve(); }, fail(res) { // 用户登录失败,提单页会提示用户登陆,否则无法下单 reject(res); }, }); }); }, getExtraInfo(event) { const { goodsId, goodsType } = event.detail; return new Promise((resolve, reject) => { resolve( { extra: { test: 123, use_trade_delivery: 1 }, marketingReady: true, // 是否需要营销 marketingVersion: 2, // 营销版本 validation: { phoneNumber: { required: true, // 手机号是否必填, 为 ture则必填,false选填,默认选填 }, }, } ); }); }, pay(event) { const { status, orderId, outOrderNo, result } = event.detail; if (status === "success") { const { code } = result; if (code === 0) { console.log( `pay success,orderId = ${orderId}, outOrderNo = ${outOrderNo}, code = ${code}` ); } else { // 支付失败(超时、取消、关闭) console.log( `pay fail = ${orderId}, outOrderNo = ${outOrderNo}, code = ${code}` ); } } else { const { errMsg } = result; console.log( `pay fail,orderId = ${orderId}, outOrderNo = ${outOrderNo}, errMsg = ${errMsg}` ); } }, error(event) { const { errMsg, errNo, errLogId } = event.detail; console.log( `error, errMsg = ${errMsg}, errNo = ${errNo}, errLogId = ${errLogId}` ); }, }, });