Distribution 分销模块
Distribution 是独立的推广分销业务模块,模块名为 spring-open-module-distribution,API 前缀预留为 /api/v1/distribution/**。它负责邀请关系、分销员、团队树、规则、归因、佣金、结算、打款尝试、风控和审计,不放进 Mall 模块内部。
当前状态
- 模块已进入 Maven reactor,并已从
preview-business-modulesprofile 毕业进入spring-open-application默认装配(与 Video / Reading 一致)。 - 默认装配下运行时缺省启用用户侧入口和业务侧佣金处理;如需关闭,可显式配置
spring.open.distribution.enabled=false。未配置佣金规则或有效推荐关系时不会产生佣金,结算超时动作仍默认keep-pending。 - 已内置业务事件来源:
spring-open-core-runtime提供中立CommerceCommissionEvent,Mall 侧在订单支付成功和售后退款通过后发布事件,Distribution 侧监听后生成佣金或扣回佣金;监听器已支持 Mall、Blog、Open Platform 和 Marketplace 的中立事件映射,具体业务是否发事件由对应模块按支付 / 退款闭环接入。 - 应用装配测试已覆盖
spring-open-application默认装配 Distribution、不再保留preview-business-modulesprofile、模块 reactor 引用和默认安全配置,避免后续拆分或 POM 调整时静默漏装。 - 首段迁移已建立完整体数据模型基线,覆盖邀请码、推荐关系、closure、团队、团队成员、分销员、等级、规则、规则层级、订单归因、佣金流水、业绩快照、结算、结算明细、打款尝试、对账、风控和审计基础表。
- Admin 后端 contract 已提供运营总览、推广邀请码、渠道素材、访问归因、分销员、个人业绩、团队业绩、团队贡献排行、分资产统计、规则、推荐关系、推荐关系 closure、推荐人更换、团队、团队创建、团队移动、团队成员迁移、团队 closure、团队成员、佣金流水、结算单、结算审核、内部打款、失败打款重试、对账记录、审计日志和风控事件入口。
- 分佣后端 contract 已提供规则层级、订单归因、规则匹配、幂等归因和 pending 佣金流水生成能力。
- 结算打款默认且唯一使用 Money 用户余额内部入账 Provider,审批通过后把结算金额写入受益用户余额账户并记录打款尝试;平台资金外流统一由 Money 余额提现承接,不在 Distribution 内登记外部转账号、Payment 打款单或链上交易哈希。
- 用户侧 contract 已提供当前用户分销中心、个人业绩、团队贡献排行、推广码 / 素材、团队成员、直属团队树、佣金流水和结算单查询;App 与 PC 用户中心已挂载分销入口,并展示业绩、团队贡献排行、素材、团队、直属团队树、佣金和结算概览。
- 业务事件接入、退款扣回、失败打款重试、对账记录、审计日志和邀请码访问归因已进入后端 contract;Admin 对账 / 审计、业务源接入矩阵、打款 Provider 验收状态和“重试失败打款”操作已经可见。
配置
spring:
open:
distribution:
enabled: true
max-relation-depth: 0
max-reward-level: 3
settlement-timeout-action: keep-pending
settlement-timeout-minutes: 1440
settlement-timeout-batch-size: 100enabled=false 时用户侧入口、公开邀请码访问和业务事件佣金生成会关闭。未配置结算超时动作时保持待审,避免自动出款。settlement-timeout-action 支持 keep-pending、auto-approve、auto-reject 和 auto-processing;auto-approve / auto-processing 会把超时待审结算单置为已审批,并立即走默认 Provider 打款。
上述配置已由 DistributionServiceProvider 声明到 lifecycle 配置 schema,后台配置中心可识别默认启用、关系深度、奖励层级和结算超时策略;未接入配置中心的部署仍可通过 application.yml / 环境变量配置。佣金生成会通过 DistributionRuleConfigResolver 优先读取配置中心里的 max-relation-depth 和 max-reward-level,关系链裁剪和奖励层级上限可运行期生效,避免修改配置后仍按启动时绑定值发放超层级佣金。
模块边界
- Mall、Blog、Open Platform 等业务模块只发布业务事件或提供快照,不直接依赖 Distribution 的规则和结算状态。
- Distribution 只保存
userId、bizId、orderNo、assetCode等标量和快照,不引用其它业务模块实体。 - 佣金与结算资产统一保存
asset_code、symbol、asset_type、raw_amount、amount和decimals,支持法币、Web3 Token 和积分等多资产。 - 历史归因、佣金流水和结算明细不可静默重算;退款、扣回、人工纠偏都应生成新流水。
Admin Contract
后台运营入口随模块默认装配开放;用户侧入口、公开邀请码访问和业务侧佣金处理缺省启用,受 spring.open.distribution.enabled 控制,显式配置为 false 时关闭:
| 方法 | 路径 | 权限 | 说明 |
|---|---|---|---|
GET | /api/v1/admin/distribution/overview | distribution:distributor:view | 运营总览统计 |
GET | /api/v1/admin/distribution/invite-codes | distribution:invite-code:view | 推广邀请码分页,支持关键字、归属用户、分销员、渠道、场景和状态筛选 |
GET | /api/v1/admin/distribution/invite-codes/{id} | distribution:invite-code:view | 推广邀请码详情 |
POST | /api/v1/admin/distribution/invite-codes | distribution:invite-code:manage | 创建推广邀请码、渠道码、素材和落地页配置 |
POST | /api/v1/admin/distribution/invite-codes/{id} | distribution:invite-code:manage | 更新推广邀请码、渠道码、素材和落地页配置 |
POST | /api/v1/admin/distribution/invite-codes/{id}/status | distribution:invite-code:manage | 启用或停用推广邀请码 |
GET | /api/v1/admin/distribution/distributors | distribution:distributor:view | 分销员分页 |
GET | /api/v1/admin/distribution/distributors/{id} | distribution:distributor:view | 分销员详情 |
GET | /api/v1/admin/distribution/distributors/{id}/performance | distribution:commission:view | 分销员个人业绩,按资产分组 |
GET | /api/v1/admin/distribution/rules | distribution:rule:view | 分销规则分页 |
GET | /api/v1/admin/distribution/rules/{id} | distribution:rule:view | 分销规则详情 |
GET | /api/v1/admin/distribution/relations | distribution:relation:view | 推荐关系分页 |
GET | /api/v1/admin/distribution/relations/{id} | distribution:relation:view | 推荐关系详情 |
POST | /api/v1/admin/distribution/relations/referrer-change | distribution:relation:change | 更换推荐人 |
GET | /api/v1/admin/distribution/relation-closures | distribution:relation:view | 推荐关系 closure 分页 |
GET | /api/v1/admin/distribution/teams | distribution:team:view | 团队分页 |
GET | /api/v1/admin/distribution/teams/tree | distribution:team:view | 按父团队、深度、状态和关键词查询团队树 |
GET | /api/v1/admin/distribution/teams/tree/export | distribution:team:view | 按当前筛选条件导出团队树 CSV |
POST | /api/v1/admin/distribution/teams | distribution:team:manage | 创建团队并写入 self / parent closure |
GET | /api/v1/admin/distribution/teams/{id} | distribution:team:view | 团队详情 |
GET | /api/v1/admin/distribution/teams/{id}/performance | distribution:team:view | 团队业绩,按当前有效成员和资产分组 |
GET | /api/v1/admin/distribution/teams/{id}/contribution-rank | distribution:team:view | 团队贡献排行,按当前有效成员和资产聚合成交、佣金、扣回和失败打款 |
GET | /api/v1/admin/distribution/teams/{id}/contribution-rank/export | distribution:team:view | 按当前筛选条件导出团队贡献排行 CSV |
POST | /api/v1/admin/distribution/teams/{id}/move | distribution:team:manage | 移动团队,拒绝自环 / 下级设为上级 |
GET | /api/v1/admin/distribution/team-closures | distribution:team:view | 团队 closure 分页 |
GET | /api/v1/admin/distribution/team-members | distribution:team:view | 团队成员分页 |
POST | /api/v1/admin/distribution/team-members/transfer | distribution:team:manage | 迁移分销员团队归属,关闭旧 active 归属并写入新归属 |
GET | /api/v1/admin/distribution/commissions | distribution:commission:view | 佣金流水分页 |
GET | /api/v1/admin/distribution/performance/assets | distribution:commission:view | 分资产业绩汇总,可按分销员、团队、时间、业务类型、场景、状态筛选 |
GET | /api/v1/admin/distribution/revenue-reports/daily | distribution:report:view | 分销收益日报,按日期、资产、分销员、团队、业务类型、场景和佣金状态聚合成交、佣金、扣回、退款与失败打款 |
GET | /api/v1/admin/distribution/revenue-reports/daily/export | distribution:report:view | 按当前筛选条件导出分销收益日报 CSV |
GET | /api/v1/admin/distribution/revenue-reports/business-sources | distribution:report:view | 查询分销业务源接入矩阵,展示已支持的业务类型、场景、必填属性、购买 / 退款支持状态和本地 contract 状态 |
POST | /api/v1/admin/distribution/revenue-reports/snapshots/generate | distribution:report:view | 生成指定日期的分销员 / 团队历史业绩快照 |
GET | /api/v1/admin/distribution/revenue-reports/performance-snapshots | distribution:report:view | 分销员历史业绩快照分页 |
GET | /api/v1/admin/distribution/revenue-reports/team-performance-snapshots | distribution:report:view | 团队历史业绩快照分页 |
GET | /api/v1/admin/distribution/revenue-reports/team-performance-trend | distribution:report:view | 按团队、日期范围、业务类型和资产读取团队历史业绩趋势 |
GET | /api/v1/admin/distribution/settlements | distribution:settlement:view | 结算单分页 |
POST | /api/v1/admin/distribution/settlements | distribution:settlement:review | 创建结算单 |
GET | /api/v1/admin/distribution/settlements/payout-providers | distribution:settlement:view | 查询可用结算打款 Provider 和目标类型 |
GET | /api/v1/admin/distribution/settlements/failed/compensation-plan | distribution:settlement:view | 查询失败打款补偿计划,按最新打款尝试给出本地重试或先对账建议 |
POST | /api/v1/admin/distribution/settlements/{id}/approve | distribution:settlement:review | 审批通过结算单,并立即尝试默认 Provider 打款 |
POST | /api/v1/admin/distribution/settlements/{id}/reject | distribution:settlement:review | 驳回结算单并释放佣金流水 |
POST | /api/v1/admin/distribution/settlements/{id}/payout | distribution:settlement:review | 执行结算入账,使用默认 internal-money-balance 把收益写入受益用户 Money 余额 |
POST | /api/v1/admin/distribution/settlements/failed/retry | distribution:settlement:review | 批量重试失败结算 / 失败打款并写审计 |
POST | /api/v1/admin/distribution/settlements/{id}/reconcile | distribution:settlement:review | 登记 Provider 侧状态、交易号和金额对账 |
GET | /api/v1/admin/distribution/reconciliations | distribution:settlement:view | 对账记录分页 |
GET | /api/v1/admin/distribution/audit-logs | distribution:settlement:view | 分销运营审计日志分页 |
GET | /api/v1/admin/distribution/risk-events | distribution:risk:view | 风控事件分页 |
推荐人更换会关闭旧 active 直接关系和旧 closure 链,创建新 active 关系并追加新 closure 链;接口禁止自己推荐自己,也禁止把自己的下级设置为新推荐人。历史订单、历史佣金和已结算记录不会被静默重算。
团队创建会校验 teamCode 唯一、上级团队有效和团队长分销员存在,创建后写入团队 self closure,并按上级团队 active closure 追加祖先关系。团队移动会拒绝把自己或自己的下级设为新上级,关闭旧外部祖先 closure,重写移动团队及其下级团队 path / level,并补齐新祖先 closure。团队树查询支持 parentTeamId、depth、limit、keyword 和 status,运营可从根团队或任意父团队懒加载子树,也可按当前条件导出 CSV。团队成员迁移会关闭该分销员当前 active 团队归属,再写入新团队归属和变更原因;如果目标团队和角色相同则幂等返回当前归属。
推广邀请码与访问归因
推广邀请码用于承载分销员推广码、渠道码、场景、素材标题、落地页、海报地址和运营备注。后台可在 /distribution/invites 创建、编辑、启用 / 停用邀请码,并复制带 code、channel 和 scene 参数的推广链接。
创建邀请码时必须提供 code,ownerUserId 和 distributorId 至少提供一个;如果传入 distributorId,系统会校验分销员存在并把邀请码归属到该分销员的用户。status=active 的邀请码允许访问归因;status=disabled 或已过期的邀请码不允许继续记录访问。访问归因入口为:
POST /api/v1/distribution/invite-codes/{code}/visit该入口会按邀请码记录 visitCount 和 lastVisitedAt,用于后台区分素材访问量和真实使用次数。邀请码被用于建立关系或生成业务归因时,业务流程可以继续递增 usageCount;历史访问记录不反推佣金和结算状态。
业绩统计 Contract
Admin 业绩统计当前提供实时聚合与历史快照入口:
GET /api/v1/admin/distribution/distributors/{id}/performanceGET /api/v1/admin/distribution/teams/{id}/performanceGET /api/v1/admin/distribution/performance/assetsGET /api/v1/admin/distribution/revenue-reports/dailyGET /api/v1/admin/distribution/revenue-reports/business-sourcesPOST /api/v1/admin/distribution/revenue-reports/snapshots/generateGET /api/v1/admin/distribution/revenue-reports/performance-snapshotsGET /api/v1/admin/distribution/revenue-reports/team-performance-snapshotsGET /api/v1/admin/distribution/revenue-reports/team-performance-trend
请求支持 startAt、endAt、bizType、scene、assetCode、status、distributorId、teamId 筛选;路径上的分销员 / 团队 ID 优先生效。统计结果始终按 assetCode + assetType + symbol 分组返回,不跨资产混合金额。
统计口径:
- 成交订单数、成交金额和可佣金基数来自
distribution_order_attribution归因快照;同一bizType + scene + bizId只计一次订单。 - 佣金状态金额来自
distribution_commission_record,覆盖pending、frozen、settleable、settling、settled和clawed_back。 - 退款金额来自扣回流水的规则快照
refundRawAmount/refundAmount,按业务退款幂等键去重;扣回佣金金额按负向佣金流水绝对值统计。 - 打款失败金额来自
distribution_settlement的status=failed或payoutStatus=failed。 - 收益日报按
reportDate + assetCode + assetType + symbol聚合实时归因、佣金和结算事实:成交数据按订单发生时间落日,佣金 / 扣回按流水创建时间落日,失败打款按结算创建时间落日。它不写新账本,也不替代 Money / Cashier 对账。 - 团队业绩当前按团队当前有效成员汇总;团队贡献排行按
teamId + distributorId + assetCode聚合,并按成交原始金额、已结算佣金、分销员 ID 和资产编码稳定排序,方便运营查看团队成员贡献。 - 历史快照使用迁移里已有的
distribution_performance_snapshot和distribution_team_performance_snapshot:后台收益报表页可选择快照日期生成分销员 / 团队快照,并分页查看历史基线;团队趋势入口按日期范围读取既有团队快照,便于运营观察连续变化。快照固化orderCount、paidRawAmount、commissionRawAmount和settledRawAmount等迁移表已有字段,不写新账本、不替代实时日报。 - 业务源接入矩阵只展示 Distribution 监听器当前本地可消费的业务来源、必填属性和幂等前缀,不伪装具体发布端或真实外部渠道已经完成生产验收;如果某业务模块尚未发布中立事件,仍按该模块自己的支付 / 退款功能簇接入。
- Admin 收益报表页支持按当前筛选条件导出分销收益日报 CSV;Admin 业绩页在填写团队 ID 后支持导出团队贡献排行 CSV。导出只读取既有实时聚合结果,不新增报表账本,不替代 Money / Cashier 对账。
用户侧 Contract
用户侧入口缺省启用,受 spring.open.distribution.enabled 控制,并只读取当前登录用户自己的分销数据; 显式配置为 false 时关闭:
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /api/v1/distribution/users/me/center | 当前用户分销员状态、推荐关系、直属下级、团队下级、团队归属、佣金聚合、最近佣金和最近结算 |
GET | /api/v1/distribution/users/me/performance | 当前用户自己的分销业绩,支持 startAt、endAt、bizType、scene、assetCode、status 筛选,按资产分组返回订单、退款、佣金和结算状态金额 |
GET | /api/v1/distribution/users/me/team-contribution-rank | 当前用户有效团队范围内的团队贡献排行,支持 teamId、startAt、endAt、bizType、scene、assetCode、status 筛选;teamId 必须属于当前用户有效团队范围 |
GET | /api/v1/distribution/users/me/invite-codes | 当前用户自己的推广码、渠道码和邀请素材分页,支持 keyword、channelCode、scene、status 筛选;只返回当前用户归属或当前分销员归属的数据 |
GET | /api/v1/distribution/users/me/team-members | 当前用户所在有效团队的成员分页,支持 teamId、distributorId、role 筛选;teamId 必须属于当前用户有效团队范围 |
GET | /api/v1/distribution/users/me/team-member-tree | 当前用户有效团队范围内的直属团队树,支持 parentDistributorId、teamId、depth、limit;父分销员必须是当前用户自己或当前用户推荐链下级,teamId 必须属于当前用户有效团队范围 |
GET | /api/v1/distribution/users/me/commissions | 当前用户自己的佣金流水分页,支持 assetCode、status 筛选 |
GET | /api/v1/distribution/users/me/settlements | 当前用户自己的结算单分页,支持 assetCode、status、payoutStatus 筛选 |
GET | /api/v1/distribution/users/me/settlements/{id} | 当前用户自己的结算单详情,返回结算明细、关联佣金流水和打款尝试;不允许读取其它用户或其它分销员的结算 |
POST | /api/v1/distribution/users/me/settlements | 当前用户选择自己的 settleable 佣金流水提交结算申请;请求只传 commissionRecordIds、traceId 和 remark,用户 ID 与分销员 ID 由登录态派生 |
App 已新增 /distribution/index,并从个人中心快捷入口、资产入口和菜单入口跳转;PC 已新增 /account/distribution,并从账户首页待办卡片与账户菜单跳转。两端分销中心会展示当前用户中心概览、个人业绩、团队贡献排行、推广素材、团队成员、直属团队树、佣金汇总、最近佣金和最近结算,并可从最近结算下钻查看结算明细、关联佣金和打款尝试。未登录用户只展示登录引导;已登录但不是分销员的用户展示空状态,不允许通过请求参数读取其它分销员、其它团队或其它用户的结算数据。
用户侧结算申请复用后台结算写入口的账本校验:所选佣金流水必须属于当前登录用户对应分销员,且同属一个资产、同一精度、状态为 settleable、未绑定其它结算单;创建成功后佣金流水进入 settling,结算单进入 submitted,后续仍由后台审核、打款、失败重试和对账流程处理。App 与 PC 分销中心只在可结算佣金汇总能对应到具体佣金流水时展示“申请结算”操作。
分佣 Service Contract
业务源暂不直接依赖 Distribution 内部表。事件监听或业务接入层把订单、购买、订阅等事件标准化后调用:
DistributionCommissionResult result = distributionCommissionService.generate(command);常见业务源可以直接使用 DistributionBizEvent 模板:
- Mall 商品订单:
mallProductOrder(...)/mallProductOrderRefund(...)。 - Blog 单篇付费文章:
blogPaidArticlePurchase(...)/blogPaidArticleRefund(...),默认携带article:{articleId}scope。 - Blog 订阅购买 / 续费:
blogSubscriptionOrder(...)/blogSubscriptionRefund(...),默认携带套餐 ID 和套餐编码两个packagescope。 - Open Platform 套餐购买 / 续费 / 补款:
openPlatformPackagePurchase(...)/openPlatformPackageRefund(...),默认携带app:{appId}、套餐 ID 和套餐编码 scope。 - Marketplace 撮合成交订单:
marketplaceMatchOrder(...)/marketplaceMatchOrderRefund(...),默认携带供需信息 ID / 编号、卖方、分类和地区 scope。
如果业务模块不希望直接依赖 Distribution,可发布 CommerceCommissionEvent 中立事件,并通过 attributes 携带文章、套餐、应用、供需信息、卖方、结算单等快照字段。Distribution 监听器会把已支持的 bizType + scene 映射为上述 DistributionBizEvent 模板;未知来源会被忽略,不影响原业务交易。
DistributionCommissionCommand 至少包含:
bizType、scene、bizId、bizNo:业务类型、场景、业务对象和业务单号。buyerUserId:产生消费或收益事件的用户。assetCode、assetType、symbol、paidRawAmount、paidAmount、decimals:同资产金额快照。occurredAt:业务发生时间,用于匹配有效关系链和有效规则。idempotencyKey:业务侧幂等键;未传时由业务字段和资产派生。scopes、attributes:文章、商品、套餐、供需信息、卖方、分类、地区、作者、商户、渠道、团队、团队分支等规则范围和业务扩展快照。
生成语义:
- 按
bizType + scene + assetCode找 enabled 且在有效期内的规则,再按scopeType + scopeId命中最具体范围;未命中规则返回no_rule,不落归因和佣金流水。团队规则使用scopeType=team、scopeId={teamId};团队分支规则使用scopeType=team-branch、scopeId={ancestorTeamId},接入方可通过DistributionBizEvent.teamScope(...)/teamBranchScope(...)固化到事件快照。 - 按
buyerUserId和occurredAt读取有效推荐关系 closure,只给 active 分销员生成佣金;无有效关系返回no_relation。 - 归因落
distribution_order_attribution,固化规则快照、关系链快照、业务 attributes、资产和幂等键。 - 规则层级落
distribution_commission_recordpending 佣金流水;支持rate、fixed、cap,费率<= 1按比例、> 1按百分比处理,派生金额统一RoundingMode.DOWN截断。 - 重复幂等键返回
idempotent和既有佣金行,不重复插入归因或流水。 - 退款 / 售后事件调用
distributionCommissionService.clawback(command);也可使用对应DistributionBizEvent.*Refund(...)模板后调用clawback(event)。 - 扣回按原归因
paidRawAmount和本次refundRawAmount比例计算每级佣金的反向金额,生成ledgerType=clawback、status=clawed_back的负向佣金流水;原归因、原佣金和原结算明细不更新。 - 扣回幂等键按业务退款单唯一,重复事件返回
idempotent和既有扣回行;如果历史已有部分扣回,新扣回会按剩余可扣回佣金额度封顶。 - 当前 contract 已覆盖 pending 佣金生成和退款扣回;冻结 / 解冻、订单完成后置为可结算和补偿重放留后续功能簇。
结算与内部打款 Contract
结算 Service 使用 DistributionSettlementService:
DistributionSettlement settlement = distributionSettlementService.createSettlement(command);
DistributionSettlement approved = distributionSettlementService.approveSettlement(command);
DistributionPayoutAttempt attempt = distributionSettlementService.payoutSettlement(command);
List<DistributionPayoutAttempt> retried = distributionSettlementService.retryFailedPayouts(command);
DistributionReconciliationRecord record = distributionSettlementService.reconcileSettlement(command);
List<DistributionSettlement> timedOut = distributionSettlementService.handleTimedOutSettlements();结算语义:
- 创建结算单时只能选择同一
distributorId + userId + assetCode + decimals下settleable且未绑定结算单的佣金流水。 - 创建成功后写入
distribution_settlement和distribution_settlement_item,并把佣金流水状态置为settling,避免重复结算。 - 审批通过只允许
submitted -> approved,随后立即进入默认 Provider 打款;驳回允许submitted / approved -> rejected,驳回会把关联佣金流水释放回settleable。 - 打款只允许
approved / failed -> paying,默认 Provider 为internal-money-balance,幂等键格式为distribution:settlement:payout:{settlementNo}:{attemptNo}。 - 打款 Provider 通过
DistributionSettlementPayoutProvider自描述name、展示名、说明、目标类型、运行模式、本地 contract 状态和验收步骤;当前内置 Provider 只负责 Money 余额入账,真实外部出账必须走 Money 提现 Provider 扩展。 - Admin 结算页提供“重试失败打款”操作,会调用
POST /api/v1/admin/distribution/settlements/failed/retry批量重试status=failed或payoutStatus=failed的结算单;重试仍复用 Provider 幂等打款、审计日志和最新结算状态刷新,不新增独立资金账本。 - 超时处理由
handleTimedOutSettlements()执行:默认keep-pending不查询、不出款;显式auto-reject会释放佣金;显式auto-approve/auto-processing会以系统操作人审批并走默认 Provider 打款。 internal-money-balanceProvider 会通过 MoneyensureAccount创建 / 获取受益用户余额账户,再写一笔ADJUST_IN用户余额流水;Provider 交易号为money-ledger:{ledgerId}。- 打款成功后结算单进入
paid、payoutStatus=paid,佣金流水进入settled;打款失败后结算单进入failed,保留失败原因,后续可重试本地余额入账。 - 失败打款批量重试会选择
status=failed或payoutStatus=failed的结算单,按更新时间和 ID 升序处理,默认最多 20 条、单次上限 100 条;每笔重试都会生成新的distribution_payout_attempt并写入distribution_audit_log。 - 失败打款补偿计划入口会读取失败结算和最新打款尝试,生成
retry-local-provider或reconcile-before-retry建议;该入口只读,不直接触发真实打款。 - 对账登记会读取结算单和最新打款尝试,固化 Provider 状态、交易号、资产和原始金额到
distribution_reconciliation_record;状态为matched或mismatched,差异原因优先使用请求值,否则由金额、交易号、打款尝试或 Provider 状态自动派生。
首段内部打款不创建 Money 提现单,因为提现状态机会先冻结并扣减用户自己的余额;分销结算是平台向用户发放收益,正确语义是先入账到用户 Money 余额,用户后续再按 Money 提现流程自行提现。
资金出口治理建议:
- 分销、商城、AI 等业务模块只负责把平台应付款结算到对应用户的 Money 余额账户。
- 用户或商户负责人需要把余额转出到银行卡、Payment Provider 或 Web3 地址时,统一走 Money 余额提现申请、审核、打款、确认和对账状态机。
- Distribution Provider Registry 会拒绝目标不是
money-balance、要求外部交易号或标记需要外部验收的 Provider,避免误注册后绕过统一提现链路。
应用装配与验证
Distribution 已进入 spring-open-application 默认装配,应用启动即加载后台运营 contract、用户侧入口和业务侧佣金处理;显式配置 spring.open.distribution.enabled=false 时会关闭用户侧入口、公开邀请码访问和业务事件佣金生成。内置业务事件来源通过 core-runtime 中立 CommerceCommissionEvent 接入:Mall 订单支付成功发布成交事件触发佣金生成,售后退款通过发布退款事件触发佣金扣回,可走通「关系绑定 → 订单支付 → 佣金生成 → 结算 → 打款 / 对账」链路。模块迁移已种子化后台菜单组和首批运营入口,前端 fallback 菜单会在后端菜单未返回时补齐已实现页面:
/distribution/invites:推广邀请码、渠道码、邀请素材和访问归因。/distribution/distributors:分销员运营。/distribution/teams:分销团队、团队树浏览 / 导出、成员迁移和团队业绩。/distribution/performance:分资产业绩、团队贡献排行、佣金流水和个人业绩查询。/distribution/revenue-reports:分销收益日报,按日期和资产查看成交、佣金、扣回、退款与失败打款。/distribution/rules:分销规则运营。/distribution/settlements:结算单运营。/distribution/reconciliations:结算对账记录查询。/distribution/audit-logs:分销运营审计日志查询。/distribution/risk-events:分销风控事件查询。
后台前端已对接上述入口:邀请码页支持渠道码、素材、落地页、海报、访问量和链接复制;分销员页展示运营总览、分页筛选和详情;团队页支持团队筛选、详情、创建、移动、成员迁移和团队业绩抽屉;业绩页支持分资产业绩汇总、团队贡献排行、团队排行导出、佣金流水筛选和个人业绩抽屉;收益报表页支持按日期、分销员、团队、业务场景、资产和佣金状态查看 / 导出分销收益日报,并展示业务源接入矩阵和打款 Provider 能力矩阵;规则页展示业务类型、场景、资产、范围和生效窗口;结算页支持创建结算单、审批通过、驳回和执行 internal-money-balance 入账;对账页展示 matched / mismatched 记录、交易号、资产金额和差异原因;审计日志页支持按动作 / 目标筛选并查看 before / after 快照;风控事件页支持按风险类型、目标、级别和状态筛选并查看证据 JSON。App / PC 用户侧分销中心已对接当前用户中心、个人业绩、团队贡献排行、推广素材、团队成员、佣金流水和结算 contract。
本模块的装配护栏由两类测试覆盖:DistributionMigrationTest 校验表结构、权限、菜单和 Admin 路由种子;DistributionApplicationAssemblyTest 校验 application POM 默认装配 Distribution、模块 reactor 仍包含该模块、应用不再保留 preview-business-modules profile,并确认缺省启用、maxRewardLevel=3、settlementTimeoutAction=keep-pending、settlementTimeoutMinutes=1440 和 settlementTimeoutBatchSize=100 等默认值不被应用装配意外改坏。
后续功能簇
- Marketplace 交易事件接入中立佣金事件或业务接入监听。
- 佣金调整、结算后补差和扣回对账。