Appearance
字段约定
清结算模式
settlementMode | 含义 |
|---|---|
CXH_DEDUCT | CXH 代扣模式。用户在 CXH 完成绑卡,后续 CXH 调通道扣款。扣款成功才计费、才发权益。 |
CHANNEL_COLLECT | 渠道收单模式。渠道自有支付体系收款,CXH 在下单成功的同时开账并发权益。退款由渠道自行处理,CXH 不参与。 |
每个订阅在 订阅下单 时由入参显式指定,事后不可修改。同一渠道下不同 SPU 可走不同模式。
状态枚举(两层分离)
设计原则:
- 主订单状态(
orderStatus) 表达订阅业务生命周期,不含支付动作 - 子订单状态(
paymentStatus) 表达单期支付与账务结果 - 判断"首扣是否成功"应查看
paymentRecords[0].paymentStatus,而非orderStatus
主订单 orderStatus
| 值 | 含义 | A 模式 | B 模式 |
|---|---|---|---|
INITIALIZING | 已下单,等待首期处理 | ✓(首扣 PROCESSING 时短暂出现) | — |
ACTIVE | 订阅活跃中(首期已生效) | ✓ | ✓ |
COMPLETED | 全部期次自然完结 | ✓ | ✓ |
UNSUBSCRIBED | 已解约 | ✓ | ✓ |
TERMINATED | 订阅未生效即终止(A 模式首扣彻底失败) | ✓ | — |
子订单 paymentStatus
| 值 | 含义 | A | B |
|---|---|---|---|
WAIT | 排队等扣款 | ✓ | — |
PROCESSING | 支付确认中(通道异步处理) | ✓ | — |
SUCCESS | 扣款成功 | ✓ | — |
FAIL_RETRY | 续费期扣款失败,等待 retry job 重试;首扣不会返回 | ✓ | — |
FAIL | 扣款失败终态,放弃 | ✓ | — |
BILLED | 已开账;权益已发,渠道侧实际扣款结果未知 | — | ✓ |
CANCELED | 主订单解约导致此期作废(仅未来期) | ✓ | ✓ |
REFUND_PART | 部分退款 | ✓ | — |
REFUND_FULL | 全额退款 | ✓ | — |
A 模式
orders/create同步响应不会出现WAIT/FAIL_RETRY(首扣已发起且终态失败直接失败)。WAIT仅在续扣排队、retry job 尚未轮到时出现;FAIL_RETRY仅可能在续费期通过orders/query/ webhook 可见。
BILLED 与 SUCCESS 的区别(B 模式专用)
BILLED 表示该期已开账、权益已发,与渠道侧实际是否扣到用户款项无关。扣款风险由渠道自担。请勿做"扣款成功"语义解读。
A 模式 orders/create 同步响应 3 种组合
| 通道行为 | orderStatus | paymentRecords[0].paymentStatus | redeemUrl | 后续 |
|---|---|---|---|---|
| 同步 SUCCESS | ACTIVE | SUCCESS | 有值 | 等续扣 job 处理后续期 |
| 同步 FAIL | TERMINATED | FAIL | null | 终态,订阅未生效 |
| PENDING(异步) | INITIALIZING | PROCESSING | null | 等通道异步回调;成功转 ACTIVE,失败转 TERMINATED;均推 webhook |
不要轮询
orders/query等异步结果,以 回调通知 为准。同步 SUCCESS 路径(redeemUrl有值)可立即下发兑换链接;其他路径等待payment.status.changedwebhook 后再分发。
其他枚举
| 类型 | 取值 |
|---|---|
agreementStatus(仅 CXH_DEDUCT) | NON_BIND / BIND_ING / BIND_SUCCESS / BIND_FAIL / CANCELED / REPLACED |
agreementSource(仅 CXH_DEDUCT) | SELF_BINDING(A.1 自绑) / SHARED_FROM_CHANNEL(A.2 协议共享) |
paymentChannelCode(仅 CXH_DEDUCT) | 动态值,由 BD 为每个渠道单独授权;通过 payment-channels/list 查询 |
bankCode(仅绑卡) | 动态值,按支付通道返回的 supportedBanks 取值;常见值如 CCB(建设银行)、ABC(农业银行) |
productCode | 动态值,由 BD 为每个渠道单独授权;通过 products/list 查询;一个 SPU 对应一组固定的周期定价 |
| 周期定价 | (periodType, period, totalCycles, cycleAmountCent) 由 SPU 预设;cycleAmountCent 取自当前渠道的分销价。下单时三个周期字段可省略,CXH 按 SPU 自动填充;cycleAmountCent 渠道传入将被忽略 |
refundSource(仅 CXH_DEDUCT) | MERCHANT_OPS(CXH 内部审核处理);B 模式 CXH 不参与退款,无该字段 |
periodType | DAY(按自然日)/ MONTH(按自然月,非 30 天);详见下方「周期日期推进规则」 |
smsStatus(仅 CXH_DEDUCT) | SEND_SUCCESS / SEND_FAIL |
命名规范
- 金额单位统一为分(cent):
amountCent/refundAmountCent/cycleAmountCent/totalPaidAmountCent - 时间格式
yyyy-MM-dd HH:mm:ss,Asia/Shanghai 时区,字符串 - CXH 单号 vs 渠道单号:
- CXH 生成、渠道不可修改:
orderNo/paymentOrderNo/refundOrderNo/agreementNo/bindOrderNo - 渠道生成、全局唯一(CXH 全局唯一性校验兜底):
externalOrderNo/externalRefundNo
- CXH 生成、渠道不可修改:
- 加密字段:请求体中使用
cxh_aes_v1:{iv}:{cipher}包装,见 签名与字段加密 - 空值:
null与字段缺失等价,响应中可省略 null 字段
B 模式字段特殊性
paidAt表示开账成功时刻(B 模式 CXH 不参与扣款,开账即视为完成)channelAgreementRef为渠道自有协议号,任意字符串,CXH 仅存储不解析refundAmountCent/totalRefundAmountCent/refundStatus/refundSource始终为0/null(CXH 不感知渠道侧退款)
期次编号
cycleNo从 1 递增,首期为 1totalCycles包含首期,例如MONTH × 12对应cycleNo1–12expectPayTime:本期计划扣款 / 开账时刻paidAt:A 模式表示实际扣款成功时刻,扣款失败时为null;B 模式表示开账成功时刻,始终有值
周期日期推进规则
下一期 expectPayTime / nextPayTime 由首扣时间按 (periodType, period) 推进:
periodType | 推进方式 | 示例(period=1) |
|---|---|---|
DAY | 自然日 + period 天 | 首扣 2026-01-31 10:00 → 第 2 期 2026-02-01 10:00 → 第 3 期 2026-02-02 10:00 |
MONTH | 按自然月加 period 月(月份字段直接 +period,日期保持) | 首扣 2026-01-15 10:00 → 第 2 期 2026-02-15 10:00 → 第 3 期 2026-03-15 10:00 |
MONTH 月底特例 | 目标月无该日时取该月最后一天 | 首扣 2026-01-31 10:00 → 第 2 期 2026-02-28 10:00(平年)→ 第 3 期 2026-03-31 10:00 → 第 4 期 2026-04-30 10:00 |
MONTH不等于 30 天。月度订阅整年扣 12 次,扣款日保持稳定;仅当首扣日为 1/29–1/31 时,2 月期次会落到 2/28 或 2/29。
时区固定为 Asia/Shanghai,日期推进仅基于年 / 月 / 日字段,与时区无关。
权益过期规则
每期权益独立有效,过期作废,不可累积。
- 每期扣款 / 开账成功后,CXH 按 SPU 配置的
(periodType, period)计算expireAt:expireAt = effectiveAt + period(periodType为 MONTH 加 period 个月,DAY 加 period 天)- 例如月卡(
MONTH × 1)第 1 期 effective2026-01-15,expire2026-02-15
- 用户必须在该期
expireAt前完成兑换;过期后该期未领取份额作废,无法补领 - 多期订阅:错过当期不影响下一期;下一期 effective 后又有新一期权益可领
- 单期 SPU(
totalCycles=1):错过即彻底失效,主订单已 COMPLETED,无补救路径 - 已锁定 (locked) / 已消费 (consumed) 部分不受 expire 影响,该流水按已发生处理