订单
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package com.ruoyi.common.core.domain.dto;
|
package com.ruoyi.common.core.domain.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8,6 +10,7 @@ import java.io.Serializable;
|
|||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
* @date 2025-01-27
|
* @date 2025-01-27
|
||||||
*/
|
*/
|
||||||
|
@Data
|
||||||
public class OrderCreateRequest implements Serializable {
|
public class OrderCreateRequest implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@@ -16,7 +19,7 @@ public class OrderCreateRequest implements Serializable {
|
|||||||
private String orderName;
|
private String orderName;
|
||||||
|
|
||||||
/** 金额(分) */
|
/** 金额(分) */
|
||||||
private Long amount;
|
private String amount;
|
||||||
|
|
||||||
/** 支付方式 aliPay/wechatPay/applePay */
|
/** 支付方式 aliPay/wechatPay/applePay */
|
||||||
private String payType;
|
private String payType;
|
||||||
@@ -30,51 +33,4 @@ public class OrderCreateRequest implements Serializable {
|
|||||||
/** 客户端IP */
|
/** 客户端IP */
|
||||||
private String clientIp;
|
private String clientIp;
|
||||||
|
|
||||||
public String getOrderName() {
|
|
||||||
return orderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOrderName(String orderName) {
|
|
||||||
this.orderName = orderName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Long getAmount() {
|
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAmount(Long amount) {
|
|
||||||
this.amount = amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPayType() {
|
|
||||||
return payType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPayType(String payType) {
|
|
||||||
this.payType = payType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPackageType() {
|
|
||||||
return packageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPackageType(String packageType) {
|
|
||||||
this.packageType = packageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceType() {
|
|
||||||
return deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceType(String deviceType) {
|
|
||||||
this.deviceType = deviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClientIp() {
|
|
||||||
return clientIp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClientIp(String clientIp) {
|
|
||||||
this.clientIp = clientIp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.ruoyi.common.core.domain.entity;
|
package com.ruoyi.common.core.domain.entity;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -36,7 +37,7 @@ public class OrderInfo extends BaseEntity
|
|||||||
|
|
||||||
/** 金额 分 */
|
/** 金额 分 */
|
||||||
@Excel(name = "金额 分")
|
@Excel(name = "金额 分")
|
||||||
private Long amount;
|
private BigDecimal amount;
|
||||||
|
|
||||||
/** 支付方式 aliPay / wechatPay / applePay */
|
/** 支付方式 aliPay / wechatPay / applePay */
|
||||||
@Excel(name = "支付方式 aliPay / wechatPay / applePay ")
|
@Excel(name = "支付方式 aliPay / wechatPay / applePay ")
|
||||||
|
|||||||
@@ -76,4 +76,6 @@ public interface OrderInfoMapper
|
|||||||
* @return 订单列表
|
* @return 订单列表
|
||||||
*/
|
*/
|
||||||
public List<OrderInfoVO> selectOrderInfoVOList(OrderInfo orderInfo);
|
public List<OrderInfoVO> selectOrderInfoVOList(OrderInfo orderInfo);
|
||||||
|
|
||||||
|
OrderInfo selectByTradeNo(String transactionId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,6 @@ public interface ShopUserService {
|
|||||||
* @param type 1 - 月 2-季 3-半年 4-年
|
* @param type 1 - 月 2-季 3-半年 4-年
|
||||||
*/
|
*/
|
||||||
ShopUser updateShopUserVipTime(Long userId, String type);
|
ShopUser updateShopUserVipTime(Long userId, String type);
|
||||||
|
|
||||||
|
ShopUser selectUserById(Long userId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,6 +205,11 @@ public class CShopUserServiceImpl implements ShopUserService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ShopUser selectUserById(Long userId) {
|
||||||
|
return shopUserMapper.selectShopUserByUserId(userId);
|
||||||
|
}
|
||||||
|
|
||||||
public ShopUser loginAndRegis(ShopUserResq shopUser) {
|
public ShopUser loginAndRegis(ShopUserResq shopUser) {
|
||||||
ShopUser member = shopUserMapper.selectShopUserByPhone(shopUser.getPhone());
|
ShopUser member = shopUserMapper.selectShopUserByPhone(shopUser.getPhone());
|
||||||
if (shopUser.getPhone() != null && StringUtils.isNull(member)) {
|
if (shopUser.getPhone() != null && StringUtils.isNull(member)) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.ruoyi.common.core.domain.dto.PaymentRequest;
|
|||||||
import com.ruoyi.common.core.domain.dto.RefundRequest;
|
import com.ruoyi.common.core.domain.dto.RefundRequest;
|
||||||
import com.ruoyi.common.core.domain.entity.OrderInfo;
|
import com.ruoyi.common.core.domain.entity.OrderInfo;
|
||||||
import com.ruoyi.common.core.domain.entity.PayStatusEnum;
|
import com.ruoyi.common.core.domain.entity.PayStatusEnum;
|
||||||
|
import com.ruoyi.common.core.domain.entity.ShopUser;
|
||||||
import com.ruoyi.common.core.domain.vo.OrderInfoVO;
|
import com.ruoyi.common.core.domain.vo.OrderInfoVO;
|
||||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
@@ -19,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -115,7 +117,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
public AjaxResult createOrder(OrderCreateRequest request) {
|
public AjaxResult createOrder(OrderCreateRequest request) {
|
||||||
try {
|
try {
|
||||||
// 参数校验
|
// 参数校验
|
||||||
if (StringUtils.isEmpty(request.getOrderName()) || request.getAmount() == null || request.getAmount() <= 0) {
|
if (StringUtils.isEmpty(request.getOrderName()) || request.getAmount() == null || new BigDecimal(request.getAmount()).compareTo(BigDecimal.ZERO) < 0 ) {
|
||||||
return AjaxResult.error("订单信息不完整");
|
return AjaxResult.error("订单信息不完整");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +133,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
orderInfo.setOrderId(System.currentTimeMillis()); // 使用时间戳作为订单号
|
orderInfo.setOrderId(System.currentTimeMillis()); // 使用时间戳作为订单号
|
||||||
orderInfo.setOrderName(request.getOrderName());
|
orderInfo.setOrderName(request.getOrderName());
|
||||||
orderInfo.setUserId(loginUser.getUserId());
|
orderInfo.setUserId(loginUser.getUserId());
|
||||||
orderInfo.setAmount(request.getAmount());
|
orderInfo.setAmount(new BigDecimal(request.getAmount()));
|
||||||
orderInfo.setPayType(request.getPayType());
|
orderInfo.setPayType(request.getPayType());
|
||||||
orderInfo.setPackageType(request.getPackageType());
|
orderInfo.setPackageType(request.getPackageType());
|
||||||
orderInfo.setDeviceType(request.getDeviceType());
|
orderInfo.setDeviceType(request.getDeviceType());
|
||||||
@@ -175,17 +177,14 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
|
|
||||||
// 检查用户权限
|
// 检查用户权限
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
// if (loginUser == null || !loginUser.getUserId().equals(orderInfo.getUserId())) {
|
if (loginUser == null || !loginUser.getUserId().equals(orderInfo.getUserId())) {
|
||||||
// return AjaxResult.error("无权限操作此订单");
|
return AjaxResult.error("无权限操作此订单");
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 调用第三方支付接口 TODO:// 待修改
|
// 调用第三方支付接口 TODO:// 待修改
|
||||||
processPayment(orderInfo, request);
|
ShopUser shopUser = processPayment(orderInfo, request);
|
||||||
|
if (shopUser != null){
|
||||||
boolean paymentResult = true;
|
return AjaxResult.success(shopUser);
|
||||||
|
|
||||||
if (paymentResult){
|
|
||||||
return AjaxResult.success("支付请求成功");
|
|
||||||
}else {
|
}else {
|
||||||
return AjaxResult.error("支付请求失败");
|
return AjaxResult.error("支付请求失败");
|
||||||
}
|
}
|
||||||
@@ -254,7 +253,7 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查退款金额
|
// 检查退款金额
|
||||||
if (request.getRefundAmount() > orderInfo.getAmount()) {
|
if (orderInfo.getAmount().compareTo(new BigDecimal(request.getRefundAmount())) > 0) {
|
||||||
return AjaxResult.error("退款金额不能大于订单金额");
|
return AjaxResult.error("退款金额不能大于订单金额");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,22 +348,23 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
/**
|
/**
|
||||||
* 处理支付过程
|
* 处理支付过程
|
||||||
*/
|
*/
|
||||||
private boolean processPayment(OrderInfo orderInfo, PaymentRequest request) {
|
private ShopUser processPayment(OrderInfo orderInfo, PaymentRequest request) {
|
||||||
String payType = orderInfo.getPayType();
|
String payType = orderInfo.getPayType();
|
||||||
// 根据支付方式调用相应的支付接口
|
// 根据支付方式调用相应的支付接口
|
||||||
switch (payType) {
|
switch (payType) {
|
||||||
case "aliPay":
|
case "aliPay":
|
||||||
//return paymentUtil.processAliPay(orderInfo, request);
|
//return paymentUtil.processAliPay(orderInfo, request);
|
||||||
return false;
|
return null;
|
||||||
case "wechatPay":
|
case "wechatPay":
|
||||||
//return paymentUtil.processWechatPay(orderInfo, request);
|
//return paymentUtil.processWechatPay(orderInfo, request);
|
||||||
return false;
|
return null;
|
||||||
case "applePay":
|
case "applePay":
|
||||||
return appleyPay.setIapCertificate(String.valueOf(orderInfo.getUserId()), request.getPaymentToken(), false);
|
return appleyPay.setIapCertificate(orderInfo.getUserId(), request.getPaymentToken(),
|
||||||
|
orderInfo, false);
|
||||||
default:
|
default:
|
||||||
Map<String, Object> errorResult = new HashMap<>();
|
Map<String, Object> errorResult = new HashMap<>();
|
||||||
errorResult.put("error", "不支持的支付方式");
|
errorResult.put("error", "不支持的支付方式");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,13 +380,13 @@ public class OrderInfoServiceImpl implements IOrderInfoService
|
|||||||
if ("1".equals(packageType)) {
|
if ("1".equals(packageType)) {
|
||||||
// 包月
|
// 包月
|
||||||
orderInfo.setEndTime(DateUtils.addMonths(now, 1));
|
orderInfo.setEndTime(DateUtils.addMonths(now, 1));
|
||||||
} else if ("3".equals(packageType)) {
|
} else if ("2".equals(packageType)) {
|
||||||
// 包季度
|
// 包季度
|
||||||
orderInfo.setEndTime(DateUtils.addMonths(now, 3));
|
orderInfo.setEndTime(DateUtils.addMonths(now, 3));
|
||||||
} else if ("6".equals(packageType)) {
|
} else if ("3".equals(packageType)) {
|
||||||
// 半年
|
// 半年
|
||||||
orderInfo.setEndTime(DateUtils.addMonths(now, 6));
|
orderInfo.setEndTime(DateUtils.addMonths(now, 6));
|
||||||
} else if ("12".equals(packageType)) {
|
} else if ("4".equals(packageType)) {
|
||||||
// 一年
|
// 一年
|
||||||
orderInfo.setEndTime(DateUtils.addMonths(now, 12));
|
orderInfo.setEndTime(DateUtils.addMonths(now, 12));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.ruoyi.system.util;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.service.ShopUserService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -12,6 +13,8 @@ public class AppleNotificationProcessor {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AppleSignedPayloadDecoder payloadDecoder;
|
private AppleSignedPayloadDecoder payloadDecoder;
|
||||||
|
@Autowired
|
||||||
|
private ShopUserService shopUserService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 完整的通知处理流程
|
* 完整的通知处理流程
|
||||||
@@ -147,6 +150,7 @@ public class AppleNotificationProcessor {
|
|||||||
log.info("处理续订事件 - 子类型: {}", notificationInfo.getSubtype());
|
log.info("处理续订事件 - 子类型: {}", notificationInfo.getSubtype());
|
||||||
|
|
||||||
if (transactionInfo != null) {
|
if (transactionInfo != null) {
|
||||||
|
// 找到最近的原始订单数据做校验 ,防止重复校验问题,创建新的订单数据,并调用 shopUserService.updateShopUserVipTime(transactionInfo.getUserId(), "1")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,13 @@ import com.alibaba.fastjson2.JSON;
|
|||||||
import com.alibaba.fastjson2.JSONArray;
|
import com.alibaba.fastjson2.JSONArray;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.ruoyi.common.core.domain.entity.OrderInfo;
|
import com.ruoyi.common.core.domain.entity.OrderInfo;
|
||||||
|
import com.ruoyi.common.core.domain.entity.ShopUser;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.system.mapper.OrderInfoMapper;
|
||||||
import com.ruoyi.system.service.IOrderInfoService;
|
import com.ruoyi.system.service.IOrderInfoService;
|
||||||
|
import com.ruoyi.system.service.ShopUserService;
|
||||||
|
import org.checkerframework.checker.units.qual.A;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -21,6 +25,7 @@ import javax.net.ssl.X509TrustManager;
|
|||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
@@ -41,6 +46,10 @@ public class AppleyPay {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IOrderInfoService orderInfoService;
|
private IOrderInfoService orderInfoService;
|
||||||
|
@Autowired
|
||||||
|
private OrderInfoMapper orderInfoMapper;
|
||||||
|
@Autowired
|
||||||
|
private ShopUserService shopUserService;
|
||||||
|
|
||||||
//购买凭证验证地址
|
//购买凭证验证地址
|
||||||
private static final String certificateUrl = "https://buy.itunes.apple.com/verifyReceipt";
|
private static final String certificateUrl = "https://buy.itunes.apple.com/verifyReceipt";
|
||||||
@@ -73,20 +82,20 @@ public class AppleyPay {
|
|||||||
* @param receipt 苹果传递前端给的值
|
* @param receipt 苹果传递前端给的值
|
||||||
* @param chooseEnv 是否时测试环境
|
* @param chooseEnv 是否时测试环境
|
||||||
*/
|
*/
|
||||||
public boolean setIapCertificate(String userId, String receipt, boolean chooseEnv) {
|
public ShopUser setIapCertificate(Long userId, String receipt, OrderInfo orderInfo,boolean chooseEnv) {
|
||||||
log.info("IOS端发送的购买凭证。数据有 userId = {},receipt = {},chooseEnv = {}",userId,receipt,chooseEnv);
|
log.info("IOS端发送的购买凭证。数据有 userId = {},receipt = {},chooseEnv = {}",userId,receipt,chooseEnv);
|
||||||
if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(receipt)) {
|
if (userId == null || StringUtils.isEmpty(receipt)) {
|
||||||
log.error("用户ID 或者 receipt为空");
|
log.error("用户ID 或者 receipt为空");
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
String url = null;
|
String url = null;
|
||||||
url = chooseEnv == true ? certificateUrl : certificateUrlTest;
|
url = chooseEnv == true ? certificateUrl : certificateUrlTest;
|
||||||
final String certificateCode = receipt;
|
final String certificateCode = receipt;
|
||||||
if (StringUtils.isNotEmpty(certificateCode)) {
|
if (StringUtils.isNotEmpty(certificateCode)) {
|
||||||
String s = sendHttpsCoon(url, certificateCode, userId);
|
return sendHttpsCoon(url, certificateCode, userId,orderInfo);
|
||||||
return "支付成功".equals(s);
|
|
||||||
} else {
|
} else {
|
||||||
return false;
|
log.error("用户ID 或者 receipt为空");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,10 +113,10 @@ public class AppleyPay {
|
|||||||
* @param userId 用户ID
|
* @param userId 用户ID
|
||||||
* @return 结果
|
* @return 结果
|
||||||
*/
|
*/
|
||||||
private String sendHttpsCoon(String url, String code, String userId) {
|
private ShopUser sendHttpsCoon(String url, String code, Long userId, OrderInfo orderParam) {
|
||||||
if (url == null || url.isEmpty()) {
|
if (url == null || url.isEmpty()) {
|
||||||
log.error("验证URL为空");
|
log.error("验证URL为空");
|
||||||
return "支付失败,验证URL为空";
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
//设置SSLContext
|
//设置SSLContext
|
||||||
@@ -138,8 +147,8 @@ public class AppleyPay {
|
|||||||
//获取输入流
|
//获取输入流
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
|
||||||
|
|
||||||
String line = null;
|
String line;
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuilder sb = new StringBuilder();
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
sb.append(line);
|
sb.append(line);
|
||||||
}
|
}
|
||||||
@@ -155,14 +164,14 @@ public class AppleyPay {
|
|||||||
if (status == null || status != 0) {
|
if (status == null || status != 0) {
|
||||||
String errorMsg = getStatusErrorMessage(status);
|
String errorMsg = getStatusErrorMessage(status);
|
||||||
log.error("苹果验证失败,状态码: {}, 错误信息: {}", status, errorMsg);
|
log.error("苹果验证失败,状态码: {}, 错误信息: {}", status, errorMsg);
|
||||||
return "支付失败,苹果验证失败: " + errorMsg;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取 latest_receipt_info,可能是数组或单个对象
|
// 获取 latest_receipt_info,可能是数组或单个对象
|
||||||
Object latestReceiptInfoObj = alljsoncode.get("latest_receipt_info");
|
Object latestReceiptInfoObj = alljsoncode.get("latest_receipt_info");
|
||||||
if (latestReceiptInfoObj == null) {
|
if (latestReceiptInfoObj == null) {
|
||||||
log.error("latest_receipt_info 为空");
|
log.error("latest_receipt_info 为空");
|
||||||
return "支付失败,未找到交易信息";
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理 latest_receipt_info(可能是数组或单个对象)
|
// 处理 latest_receipt_info(可能是数组或单个对象)
|
||||||
@@ -172,7 +181,7 @@ public class AppleyPay {
|
|||||||
JSONArray receiptArray = (JSONArray) latestReceiptInfoObj;
|
JSONArray receiptArray = (JSONArray) latestReceiptInfoObj;
|
||||||
if (receiptArray.isEmpty()) {
|
if (receiptArray.isEmpty()) {
|
||||||
log.error("latest_receipt_info 数组为空");
|
log.error("latest_receipt_info 数组为空");
|
||||||
return "支付失败,交易信息数组为空";
|
return null;
|
||||||
}
|
}
|
||||||
// 获取最新的交易记录(数组最后一个元素)
|
// 获取最新的交易记录(数组最后一个元素)
|
||||||
Object lastReceipt = receiptArray.get(receiptArray.size() - 1);
|
Object lastReceipt = receiptArray.get(receiptArray.size() - 1);
|
||||||
@@ -184,7 +193,7 @@ public class AppleyPay {
|
|||||||
|
|
||||||
if (latestTransaction == null) {
|
if (latestTransaction == null) {
|
||||||
log.error("无法解析交易信息");
|
log.error("无法解析交易信息");
|
||||||
return "支付失败,无法解析交易信息";
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取关键信息
|
// 获取关键信息
|
||||||
@@ -192,9 +201,17 @@ public class AppleyPay {
|
|||||||
String productId = latestTransaction.getProductId();
|
String productId = latestTransaction.getProductId();
|
||||||
String expiresDateMs = latestTransaction.getExpiresDateMs();
|
String expiresDateMs = latestTransaction.getExpiresDateMs();
|
||||||
|
|
||||||
|
// 查询交易信息是否已经存在
|
||||||
|
OrderInfo selectOrderInfo = orderInfoMapper.selectByTradeNo(transactionId);
|
||||||
|
if (selectOrderInfo != null){
|
||||||
|
log.warn("交易ID {} 已存在,可能重复处理。用户ID: {}", transactionId, userId);
|
||||||
|
// 交易信息已存在
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isEmpty(transactionId)) {
|
if (StringUtils.isEmpty(transactionId)) {
|
||||||
log.error("transaction_id 为空");
|
log.error("transaction_id 为空");
|
||||||
return "支付失败,交易ID为空";
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查订单是否已处理(防重复发货)
|
// 检查订单是否已处理(防重复发货)
|
||||||
@@ -208,7 +225,7 @@ public class AppleyPay {
|
|||||||
OrderInfo existingOrder = existingOrders.get(0);
|
OrderInfo existingOrder = existingOrders.get(0);
|
||||||
if (existingOrder.getPayStatus() != null && existingOrder.getPayStatus() >= 2) {
|
if (existingOrder.getPayStatus() != null && existingOrder.getPayStatus() >= 2) {
|
||||||
log.info("订单已处理,返回成功。订单ID: {}, 交易ID: {}", existingOrder.getOrderId(), transactionId);
|
log.info("订单已处理,返回成功。订单ID: {}, 交易ID: {}", existingOrder.getOrderId(), transactionId);
|
||||||
return "支付成功";
|
return shopUserService.selectUserById(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +237,7 @@ public class AppleyPay {
|
|||||||
if (expiresTimestamp < currentTimestamp) {
|
if (expiresTimestamp < currentTimestamp) {
|
||||||
log.warn("订阅已过期。交易ID: {}, 过期时间: {}, 当前时间: {}",
|
log.warn("订阅已过期。交易ID: {}, 过期时间: {}, 当前时间: {}",
|
||||||
transactionId, new Date(expiresTimestamp), new Date(currentTimestamp));
|
transactionId, new Date(expiresTimestamp), new Date(currentTimestamp));
|
||||||
return "支付失败,订阅已过期";
|
return null;
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
log.warn("无法解析过期时间: {}", expiresDateMs);
|
log.warn("无法解析过期时间: {}", expiresDateMs);
|
||||||
@@ -229,83 +246,92 @@ public class AppleyPay {
|
|||||||
|
|
||||||
// 根据产品ID处理不同的订阅类型
|
// 根据产品ID处理不同的订阅类型
|
||||||
String packageType = null;
|
String packageType = null;
|
||||||
String orderName = null;
|
String orderName;
|
||||||
Long amount = null; // 金额(分)
|
BigDecimal amount; // 金额(分)
|
||||||
|
|
||||||
|
// 计算服务开始和结束时间
|
||||||
|
Date startTime = new Date();
|
||||||
|
|
||||||
|
|
||||||
|
// 创建订单记录
|
||||||
|
OrderInfo orderInfo = new OrderInfo();
|
||||||
|
orderInfo.setOrderId(orderParam.getOrderId());
|
||||||
|
|
||||||
|
orderInfo.setUserId(userId);
|
||||||
|
orderInfo.setPayType("applePay");
|
||||||
|
orderInfo.setPayStatus(2L); // 2-待出货
|
||||||
|
orderInfo.setPayTime(DateUtils.getNowDate());
|
||||||
|
orderInfo.setStartTime(startTime);
|
||||||
|
|
||||||
|
orderInfo.setTradeNo(transactionId);
|
||||||
|
orderInfo.setCallbackContent(sb.toString()); // 保存完整的回调内容
|
||||||
|
orderInfo.setCallTime(DateUtils.getNowDate());
|
||||||
|
orderInfo.setCallbackContent(transactionId);
|
||||||
|
|
||||||
|
orderInfo.setIdDel(0L);
|
||||||
|
orderInfo.setVersion(1L);
|
||||||
|
orderInfo.setCreateTime(DateUtils.getNowDate());
|
||||||
|
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
||||||
|
|
||||||
if ("com.mingyue.product.month".equals(productId)) {
|
if ("com.mingyue.product.month".equals(productId)) {
|
||||||
// 月付
|
// 月付
|
||||||
packageType = "1";
|
packageType = "1";
|
||||||
orderName = "VIP会员包月";
|
orderName = "VIP会员包月";
|
||||||
amount = 1200L; // 12元 = 1200分
|
amount = new BigDecimal("268.00"); // 12元 = 1200分
|
||||||
log.info("用户ID:{}, 产品:月付订阅", userId);
|
log.info("用户ID:{}, 产品:月付订阅", userId);
|
||||||
|
orderInfo.setAmount(amount);
|
||||||
|
orderInfo.setOrderName(orderName);
|
||||||
|
Date endTime = calculateEndTime(startTime, packageType);
|
||||||
|
orderInfo.setEndTime(endTime);
|
||||||
|
orderInfo.setPackageType(packageType);
|
||||||
|
orderInfoService.updateOrderInfo(orderInfo);
|
||||||
|
return shopUserService.updateShopUserVipTime(userId, "1");
|
||||||
} else if ("com.mingyue.product.quarterly".equals(productId)) {
|
} else if ("com.mingyue.product.quarterly".equals(productId)) {
|
||||||
// 季付
|
// 季付
|
||||||
packageType = "2";
|
packageType = "2";
|
||||||
orderName = "VIP会员包季度";
|
orderName = "VIP会员包季度";
|
||||||
amount = 3000L; // 30元 = 3000分
|
amount = new BigDecimal("70.00"); // 30元 = 3000分
|
||||||
log.info("用户ID:{}, 产品:季付订阅", userId);
|
log.info("用户ID:{}, 产品:季付订阅", userId);
|
||||||
|
Date endTime = calculateEndTime(startTime, packageType);
|
||||||
|
orderInfo.setAmount(amount);
|
||||||
|
orderInfo.setOrderName(orderName);
|
||||||
|
orderInfo.setEndTime(endTime);
|
||||||
|
orderInfo.setPackageType(packageType);
|
||||||
|
orderInfoService.updateOrderInfo(orderInfo);
|
||||||
|
return shopUserService.updateShopUserVipTime(userId, "2");
|
||||||
} else if ("com.mingyue.product.semiAnnual".equals(productId)) {
|
} else if ("com.mingyue.product.semiAnnual".equals(productId)) {
|
||||||
// 半年付
|
// 半年付
|
||||||
packageType = "3";
|
packageType = "3";
|
||||||
orderName = "VIP会员包半年";
|
orderName = "VIP会员包半年";
|
||||||
amount = 6000L; // 60元 = 6000分(假设)
|
amount = new BigDecimal("135.00"); // 60元 = 6000分(假设)
|
||||||
log.info("用户ID:{}, 产品:半年付订阅", userId);
|
log.info("用户ID:{}, 产品:半年付订阅", userId);
|
||||||
|
Date endTime = calculateEndTime(startTime, packageType);
|
||||||
|
orderInfo.setAmount(amount);
|
||||||
|
orderInfo.setOrderName(orderName);
|
||||||
|
orderInfo.setEndTime(endTime);
|
||||||
|
orderInfo.setPackageType(packageType);
|
||||||
|
orderInfoService.updateOrderInfo(orderInfo);
|
||||||
|
return shopUserService.updateShopUserVipTime(userId, "3");
|
||||||
} else if ("com.mingyue.product.annual".equals(productId)) {
|
} else if ("com.mingyue.product.annual".equals(productId)) {
|
||||||
// 年付
|
// 年付
|
||||||
packageType = "4";
|
packageType = "4";
|
||||||
orderName = "VIP会员包年";
|
orderName = "VIP会员包年";
|
||||||
amount = 12000L; // 120元 = 12000分(假设)
|
amount = new BigDecimal("18.00"); // 120元 = 12000分(假设)
|
||||||
log.info("用户ID:{}, 产品:年付订阅", userId);
|
log.info("用户ID:{}, 产品:年付订阅", userId);
|
||||||
} else {
|
|
||||||
log.error("用户ID:{}, 未知的产品ID: {}", userId, productId);
|
|
||||||
return "支付失败,未知的产品ID: " + productId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建或更新订单
|
|
||||||
try {
|
|
||||||
// 计算服务开始和结束时间
|
|
||||||
Date startTime = new Date();
|
|
||||||
Date endTime = calculateEndTime(startTime, packageType);
|
|
||||||
|
|
||||||
// 创建订单记录
|
|
||||||
OrderInfo orderInfo = new OrderInfo();
|
|
||||||
orderInfo.setId(java.util.UUID.randomUUID().toString().replace("-", ""));
|
|
||||||
orderInfo.setOrderId(System.currentTimeMillis());
|
|
||||||
orderInfo.setOrderName(orderName);
|
|
||||||
orderInfo.setUserId(Long.parseLong(userId));
|
|
||||||
orderInfo.setAmount(amount);
|
orderInfo.setAmount(amount);
|
||||||
orderInfo.setPayType("applePay");
|
orderInfo.setOrderName(orderName);
|
||||||
orderInfo.setPayStatus(2L); // 2-待出货
|
Date endTime = calculateEndTime(startTime, packageType);
|
||||||
orderInfo.setPayTime(DateUtils.getNowDate());
|
|
||||||
orderInfo.setStartTime(startTime);
|
|
||||||
orderInfo.setEndTime(endTime);
|
orderInfo.setEndTime(endTime);
|
||||||
orderInfo.setPackageType(packageType);
|
orderInfo.setPackageType(packageType);
|
||||||
orderInfo.setTradeNo(transactionId);
|
orderInfoService.updateOrderInfo(orderInfo);
|
||||||
orderInfo.setCallbackContent(sb.toString()); // 保存完整的回调内容
|
return shopUserService.updateShopUserVipTime(userId, "4");
|
||||||
orderInfo.setCallTime(DateUtils.getNowDate());
|
} else {
|
||||||
orderInfo.setIdDel(0L);
|
log.error("用户ID:{}, 未知的产品ID: {}", userId, productId);
|
||||||
orderInfo.setVersion(1L);
|
return null;
|
||||||
orderInfo.setCreateTime(DateUtils.getNowDate());
|
|
||||||
orderInfo.setUpdateTime(DateUtils.getNowDate());
|
|
||||||
|
|
||||||
// 保存订单
|
|
||||||
int result = orderInfoService.insertOrderInfo(orderInfo);
|
|
||||||
if (result > 0) {
|
|
||||||
log.info("订单创建成功。订单ID: {}, 交易ID: {}, 用户ID: {}, 产品: {}",
|
|
||||||
orderInfo.getOrderId(), transactionId, userId, productId);
|
|
||||||
return "支付成功";
|
|
||||||
} else {
|
|
||||||
log.error("订单创建失败。交易ID: {}, 用户ID: {}", transactionId, userId);
|
|
||||||
return "支付失败,订单创建失败";
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("创建订单异常。交易ID: {}, 用户ID: {}, 异常: {}", transactionId, userId, e.getMessage(), e);
|
|
||||||
return "支付失败,订单创建异常: " + e.getMessage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("向苹果发起验证支付请求是否有效出现异常:{}", e.getMessage(), e);
|
log.error("向苹果发起验证支付请求是否有效出现异常:{}", e.getMessage(), e);
|
||||||
return "支付过程中,出现了异常: " + e.getMessage();
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,13 +350,13 @@ public class AppleyPay {
|
|||||||
case "1": // 月付
|
case "1": // 月付
|
||||||
calendar.add(Calendar.MONTH, 1);
|
calendar.add(Calendar.MONTH, 1);
|
||||||
break;
|
break;
|
||||||
case "3": // 季付
|
case "2": // 季付
|
||||||
calendar.add(Calendar.MONTH, 3);
|
calendar.add(Calendar.MONTH, 3);
|
||||||
break;
|
break;
|
||||||
case "6": // 半年付
|
case "3": // 半年付
|
||||||
calendar.add(Calendar.MONTH, 6);
|
calendar.add(Calendar.MONTH, 6);
|
||||||
break;
|
break;
|
||||||
case "12": // 年付
|
case "4": // 年付
|
||||||
calendar.add(Calendar.YEAR, 1);
|
calendar.add(Calendar.YEAR, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -219,4 +219,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</where>
|
</where>
|
||||||
ORDER BY o.create_time DESC
|
ORDER BY o.create_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectByTradeNo" resultMap="OrderInfoResult">
|
||||||
|
SELECT * FROM order_info WHERE trade_no = #{tradeNo}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user