|
|
@@ -0,0 +1,89 @@
|
|
|
+package com.etotem.cfc.task;
|
|
|
+
|
|
|
+import com.etotem.cfc.entity.PaymentOrder;
|
|
|
+import com.etotem.cfc.entity.VirtualGoodsConfig;
|
|
|
+import com.etotem.cfc.service.SysConfigService;
|
|
|
+import com.etotem.cfc.service.VirtualGoodsConfigService;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.springframework.test.util.ReflectionTestUtils;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
+
|
|
|
+/**
|
|
|
+ * VirtualPayTimeoutTask 误杀防护单测。
|
|
|
+ *
|
|
|
+ * 背景:createOrder 在"虚拟道具未配置"时降级普通微信支付(v3 JSAPI 通道),
|
|
|
+ * 这类订单在 xpay 侧不存在。旧逻辑对全部 pending 会员订单统一 xpay 查单,
|
|
|
+ * 查不到即 STATUS_ORDER_NOT_FOUND 误置 cancelled(2026-10-22 订单48 事件)。
|
|
|
+ *
|
|
|
+ * 修复判据与 MembershipService.createOrder 降级逻辑同源:
|
|
|
+ * 仅当 系统开关 member_pay_virtual_enabled != "0" 且 virtual_goods_config
|
|
|
+ * 中存在启用的 MEMBERSHIP 道具配置时,订单才属于虚拟支付通道、才允许 xpay 查单。
|
|
|
+ */
|
|
|
+public class VirtualPayTimeoutTaskTest {
|
|
|
+
|
|
|
+ private VirtualPayTimeoutTask task;
|
|
|
+ private SysConfigService sysConfigService;
|
|
|
+ private VirtualGoodsConfigService virtualGoodsConfigService;
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ public void setUp() {
|
|
|
+ task = new VirtualPayTimeoutTask();
|
|
|
+ sysConfigService = mock(SysConfigService.class);
|
|
|
+ virtualGoodsConfigService = mock(VirtualGoodsConfigService.class);
|
|
|
+ ReflectionTestUtils.setField(task, "sysConfigService", sysConfigService);
|
|
|
+ ReflectionTestUtils.setField(task, "virtualGoodsConfigService", virtualGoodsConfigService);
|
|
|
+ }
|
|
|
+
|
|
|
+ private PaymentOrder basicOrder() {
|
|
|
+ PaymentOrder order = new PaymentOrder();
|
|
|
+ order.setOrderNo("ORD-TEST-BASIC");
|
|
|
+ order.setFamilyId(58L);
|
|
|
+ order.setLevelCode("BASIC");
|
|
|
+ order.setStatus("pending");
|
|
|
+ return order;
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 开关开启 + 有道具配置 → 虚拟支付通道,允许查单 */
|
|
|
+ @Test
|
|
|
+ public void isVirtualPaymentOrder_whenSwitchOnAndGoodsConfigured() {
|
|
|
+ when(sysConfigService.getValue("member_pay_virtual_enabled")).thenReturn("1");
|
|
|
+ when(virtualGoodsConfigService.getEnabled("MEMBERSHIP", "BASIC")).thenReturn(new VirtualGoodsConfig());
|
|
|
+ assertTrue(task.isVirtualPaymentOrder(basicOrder()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 开关开启 + 无道具配置(订单48 场景:BASIC 无配置)→ 普通支付通道,跳过 */
|
|
|
+ @Test
|
|
|
+ public void notVirtualPaymentOrder_whenNoGoodsConfig() {
|
|
|
+ when(sysConfigService.getValue("member_pay_virtual_enabled")).thenReturn("1");
|
|
|
+ when(virtualGoodsConfigService.getEnabled("MEMBERSHIP", "BASIC")).thenReturn(null);
|
|
|
+ assertFalse(task.isVirtualPaymentOrder(basicOrder()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 开关关闭(=0)→ 全部走普通支付,跳过 */
|
|
|
+ @Test
|
|
|
+ public void notVirtualPaymentOrder_whenSwitchOff() {
|
|
|
+ when(sysConfigService.getValue("member_pay_virtual_enabled")).thenReturn("0");
|
|
|
+ assertFalse(task.isVirtualPaymentOrder(basicOrder()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 开关未设置(null) → 按 createOrder 缺省逻辑视为开启,但有配置才算虚拟 */
|
|
|
+ @Test
|
|
|
+ public void defaultSwitchOn_whenConfigMissing() {
|
|
|
+ when(sysConfigService.getValue("member_pay_virtual_enabled")).thenReturn(null);
|
|
|
+ when(virtualGoodsConfigService.getEnabled("MEMBERSHIP", "BASIC")).thenReturn(new VirtualGoodsConfig());
|
|
|
+ assertTrue(task.isVirtualPaymentOrder(basicOrder()));
|
|
|
+ }
|
|
|
+
|
|
|
+ /** 开关未设置(null) + 无配置 → 普通支付 */
|
|
|
+ @Test
|
|
|
+ public void defaultSwitchOnButNoGoods() {
|
|
|
+ when(sysConfigService.getValue("member_pay_virtual_enabled")).thenReturn(null);
|
|
|
+ when(virtualGoodsConfigService.getEnabled("MEMBERSHIP", "BASIC")).thenReturn(null);
|
|
|
+ assertFalse(task.isVirtualPaymentOrder(basicOrder()));
|
|
|
+ }
|
|
|
+}
|