From 7bbd9688f58fd0ce612e9c2d3b3d0ccb64dffa2e Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期六, 12 九月 2026 13:42:08 +0800
Subject: [PATCH] refactor(merchant): 斗拱能力查询移出数据库事务

---
 talent-card-server/src/test/java/com/talentcard/server/business/merchant/MerchantPaymentReadinessServiceTests.java |   49 +++++++++++++++++++++++++++++++++++--------------
 1 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/talent-card-server/src/test/java/com/talentcard/server/business/merchant/MerchantPaymentReadinessServiceTests.java b/talent-card-server/src/test/java/com/talentcard/server/business/merchant/MerchantPaymentReadinessServiceTests.java
index c01e2d1..4a2dfa0 100644
--- a/talent-card-server/src/test/java/com/talentcard/server/business/merchant/MerchantPaymentReadinessServiceTests.java
+++ b/talent-card-server/src/test/java/com/talentcard/server/business/merchant/MerchantPaymentReadinessServiceTests.java
@@ -74,7 +74,7 @@
 
     @Test
     void allowsPaymentOnceAutoSettlementIsOffAndEncashmentIsConfirmed() {
-        stubProvider("NORMAL", "0", "1");
+        confirmSnapshot("NORMAL", "0", "1");
 
         MerchantPaymentReadinessService.Readiness readiness = readinessService.readiness(merchantId, storeId);
 
@@ -88,8 +88,8 @@
     }
 
     @Test
-    void blocksPaymentWhileAutoSettlementIsStillOn() {
-        stubProvider("NORMAL", "1", "1");
+    void rejectsANewPaidOrderOnceAutoSettlementIsBackOn() {
+        confirmSnapshot("NORMAL", "1", "1");
 
         assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
                 .isInstanceOf(BusinessException.class)
@@ -97,8 +97,8 @@
     }
 
     @Test
-    void blocksPaymentWhenEncashmentCapabilityIsUnavailable() {
-        stubProvider("NORMAL", "0", "0");
+    void rejectsANewPaidOrderWhenEncashmentCapabilityIsUnavailable() {
+        confirmSnapshot("NORMAL", "0", "0");
 
         assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
                 .isInstanceOf(BusinessException.class)
@@ -106,8 +106,8 @@
     }
 
     @Test
-    void blocksPaymentWhenTheSubMerchantIsFrozen() {
-        stubProvider("FREEZEWITHDRAWAL", "0", "1");
+    void rejectsANewPaidOrderWhenTheSubMerchantIsFrozen() {
+        confirmSnapshot("FREEZEWITHDRAWAL", "0", "1");
 
         assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
                 .isInstanceOf(BusinessException.class)
@@ -115,22 +115,29 @@
     }
 
     @Test
-    void blocksPaymentWhenTheProviderRejectsTheCapabilityQuery() {
+    void aRejectedProviderQueryLeavesTheSnapshotUnconfirmed() {
         when(capabilityGateway.query(any(HuifuMerchantCapabilityQueryCommand.class)))
                 .thenReturn(HuifuMerchantCapabilityGateway.CapabilityResult.failed("99999999", "商户不存在"));
 
+        Map<String, Object> capability = readinessService.capability(applicationId);
+
+        assertThat(capability).containsEntry("autoSettleDisabled", false).containsEntry("verifiedAt", "");
+        assertThat(jdbc.queryForObject("select capability_response_code from merchant_onboarding_application where id=?", String.class, applicationId)).isEqualTo("99999999");
         assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
                 .isInstanceOf(BusinessException.class)
                 .hasMessageContaining("待确认");
     }
 
     @Test
-    void blocksPaymentWhenTheProviderQueryTimesOut() {
+    void aProviderTimeoutLeavesTheSnapshotUnconfirmed() {
         when(capabilityGateway.query(any(HuifuMerchantCapabilityQueryCommand.class)))
                 .thenThrow(new HuifuPaymentGatewayException("timeout", true, null));
 
-        assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
-                .isInstanceOf(BusinessException.class);
+        assertThat(readinessService.refresh(applicationId)).containsEntry("verifiedAt", "");
+
+        assertThat(jdbc.queryForObject("select capability_response_message from merchant_onboarding_application where id=?", String.class, applicationId))
+                .isEqualTo("商户收款能力查询结果待确认");
+        assertThat(readinessService.readiness(merchantId, storeId).ready()).isFalse();
     }
 
     @Test
@@ -155,12 +162,20 @@
 
     @Test
     void reusesTheConfirmedSnapshotInsteadOfQueryingTheProviderAgain() {
-        stubProvider("NORMAL", "0", "1");
-        readinessService.requirePayable(merchantId, storeId);
+        confirmSnapshot("NORMAL", "0", "1");
 
-        readinessService.requirePayable(merchantId, storeId);
+        assertThat(readinessService.readiness(merchantId, storeId).ready()).isTrue();
 
         verify(capabilityGateway, times(1)).query(any(HuifuMerchantCapabilityQueryCommand.class));
+    }
+
+    @Test
+    void blocksPaymentUntilTheSnapshotHasBeenConfirmed() {
+        // The payment path never calls the provider itself, so an unconfirmed snapshot must block.
+        assertThatThrownBy(() -> readinessService.requirePayable(merchantId, storeId))
+                .isInstanceOf(BusinessException.class)
+                .hasMessageContaining("待确认");
+        verify(capabilityGateway, never()).query(any(HuifuMerchantCapabilityQueryCommand.class));
     }
 
     @Test
@@ -181,6 +196,12 @@
         return prefix + suffix.substring(Math.max(0, suffix.length() - 8));
     }
 
+    /** Stores a provider snapshot through the admin refresh path. */
+    private void confirmSnapshot(String merchantStatus, String settleStatus, String cashSwitch) {
+        stubProvider(merchantStatus, settleStatus, cashSwitch);
+        readinessService.refresh(applicationId);
+    }
+
     private void stubProvider(String merchantStatus, String settleStatus, String cashSwitch) {
         when(capabilityGateway.query(any(HuifuMerchantCapabilityQueryCommand.class)))
                 .thenReturn(new HuifuMerchantCapabilityGateway.CapabilityResult(true, "00000000", "成功", merchantStatus, settleStatus, "D1", cashSwitch, "DM"));

--
Gitblit v1.7.1