From ae6c99ae74b9336b80823e545bc41eb66e9fb337 Mon Sep 17 00:00:00 2001 From: menxipeng Date: Sat, 8 Nov 2025 12:03:25 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E9=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/AppleNotificationProcessor.java | 170 +++++++++++++++++- 1 file changed, 167 insertions(+), 3 deletions(-) diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/util/AppleNotificationProcessor.java b/ruoyi-system/src/main/java/com/ruoyi/system/util/AppleNotificationProcessor.java index 3c5d138..bd0df8d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/util/AppleNotificationProcessor.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/util/AppleNotificationProcessor.java @@ -1,12 +1,23 @@ package com.ruoyi.system.util; import com.alibaba.fastjson2.JSONObject; +import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.core.domain.entity.OrderInfo; +import com.ruoyi.common.core.domain.entity.ShopUser; +import com.ruoyi.system.mapper.OrderInfoMapper; +import com.ruoyi.system.service.IOrderInfoService; import com.ruoyi.system.service.ShopUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.math.BigDecimal; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.UUID; + @Component @Slf4j public class AppleNotificationProcessor { @@ -15,6 +26,10 @@ public class AppleNotificationProcessor { private AppleSignedPayloadDecoder payloadDecoder; @Autowired private ShopUserService shopUserService; + @Autowired + private OrderInfoMapper orderInfoMapper; + @Autowired + private IOrderInfoService orderInfoService; /** * 完整的通知处理流程 @@ -149,10 +164,159 @@ public class AppleNotificationProcessor { RenewalInfo renewalInfo) { log.info("处理续订事件 - 子类型: {}", notificationInfo.getSubtype()); - if (transactionInfo != null) { - // 找到最近的原始订单数据做校验 ,防止重复校验问题,创建新的订单数据,并调用 shopUserService.updateShopUserVipTime(transactionInfo.getUserId(), "1") - + if (transactionInfo == null) { + log.warn("续订事件中交易信息为空"); + return; } + + String transactionId = transactionInfo.getTransactionId(); + String originalTransactionId = transactionInfo.getOriginalTransactionId(); + String productId = transactionInfo.getProductId(); + + if (StringUtils.isEmpty(transactionId) || StringUtils.isEmpty(originalTransactionId)) { + log.error("续订事件中交易ID或原始交易ID为空"); + return; + } + + // 1. 检查当前交易ID是否已处理(防止重复处理) + OrderInfo existingOrder = orderInfoMapper.selectByTradeNo(transactionId); + if (existingOrder != null) { + log.warn("交易ID {} 已存在,可能重复处理。订单ID: {}", transactionId, existingOrder.getOrderId()); + // 如果订单已存在且已支付,直接返回(幂等性处理) + if (existingOrder.getPayStatus() != null && existingOrder.getPayStatus() >= 2) { + log.info("订单已处理,跳过。订单ID: {}, 交易ID: {}", existingOrder.getOrderId(), transactionId); + return; + } + } + + // 2. 根据原始交易ID查找最近的原始订单,获取用户ID + OrderInfo queryOrder = new OrderInfo(); + queryOrder.setCallbackContent(originalTransactionId); + queryOrder.setPayType("applePay"); + List originalOrders = orderInfoService.selectOrderInfoList(queryOrder); + + Long userId = null; + if (originalOrders != null && !originalOrders.isEmpty()) { + // 找到最近的原始订单(按创建时间倒序,取第一个) + OrderInfo originalOrder = originalOrders.stream() + .filter(order -> order.getUserId() != null) + .findFirst() + .orElse(null); + if (originalOrder != null) { + userId = originalOrder.getUserId(); + log.info("从原始订单获取用户ID: {}, 原始交易ID: {}", userId, originalTransactionId); + } + } + + if (userId == null) { + log.error("无法从原始交易ID {} 找到用户ID,无法处理续订", originalTransactionId); + return; + } + + // 3. 根据产品ID确定套餐类型和订单信息 + String packageType = null; + String orderName = null; + BigDecimal amount = null; + + if ("com.mingyue.product.month".equals(productId)) { + packageType = "1"; + orderName = "VIP会员包月"; + amount = new BigDecimal("268.00"); + } else if ("com.mingyue.product.quarterly".equals(productId)) { + packageType = "2"; + orderName = "VIP会员包季度"; + amount = new BigDecimal("70.00"); + } else if ("com.mingyue.product.semiAnnual".equals(productId)) { + packageType = "3"; + orderName = "VIP会员包半年"; + amount = new BigDecimal("135.00"); + } else if ("com.mingyue.product.annual".equals(productId)) { + packageType = "4"; + orderName = "VIP会员包年"; + amount = new BigDecimal("18.00"); + } else { + log.error("未知的产品ID: {}, 用户ID: {}", productId, userId); + return; + } + + // 4. 创建新的订单记录 + Date startTime = new Date(); + Date endTime = calculateEndTime(startTime, packageType); + + OrderInfo newOrder = new OrderInfo(); + newOrder.setId(UUID.randomUUID().toString().replace("-", "")); + newOrder.setOrderId(System.currentTimeMillis()); + newOrder.setUserId(userId); + newOrder.setPayType("applePay"); + newOrder.setPayStatus(2L); // 2-待出货 + newOrder.setPayTime(DateUtils.getNowDate()); + newOrder.setStartTime(startTime); + newOrder.setEndTime(endTime); + newOrder.setTradeNo(transactionId); + newOrder.setCallbackContent(transactionId); + newOrder.setCallTime(DateUtils.getNowDate()); + newOrder.setOrderName(orderName); + newOrder.setAmount(amount); + newOrder.setPackageType(packageType); + newOrder.setIdDel(0L); + newOrder.setVersion(1L); + newOrder.setCreateTime(DateUtils.getNowDate()); + newOrder.setUpdateTime(DateUtils.getNowDate()); + + // 5. 保存订单并更新用户VIP时间 + try { + int insertResult = orderInfoService.insertOrderInfo(newOrder); + if (insertResult > 0) { + log.info("续订订单创建成功,订单ID: {}, 交易ID: {}, 用户ID: {}", + newOrder.getOrderId(), transactionId, userId); + + // 更新用户VIP时间 + ShopUser updatedUser = shopUserService.updateShopUserVipTime(userId, packageType); + if (updatedUser != null && updatedUser.getMsg() == null) { + log.info("用户VIP时间更新成功,用户ID: {}, 套餐类型: {}", userId, packageType); + } else { + String errorMsg = updatedUser != null ? updatedUser.getMsg() : "未知错误"; + log.error("用户VIP时间更新失败,用户ID: {}, 错误信息: {}", userId, errorMsg); + } + } else { + log.error("续订订单创建失败,交易ID: {}, 用户ID: {}", transactionId, userId); + } + } catch (Exception e) { + log.error("处理续订事件异常,交易ID: {}, 用户ID: {}, 错误: {}", + transactionId, userId, e.getMessage(), e); + } + } + + /** + * 根据套餐类型计算结束时间 + * + * @param startTime 开始时间 + * @param packageType 套餐类型:1-月付, 2-季付, 3-半年付, 4-年付 + * @return 结束时间 + */ + private Date calculateEndTime(Date startTime, String packageType) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(startTime); + + switch (packageType) { + case "1": // 月付 + calendar.add(Calendar.MONTH, 1); + break; + case "2": // 季付 + calendar.add(Calendar.MONTH, 3); + break; + case "3": // 半年付 + calendar.add(Calendar.MONTH, 6); + break; + case "4": // 年付 + calendar.add(Calendar.YEAR, 1); + break; + default: + calendar.add(Calendar.MONTH, 1); // 默认1个月 + break; + } + + return calendar.getTime(); } private void handleRenewalFailureEvent(NotificationInfo notificationInfo,