|
@@ -11,6 +11,7 @@ import org.springframework.stereotype.Service;
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
|
|
+import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.LinkedHashMap;
|
|
import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
@@ -36,6 +37,12 @@ public class VirtualPayService {
|
|
|
@Resource
|
|
@Resource
|
|
|
private AssessmentOrderService assessmentOrderService;
|
|
private AssessmentOrderService assessmentOrderService;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private VirtualGoodsConfigService virtualGoodsConfigService;
|
|
|
|
|
+
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private PackagePurchaseService packagePurchaseService;
|
|
|
|
|
+
|
|
|
@Value("${wechat.appid}")
|
|
@Value("${wechat.appid}")
|
|
|
private String appid;
|
|
private String appid;
|
|
|
|
|
|
|
@@ -104,6 +111,54 @@ public class VirtualPayService {
|
|
|
return dto;
|
|
return dto;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 测评订单虚拟支付下单参数编排(防循环依赖:编排放本类,AssessmentOrderService 单向被依赖)。
|
|
|
|
|
+ * 订单保持 pending;查不到道具映射返回 null(调用方转 46001 "该商品暂未开放购买")。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param appointmentId 前端可选传入,回填订单修复 appointmentId 链路断点
|
|
|
|
|
+ */
|
|
|
|
|
+ public VirtualPayParamsDTO generateAssessmentPayParams(String orderNo, String payType,
|
|
|
|
|
+ String sessionKey, Long appointmentId) {
|
|
|
|
|
+ // 1. 查订单 + 校验 pending
|
|
|
|
|
+ AssessmentOrder order = assessmentOrderService.getByOrderNo(orderNo);
|
|
|
|
|
+ if (order == null || !"pending".equals(order.getStatus())) {
|
|
|
|
|
+ log.warn("生成测评支付参数失败,订单不存在或非pending: orderNo={}", orderNo);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 回填 appointmentId(修复链路断点:createOrder 从不赋值)
|
|
|
|
|
+ if (appointmentId != null && order.getAppointmentId() == null) {
|
|
|
|
|
+ order.setAppointmentId(appointmentId);
|
|
|
|
|
+ order.setUpdatedAt(new Date());
|
|
|
|
|
+ assessmentOrderService.updateById(order);
|
|
|
|
|
+ log.info("支付下单回填预约关联: orderNo={}, appointmentId={}", orderNo, appointmentId);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 查 virtual_goods_config:goodsType=ASSESSMENT_PACKAGE, bizKey=订单packageId → null → 调用方 46001
|
|
|
|
|
+ VirtualGoodsConfig config = virtualGoodsConfigService.getEnabled("ASSESSMENT_PACKAGE",
|
|
|
|
|
+ String.valueOf(order.getPackageId()));
|
|
|
|
|
+ if (config == null) {
|
|
|
|
|
+ log.warn("测评道具未配置或停用: packageId={}", order.getPackageId());
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 服务端重算金额(不信任前端传参):total_fee = getPackagePrice(...).totalPrice
|
|
|
|
|
+ Map<String, Object> price = packagePurchaseService.getPackagePrice(order.getPackageId(), order.getGuideId(), null);
|
|
|
|
|
+ if (price == null || price.get("totalPrice") == null) {
|
|
|
|
|
+ log.warn("测评套餐服务端计价失败: packageId={}", order.getPackageId());
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+ Integer totalFee = ((Number) price.get("totalPrice")).intValue();
|
|
|
|
|
+ if (totalFee < 100) { // 金额 >= 1元
|
|
|
|
|
+ log.warn("测评套餐金额异常(<1元): packageId={}, totalFee={}", order.getPackageId(), totalFee);
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 组装 attach + product_info 并生成支付参数(订单保持 pending,不置 paid)
|
|
|
|
|
+ String attach = "assessment:" + order.getPackageId();
|
|
|
|
|
+ return generatePayParams(config, orderNo, totalFee, order.getPackageName(), attach, sessionKey);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 处理虚拟支付发货推送(xpay_goods_deliver_notify)。
|
|
* 处理虚拟支付发货推送(xpay_goods_deliver_notify)。
|
|
|
* 按 OutTradeNo 前缀路由:A→测评,ORD→会员(TODO Task 7),SUB→订阅(TODO Task 8)。
|
|
* 按 OutTradeNo 前缀路由:A→测评,ORD→会员(TODO Task 7),SUB→订阅(TODO Task 8)。
|
|
@@ -128,8 +183,8 @@ public class VirtualPayService {
|
|
|
log.info("虚拟支付发货推送重复通知,订单已终态: outTradeNo={}, status={}", outTradeNo, existing.getStatus());
|
|
log.info("虚拟支付发货推送重复通知,订单已终态: outTradeNo={}, status={}", outTradeNo, existing.getStatus());
|
|
|
return successResult();
|
|
return successResult();
|
|
|
}
|
|
}
|
|
|
- // 测评订单:标记已付 + 佣金结算
|
|
|
|
|
- assessmentOrderService.paySuccess(outTradeNo, transactionId, "virtual");
|
|
|
|
|
|
|
+ // 测评订单:标记已付 + 佣金结算 + 预约确认
|
|
|
|
|
+ assessmentOrderService.handleVirtualPaySuccess(outTradeNo, transactionId);
|
|
|
} else if (outTradeNo.startsWith("ORD") || outTradeNo.startsWith("SUB")) {
|
|
} else if (outTradeNo.startsWith("ORD") || outTradeNo.startsWith("SUB")) {
|
|
|
// TODO Task 7/8: 会员(ORD) / 订阅(SUB) 标记已付 + 解锁权益,暂未接入,记录日志返回成功
|
|
// TODO Task 7/8: 会员(ORD) / 订阅(SUB) 标记已付 + 解锁权益,暂未接入,记录日志返回成功
|
|
|
log.warn("虚拟支付发货推送暂未接入会员/订阅处理: outTradeNo={}", outTradeNo);
|
|
log.warn("虚拟支付发货推送暂未接入会员/订阅处理: outTradeNo={}", outTradeNo);
|