436 lines
20 KiB
Markdown
436 lines
20 KiB
Markdown
# Spec 01:多租户媒体发布平台(余额隔离 / 订单与退款 / 内容定价)
|
||
|
||
> 目标:把“同一用户属于多个租户、租户可为用户充值、余额仅能在当前租户消费、租户管理员可查看订单并退款、管理员发布内容可配置价格与折扣”等需求落到可实现的业务规格,作为后续数据模型/API/权限/流程实现依据。
|
||
|
||
## 1. 背景与范围
|
||
|
||
### 1.1 背景
|
||
- 平台支持视频/音频/图片的媒体内容发布与售卖(或付费访问)。
|
||
- 平台面向多租户(Tenant):不同租户之间的数据、资金、内容必须严格隔离。
|
||
- 同一用户(User)可加入多个租户;在每个租户内拥有独立的“租户内余额”用于消费该租户内的业务。
|
||
- 租户管理员(Tenant Admin)能对订单进行查看、发起退款等操作;管理员发布的内容可配置价格与折扣策略。
|
||
|
||
### 1.2 本 spec 覆盖
|
||
- 多租户身份与权限:同一用户多租户归属、租户内角色。
|
||
- 余额体系:租户为用户充值、租户内余额隔离、消费与退款回滚。
|
||
- 商品与订单:内容定价、折扣、下单、扣款、退款、订单审计。
|
||
- 媒体发布:内容/媒体资源的基础生命周期(上传、审核/上架、购买/访问)。
|
||
|
||
### 1.3 明确不做(暂定)
|
||
- 广告分发、推荐算法、复杂分账(创作者分成)、第三方支付直连(如微信/支付宝)细节。
|
||
- 版权确权、内容风控/涉政涉黄自动审核体系(仅预留状态与接口)。
|
||
- 跨租户资产迁移、跨租户合并结算。
|
||
|
||
## 2. 角色与核心术语
|
||
|
||
### 2.1 角色(Actors)
|
||
- 平台超级管理员(Super Admin):平台级别的租户管理/风控/对账(可选,视项目现状)。
|
||
- 租户管理员(Tenant Admin):租户内运营角色;发布内容、设置价格与折扣、查看订单与退款。
|
||
- 租户成员(Member):属于某租户的普通用户;可消费该租户内容、可发布内容(若租户开放)。
|
||
- 游客/未加入租户用户:只能浏览公开内容(若允许),不可使用租户余额。
|
||
|
||
### 2.2 核心术语
|
||
- Tenant(租户):逻辑隔离域,拥有自己的内容、订单、余额账本规则。
|
||
- TenantUser(租户成员关系):User 在某个 Tenant 下的身份载体(含 role、balance、状态等)。
|
||
- Balance(余额):以 TenantUser 为维度的可用余额;只可在当前 Tenant 内消费与退款回滚。
|
||
- Ledger(账本/流水):所有余额变动必须落到可审计流水(增、减、冻结/解冻、退款)。
|
||
- Content(内容):一条可出售/可访问的媒体内容实体(可关联多媒体资源)。
|
||
- MediaAsset(媒体资源):视频/音频/图片的文件对象(含转码/封面/时长/尺寸等元数据)。
|
||
- Price(价格):内容在某租户内的定价;折扣可作用于价格形成最终成交价。
|
||
- Order(订单):用户在租户内对内容的购买/消费记录;支持退款。
|
||
|
||
## 3. 多租户与权限模型
|
||
|
||
### 3.1 多租户原则
|
||
- 所有业务数据必须带 `tenant_id`(或可推导的 tenant 归属),并在查询/写入时强制校验租户边界。
|
||
- 同一 user 在不同 tenant 下的余额、订单、内容访问权限互不影响。
|
||
|
||
### 3.2 租户内角色(最小集合)
|
||
- `member`:默认角色。
|
||
- `tenant_admin`:租户管理员。
|
||
|
||
> 备注:代码侧已有 `TenantUserRole`(member/tenant_admin),可以作为对齐基准。
|
||
|
||
### 3.3 权限矩阵(建议)
|
||
- member:
|
||
- 可查看本租户可见内容(公开/已购买/订阅等策略见后文)。
|
||
- 可用本租户余额购买内容/消费服务。
|
||
- 可查看自己的订单与余额流水。
|
||
- tenant_admin:
|
||
- 拥有 member 的所有权限。
|
||
- 可创建/编辑/下架内容;配置价格与折扣。
|
||
- 可查看租户内订单(按条件检索/导出)。
|
||
- 可发起退款(遵循退款规则/风控规则)。
|
||
- 可为租户内用户充值(如果业务允许“租户给用户发放额度”)。
|
||
- super admin(可选):
|
||
- 可查看全平台租户与全局审计(不在本 spec 强制实现,但建议预留)。
|
||
|
||
## 4. 余额体系(Tenant 内隔离)
|
||
|
||
### 4.1 账户维度
|
||
- 余额账户 = `TenantUser` 维度(tenant_id + user_id)。
|
||
- `balance_available`(可用余额):可直接消费。
|
||
- `balance_frozen`(冻结余额,可选):用于“待支付/待确认/争议期”等场景,避免并发重复扣款。
|
||
|
||
> 你已确认需要冻结机制(5.B)。当前项目已有 `tenant_users.balance`(bigint),可作为 `balance_available` 的第一版;建议新增 `balance_frozen`(bigint)并配套流水类型 `freeze/unfreeze`。
|
||
|
||
### 4.2 充值(租户为用户充值)
|
||
定义:租户向其成员发放/充值额度,用户只能在该租户内使用。
|
||
|
||
规则建议:
|
||
- 充值必须产生一条“充值订单”或“余额流水”(建议两者都存在:订单做业务视角,流水做账本视角)。
|
||
- 充值需支持幂等:相同外部业务单号/请求幂等键重复请求,不可重复入账。
|
||
- 充值来源(可枚举):
|
||
- `tenant_grant`:租户后台人工/批量发放额度。
|
||
- `user_pay`:用户实际支付购买额度(本期不做,仅预留)。
|
||
|
||
### 4.3 消费(余额扣减)
|
||
定义:用户在租户内使用余额购买内容(或支付发布/服务费用)。
|
||
|
||
你已确认“消费=购买租户内付费内容”(1.A),本 spec 将仅覆盖 `content_purchase`,发布收费等其他计费暂不纳入本期范围。
|
||
|
||
关键规则:
|
||
- 订单必须绑定 `tenant_id`,扣款只能操作该 `tenant_id` 下的 `TenantUser` 余额。
|
||
- 扣款以“最终成交价”为准,成交价由“基础价 + 折扣/优惠”计算。
|
||
- 余额不足则拒绝下单/支付。
|
||
- 需要防止并发超卖/重复扣款:建议在创建支付时使用冻结余额或基于数据库事务 + 行锁。
|
||
|
||
### 4.4 退款(订单退款回滚余额)
|
||
定义:租户管理员可对订单发起退款,退款金额回到原租户余额账户。
|
||
|
||
规则建议:
|
||
- 退款必须可追溯:关联原订单、原扣款流水。
|
||
- 支持两种策略(二选一或都做):
|
||
1) 全额退款:仅允许对未消费/未解锁的内容退款。
|
||
2) 部分退款:按已消费比例/争议裁决退款(需要更复杂的计费与权益计算)。
|
||
- 你已确认仅做“全额退款 + 限时间窗”(4.A):
|
||
- 默认规则:`refundable_until = paid_at + 24h`;
|
||
- 管理侧强制退款:`tenant_admin` 可忽略时间窗强制退款(必须写明原因并强审计)。
|
||
- 退款结果必须幂等:同一笔退款请求不可重复入账。
|
||
- 退款权限:仅 `tenant_admin`(或更高)可操作;member 只能发起“退款申请”。
|
||
|
||
## 5. 内容与媒体模型
|
||
|
||
### 5.1 MediaAsset(媒体资源)
|
||
支持类型:
|
||
- video:原始文件 + 转码产物 + 封面 + 时长 + 分辨率 + 编码信息
|
||
- audio:原始文件 + 转码产物 + 时长 + 码率
|
||
- image:原始文件 + 缩略图 + 尺寸
|
||
|
||
最小字段建议:
|
||
- `id`
|
||
- `tenant_id`
|
||
- `user_id`
|
||
- `type`(video/audio/image)
|
||
- `storage_provider`、`bucket`、`object_key`(或 url)
|
||
- `status`(uploaded/processing/ready/failed/deleted)
|
||
- `meta`(JSON:时长/尺寸/码率/哈希等)
|
||
- `created_at/updated_at`
|
||
|
||
### 5.2 Content(内容)
|
||
一条内容可以关联 0..N 个媒体资源(例如:视频+封面图+音频)。
|
||
|
||
最小字段建议:
|
||
- `id`
|
||
- `tenant_id`
|
||
- `user_id`
|
||
- `title`、`description`
|
||
- `status`(draft/reviewing/published/unpublished/blocked)
|
||
- `visibility`(public/tenant_only/private;可扩展)
|
||
- `preview_seconds`(默认 60)
|
||
- `preview_downloadable`(默认 false)
|
||
- `published_at`
|
||
- `created_at/updated_at`
|
||
|
||
## 6. 定价与折扣
|
||
|
||
### 6.1 定价模型(建议)
|
||
价格以“最小货币单位”存储(例如分),避免浮点误差:
|
||
- `price_amount`(int64,单位分)
|
||
- `currency`(本期固定 CNY;多币种为后续扩展)
|
||
|
||
### 6.2 折扣模型(建议最小集合)
|
||
折扣针对内容的成交价计算,可先实现“单一折扣规则”:
|
||
- `discount_type`:
|
||
- `none`
|
||
- `percent`(如 20% off)
|
||
- `amount`(立减)
|
||
- `discount_value`:percent(0-100) 或 amount(分)
|
||
- `discount_start_at` / `discount_end_at`(可选)
|
||
|
||
计算规则:
|
||
- percent:`final = price_amount * (100 - percent) / 100`
|
||
- amount:`final = max(0, price_amount - amount)`
|
||
- 必须记录下单时的“成交快照”(避免事后改价影响历史订单)。
|
||
|
||
### 6.3 谁能设置
|
||
- 仅 `tenant_admin` 可为其发布的内容设置/修改价格与折扣。
|
||
- 如果未来允许“作者发布但管理员定价”,需要在权限上增加“作者/运营”区分。
|
||
|
||
## 7. 订单模型(购买内容)
|
||
|
||
### 7.1 订单类型(建议)
|
||
为后续扩展预留 `order_type`:
|
||
- `content_purchase`:购买内容(本 spec 核心)
|
||
- `topup`:充值订单(租户发放/用户支付)
|
||
> 你已确认本期只做 1.A + 2.A,因此 `content_purchase` + `topup(tenant_grant)` 为主,`user_pay`/`service_fee` 仅作为未来扩展位保留。
|
||
|
||
### 7.2 订单状态(建议)
|
||
以余额支付为例(不接三方):
|
||
- `created`:已创建待支付(可选,若立即扣款可跳过)
|
||
- `paid`:已扣款/支付成功
|
||
- `refunding`:退款处理中
|
||
- `refunded`:已退款
|
||
- `canceled`:已取消(未扣款)
|
||
- `failed`:失败(扣款失败/规则校验失败)
|
||
|
||
冻结机制下的状态约束建议:
|
||
- 进入 `paid` 前如发生错误(例如订单落库失败),必须执行 `unfreeze` 回滚冻结余额,并将订单标记为 `failed` 或不落库(但需保证幂等返回一致)。
|
||
- 你已确认:订单创建成功但写 `debit_purchase` 失败时,不保留该订单记录;幂等返回“失败 + 已回滚冻结”。
|
||
|
||
### 7.3 订单字段建议
|
||
- `id`
|
||
- `tenant_id`
|
||
- `buyer_user_id`
|
||
- `order_type`
|
||
- `amount_original`(原价)
|
||
- `amount_discount`(优惠金额)
|
||
- `amount_paid`(实付)
|
||
- `currency`
|
||
- `status`
|
||
- `snapshot`(JSON:下单时价格/折扣/内容标题等快照)
|
||
- `created_at/paid_at/refunded_at`
|
||
> 订单操作者如需审计,建议使用 `operator_user_id`(例如后台代下单/代退款),或在 `snapshot` 中记录。
|
||
|
||
### 7.4 订单明细(OrderItem,建议)
|
||
内容购买通常 1 单 1 内容,但用明细便于扩展:
|
||
- `order_id`
|
||
- `content_id`
|
||
- `content_owner_user_id`(可选,用于后续分成/对账)
|
||
- `amount_line`(该行实付)
|
||
- `snapshot`(内容快照)
|
||
|
||
## 8. 余额流水(账本 Ledger)
|
||
|
||
### 8.1 设计原则
|
||
- 余额的每一次变化都必须有流水记录,可审计、可对账、可回放。
|
||
- 流水必须带 `tenant_id` 与 `tenant_user_id`(或 tenant_id+user_id)。
|
||
- 所有入账/出账/退款都强制关联“业务单据”(订单/退款单)。
|
||
|
||
### 8.2 流水类型(建议)
|
||
- `credit_topup`:充值入账
|
||
- `debit_purchase`:购买扣款
|
||
- `credit_refund`:退款回滚
|
||
- `freeze` / `unfreeze`:冻结/解冻(可选)
|
||
- `adjustment`:人工调账(需强审计)
|
||
|
||
### 8.3 幂等与一致性
|
||
- 流水表建议使用 `idempotency_key` 或 `biz_ref_type + biz_ref_id` 做唯一约束,防止重复入账。
|
||
- 扣款与订单状态更新必须在一个事务内完成(或使用可靠消息最终一致)。
|
||
|
||
## 9. 关键流程(建议版)
|
||
|
||
### 9.1 加入租户
|
||
1) user 通过邀请/申请加入 tenant
|
||
2) 创建 `TenantUser(tenant_id,user_id,role=member,balance=0)`
|
||
3) tenant_admin 可提升为 `tenant_admin`
|
||
|
||
### 9.2 租户为用户充值
|
||
1) tenant_admin 在后台选择 tenant_user、输入金额、填写备注/原因
|
||
2) 创建 `topup` 订单(或 topup 记录)
|
||
3) 写入 ledger:`credit_topup`
|
||
4) 增加 tenant_user.balance
|
||
5) 返回充值结果与可用余额
|
||
|
||
### 9.3 用户购买内容(余额支付)
|
||
1) buyer 选择 tenant 下某 content
|
||
2) 系统计算成交价(读取当前 price+discount),生成订单快照
|
||
3) 校验余额足够、内容可售、用户在该 tenant 下有效
|
||
4) 冻结余额:写入 ledger:`freeze`,`balance_available -= amount_paid`,`balance_frozen += amount_paid`
|
||
5) 创建订单(status=paid 或 created→paid)
|
||
6) 扣款落账:写入 ledger:`debit_purchase`,`balance_frozen -= amount_paid`(表示冻结转为最终扣款)
|
||
7) 写入“购买权益”(见 9.5)
|
||
|
||
失败回滚(必须):
|
||
- 若步骤 4 成功而步骤 5/6 失败:必须写入 `unfreeze` 并回滚余额(`balance_available += amount_paid`,`balance_frozen -= amount_paid`),同时保证幂等键再次请求能返回最终一致结果。
|
||
- 若步骤 5 成功但步骤 6 失败:执行 `unfreeze` 回滚后不落库订单,并对该幂等键固定返回“失败+已回滚”(不可重复创建新订单)。
|
||
|
||
### 9.4 租户管理员退款
|
||
1) tenant_admin 选中订单,校验可退款(状态/风控/时间窗)
|
||
2) 创建退款记录(可选),订单状态→refunding
|
||
3) 写入 ledger:`credit_refund`(金额=退款金额)
|
||
4) 增加 tenant_user.balance(可用余额)
|
||
5) 订单状态→refunded,记录 refunded_at 与操作者
|
||
6) 收回/标记权益(若需要)
|
||
|
||
你已确认退款对权益的处理:
|
||
- 退款成功后,将对应 `content_access.status` 置为 `revoked`(立即失效)。
|
||
|
||
### 9.5 购买权益(访问控制)
|
||
最小实现建议:记录 `content_access`(tenant_id, content_id, user_id, order_id, status, created_at)。
|
||
- 访问内容时,校验:
|
||
- content 是否公开(public)或
|
||
- user 是否拥有 `content_access` 且有效
|
||
|
||
你已确认需要“试看/预览”(3.B),建议增加:
|
||
- `content_assets.role=preview`(或单独字段),允许未购买用户访问 preview 资源;
|
||
- 正片资源(main)仍需 `content_access` 校验;
|
||
- 订单快照中记录“当时预览策略”,避免策略变更导致争议。
|
||
|
||
预览边界建议(最小可用):
|
||
- preview 资源必须与 main 资源彻底区分(不同 object_key / 不同转码模板),避免客户端绕过。
|
||
- preview 可以额外加频控/防盗链(后续),但不影响本期的租户隔离与权益校验。
|
||
|
||
你已确认的试看策略:
|
||
- 固定时长试看:默认前 `60s`(仅 streaming,不允许下载)。
|
||
|
||
## 10. 查询与后台能力(Tenant Admin)
|
||
|
||
### 10.1 订单查询
|
||
筛选条件建议:
|
||
- 时间范围(created_at/paid_at)
|
||
- buyer_user_id / 用户关键字
|
||
- content_id / 内容标题关键字
|
||
- 订单状态、订单类型
|
||
- 金额范围
|
||
|
||
### 10.2 退款操作
|
||
输入项建议:
|
||
- 退款金额(默认=实付)
|
||
- 退款原因(枚举 + 备注)
|
||
- 是否立即生效(余额体系通常立即入账)
|
||
|
||
输出与审计:
|
||
- 记录操作者、操作时间、原订单快照、退款快照、对应流水 id
|
||
|
||
## 11. 已确认的关键决策(用于锁定实现)
|
||
|
||
你已确认:
|
||
- 消费=购买租户内付费内容(1.A)
|
||
- 充值来源=仅租户后台发放额度(2.A)
|
||
- 内容支持试看/预览(3.B):固定时长前 `60s`,不允许下载
|
||
- 退款=全额退款 + 默认时间窗 `paid_at + 24h`,且租户管理侧允许强制退款(需强审计)
|
||
- 余额需要冻结机制(5.B),并要求“失败回滚 + 幂等返回一致”
|
||
- 金额=仅 CNY(分)(6.A)
|
||
|
||
## 12. 里程碑拆分(建议)
|
||
- M1:TenantUser 余额隔离 + 充值入账 + 余额支付下单 + 订单查询 + 全额退款。
|
||
- M2:内容发布全链路(media asset/processing 状态)、内容访问权益、折扣生效与订单快照。
|
||
- M3:冻结/部分退款/风控规则/对账导出/批量充值。
|
||
|
||
## 13. 数据模型草案(供对齐)
|
||
|
||
> 注:字段名为建议,最终以现有项目的命名/生成器约束为准。金额统一用 `int64`(分)。
|
||
|
||
### 13.1 tenant_users(已存在,建议扩展方向)
|
||
- `tenant_id`, `user_id`
|
||
- `role`(member/tenant_admin)
|
||
- `balance`(可用余额,已存在)
|
||
- (可选)`balance_frozen`
|
||
- `status`(active/disabled/pending 等)
|
||
|
||
### 13.2 media_assets
|
||
- `id`, `tenant_id`, `user_id`, `type`
|
||
- `status`(uploaded/processing/ready/failed/deleted)
|
||
- `provider`, `bucket`, `object_key`(或 `url`)
|
||
- `meta`(JSON:hash、duration、width、height、bitrate、codec...)
|
||
- `created_at`, `updated_at`
|
||
|
||
### 13.3 contents
|
||
- `id`, `tenant_id`, `user_id`
|
||
- `title`, `description`
|
||
- `status`(draft/reviewing/published/unpublished/blocked)
|
||
- `visibility`(public/tenant_only/private)
|
||
- `published_at`, `created_at`, `updated_at`
|
||
|
||
### 13.4 content_assets(内容与媒体关联表)
|
||
- `tenant_id`, `content_id`, `asset_id`
|
||
- `role`(main/cover/preview 等)
|
||
- `sort`
|
||
|
||
### 13.5 content_prices(内容定价;或直接放 contents)
|
||
- `tenant_id`, `user_id`, `content_id`
|
||
- `currency`
|
||
- `price_amount`
|
||
- `discount_type`, `discount_value`
|
||
- `discount_start_at`, `discount_end_at`
|
||
- `updated_at`
|
||
|
||
### 13.6 orders / order_items
|
||
- orders:
|
||
- `id`, `tenant_id`, `buyer_user_id`, `order_type`, `status`
|
||
- `amount_original`, `amount_discount`, `amount_paid`, `currency`
|
||
- `snapshot`(JSON),`idempotency_key`(唯一)
|
||
- `created_at`, `paid_at`, `refunded_at`
|
||
- order_items:
|
||
- `order_id`, `tenant_id`, `content_id`
|
||
- `amount_line`
|
||
- `snapshot`(JSON)
|
||
|
||
### 13.7 balance_ledgers(强烈建议新增)
|
||
- `id`, `tenant_id`, `user_id`(或 `tenant_user_id`)
|
||
- `direction`(credit/debit)
|
||
- `type`(credit_topup/debit_purchase/credit_refund/...)
|
||
- `amount`(正数)
|
||
- `balance_before`, `balance_after`(可选但强审计)
|
||
- `biz_ref_type`, `biz_ref_id`(唯一约束,幂等)
|
||
- `operator_user_id`(谁触发:admin/buyer/system)
|
||
- `note`, `created_at`
|
||
|
||
### 13.8 content_access(购买权益)
|
||
- `tenant_id`, `content_id`, `user_id`, `order_id`
|
||
- `status`(active/revoked/expired)
|
||
- `created_at`, `revoked_at`
|
||
|
||
## 14. API 草案(只描述意图,不锁死路径)
|
||
|
||
### 14.1 租户侧(Tenant Admin)
|
||
- 充值:
|
||
- `POST /tenants/:tenant_id/users/:user_id/topup`(amount, note, idempotency_key)
|
||
- 订单查询:
|
||
- `GET /tenants/:tenant_id/orders`(分页+筛选)
|
||
- `GET /tenants/:tenant_id/orders/:id`
|
||
- 退款:
|
||
- `POST /tenants/:tenant_id/orders/:id/refund`(amount?, reason, idempotency_key)
|
||
- 内容管理:
|
||
- `POST /tenants/:tenant_id/contents`(草稿)
|
||
- `PATCH /tenants/:tenant_id/contents/:id`(编辑/上架/下架)
|
||
- `PUT /tenants/:tenant_id/contents/:id/price`(价格+折扣)
|
||
|
||
### 14.2 用户侧(Member)
|
||
- 浏览内容:
|
||
- `GET /tenants/:tenant_id/contents`(可见列表)
|
||
- `GET /tenants/:tenant_id/contents/:id`
|
||
- 购买:
|
||
- `POST /tenants/:tenant_id/orders`(content_id, idempotency_key)
|
||
- 我的订单/余额:
|
||
- `GET /tenants/:tenant_id/me/orders`
|
||
- `GET /tenants/:tenant_id/me/balance`
|
||
- `GET /tenants/:tenant_id/me/ledgers`
|
||
|
||
## 15. 边界条件与非功能要求(落地时容易踩坑)
|
||
|
||
### 15.1 并发与一致性
|
||
- 同一用户并发下单:必须避免“余额被扣成负数”(事务行锁/冻结机制/乐观锁三选一)。
|
||
- 同一幂等键重复请求:返回同一订单/同一结果,不重复扣款/入账。
|
||
- 价格/折扣被修改:历史订单不受影响,必须依赖订单快照。
|
||
|
||
### 15.2 多租户隔离
|
||
- 任何带 `order_id/content_id/asset_id` 的 API,都必须校验其 `tenant_id` 属于当前上下文租户。
|
||
- 后台“按用户查询订单/余额”也必须限定到租户维度,避免跨租户泄露。
|
||
|
||
### 15.3 金额与舍入
|
||
- 金额统一使用整数分;percent 折扣的舍入规则需要固定(建议向下取整),并写入订单快照。
|
||
|
||
### 15.4 审计与追责
|
||
- 充值、退款、调账必须记录 `operator_user_id`、原因、时间、请求来源。
|
||
- 建议为后台敏感操作增加二次确认/权限分级(后续)。
|
||
|
||
### 15.6 试看与禁下载(3.B 已确认)
|
||
- 必须从“资源形态”上实现禁下载:preview 仅提供 60s 的独立转码产物,不复用 main 资源。
|
||
- 媒体访问接口仅下发短时效播放凭证/地址(例如签名 URL/Token),避免返回可长期复用的直链。
|
||
- 客户端不提供“下载”入口不构成安全措施,服务端与存储策略必须生效。
|
||
|
||
### 15.5 可观测性
|
||
- 关键链路(下单扣款/退款入账/上传处理)打点日志:tenant_id、user_id、biz_ref、耗时、结果码。
|