Files
break 9959168e22
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Failing after 5h7m21s
完成支付失败商户轮换禁用
2026-09-22 15:58:03 +08:00

8.1 KiB
Raw Blame History

MODIFIED Requirements

Requirement: 商户池唯一性与轮询配置

系统 SHALL 为每种支付方式最多启用一个商户池;停用历史池可保留,但不得同时启用多个同支付方式池。商户池成员支付方式 MUST 与池一致,成员按明确顺序排列;金额/笔数方式必须配置 每轮累计、自然日累计 或 自然月累计 统计周期,时间方式必须配置最小为 1 分钟的数值、单位和起始时间。

金额和笔数轮询 SHALL 按新支付单创建时形成的路由尝试事实统计,不再仅统计已确认支付成功结果。一次新支付在本地支付单、冻结商户路由和路由尝试事实成功提交后,按冻结商户、商户池、统计世代和支付金额计入一次;该支付之后成功、明确失败、取消、过期或结果未知,均不得再次计入、回冲或改写该统计事实。支付创建时 MUST 冻结本次路由所属的统计世代;当前选路只读取当前统计世代的路由尝试事实,金额与笔数累计 MUST 只统计与当前统计世代匹配的事实,自然日与自然月方式另加支付创建时间不早于当期窗口起点。达到阈值的成员在当前周期跳过;全部成员均达到阈值时的行为按统计周期区分:每轮累计 MUST 视为当轮结束,以当前支付创建提交时间为新起点开启新一轮并从零重新累计,MUST NOT 因当轮全部达标而拒绝创建,开启新一轮 MUST 以条件更新递增统计世代,仅在当前世代未被并发改变时成功,更新冲突 MUST 按并发冲突拒绝创建本次支付;自然日累计 与 自然月累计 MUST 拒绝创建新支付单并提示当前周期暂无可用商户。池内只有一个启用成员时该成员 MUST 被固定选中:MUST NOT 因达到阈值而在当前周期被跳过,也 MUST NOT 因全部成员达标而拒绝创建,该规则优先于自然周期拒绝语义。时间轮询自起始时间按固定时段和成员顺序选择,成员停用即时跳下一个可用成员但不重置时段;修改时间周期数值、单位、起始时间或成员顺序并保存成功后,系统 MUST 以保存成功时间为新起点并从前述成员列表第一项重新计算时段,MUST NOT 沿用请求提交前的起点。修改阈值保留当前统计,修改统计周期、金额/笔数方式、时间周期、起始时间或每轮排序按既有规则开启新周期;自然周期排序调整保留未移除成员累计。

支付预下单获得明确失败结果时,系统 MUST 将本次支付冻结的商户自动置为禁用,并记录与该支付单关联的安全失败原因和发生时间;后续新支付 MUST 重新读取商户池,仅从启用商户中选择,不得继续命中该商户。该失败支付单 MUST 按当前失败语义结束,系统 MUST NOT 自动将同一支付单改挂其他商户或向其他商户重试。结果未知、无法证明渠道未受理或仅本地请求上下文取消时,系统 MUST NOT 仅凭该结果自动禁用商户或创建第二个渠道支付。

Scenario: 并发预下单未预占额度

  • WHEN 多个客户并发创建金额或笔数轮询支付单且当前成员尚未达到阈值
  • THEN 系统可使这些支付单均命中当前成员,每个成功提交的支付单各计入一次冻结商户的路由尝试金额/笔数,后续支付结果不改变已创建支付单的商户归属

Scenario: 路由尝试在支付创建时计入

  • GIVEN 一个新支付单已在本地事务中成功创建并冻结商户、商户池和统计世代
  • WHEN 后续渠道支付成功、明确失败、取消、过期或结果未知
  • THEN 金额/笔数轮询均只保留该支付创建时的一次统计,不因后续结果重复计入或回冲

Scenario: 迟到首次成功归属冻结统计世代

  • GIVEN 支付已创建但尚未成功,之后商户池切换统计周期、成员或排序
  • WHEN 该支付首次确认成功
  • THEN 系统不新增第二条路由尝试事实,不改写当前选路统计;支付仍按创建时冻结的商户处理

Scenario: 每轮累计全部达标开启新一轮

  • GIVEN 启用商户池统计周期为每轮累计,且本轮全部成员均已达到阈值
  • WHEN 客户创建新的支付单
  • THEN 系统开启新一轮、各成员从零累计,并选中成员顺序第一项,不返回暂无可用商户

Scenario: 当期没有可用商户

  • WHEN 启用商户池中不存在启用且未达阈值的成员,或商户池已停用
  • THEN 系统拒绝创建新支付单并提示暂无可用商户,不回退到旧综合支付配置

Scenario: 自然周期全部达标拒绝创建

  • GIVEN 启用商户池统计周期为自然日累计或自然月累计,且当前周期全部成员均已达到阈值
  • WHEN 客户创建新的支付单
  • THEN 系统拒绝创建并提示当前周期暂无可用商户,不回退到旧综合支付配置

Scenario: 单成员池达标后仍可收款

  • GIVEN 启用商户池只有一个启用成员,且该成员在当前自然日或自然月周期内已达到阈值
  • WHEN 客户创建新的支付单
  • THEN 系统仍选中该成员,不返回暂无可用商户

Scenario: 明确预下单失败自动禁用商户

  • GIVEN 新支付已冻结商户 A,且渠道明确返回该商户或其凭证不可用的失败结果
  • WHEN 本次预下单结束为明确失败
  • THEN 系统将商户 A 自动禁用,记录支付单关联的安全失败原因,且本次支付不自动改挂其他商户

Scenario: 禁用商户不再被后续支付命中

  • GIVEN 商户 A 因明确预下单失败已被自动禁用,商户池中还有启用商户 B
  • WHEN 下一笔新支付创建
  • THEN 系统跳过商户 A 并按当前金额/笔数/时间规则选择商户 B

Scenario: 结果未知不自动禁用

  • GIVEN 新支付已冻结商户 A,外部请求超时、连接中断、响应无法确认或请求上下文取消
  • WHEN 系统无法证明渠道明确拒绝且无法确认是否已受理
  • THEN 系统保留商户 A 的当前启用状态,保留原支付单进入既有查单/恢复边界,不创建第二个渠道支付

Scenario: 失败账户并发禁用幂等

  • GIVEN 多个已冻结商户 A 的支付请求都得到明确失败
  • WHEN 多个失败处理并发执行
  • THEN 商户 A 最终为禁用状态,失败留痕不重复推进路由统计,已提交的支付单仍保留各自冻结的商户 A

Scenario: 金额轮换不区分支付结果

  • GIVEN 金额轮询阈值为 100 元,商户 A 已有 80 元路由尝试累计
  • WHEN 下一笔 30 元支付单创建后随后明确失败
  • THEN 商户 A 的当前统计累计为 110 元,下一笔新支付跳过商户 A 并选择下一个可用成员

Scenario: 笔数轮换不区分支付结果

  • GIVEN 笔数轮询阈值为 2 笔,商户 A 已有 1 笔路由尝试累计
  • WHEN 下一笔支付单创建后随后取消或预下单明确失败
  • THEN 商户 A 的当前统计累计为 2 笔,下一笔新支付跳过商户 A 并选择下一个可用成员

Scenario: 历史支付仍按冻结商户服务

  • GIVEN 支付单已冻结商户 A,之后商户 A 因另一笔支付明确失败被禁用
  • WHEN 系统处理该历史支付的回调、查单或原路退款
  • THEN 系统仍按该支付单冻结的商户 A 读取当前凭证和处理历史事实,不因商户停用改挂其他商户

Scenario: 修改时间轮询配置后起点重算

  • GIVEN 时间轮询商户池已存在起始时间与成员顺序
  • WHEN 授权账号修改周期数值、单位、起始时间或成员顺序并保存成功
  • THEN 系统以保存成功时间作为新起点,后续时段从成员列表第一项重新计算,不沿用请求提交前的时段

Scenario: 创建提交即计入且失败不回冲

  • GIVEN 新支付单已冻结商户、商户池和统计世代并成功提交路由尝试事实
  • WHEN 预下单明确失败、取消、过期或结果未知
  • THEN 金额/笔数累计仍保留创建提交时的一次计数,且不会因后续结果新增、回冲或改写路由尝试事实