预下单回调
通过模板组件/JS API 发起下单时,抖音开平交易系统会请求开发者服务,将下单信息传递给开发者服务。
使用限制
调用接口前序先完成预下单扩展点设置,请参考行业模板配置文档
接口说明
无
基本信息
基本信息 | |
---|---|
HTTP URL | 预下单回调地址的设置请参考行业模板配置文档-实现扩展点 create_order_callback |
HTTP Method | POST |
请求头
参见通用参数。
请求参数
名称 | 类型 | 是否必填 | 描述 | 示例值 |
---|---|---|---|---|
msg | string | 是 | 预下单相关信息的 json 字符串,详情参见msg字段 | 详情参见请求示例 |
type | string | 是 | 枚举值:- pre_create_order:预下单回调- pre_create_refund:退款审核回调- query_marketing_info:营销信息查询回调- calculate_price:营销算价回调 | "pre_create_order" |
version | string | 是 | 固定值:"2.0",即回调版本,用于开发者识别回调参数的变更 | "2.0" |
msg 字段
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
order_id | string | 是 | 抖音开平侧生成的订单号 |
goods | Array | 否,与sku_list字段二选一 | 商品信息,详情见goods字段 |
sku_list | Array | 否,与goods字段二选一 | 商品信息,详情见 sku_list参数 部分,sku下单会返回,该字段未来会取代goods字段,goods字段会逐步淘汰,使用该字段下单暂不支持营销扩展点能力 |
total_amount | int64 | 是 | 订单总价格,单位分用户实付金额 = total_amount - discount |
discount | int64 | 是 | 订单折扣,单位分 |
cp_extra | string | 否 | 预下单时开发者定义的透传信息 |
create_order_time | int64 | 是 | 订单创建时间,13 位时间戳,单位毫秒 |
open_id | string | 是 | 用户 OpenID |
phone_num | string | 否 | 用户手机号 |
contact_name | string | 否 | 联系人姓名 |
app_id | string | 是 | 小程序id |
union_id | string | 否 | 用户的 UnionID |
delivery_type | int | 是 | 核销类型,开平告知此订单是否可走闭环核销判断结果。- 0:三方码,开发者自行处理券码生成及展示,通过 push_delivery 接口推送核销状态。- 1:抖音码,抖音开平负责生券,开发者使用核销组件展示,使用验券准备和验券接口核销。 |
price_calculation_detail | object | 否 | 营销算价结果信息,详情见字段描述 |
address | object | 否 | 有物流配送需求的时候提单页会让用户填入配送地址,本字段存储用户的收货地址。注:本字段当前仅开放给泛知识行业使用,其他行业可暂时不用关注该字段 |
open_book_info | object | 否 | 预约信息,目前应用于酒旅、门票预售券类场景中,详情参见open_book_info字段说明 |
item_order_info_list | Array | 是 | item_order信息,详情参见item_order_info_list字段说明 |
price_calculation_detail 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
calculation_type | int32 | 是 | 算价维度类型- 1: 计算到goods层- 2: 计算到item层 |
goods_discount_detail | Array | 否 | 商品算价结果,详情见字段描述 |
order_discount_detail | object | 否 | 订单算价结果,详情见字段描述 |
item_discount_detail | Array | 否 | 单商品算价结果详情见字段描述 |
ext_calculation_no | string | 否 | 外部算价结果号 |
说明:
- 订单原价total_amount,订单总优惠total_discount_amount
- total_amount = sum(goods_calculation_result_info.total_amount) = sum(item_calculation_result_info.total_amount)
- total_discount_amount=order_total_discount_amount + goods_total_discount_amount,订单总优惠金额=商品维度的优惠金额+订单维度的优惠金额
- calculation_type表示计算优惠分摊的类型
- calculation_type=1,将优惠分摊到goods层,请求体包含order_calculation_result_info,goods_calculation_result_info,
- calculation_type=2,将优惠分摊到item层,请求体包含order_calculation_result_info,goods_calculation_result_info,item_calculation_result_info
- order_calculation_result_info,goods_calculation_result_info,item_calculation_result_info表达的是优惠分摊逻辑。order, goods, item代表订单的三层结构,order有N个goods,每个goods有M个item(M表示份数),item表示单份商品。订单总优惠金额 = order层的优惠聚合 = goods层的优惠聚合 = item层的优惠聚合
- 举个例子,一笔订单购买2杯奶茶,总价100元,使用80-10活动和星冰乐单品立减5元优惠券,实付金额85元,表达分摊的逻辑如下
- 订单总优惠金额 total_discount_amount =1500,单位[分]
- order层,order_calculation_result_info,order_total_discount_amount=1000,goods_total_discount_amount=500
- goods层,goods_calculation_result_info数组长度为1,goods[0].total_discount_amount=1500
- item层,item_calculation_result_info数组长度为2,items[0].total_discount_amount=750,items[1].total_discount_amount=750
order_discount_detail 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
order_total_discount_amount | number | 是 | 订单维度总优惠金额,单位分 |
goods_total_discount_amount | number | 是 | 商品(sku)维度总优惠金额,单位分 |
marketing_detail_info | Array | 否 | 营销明细,详情见字段描述 |
goods_discount_detail 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
goods_id | string | 是 | 商品 id |
quantity | number | 是 | 购买数量 |
total_amount | number | 是 | 商品总价,单位分 |
discount_amount | number | 是 | 该商品总优惠金额该商品的实付金额 = total_amount - discount_amount |
marketing_detail_info | Array | 否 | 营销明细,详情见字段描述 |
item_discount_detail 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
goods_id | string | 是 | 商品 id |
total_amount | number | 是 | 商品总价,单位分 |
discount_amount | number | 是 | 该商品总优惠金额该商品的实付金额 = total_amount - discount_amount |
marketing_detail_info | Array | 否 | 营销明细,详情见字段描述 |
marketing_detail 字段说明
说明:
- marketing_detail_info在order,goods,item三个层级都有,区别是它表示某个营销项在这一层级分摊的优惠金额。比如一笔订单购买2杯奶茶,总价100元,使用优惠券A满100-10元,实付90元。优惠券A会出现在3个层级的marketing_detail_info里
- 在order层,detailA.discount_amount=1000,单位[分]
- 在goods层,detailA.discount_amount=1000,
- 在item层,由于优惠分摊到两份商品上,detailA1.discount_amount=500,detailA1.discount_amount=500
- discount_range,表示优惠的维度,举个例子
- 星冰乐单品5折券属于商品维度优惠,discount_range=2
- 订单满200-20属于订单维度优惠,discount_range=1
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
id | string | 是 | 营销 ID(用户身份 ID、优惠券 ID、积分 ID 或者活动 ID) |
type | number | 是 | 营销类型,- 1:用户身份- 2:优惠券- 3:积分- 4:活动 |
discount_amount | number | 是 | 该营销策略优惠金额,单位分 |
title | string | 是 | 营销名称 |
note | string | 否 | 营销备注 |
discount_range | number | 是 | 营销适用维度:- 1:订单维度- 2:商品维度 |
subtype | string | 否 | 营销子类型 |
value | i64 | 否 | 不同 type 含义不同,比如 type 为 4 时指积分值 |
goods 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
img_url | string | 是 | 商品图片链接 |
title | string | 是 | 商品标题 |
sub_title | string | 否 | 商品副标题 |
labels | string | 是 | 商品标签,对应 POI 多门店 SPU 同步的 sub_title,例如:随时退|免预约|提前 3 日预约 (“|”是中文类型) |
date_rule | string | 是 | 券的可用时间(目前仅用于展示),例如:“周一至周五可用”、“非节假日可用” |
origin_price | int64 | 是 | 商品原价,单位分 |
price | int64 | 是 | 商品去掉折扣后的单价,单位分 |
quantity | int64 | 是 | 购买的商品数量 |
poi_id | string | 否 | 对应门店的 POI ID |
goods_id | string | 是 | 商品 ID |
item_order_id_list | Array | 是 | item_order_id 列表,id 个数与 quantity 一致 |
goods_id_type | int32 | 是 | 商品 ID 类别,- 1:POI 商品- 2:非 POI 商品 |
item_order_info_list | Array | 是 | item_order 相关信息,详情见item_order_info字段描述 |
goods_book_info | object | 否 | 预约信息,使用在门票、酒旅预售券等业务场景,详情见字段描述 |
goods_book_info 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
book_type | string | 是 | 预约类型,- 1:不需要预约- 2:在线预约 |
cancel_policy | string | 否 | 取消政策,- 1:预约后不可取消- 2:预约后可取消 |
item_order_info 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
item_order_id | string | 是 | item 单 ID |
price | int64 | 是 | 商品优惠后价格 |
sku_list 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
quantity | Int32 | 是 | 下单SKU数量 |
sku_id | string | 是 | 商品sku_id |
sku_id_type | int32 | 是 | sku_id类型1:商品库skuId2:非商品库skuId |
price | Int64 | 是 | 去掉折扣后的单价 |
origin_price | int64 | 是 | SKU原价 |
atts | object | 否 | sku属性 |
goods_info | object | 否 | 商品信息,详情请看 goods_info |
atts 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
ticket_name | string | 否 | 门票-票种类型,长度 <= 128 byte |
date | string | 否 | 门票日期,示例 2006-01-02,日期格式需为 yy-mm-dd |
goods_info 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
img_url | string | 是 | 商品图片链接 |
title | string | 是 | 商品标题 |
sub_title | string | 是 | 商品副标题 |
labels | string | 是 | 商品标签,对应poi多门店SPU同步的sub_title,例如:随时退|免预约|提前3日预约 (“|”是中文类型) |
date_rule | string | 是 | 券的可用时间(目前仅用于展示),例如:“周一至周五可用”、“非节假日可用” |
poi_id | string | 否 | 对应门店的Poi ID |
goods_id | string | 是 | 商品id |
goods_id_type | int32 | 是 | 商品id类别,1:poi商品,2:非poi商品 |
goods_book_info | object | 否 | 预约信息,详情见 goods_book_info说明 |
open_book_info 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
book_id | string | 是 | 预约单id |
item_book_info_list | Array | 是 | 每个item的预约信息,详见 ItemBookInfo |
ItemBookInfo 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
poi_id | string | 是 | 预约门店的poiId |
shop_name | string | 是 | 预约门店的名称 |
ext_shop_id | string | 是 | 预约门店的外部店铺id |
goods_id | string | 是 | 商品id |
book_start_time | int64 | 是 | 预约的开始时间(ms),13位毫秒时间戳 |
book_end_time | int64 | 是 | 预约的结束时间(ms),13位毫秒时间戳 |
user_info_list | Array | 否 | 用户信息,详见 UserInfo |
UserInfo 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
name | string | 否 | 使用人名称 |
phone | string | 否 | 电话号码 |
id_card_no | string | 否 | 身份证号码 |
item_order_info_list 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
sku_id | string | 否 | 商品sku_id |
sku_id_type | int32 | 否 | sku_id类型1:商品库skuId2:非商品库skuId |
goods_id | string | 是 | 商品id |
goods_id_type | int32 | 是 | 商品id类型 |
item_order_id | string | 是 | 商品单ID |
price | number | 是 | item单实付金额 |
address 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
user_address_id | string | 否 | 用户在抖音内的地址id,标志用户在抖音体系内的留存的某个唯一地址信息 |
location_address_info | object | 是 | 地理位置信息,详见下述字段 |
door_plate_num | string | 否 | 门牌号 |
connect_name | string | 否 | 联系人名字 |
phone | string | 是 | 联系电话 |
detail_address | string | 详细地址信息 | 详细地址信息 |
location_address_info 字段说明
名称 | 类型 | 是否必填 | 描述 |
---|---|---|---|
location_id | string | 否 | 抖音内部唯一地理位置id,长度<=64byte |
location_address | string | 否 | 具体地理位置信息,例子:东长安街16号天安门广场东侧中国国家博物馆内 |
province_name | string | 是 | 省份名称 |
province_code | string | 是 | 省份代码,参见:全国地区代码 |
city_name | string | 是 | 城市名称 |
city_code | string | 是 | 城市编码,参见:全国地区代码 |
district_name | string | 是 | 区/县名称 |
district_code | string | 是 | 区/县代码,参见:全国地区代码 |
town_name | string | 否 | 镇/村名称 |
town_code | string | 否 | 镇/村代码 |
location_name | string | 是 | 具体地址,eg:中国国家博物馆 |
address 字段整体范例
{
"user_address_id": "7167209364301185316",
"location_address_info": {
"location_id": "22535659096582631",
"location_address": "东长安街16号天安门广场东侧中国国家博物馆内",
"province_name": "北京市",
"province_code": "110000",
"city_code": "110100",
"city_name": "北京市",
"district_code": "110101",
"district_name": "东城区",
"town_code": "",
"town_name": "",
"location_name": "中国国家博物馆"
},
"door_plate_num": "北京xx胡同口xxx号",
"connect_name": "北京小老爷们",
"phone": "12345666669",
"gender": 1,
"detail_address": "东长安街16号天安门广场东侧中国国家博物馆内中国国家博物馆北京"
}
请求示例
curl --location --request POST 'https://xxxxxxx.net/api/v2/create_order?timestamp=1345678901234&nonce=iuy987q4htafreqw' \
--header 'Content-Type: application/json'
--data-raw='{
"version": "2.0",
"msg": "序列化后的json字符串",
"type": "pre_create_order"
}'
msg 内部结构:
/* msg结构 */
{
"order_id": "614167279916",
"goods": [
{
"img_url": "http://xxx",
"title": "xxx",
"sub_title": "xxx",
"labels": "过期退|随时退",
"date_rule": "xxx",
"origin_price": 800,
"price": 750,
"quantity": 2,
"poi_id": "",
"goods_id": "xxx",
"item_order_id_list": [
"1xxx",
"2xxx"
]
}
],
"price_calculation_detail":{
"calculation_type":1,
"order_discount_detail":{
"order_total_discount_amount":0,
"goods_total_discount_amount":93,
"marketing_detail_info":[
{
"id":"activity_id_2_fen_MOCK_",
"type":4,
"discount_amount":2,
"title":"[活动] 满 0.20 减 0.02 元",
"note":"活动优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值"
},
{
"id":"activity_id_1_fen_MOCK_",
"type":4,
"discount_amount":1,
"title":"[活动] 满 0.10 减 0.01 元",
"note":"活动优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值"
},
{
"id":"coupon_id_90_fen_MOCK_",
"type":2,
"discount_amount":90,
"title":"[券] 满 0.91 减 0.90 元",
"note":"用券优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值",
"code":"coupon_id_90_fen_MOCK_"
}
]
},
"goods_discount_detail":[
{
"goods_id":"7116845279713691692",
"quantity":1,
"total_amount":100,
"total_discount_amount":93,
"marketing_detail_info":[
{
"id":"activity_id_2_fen_MOCK_",
"type":4,
"discount_amount":2,
"title":"[活动] 满 0.20 减 0.02 元",
"note":"活动优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值"
},
{
"id":"activity_id_1_fen_MOCK_",
"type":4,
"discount_amount":1,
"title":"[活动] 满 0.10 减 0.01 元",
"note":"活动优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值"
},
{
"id":"coupon_id_90_fen_MOCK_",
"type":2,
"discount_amount":90,
"title":"[券] 满 0.91 减 0.90 元",
"note":"用券优惠",
"discount_range":2,
"subtype":"商家侧子营销类型默认值",
"code":"coupon_id_90_fen_MOCK_"
}
],
"sku_id":null
}
],
"item_discount_detail":[
]
},
"total_amount": 1600,
"discount": 100,
"cp_extra": "xxx",
"create_order_time": 1642491214992,
"open_id": "xxx",
"phone_num": "xxx",
"contact_name": "xxx",
"app_id": "xxx",
"union_id": "xxx"
}
/* 响应 */
{
"err_no" : 0,
"err_tips" : "success",
"data": {
"out_order_no" : "89876867867087", //开发者的单号
"pay_expire_seconds": 300, //单位秒
"order_entry_schema": {
"path": "page/refundDetail/xxx", //订单详情页路径
"params": "{"id": 1}" //订单详情页路径参数
},
"order_valid_time":[
{
"goods_id": "xxx",
"valid_start_time": 1232312000, //毫秒
"valid_end_time": 1231231000 //毫秒
}
]
}
}
响应参数
字段名 | 类型 | 是否必传 | 字段描述 |
---|---|---|---|
err_no | int | 是 | 错误码,0 代表成功 |
err_tips | string | 是 | 错误提示信息 |
data | object | 是 | 预下单的信息 |
data 字段说明
名称 | 类型 | 是否必传 | 描述 |
---|---|---|---|
out_order_no | string | 是 | 开发者的单号,长度小于等于 64 byte |
pay_expire_seconds | int64 | 否 | 支付超时时间,单位秒,例如 300 表示 300 秒后过期;不传或传 0 会使用默认值 300,最大不能超过48小时。 |
order_entry_schema | object | 是 | 订单详情页信息,详情参见order_entry_schema字段说明 |
order_valid_time | Array | 否 | 券的有效期,注意: |
- 非 POI 商品必传,POI 商品会从 POI 库里查询有效期信息,不会使用开发者传的数据。
| 2. 如果是非 POI 商品,每个 goods_id 都要传券的有效期信息,否则会下单失败。
- | | | |
| ----------------------------------------------------- | --------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| order_goods_info | Array | 否 | 订单的商品相关信息 |
| pay_notify_url | string | 否 | 支付结果通知地址,必须是 HTTPS 类型。若不填,默认使用在行业模板配置-消息通知中设置的支付回调地址。 |
| cp_delivery_type | int | 否 | 开发者指定核销类型。如有三方码场景,可通过此参数指定。请注意指定三方码参数需要申请白名单,不在白名单内的此订单会做下单失败处理。有效值:- 0:无特殊处理- 1: 三方码方案- 其他:其他值都会按照0值处理 |
| delivery_qrcode_redirect | string | 否 | 开发者可通过此参数指定此订单的核销二维码的跳转 URL。如果是闭环核销,开平的核销组件会使用此 URL 生成二维码,商家核销时即可实现跳转到指定 URL。如果传该参数,必须是 HTTPS 链接,长度小于等于 256 字节。不满足要求的会导致预下单失败。 |
| cp_book_info | object | 否,预下单请求中带open_book_info时必传 | 用户预约信息 |order_entry_schema 字段说明
名称 类型 是否必传 描述 path string 是 订单详情页跳转路径,没有前导的“/”,长度 <= 512 byte params string 否 订单详情页路径参数,自定义的 json 结构,序列化成字符串存入该字段,平台不限制,但是写入的内容需要能够保证生成访问订单详情的 schema 能正确跳转到小程序内部的订单详情页,长度须 <= 512byte order_valid_time 字段说明
名称 类型 是否必传 描述 goods_id string 是 商品 id valid_start_time int64 否 券的有效期开始时间,单位毫秒,须大于 0 valid_end_time int64 否 券的有效期结束时间,单位毫秒,须大于 0,且须大于 valid_start_time 和当前时间 valid_duration int64 否 - 券的相对有效时间,单位毫秒,须大于 0
- 与 valid_start_time、valid_end_time 组合,
- 至少回传一个,否则会下单失败
- 都合法优先使用 valid_start_time、valid_end_time 组合
| 4. 当 valid_duration 有效时,
-
-
券的有效期开始时间 S = 订单支付完成时间- 券的有效期结束时间 E = 1天 + 向下按天截断(S + valid_duration))。例如:valid_duration = 86400000 ms(一天),S = 2021.1.1 6:00,E = 2021.1.2 23:59:59
-
order_goods_info 字段说明
- 本字段可不填
- 指定商户号下单需要开白名单,不开白名单会导致下单失败,有需要的请提oncall
- 对每个商品,请填写正确的收款商户号;如果未填写,将默认使用小程序进件商户号。响应里的商品id需要与请求的商品id保持一致。
- 目前的下单场景里只包含一种商品,未来可能会支持多个商品,所以结构是列表由于目前不支持购物车模式,只能用1个商户号收款。所以如果存在多商品的情况,对于每个商品请填写相同的商户号。
字段名 类型 是否必传 字段描述 goods_id string 是 商品id,注意这里需要传string类型 merchant_uid string 是 收款商户号,请填写正确的完成进件的商户号。如果未填写,将默认使用小程序进件商户号。指定商户号下单需要开白名单,不开白名单会导致下单失败,有需要的请提oncall。 cp_book_info 说明
字段名 类型 是否必传 字段描述 out_book_no string 是 外部预约单号,长度 <= 64 byte 响应示例
curl --location --request POST 'http://dev-cn.your-api-server.com/api/v2/create_order?timestamp=1345678901234&nonce=iuy987q4htafreqw' \
--header 'Content-Type: application/json' \
--data-raw '{
"version": "2.0",
"msg": "序列化后的json字符串",
"type": "pre_create_order"
}'
{
"err_no": 0,
"err_tips": "success",
"data": {
"out_order_no": "89876867867087",
"pay_expire_seconds": 300,
"order_entry_schema": {
"path": "page/refundDetail/xxx",
"params": "{\"id\": 1}"
},
"order_valid_time": [
{
"goods_id": "xxx",
"valid_start_time": 1232312000,
"valid_end_time": 1231231000
}
],
"order_goods_info": [
{
"goods_id": "xxx",
"merchant_uid": "12345"
}
]
}
}