跳到内容

Distribution 分销模块

Distribution 是独立的推广分销业务模块,模块名为 spring-open-module-distribution,API 前缀预留为 /api/v1/distribution/**。它负责邀请关系、分销员、团队树、规则、归因、佣金、结算、打款尝试、风控和审计,不放进 Mall 模块内部。

当前状态

  • 模块已进入 Maven reactor,并已从 preview-business-modules profile 毕业进入 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-modules profile、模块 reactor 引用和默认安全配置,避免后续拆分或 POM 调整时静默漏装。
  • 首段迁移已建立完整体数据模型基线,覆盖邀请码、推荐关系、closure、团队、团队成员、分销员、等级、规则、规则层级、订单归因、佣金流水、业绩快照、结算、结算明细、打款尝试、对账、风控和审计基础表。
  • Admin 后端 contract 已提供运营总览、推广邀请码、渠道素材、访问归因、分销员、个人业绩、团队业绩、团队贡献排行、分资产统计、规则、推荐关系、推荐关系 closure、推荐人更换、团队、团队创建、团队移动、团队成员迁移、团队 closure、团队成员、佣金流水、结算单、结算审核、内部打款、失败打款重试、对账记录、审计日志和风控事件入口。
  • 分佣后端 contract 已提供规则层级、订单归因、规则匹配、幂等归因和 pending 佣金流水生成能力。
  • 结算打款默认且唯一使用 Money 用户余额内部入账 Provider,审批通过后把结算金额写入受益用户余额账户并记录打款尝试;平台资金外流统一由 Money 余额提现承接,不在 Distribution 内登记外部转账号、Payment 打款单或链上交易哈希。
  • 用户侧 contract 已提供当前用户分销中心、个人业绩、团队贡献排行、推广码 / 素材、团队成员、直属团队树、佣金流水和结算单查询;App 与 PC 用户中心已挂载分销入口,并展示业绩、团队贡献排行、素材、团队、直属团队树、佣金和结算概览。
  • 业务事件接入、退款扣回、失败打款重试、对账记录、审计日志和邀请码访问归因已进入后端 contract;Admin 对账 / 审计、业务源接入矩阵、打款 Provider 验收状态和“重试失败打款”操作已经可见。

配置

yaml
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: 100

enabled=false 时用户侧入口、公开邀请码访问和业务事件佣金生成会关闭。未配置结算超时动作时保持待审,避免自动出款。settlement-timeout-action 支持 keep-pendingauto-approveauto-rejectauto-processingauto-approve / auto-processing 会把超时待审结算单置为已审批,并立即走默认 Provider 打款。

上述配置已由 DistributionServiceProvider 声明到 lifecycle 配置 schema,后台配置中心可识别默认启用、关系深度、奖励层级和结算超时策略;未接入配置中心的部署仍可通过 application.yml / 环境变量配置。佣金生成会通过 DistributionRuleConfigResolver 优先读取配置中心里的 max-relation-depthmax-reward-level,关系链裁剪和奖励层级上限可运行期生效,避免修改配置后仍按启动时绑定值发放超层级佣金。

模块边界

  • Mall、Blog、Open Platform 等业务模块只发布业务事件或提供快照,不直接依赖 Distribution 的规则和结算状态。
  • Distribution 只保存 userIdbizIdorderNoassetCode 等标量和快照,不引用其它业务模块实体。
  • 佣金与结算资产统一保存 asset_codesymbolasset_typeraw_amountamountdecimals,支持法币、Web3 Token 和积分等多资产。
  • 历史归因、佣金流水和结算明细不可静默重算;退款、扣回、人工纠偏都应生成新流水。

Admin Contract

后台运营入口随模块默认装配开放;用户侧入口、公开邀请码访问和业务侧佣金处理缺省启用,受 spring.open.distribution.enabled 控制,显式配置为 false 时关闭:

方法路径权限说明
GET/api/v1/admin/distribution/overviewdistribution:distributor:view运营总览统计
GET/api/v1/admin/distribution/invite-codesdistribution:invite-code:view推广邀请码分页,支持关键字、归属用户、分销员、渠道、场景和状态筛选
GET/api/v1/admin/distribution/invite-codes/{id}distribution:invite-code:view推广邀请码详情
POST/api/v1/admin/distribution/invite-codesdistribution:invite-code:manage创建推广邀请码、渠道码、素材和落地页配置
POST/api/v1/admin/distribution/invite-codes/{id}distribution:invite-code:manage更新推广邀请码、渠道码、素材和落地页配置
POST/api/v1/admin/distribution/invite-codes/{id}/statusdistribution:invite-code:manage启用或停用推广邀请码
GET/api/v1/admin/distribution/distributorsdistribution:distributor:view分销员分页
GET/api/v1/admin/distribution/distributors/{id}distribution:distributor:view分销员详情
GET/api/v1/admin/distribution/distributors/{id}/performancedistribution:commission:view分销员个人业绩,按资产分组
GET/api/v1/admin/distribution/rulesdistribution:rule:view分销规则分页
GET/api/v1/admin/distribution/rules/{id}distribution:rule:view分销规则详情
GET/api/v1/admin/distribution/relationsdistribution:relation:view推荐关系分页
GET/api/v1/admin/distribution/relations/{id}distribution:relation:view推荐关系详情
POST/api/v1/admin/distribution/relations/referrer-changedistribution:relation:change更换推荐人
GET/api/v1/admin/distribution/relation-closuresdistribution:relation:view推荐关系 closure 分页
GET/api/v1/admin/distribution/teamsdistribution:team:view团队分页
GET/api/v1/admin/distribution/teams/treedistribution:team:view按父团队、深度、状态和关键词查询团队树
GET/api/v1/admin/distribution/teams/tree/exportdistribution:team:view按当前筛选条件导出团队树 CSV
POST/api/v1/admin/distribution/teamsdistribution:team:manage创建团队并写入 self / parent closure
GET/api/v1/admin/distribution/teams/{id}distribution:team:view团队详情
GET/api/v1/admin/distribution/teams/{id}/performancedistribution:team:view团队业绩,按当前有效成员和资产分组
GET/api/v1/admin/distribution/teams/{id}/contribution-rankdistribution:team:view团队贡献排行,按当前有效成员和资产聚合成交、佣金、扣回和失败打款
GET/api/v1/admin/distribution/teams/{id}/contribution-rank/exportdistribution:team:view按当前筛选条件导出团队贡献排行 CSV
POST/api/v1/admin/distribution/teams/{id}/movedistribution:team:manage移动团队,拒绝自环 / 下级设为上级
GET/api/v1/admin/distribution/team-closuresdistribution:team:view团队 closure 分页
GET/api/v1/admin/distribution/team-membersdistribution:team:view团队成员分页
POST/api/v1/admin/distribution/team-members/transferdistribution:team:manage迁移分销员团队归属,关闭旧 active 归属并写入新归属
GET/api/v1/admin/distribution/commissionsdistribution:commission:view佣金流水分页
GET/api/v1/admin/distribution/performance/assetsdistribution:commission:view分资产业绩汇总,可按分销员、团队、时间、业务类型、场景、状态筛选
GET/api/v1/admin/distribution/revenue-reports/dailydistribution:report:view分销收益日报,按日期、资产、分销员、团队、业务类型、场景和佣金状态聚合成交、佣金、扣回、退款与失败打款
GET/api/v1/admin/distribution/revenue-reports/daily/exportdistribution:report:view按当前筛选条件导出分销收益日报 CSV
GET/api/v1/admin/distribution/revenue-reports/business-sourcesdistribution:report:view查询分销业务源接入矩阵,展示已支持的业务类型、场景、必填属性、购买 / 退款支持状态和本地 contract 状态
POST/api/v1/admin/distribution/revenue-reports/snapshots/generatedistribution:report:view生成指定日期的分销员 / 团队历史业绩快照
GET/api/v1/admin/distribution/revenue-reports/performance-snapshotsdistribution:report:view分销员历史业绩快照分页
GET/api/v1/admin/distribution/revenue-reports/team-performance-snapshotsdistribution:report:view团队历史业绩快照分页
GET/api/v1/admin/distribution/revenue-reports/team-performance-trenddistribution:report:view按团队、日期范围、业务类型和资产读取团队历史业绩趋势
GET/api/v1/admin/distribution/settlementsdistribution:settlement:view结算单分页
POST/api/v1/admin/distribution/settlementsdistribution:settlement:review创建结算单
GET/api/v1/admin/distribution/settlements/payout-providersdistribution:settlement:view查询可用结算打款 Provider 和目标类型
GET/api/v1/admin/distribution/settlements/failed/compensation-plandistribution:settlement:view查询失败打款补偿计划,按最新打款尝试给出本地重试或先对账建议
POST/api/v1/admin/distribution/settlements/{id}/approvedistribution:settlement:review审批通过结算单,并立即尝试默认 Provider 打款
POST/api/v1/admin/distribution/settlements/{id}/rejectdistribution:settlement:review驳回结算单并释放佣金流水
POST/api/v1/admin/distribution/settlements/{id}/payoutdistribution:settlement:review执行结算入账,使用默认 internal-money-balance 把收益写入受益用户 Money 余额
POST/api/v1/admin/distribution/settlements/failed/retrydistribution:settlement:review批量重试失败结算 / 失败打款并写审计
POST/api/v1/admin/distribution/settlements/{id}/reconciledistribution:settlement:review登记 Provider 侧状态、交易号和金额对账
GET/api/v1/admin/distribution/reconciliationsdistribution:settlement:view对账记录分页
GET/api/v1/admin/distribution/audit-logsdistribution:settlement:view分销运营审计日志分页
GET/api/v1/admin/distribution/risk-eventsdistribution:risk:view风控事件分页

推荐人更换会关闭旧 active 直接关系和旧 closure 链,创建新 active 关系并追加新 closure 链;接口禁止自己推荐自己,也禁止把自己的下级设置为新推荐人。历史订单、历史佣金和已结算记录不会被静默重算。

团队创建会校验 teamCode 唯一、上级团队有效和团队长分销员存在,创建后写入团队 self closure,并按上级团队 active closure 追加祖先关系。团队移动会拒绝把自己或自己的下级设为新上级,关闭旧外部祖先 closure,重写移动团队及其下级团队 path / level,并补齐新祖先 closure。团队树查询支持 parentTeamIddepthlimitkeywordstatus,运营可从根团队或任意父团队懒加载子树,也可按当前条件导出 CSV。团队成员迁移会关闭该分销员当前 active 团队归属,再写入新团队归属和变更原因;如果目标团队和角色相同则幂等返回当前归属。

推广邀请码与访问归因

推广邀请码用于承载分销员推广码、渠道码、场景、素材标题、落地页、海报地址和运营备注。后台可在 /distribution/invites 创建、编辑、启用 / 停用邀请码,并复制带 codechannelscene 参数的推广链接。

创建邀请码时必须提供 codeownerUserIddistributorId 至少提供一个;如果传入 distributorId,系统会校验分销员存在并把邀请码归属到该分销员的用户。status=active 的邀请码允许访问归因;status=disabled 或已过期的邀请码不允许继续记录访问。访问归因入口为:

http
POST /api/v1/distribution/invite-codes/{code}/visit

该入口会按邀请码记录 visitCountlastVisitedAt,用于后台区分素材访问量和真实使用次数。邀请码被用于建立关系或生成业务归因时,业务流程可以继续递增 usageCount;历史访问记录不反推佣金和结算状态。

业绩统计 Contract

Admin 业绩统计当前提供实时聚合与历史快照入口:

  • GET /api/v1/admin/distribution/distributors/{id}/performance
  • GET /api/v1/admin/distribution/teams/{id}/performance
  • GET /api/v1/admin/distribution/performance/assets
  • GET /api/v1/admin/distribution/revenue-reports/daily
  • GET /api/v1/admin/distribution/revenue-reports/business-sources
  • POST /api/v1/admin/distribution/revenue-reports/snapshots/generate
  • GET /api/v1/admin/distribution/revenue-reports/performance-snapshots
  • GET /api/v1/admin/distribution/revenue-reports/team-performance-snapshots
  • GET /api/v1/admin/distribution/revenue-reports/team-performance-trend

请求支持 startAtendAtbizTypesceneassetCodestatusdistributorIdteamId 筛选;路径上的分销员 / 团队 ID 优先生效。统计结果始终按 assetCode + assetType + symbol 分组返回,不跨资产混合金额。

统计口径:

  • 成交订单数、成交金额和可佣金基数来自 distribution_order_attribution 归因快照;同一 bizType + scene + bizId 只计一次订单。
  • 佣金状态金额来自 distribution_commission_record,覆盖 pendingfrozensettleablesettlingsettledclawed_back
  • 退款金额来自扣回流水的规则快照 refundRawAmount / refundAmount,按业务退款幂等键去重;扣回佣金金额按负向佣金流水绝对值统计。
  • 打款失败金额来自 distribution_settlementstatus=failedpayoutStatus=failed
  • 收益日报按 reportDate + assetCode + assetType + symbol 聚合实时归因、佣金和结算事实:成交数据按订单发生时间落日,佣金 / 扣回按流水创建时间落日,失败打款按结算创建时间落日。它不写新账本,也不替代 Money / Cashier 对账。
  • 团队业绩当前按团队当前有效成员汇总;团队贡献排行按 teamId + distributorId + assetCode 聚合,并按成交原始金额、已结算佣金、分销员 ID 和资产编码稳定排序,方便运营查看团队成员贡献。
  • 历史快照使用迁移里已有的 distribution_performance_snapshotdistribution_team_performance_snapshot:后台收益报表页可选择快照日期生成分销员 / 团队快照,并分页查看历史基线;团队趋势入口按日期范围读取既有团队快照,便于运营观察连续变化。快照固化 orderCountpaidRawAmountcommissionRawAmountsettledRawAmount 等迁移表已有字段,不写新账本、不替代实时日报。
  • 业务源接入矩阵只展示 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当前用户自己的分销业绩,支持 startAtendAtbizTypesceneassetCodestatus 筛选,按资产分组返回订单、退款、佣金和结算状态金额
GET/api/v1/distribution/users/me/team-contribution-rank当前用户有效团队范围内的团队贡献排行,支持 teamIdstartAtendAtbizTypesceneassetCodestatus 筛选;teamId 必须属于当前用户有效团队范围
GET/api/v1/distribution/users/me/invite-codes当前用户自己的推广码、渠道码和邀请素材分页,支持 keywordchannelCodescenestatus 筛选;只返回当前用户归属或当前分销员归属的数据
GET/api/v1/distribution/users/me/team-members当前用户所在有效团队的成员分页,支持 teamIddistributorIdrole 筛选;teamId 必须属于当前用户有效团队范围
GET/api/v1/distribution/users/me/team-member-tree当前用户有效团队范围内的直属团队树,支持 parentDistributorIdteamIddepthlimit;父分销员必须是当前用户自己或当前用户推荐链下级,teamId 必须属于当前用户有效团队范围
GET/api/v1/distribution/users/me/commissions当前用户自己的佣金流水分页,支持 assetCodestatus 筛选
GET/api/v1/distribution/users/me/settlements当前用户自己的结算单分页,支持 assetCodestatuspayoutStatus 筛选
GET/api/v1/distribution/users/me/settlements/{id}当前用户自己的结算单详情,返回结算明细、关联佣金流水和打款尝试;不允许读取其它用户或其它分销员的结算
POST/api/v1/distribution/users/me/settlements当前用户选择自己的 settleable 佣金流水提交结算申请;请求只传 commissionRecordIdstraceIdremark,用户 ID 与分销员 ID 由登录态派生

App 已新增 /distribution/index,并从个人中心快捷入口、资产入口和菜单入口跳转;PC 已新增 /account/distribution,并从账户首页待办卡片与账户菜单跳转。两端分销中心会展示当前用户中心概览、个人业绩、团队贡献排行、推广素材、团队成员、直属团队树、佣金汇总、最近佣金和最近结算,并可从最近结算下钻查看结算明细、关联佣金和打款尝试。未登录用户只展示登录引导;已登录但不是分销员的用户展示空状态,不允许通过请求参数读取其它分销员、其它团队或其它用户的结算数据。

用户侧结算申请复用后台结算写入口的账本校验:所选佣金流水必须属于当前登录用户对应分销员,且同属一个资产、同一精度、状态为 settleable、未绑定其它结算单;创建成功后佣金流水进入 settling,结算单进入 submitted,后续仍由后台审核、打款、失败重试和对账流程处理。App 与 PC 分销中心只在可结算佣金汇总能对应到具体佣金流水时展示“申请结算”操作。

分佣 Service Contract

业务源暂不直接依赖 Distribution 内部表。事件监听或业务接入层把订单、购买、订阅等事件标准化后调用:

java
DistributionCommissionResult result = distributionCommissionService.generate(command);

常见业务源可以直接使用 DistributionBizEvent 模板:

  • Mall 商品订单:mallProductOrder(...) / mallProductOrderRefund(...)
  • Blog 单篇付费文章:blogPaidArticlePurchase(...) / blogPaidArticleRefund(...),默认携带 article:{articleId} scope。
  • Blog 订阅购买 / 续费:blogSubscriptionOrder(...) / blogSubscriptionRefund(...),默认携带套餐 ID 和套餐编码两个 package scope。
  • Open Platform 套餐购买 / 续费 / 补款:openPlatformPackagePurchase(...) / openPlatformPackageRefund(...),默认携带 app:{appId}、套餐 ID 和套餐编码 scope。
  • Marketplace 撮合成交订单:marketplaceMatchOrder(...) / marketplaceMatchOrderRefund(...),默认携带供需信息 ID / 编号、卖方、分类和地区 scope。

如果业务模块不希望直接依赖 Distribution,可发布 CommerceCommissionEvent 中立事件,并通过 attributes 携带文章、套餐、应用、供需信息、卖方、结算单等快照字段。Distribution 监听器会把已支持的 bizType + scene 映射为上述 DistributionBizEvent 模板;未知来源会被忽略,不影响原业务交易。

DistributionCommissionCommand 至少包含:

  • bizTypescenebizIdbizNo:业务类型、场景、业务对象和业务单号。
  • buyerUserId:产生消费或收益事件的用户。
  • assetCodeassetTypesymbolpaidRawAmountpaidAmountdecimals:同资产金额快照。
  • occurredAt:业务发生时间,用于匹配有效关系链和有效规则。
  • idempotencyKey:业务侧幂等键;未传时由业务字段和资产派生。
  • scopesattributes:文章、商品、套餐、供需信息、卖方、分类、地区、作者、商户、渠道、团队、团队分支等规则范围和业务扩展快照。

生成语义:

  • bizType + scene + assetCode 找 enabled 且在有效期内的规则,再按 scopeType + scopeId 命中最具体范围;未命中规则返回 no_rule,不落归因和佣金流水。团队规则使用 scopeType=teamscopeId={teamId};团队分支规则使用 scopeType=team-branchscopeId={ancestorTeamId},接入方可通过 DistributionBizEvent.teamScope(...) / teamBranchScope(...) 固化到事件快照。
  • buyerUserIdoccurredAt 读取有效推荐关系 closure,只给 active 分销员生成佣金;无有效关系返回 no_relation
  • 归因落 distribution_order_attribution,固化规则快照、关系链快照、业务 attributes、资产和幂等键。
  • 规则层级落 distribution_commission_record pending 佣金流水;支持 ratefixedcap,费率 <= 1 按比例、> 1 按百分比处理,派生金额统一 RoundingMode.DOWN 截断。
  • 重复幂等键返回 idempotent 和既有佣金行,不重复插入归因或流水。
  • 退款 / 售后事件调用 distributionCommissionService.clawback(command);也可使用对应 DistributionBizEvent.*Refund(...) 模板后调用 clawback(event)
  • 扣回按原归因 paidRawAmount 和本次 refundRawAmount 比例计算每级佣金的反向金额,生成 ledgerType=clawbackstatus=clawed_back 的负向佣金流水;原归因、原佣金和原结算明细不更新。
  • 扣回幂等键按业务退款单唯一,重复事件返回 idempotent 和既有扣回行;如果历史已有部分扣回,新扣回会按剩余可扣回佣金额度封顶。
  • 当前 contract 已覆盖 pending 佣金生成和退款扣回;冻结 / 解冻、订单完成后置为可结算和补偿重放留后续功能簇。

结算与内部打款 Contract

结算 Service 使用 DistributionSettlementService

java
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 + decimalssettleable 且未绑定结算单的佣金流水。
  • 创建成功后写入 distribution_settlementdistribution_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=failedpayoutStatus=failed 的结算单;重试仍复用 Provider 幂等打款、审计日志和最新结算状态刷新,不新增独立资金账本。
  • 超时处理由 handleTimedOutSettlements() 执行:默认 keep-pending 不查询、不出款;显式 auto-reject 会释放佣金;显式 auto-approve / auto-processing 会以系统操作人审批并走默认 Provider 打款。
  • internal-money-balance Provider 会通过 Money ensureAccount 创建 / 获取受益用户余额账户,再写一笔 ADJUST_IN 用户余额流水;Provider 交易号为 money-ledger:{ledgerId}
  • 打款成功后结算单进入 paidpayoutStatus=paid,佣金流水进入 settled;打款失败后结算单进入 failed,保留失败原因,后续可重试本地余额入账。
  • 失败打款批量重试会选择 status=failedpayoutStatus=failed 的结算单,按更新时间和 ID 升序处理,默认最多 20 条、单次上限 100 条;每笔重试都会生成新的 distribution_payout_attempt 并写入 distribution_audit_log
  • 失败打款补偿计划入口会读取失败结算和最新打款尝试,生成 retry-local-providerreconcile-before-retry 建议;该入口只读,不直接触发真实打款。
  • 对账登记会读取结算单和最新打款尝试,固化 Provider 状态、交易号、资产和原始金额到 distribution_reconciliation_record;状态为 matchedmismatched,差异原因优先使用请求值,否则由金额、交易号、打款尝试或 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=3settlementTimeoutAction=keep-pendingsettlementTimeoutMinutes=1440settlementTimeoutBatchSize=100 等默认值不被应用装配意外改坏。

后续功能簇

  1. Marketplace 交易事件接入中立佣金事件或业务接入监听。
  2. 佣金调整、结算后补差和扣回对账。

Released under the Apache License 2.0.