21 KiB
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 字符串(如 interceptItemListResult、threshold_instruction)使用 \" 转义双引号,解析时需先 stripslashes 再 json_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() 中追加解析。