|
@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
|
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
|
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import com.payment.platform.module.payment.apikey.entity.TenantApiKeyEntity;
|
|
import com.payment.platform.module.payment.apikey.entity.TenantApiKeyEntity;
|
|
|
import com.payment.platform.module.payment.apikey.mapper.TenantApiKeyMapper;
|
|
import com.payment.platform.module.payment.apikey.mapper.TenantApiKeyMapper;
|
|
|
import com.payment.platform.module.payment.har.config.HarProperties;
|
|
import com.payment.platform.module.payment.har.config.HarProperties;
|
|
@@ -24,6 +26,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|
|
import org.springframework.http.HttpEntity;
|
|
import org.springframework.http.HttpEntity;
|
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.HttpStatus;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.http.ResponseEntity;
|
|
|
|
|
+import org.springframework.util.MultiValueMap;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.charset.StandardCharsets;
|
|
@@ -160,6 +163,36 @@ class HarCallbackServiceTest {
|
|
|
verify(publisher).changed(OrderEventPublisher.CHANNEL_HAR_ORDER, TENANT);
|
|
verify(publisher).changed(OrderEventPublisher.CHANNEL_HAR_ORDER, TENANT);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 推给商户服务器的 content **不含 third_shop_code**(2026-10-09 隐藏门店)。
|
|
|
|
|
+ *
|
|
|
|
|
+ * <p>content 是回调报文,直接落进商户服务器与对接人的日志里,租户与调用方都看得见;
|
|
|
|
|
+ * 门店编码在去门店前是发出去的,隐藏门店后不能再发。断言抓的是**真实表单**
|
|
|
|
|
+ * (捕获 postForEntity 的 HttpEntity),不是读 buildContent 源码 —— 源码文本不承重。
|
|
|
|
|
+ */
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void notifyEnterprise_contentDoesNotCarryShopCode() throws Exception {
|
|
|
|
|
+ stubKeyWithUrl("https://merchant.example.com/cb");
|
|
|
|
|
+ stubPushOk();
|
|
|
|
|
+ when(orderMapper.update(isNull(), any())).thenReturn(1);
|
|
|
|
|
+
|
|
|
|
|
+ HarOrderEntity o = order("K1");
|
|
|
|
|
+ o.setThirdShopCode("SP2026ABCDEFGHIJ");
|
|
|
|
|
+ service.notifyEnterprise(o);
|
|
|
|
|
+
|
|
|
|
|
+ ArgumentCaptor<HttpEntity> entity = ArgumentCaptor.forClass(HttpEntity.class);
|
|
|
|
|
+ verify(restTemplate, timeout(3000)).postForEntity(
|
|
|
|
|
+ eq("https://merchant.example.com/cb"), entity.capture(), eq(String.class));
|
|
|
|
|
+
|
|
|
|
|
+ MultiValueMap form = (MultiValueMap) entity.getValue().getBody();
|
|
|
|
|
+ assertNotNull(form, "推送体必须是 notify_id/timestamp/content 三格表单");
|
|
|
|
|
+ JsonNode content = new ObjectMapper().readTree(String.valueOf(form.getFirst("content")));
|
|
|
|
|
+ assertEquals("HAR1", content.path("third_order_no").asText(),
|
|
|
|
|
+ "正对照:回调报文本身要正常发出,其余字段都在。实测: " + content);
|
|
|
|
|
+ assertFalse(content.has("third_shop_code"),
|
|
|
|
|
+ "回调 content 不得出现 third_shop_code。实测: " + content);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 推送抛异常 ⇒ 记 FAILED,且**恰好一次 POST** —— 线程内不重试。
|
|
* 推送抛异常 ⇒ 记 FAILED,且**恰好一次 POST** —— 线程内不重试。
|
|
|
*
|
|
*
|