Skip to content

fix(payment): 退款重试耗尽时两个入口统一建差账工单并补扫漏建工单 - #41

Merged
Emryswu merged 1 commit into
mainfrom
fix/payment-retry-exhaustion
Nov 1, 2026
Merged

Emryswu merged 1 commit into
mainfrom
fix/payment-retry-exhaustion

Conversation

@Emryswu

@Emryswu Emryswu commented Nov 1, 2026

Copy link
Copy Markdown
Owner

问题

退款重试耗尽时,可能既不再重试、也不开差账工单。渠道拒绝后通过事件立即重试,但事件入口忽略了 attempt() 返回的“已放弃请求”:例如前七次被渠道拒绝、第八次遇到网络异常,请求变成 ABANDONED,定时扫描不再捞它,退款就没人接着处理了。同样情况走定时重试入口则会正常建单。

另外,ABANDONED 状态先于工单的 REQUIRES_NEW 事务提交,如果建工单这一步自身失败,该请求也会永久漏单。

修改

  • PaymentDispatchService.attempt() 在耗尽时直接建差账工单,事件入口与定时入口共用同一处理逻辑。
  • PaymentRequestRetryJob 新增补扫:按重试间隔查找“ABANDONED 但没有对应差账工单”的请求并补建工单,工单按 discrepancy key 去重,重复执行只会有一张。
  • PaymentRequestRepository 新增 findAbandonedWithoutTicket() 查询。
  • README 出站表格同步说明。

验证

  • 新增 PaymentRetryExhaustionIntegrationTest:前七次渠道拒绝、第八次网络异常,事件入口与定时入口均为“尝试 8 次、工单 1 张”,重复触发不会多建单。
  • 新增 AbandonedPaymentTicketBackstopIntegrationTest:漏建工单的 ABANDONED 请求被补扫建单且只建一张;订单不存在的请求不会被捞取。
  • 本地 mvnw clean verify:241 项通过,17 项 MySQL/RabbitMQ 测试因无 Docker 跳过;新查询在 MySQL 上的表现以 CI 为准。

出站请求重试耗尽改由 PaymentDispatchService 在标记 ABANDONED 后直接建工单,
事件首发和定时重试两条路径行为一致,PaymentRequestRetryJob 不再自己建单。

ABANDONED 先提交、工单在独立事务里写,建单失败时请求已退出重试扫描,
会一直没人处理。PaymentRequestRetryJob 新增按重试间隔运行的补扫,找出
没有 outbound| 差账工单的 ABANDONED 请求逐条补建,依赖差账键去重保证幂等。

Signed-off-by: Emrys <219520811+Emryswu@users.noreply.github.com>
@Emryswu
Emryswu merged commit a5ca06c into main Nov 1, 2026
12 of 13 checks passed
@Emryswu
Emryswu deleted the fix/payment-retry-exhaustion branch November 1, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant