From c46ef64cd3cc90da78bc7946a9a0666d035a680e Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期四, 17 九月 2026 17:23:41 +0800
Subject: [PATCH] fix(payment): 取消意图落库自动落地,对账间隔回到设计的一分钟

---
 talent-card-server/src/main/java/com/talentcard/server/business/payment/PaymentReconciliationService.java |   32 +++++++++++++++++++++++++++++++-
 1 files changed, 31 insertions(+), 1 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/payment/PaymentReconciliationService.java b/talent-card-server/src/main/java/com/talentcard/server/business/payment/PaymentReconciliationService.java
index 168415c..b79e4b9 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/payment/PaymentReconciliationService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/payment/PaymentReconciliationService.java
@@ -66,7 +66,37 @@
     public Map<String, Object> reconcile(int pendingAfterMinutes) {
         int paymentChecked = reconcilePayments(pendingAfterMinutes);
         int refundChecked = reconcileRefunds(pendingAfterMinutes);
-        return Map.of("paymentChecked", paymentChecked, "refundChecked", refundChecked);
+        // 关单结论回来之后,替已经点过取消的用户把订单收掉。放在查单/关单之后:同一轮里先把这次尝试
+        // 问出结论,再决定这笔订单能不能结束。
+        int cancelledOnRequest = cancelOrdersAwaitingCloseConclusion();
+        return Map.of("paymentChecked", paymentChecked, "refundChecked", refundChecked,
+                "cancelledOnRequest", cancelledOnRequest);
+    }
+
+    /**
+     * 落地「用户点过取消、但当时关单还没有结论」的订单。
+     *
+     * <p>取消在通道说「关单处理中」时只能先受理(见 {@code PendingOrderPortalService.cancel}),订单要等
+     * 每笔尝试都有了结论才能结束。那之后必须有人替用户把这一步走完:关单关掉了就取消,通道说钱收下了就
+     * 交给结算把它翻成已支付——否则用户点的取消会随着页面关掉而丢失,订单一直挂在「待支付」,他只能再点
+     * 一次取消,或者等到 15 分钟超时被清理收掉。
+     *
+     * <p>条件与「取消」本身一致:不留未定局的尝试(它们还可能被支付),也不取消已经收到钱的订单。
+     */
+    private int cancelOrdersAwaitingCloseConclusion() {
+        return jdbc.update("""
+                update benefit_order o set o.order_status = 2
+                where o.order_status = 0 and o.deleted = 0 and o.cancel_requested_at is not null
+                  and not exists (
+                    select 1 from payment_transaction p
+                    where p.order_id = o.id
+                      and p.status in ('CREATED', 'PREPAY_CREATED', 'CREATE_UNKNOWN', 'CLOSING', 'CANCEL_UNCONFIRMED')
+                  )
+                  and not exists (
+                    select 1 from payment_transaction p
+                    where p.order_id = o.id and p.status = 'SUCCEEDED'
+                  )
+                """);
     }
 
     /** What the provider said about the payments of one order whose local state is still undecided. */

--
Gitblit v1.7.1