Files
datahub/docs/Tmall退款子项Attribute数据解析.md
T
2026-02-25 15:29:20 +08:00

21 KiB
Raw Blame History

Tmall 退款子项 Attribute 数据解析

概述

Tmall 退款子项(refund_item)的 attribute 字段是一个编码后的键值对字符串,包含退款单的完整业务上下文:商品信息、金额构成、资金渠道、物流拦截、优惠明细等。

该字段由 Refund::parseRefundItemAttribute(string $attribute) 方法解析为结构化数组。

相关代码路径:

  • 解析器:app/Platform/Tmall/EntityParse/Refund.php
  • 测试:test/Cases/Platform/Tmall/EntityParse/RefundAttributeParseTest.php

1. 编码格式

1.1 原始格式

;key1:value1;key2:value2;key3:value3;
  • 字段之间以 ;(分号)分隔
  • 键与值之间以 :(冒号,首个)分隔
  • 字符串可能以 ; 开头或结尾

1.2 字符编码规则

由于 ;: 被用作分隔符,值中出现的原始 ;: 会被转义

编码 解码后 说明
#3B : (冒号) 值中的冒号被替换为 #3B
#3A ; (分号) 值中的分号被替换为 #3A

注意:编码标识与 ASCII 码位相反 —— #3B; 的 ASCII 码,但在此编码中代表 :。这是 Tmall 的特定编码约定。

1.3 JSON 转义

attribute 中内嵌的 JSON 字符串(如 interceptItemListResultthreshold_instruction)使用 \" 转义双引号,解析时需先 stripslashesjson_decode

1.4 解码示例

原始: bgmtc:2026-02-24 13#3B47#3B41
解码: bgmtc = 2026-02-24 13:47:41

原始: sku:5085821404607|口味#3B橘子味#3A颜色分类#3B维C 250mg
解码: sku = 5085821404607|口味:橘子味;颜色分类:维C 250mg

2. 字段详解

2.1 基本信息

原始 key 解析后 key 类型 说明
bizCode biz_code string 业务编码。tmall.hk.refund = 天猫国际退款,tmall.refund = 天猫国内退款
sdkCode sdk_code string SDK 来源标识。如 ali.china.tmall.tmallhk
shop_name shop_name string 店铺名称
workflowName workflow_name string 工作流名称,通常为 refund
opRole op_role string 操作角色。daemon = 系统自动处理

2.2 商品信息

原始 key 解析后 key 类型 说明
sku sku object SKU 结构化对象,见下方 SKU 解析
itemBuyAmount item_buy_amount int 购买数量
itemPrice item_price int 商品 SKU 单价(分),注意这是原始标价,非实际成交价
leavesCat leaves_cat string 叶子类目 ID
rootCat root_cat string 根类目 ID
isVirtual is_virtual bool 是否虚拟商品

SKU 解析格式: SKU_ID|属性名:属性值;属性名:属性值

{
    "sku_id": "5085821404607",
    "properties": {
        "口味": "橘子味",
        "颜色分类": "维C 250mg"
    }
}

2.3 退款金额

所有金额单位均为 分(CNY

原始 key 解析后 key 类型 说明
apply_init_refund_fee apply_init_refund_fee int 申请退款金额(消费者发起退款时的金额)
EXmrf ex_max_refund_fee int 最大可退金额
ol_tf online_refund_fee int 在线退款金额
refundPostFee refund_post_fee int 退款运费
mainOrderPostFee main_order_post_fee int 主订单运费
toSellerFee to_seller_fee int 卖家应付金额

2.4 退款原因与类型

原始 key 解析后 key 类型 说明
apply_reason_text apply_reason_text string 退款原因文本,如 不喜欢/不想要
apply_text_id apply_text_id string 退款原因 ID,如 175001
disputeRequest dispute_request int 是否有纠纷请求(1=有)
disputeTradeStatus dispute_trade_status int 纠纷交易状态
DBT dbt string 退款业务类型(Dispute Business Type

DBT 常见值:

含义
InterceptUnconsignRefund 拦截未发货退款(仓库拦截成功后的退款)
RefundBySeller 卖家主动退款
RefundByBuyer 买家申请退款

2.5 退款特征标识

原始 key 解析后 key 类型 说明
clj_zero_second_refund clj_zero_second_refund bool 0秒闪电退款(关键判定字段,详见第 3 节)
tmgSimpleZeroRefund tmg_simple_zero_refund bool 简易0秒退款
warehouseRefund warehouse_refund bool 仓库退款
part_refund part_refund bool 部分退款
percent_refund percent_refund bool 比例退款
products products string 退款产品标识。timeoutrefund^ = 超时退款

2.6 资金流 (fundFlowInfo)

资金流描述了退款涉及的各支付渠道及金额分配。

原始格式: TYPE^GROUP^NAME^AMOUNT|TYPE^GROUP^NAME^AMOUNT

解析后为数组:

[
    {
        "type": "CASH",
        "group": "ALIPAY_FUND",
        "name": "支付宝",
        "amount": 15489
    },
    {
        "type": "OTHER_ASSETS",
        "group": "OTHER_ASSETS_GROUP",
        "name": "优惠",
        "amount": 2211
    }
]
字段 说明
type 资金类型。CASH = 现金,OTHER_ASSETS = 其他资产(优惠券、红包等)
group 资金组。ALIPAY_FUND = 支付宝,OTHER_ASSETS_GROUP = 优惠资产组
name 显示名称
amount 金额(分)
原始 key 解析后 key 类型 说明
payMode pay_mode string 支付方式。如 alipay
pay_lock pay_lock string 支付锁定方。system = 系统锁定

注意: 并非所有退款单都包含 fundFlowInfo。缺失时 fund_flow 返回空数组 []

2.7 优惠信息

pmtR 格式: TYPE^AMOUNT|TYPE^AMOUNT|

[
    {
        "type": "TAPP_USERCOUPON_SP",
        "amount": 2211
    }
]
优惠类型 (type) 说明
TAPP_USERCOUPON_SP 平台优惠券(满减券、消费券等)
原始 key 解析后 key 类型 说明
pmtR promotions array 优惠明细列表
has_threshold_coupon has_threshold_coupon bool 是否使用门槛优惠券
threshold_instruction threshold_instruction object 门槛券指令详情(JSON

2.8 价保信息

格式: START_TIME~END_TIME

{
    "start": "2026-02-24 13:47:45",
    "end": "2026-03-16 23:59:59"
}

表示该订单在此时间范围内享有价格保护,若商品降价可申请差价退款。

2.9 物流拦截

原始 key 解析后 key 类型 说明
interceptType intercept_type string 拦截类型。clj = 菜鸟物流
interceptStatus intercept_status int 拦截状态。2 = 拦截完成
interceptItemListResult intercept_items array 拦截结果明细(JSON),见下方
abilityTemplateCode ability_template_code string 能力模板。WAREHOUSE_INTERCEPT_ABILITY^1^2 = 仓库拦截
abilitySuccessFlag ability_success_flag bool 拦截能力是否执行成功
sellerOpAbWarehouseIntercept warehouse_intercept_op int 卖家仓库拦截操作状态

拦截结果示例:

[
    {
        "subBizOrderId": 5081613120736477027,
        "interceptDate": "Feb 24, 2026 1:48:02 PM",
        "logisticInterceptEnum": "INTERCEPT_SUCCESS"
    }
]
logisticInterceptEnum 含义
INTERCEPT_SUCCESS 拦截成功
INTERCEPT_FAIL 拦截失败

2.10 卖家 / 买家信息

原始 key 解析后 key 类型 说明
seller_batch seller_batch bool 是否批量处理
seller_audit seller_audit int 卖家审核状态。0 = 未审核
hasSellerMemo has_seller_memo bool 是否有卖家备注
userCredit user_credit int 买家信用等级(1-5,数值越大信用越高)
agreeSource agree_source string 退款同意来源。clj = 菜鸟系统自动同意

2.11 其他标识

原始 key 解析后 key 类型 说明
chnlObn channel_sub_order_id string 渠道子订单编号
lastOrder last_order bool 是否为主单的最后一笔子单
b2c b2c bool 是否 B2C 交易
bgmtc bgmtc string 退款后台创建时间

3. 「未发货0秒退」判定规则

3.1 业务背景

「未发货0秒退」(也称闪电退款、秒退)是指买家下单后立刻反悔申请退款的场景,常见于:

  • 买家下单后立即后悔
  • 凑单满减后取消多余订单
  • 下单后发现地址、规格错误

核心问题: Tmall 对此类订单不会推送原始订单数据到商家系统。因此通过标准订单 API 无法抽取到这些订单,只能通过退款单的 attribute 字段反向发现并重建订单信息。

3.2 判定条件

parseRefundItemAttribute 返回值中判定:

$attr = $parser->parseRefundItemAttribute($attribute);

// 核心判定字段
$isInstantRefund = $attr['clj_zero_second_refund'] === true;

clj_zero_second_refund 是唯一的判定依据。当值为 true 时,该退款单对应的订单属于「未发货0秒退」。

3.3 辅助佐证字段

以下字段通常与 clj_zero_second_refund = true 同时出现,可用于交叉验证:

字段 典型值 含义
tmg_simple_zero_refund true 简易0秒退款标记
warehouse_refund true 仓库退款(货物尚在仓库中)
dbt InterceptUnconsignRefund 拦截未发货退款
intercept_type clj 菜鸟物流拦截
intercept_items[].logisticInterceptEnum INTERCEPT_SUCCESS 拦截成功
agree_source clj 菜鸟系统自动同意退款
op_role daemon 系统自动处理(非人工)
products timeoutrefund^ 超时退款产品标识

3.4 判定流程图

退款子项 refund_item
    │
    ▼
解析 attribute 字段
    │
    ▼
clj_zero_second_refund == true ?
    │
    ├─ YES → 「未发货0秒退」
    │         │
    │         ▼
    │     该退款对应的订单在 orders 表中可能不存在
    │         │
    │         ▼
    │     需要调用 fixInstantRefundOrders() 重建订单
    │
    └─ NO  → 正常退款流程,订单应已存在于 orders 表

3.5 与 RefundType 的关系

系统 RefundType 枚举中 INSTANT_REFUND_WITHOUT_RETURN (=5) 对应此场景:

RefundType 说明 对应 attribute 判定
RETURN_BEFORE_SHIPPING 1 未发货前退款(常规) good_status = BUYER_NOT_RECEIVED
RETURN_AND_REFUND 2 退货退款 has_good_return = true
PARTIAL_REFUND 3 退货后部分退款
REFUND_WITHOUT_RETURN 4 无须退货的退款 good_status = BUYER_RECEIVED
INSTANT_REFUND_WITHOUT_RETURN 5 闪电退款(0秒退) clj_zero_second_refund = true

注意:getRefundTypeId() 基于退款 API 的 has_good_return / good_status 字段判定退款类型。而 clj_zero_second_refund 来自 attribute 字段,是更细粒度的闪电退款判定。两者配合使用可精确识别退款类型。


4. 退款金额构成与还原

4.1 金额要素关系

退款单中涉及多个金额字段,它们的关系如下:

商品 SKU 标价 (item_price)
    │
    ├─ 平台优惠(官方立减等)→ 不在 attribute 中,需从订单获取
    │
    ▼
商品实际成交价(不直接存在于 attribute)
    │
    ├─ 优惠券抵扣 (promotions)
    │
    ▼
用户实际支付金额(现金部分)

4.2 attribute 中可获取的金额

字段 含义 示例
item_price SKU 标价(非成交价) 39900 (¥399.00)
apply_init_refund_fee 退款金额 = 成交价 - 平台优惠 17700 (¥177.00)
ex_max_refund_fee 最大可退金额(通常 = 退款金额) 17700 (¥177.00)
online_refund_fee 在线退款金额(通常 = 退款金额) 17700 (¥177.00)
promotions[].amount 优惠券金额 2211 (¥22.11)
fund_flow[].amount 各渠道退回金额明细 见下方

4.3 从 attribute 还原支付金额

以真实样本 A 为例(商品:维C 250mg 橘子味):

消费者视角的订单明细(来自消费者端页面):

商品总价               ¥ 893.00       ← attribute 中不存在
官方立减             - ¥ 224.00       ← attribute 中不存在
红包/优惠券          - ¥  65.89       ← promotions (部分使用)
运费                   ¥   0.00       ← main_order_post_fee
实付款                 ¥ 603.11       ← 需通过 fund_flow 计算

attribute 中可以确定的等式:

退款金额 (apply_init_refund_fee) = 商品成交价 - 平台补贴
                                  = 商品总价 - 官方立减
                          17700分 = ¥177.00

实际退回 = fund_flow 中各渠道金额之和
         = CASH(支付宝) + OTHER_ASSETS(优惠)
         = 15489 + 2211
         = 17700分 = ¥177.00

4.4 金额还原公式

可直接计算的:

退款总额 = apply_init_refund_fee = ex_max_refund_fee = online_refund_fee
         = Σ fund_flow[i].amount  (当 fund_flow 存在时)

用户现金退回 = fund_flow 中 type=CASH 的 amount 之和
优惠资产退回 = fund_flow 中 type=OTHER_ASSETS 的 amount 之和

无法直接从 attribute 计算的:

商品成交价 = 退款金额 + 平台补贴(官方立减等)
            → 平台补贴不在 attribute 中

用户实际支付 = 退款金额 - 优惠券抵扣
             = apply_init_refund_fee - Σ promotions[i].amount
             = 17700 - 2211
             = 15489分 = ¥154.89

SKU标价与成交价差 = item_price - (退款金额 + 平台补贴)
                   → 无法精确计算,因为平台补贴未知

4.5 fund_flow 存在时的完整还原

fund_flow 存在时,可以精确知道各渠道的退款去向:

退款金额 ¥177.00
    │
    ├─ CASH / ALIPAY_FUND / 支付宝     → ¥154.89  (退回支付宝余额)
    │
    └─ OTHER_ASSETS / 优惠             → ¥ 22.11  (退回优惠券/红包)

验证: ¥154.89 + ¥22.11 = ¥177.00 ✓

4.6 fund_flow 缺失时的近似推算

fund_flow 不存在时(如样本 B),只能用 promotions 近似推算:

退款金额 (apply_init_refund_fee)     = 66900 (¥669.00)
优惠券抵扣 (promotions[0].amount)    =  6589 (¥ 65.89)

用户现金退回 ≈ 退款金额 - 优惠券
             = 66900 - 6589
             = 60311 (¥603.11)

此为近似值。在多种优惠叠加(多张券、跨店满减等)的场景下,promotions 可能不完整。fund_flow 是唯一可靠的渠道拆分数据源。

4.7 金额关系总结图

┌─────────────────────────────────────────────────┐
│              SKU 标价 (item_price)               │
│                   ¥399.00                        │
├──────────────────┬──────────────────────────────┤
│   平台补贴(未知)  │    商品成交价(未知)            │
│                  │         ¥???                  │
│                  ├──────────────────────────────┤
│                  │ 退款金额 (apply_init_refund_fee)│
│                  │         ¥177.00                │
│                  ├────────────┬─────────────────┤
│                  │ 优惠券退回   │   现金退回        │
│                  │ ¥22.11     │   ¥154.89       │
│                  │ (OTHER_ASSETS) │  (CASH)      │
│                  │ → 退回红包   │  → 退回支付宝    │
└──────────────────┴────────────┴─────────────────┘

可从 attribute 获取: ■  退款金额、优惠券退回、现金退回
无法从 attribute 获取: □  SKU标价→成交价的差额(平台补贴)

5. 完整字段速查表

# 原始 key 解析后 key 类型 分组
1 bizCode biz_code string 基本信息
2 sdkCode sdk_code string 基本信息
3 shop_name shop_name string 基本信息
4 workflowName workflow_name string 基本信息
5 opRole op_role string 基本信息
6 sku sku object 商品信息
7 itemBuyAmount item_buy_amount int 商品信息
8 itemPrice item_price int(分) 商品信息
9 leavesCat leaves_cat string 商品信息
10 rootCat root_cat string 商品信息
11 isVirtual is_virtual bool 商品信息
12 apply_init_refund_fee apply_init_refund_fee int(分) 退款金额
13 EXmrf ex_max_refund_fee int(分) 退款金额
14 ol_tf online_refund_fee int(分) 退款金额
15 refundPostFee refund_post_fee int(分) 退款金额
16 mainOrderPostFee main_order_post_fee int(分) 退款金额
17 toSellerFee to_seller_fee int(分) 退款金额
18 apply_reason_text apply_reason_text string 退款原因
19 apply_text_id apply_text_id string 退款原因
20 disputeRequest dispute_request int 退款原因
21 disputeTradeStatus dispute_trade_status int 退款原因
22 DBT dbt string 退款原因
23 clj_zero_second_refund clj_zero_second_refund bool 退款标识
24 tmgSimpleZeroRefund tmg_simple_zero_refund bool 退款标识
25 warehouseRefund warehouse_refund bool 退款标识
26 part_refund part_refund bool 退款标识
27 percent_refund percent_refund bool 退款标识
28 products products string 退款标识
29 fundFlowInfo fund_flow array 资金流
30 payMode pay_mode string 资金流
31 pay_lock pay_lock string 资金流
32 pmtR promotions array 优惠信息
33 has_threshold_coupon has_threshold_coupon bool 优惠信息
34 threshold_instruction threshold_instruction object 优惠信息
35 price_protection price_protection object 价保
36 interceptType intercept_type string 物流拦截
37 interceptStatus intercept_status int 物流拦截
38 interceptItemListResult intercept_items array 物流拦截
39 abilityTemplateCode ability_template_code string 物流拦截
40 abilitySuccessFlag ability_success_flag bool 物流拦截
41 sellerOpAbWarehouseIntercept warehouse_intercept_op int 物流拦截
42 seller_batch seller_batch bool 卖家/买家
43 seller_audit seller_audit int 卖家/买家
44 hasSellerMemo has_seller_memo bool 卖家/买家
45 userCredit user_credit int 卖家/买家
46 agreeSource agree_source string 卖家/买家
47 chnlObn channel_sub_order_id string 其他
48 lastOrder last_order bool 其他
49 b2c b2c bool 其他
50 bgmtc bgmtc string 其他

6. 未解析的原始字段

以下字段存在于 attribute 中但未纳入结构化解析(多为 Tmall 内部标识,业务价值较低):

key 说明
sgr 内部标识
nrp 新退款流程标识
rp3 退款 3.0 标识
sars 售后服务标识 (skip = 跳过)
tos 超时策略
tod 超时时长(ms),如 86400000 = 24小时
fps 内部标识
newUltron Ultron 版本
r_r_l 退款原因层级
newRefund 退款版本(如 rp2
appName 应用名(如 rtee
_F_tlmType 天猫类型(如 B_taobao
_F_uplus UPlus 标识
enfunddetail 是否启用资金明细
agrExctT 退款同意精确时间戳(ms
agrExctd 退款同意是否已执行
sellerFlag 卖家标记
jibuBizCode 极步业务编码(如 tmall.jibu
sync 同步标识
cPartRefund C端部分退款标识

如有业务需要,可在 parseRefundItemAttribute() 中追加解析。