|
@@ -7,6 +7,7 @@ import com.etotem.cfc.entity.MemberSubscription;
|
|
|
import com.etotem.cfc.entity.MemberSubscriptionOrder;
|
|
import com.etotem.cfc.entity.MemberSubscriptionOrder;
|
|
|
import com.etotem.cfc.entity.PaymentOrder;
|
|
import com.etotem.cfc.entity.PaymentOrder;
|
|
|
import com.etotem.cfc.entity.User;
|
|
import com.etotem.cfc.entity.User;
|
|
|
|
|
+import com.etotem.cfc.entity.VirtualGoodsConfig;
|
|
|
import com.etotem.cfc.mapper.AssessmentOrderMapper;
|
|
import com.etotem.cfc.mapper.AssessmentOrderMapper;
|
|
|
import com.etotem.cfc.mapper.FamilyMapper;
|
|
import com.etotem.cfc.mapper.FamilyMapper;
|
|
|
import com.etotem.cfc.mapper.MemberSubscriptionOrderMapper;
|
|
import com.etotem.cfc.mapper.MemberSubscriptionOrderMapper;
|
|
@@ -15,6 +16,8 @@ import com.etotem.cfc.mapper.UserMapper;
|
|
|
import com.etotem.cfc.service.AssessmentOrderService;
|
|
import com.etotem.cfc.service.AssessmentOrderService;
|
|
|
import com.etotem.cfc.service.MemberSubscriptionService;
|
|
import com.etotem.cfc.service.MemberSubscriptionService;
|
|
|
import com.etotem.cfc.service.MembershipService;
|
|
import com.etotem.cfc.service.MembershipService;
|
|
|
|
|
+import com.etotem.cfc.service.SysConfigService;
|
|
|
|
|
+import com.etotem.cfc.service.VirtualGoodsConfigService;
|
|
|
import com.etotem.cfc.service.VirtualPayService;
|
|
import com.etotem.cfc.service.VirtualPayService;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -68,6 +71,12 @@ public class VirtualPayTimeoutTask {
|
|
|
@Resource
|
|
@Resource
|
|
|
private FamilyMapper familyMapper;
|
|
private FamilyMapper familyMapper;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private SysConfigService sysConfigService;
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private VirtualGoodsConfigService virtualGoodsConfigService;
|
|
|
|
|
+
|
|
|
@Value("${virtual-pay.payment-timeout-minutes:30}")
|
|
@Value("${virtual-pay.payment-timeout-minutes:30}")
|
|
|
private int paymentTimeoutMinutes;
|
|
private int paymentTimeoutMinutes;
|
|
|
|
|
|
|
@@ -161,8 +170,36 @@ public class VirtualPayTimeoutTask {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 判定订单是否属于"虚拟支付通道"(即下单时走 xpay,后续需要 xpay query_order 兜底)。
|
|
|
|
|
+ * 判据与 MembershipService.createOrder 降级逻辑同源:开关开启 且 该 levelCode
|
|
|
|
|
+ * 在 virtual_goods_config 中有启用的 MEMBERSHIP 道具。不满足则必然走了普通支付
|
|
|
|
|
+ * (v3-notify 通道),不应被 xpay 查单任务处理。
|
|
|
|
|
+ */
|
|
|
|
|
+ boolean isVirtualPaymentOrder(PaymentOrder order) {
|
|
|
|
|
+ if (order == null || order.getLevelCode() == null) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ String switchVal = sysConfigService.getValue("member_pay_virtual_enabled");
|
|
|
|
|
+ boolean virtualEnabled = !"0".equals(switchVal);
|
|
|
|
|
+ if (!virtualEnabled) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ VirtualGoodsConfig cfg = virtualGoodsConfigService.getEnabled("MEMBERSHIP", order.getLevelCode());
|
|
|
|
|
+ return cfg != null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/** ORD 前缀(会员订单)单笔处理,返回是否处理(解锁/关单) */
|
|
/** ORD 前缀(会员订单)单笔处理,返回是否处理(解锁/关单) */
|
|
|
private boolean handlePaymentOrder(PaymentOrder order) {
|
|
private boolean handlePaymentOrder(PaymentOrder order) {
|
|
|
|
|
+ // 误杀防护(2026-10-22 订单48 事件):普通支付降级订单在 xpay 侧不存在,
|
|
|
|
|
+ // queryOrder 必然返回 STATUS_ORDER_NOT_FOUND 并会被误置 cancelled。
|
|
|
|
|
+ // 仅虚拟支付通道订单(开关开启 + 有道具配置)才允许 xpay 查单,与普通支付通道
|
|
|
|
|
+ // 订单(走 v3-notify)的查询/关单路径解耦。
|
|
|
|
|
+ if (!isVirtualPaymentOrder(order)) {
|
|
|
|
|
+ log.info("虚拟支付超时兜底: 非虚拟支付渠道会员订单, 跳过不查单不关单: orderNo={}, levelCode={}",
|
|
|
|
|
+ order.getOrderNo(), order.getLevelCode());
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
// family_id=NULL 的订单(下单接口未校验历史脏数据):无法向微信查单,直接置 cancelled
|
|
// family_id=NULL 的订单(下单接口未校验历史脏数据):无法向微信查单,直接置 cancelled
|
|
|
if (order.getFamilyId() == null) {
|
|
if (order.getFamilyId() == null) {
|
|
|
order.setStatus("cancelled");
|
|
order.setStatus("cancelled");
|