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/portal/PendingOrderPortalService.java |   21 +++++++++++++++++++--
 1 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/talent-card-server/src/main/java/com/talentcard/server/business/portal/PendingOrderPortalService.java b/talent-card-server/src/main/java/com/talentcard/server/business/portal/PendingOrderPortalService.java
index 99c8f5f..cf782fc 100644
--- a/talent-card-server/src/main/java/com/talentcard/server/business/portal/PendingOrderPortalService.java
+++ b/talent-card-server/src/main/java/com/talentcard/server/business/portal/PendingOrderPortalService.java
@@ -246,9 +246,13 @@
 		if (confirmation.collected()) throw new BusinessException(ErrorCode.CONFLICT, "订单已支付,不能取消");
 		if (confirmation.state() == PendingPaymentState.UNCONFIRMED) {
 			// 关单没有结论(通道答「处理中」或干脆没答上来):这次「支付结果不确定」只属于它所属的
-			// 那一次支付尝试,不该把整笔订单停摆成一个永久报错。取消的意图先被接受并记录,订单本身
-			// 不动——后台每分钟重试关单,有关闭或已收款的结论时再落地(关掉了就取消,钱收下了就
+			// 那一次支付尝试,不该把整笔订单停摆成一个永久报错。取消的意图先被接受**并落库**,订单
+			// 本身不动——后台每分钟重试关单,有关闭或已收款的结论时再落地(关掉了就取消,钱收下了就
 			// 翻成已支付并告知用户)。页面按「取消处理中」渲染。
+			//
+			// 意图必须落库:结论可能几分钟后才回来(关单补偿在后台跑),只把 cancelPending 交给客户端
+			// 等于赌页面一直开着。旧实现就是这样,结果关单真关掉之后没人收那笔订单,用户点的取消丢了。
+			recordCancelRequest(orderNo, talentId);
 			return cancellationPending(orderNo, talentId, confirmation.paymentNo());
 		}
 		// 过了支付时限的订单在这里结束:条件写在 SQL 里,跨实例只有一个赢家。
@@ -289,6 +293,19 @@
 		return result;
 	}
 
+	/**
+	 * 把「用户点了取消」落库,等关单有了结论由对账替他把订单收掉。
+	 *
+	 * <p>只写第一条时间戳:用户反复点取消不该把受理时间往后推,那是「他最早什么时候要取消」。
+	 */
+	private void recordCancelRequest(String orderNo, Long talentId) {
+		jdbcTemplate.update("""
+			update benefit_order set cancel_requested_at = now()
+			where order_no = ? and talent_id = ? and deleted = 0 and order_status = 0
+			  and cancel_requested_at is null
+			""", orderNo, talentId);
+	}
+
 	/** 单个订单的到期结束:条件写在 SQL 里,跨实例只有一个赢家。未定局的支付尝试照上面同样的理由排除。 */
 	private void expireOrder(String orderNo, Long talentId) {
 		jdbcTemplate.update("""

--
Gitblit v1.7.1