feat: 重新梳理订单支付流程
parent
6cdd1c1592
commit
5cb0a8e0bf
|
|
@ -9,6 +9,7 @@ import com.ruoyi.xkt.domain.AlipayCallback;
|
|||
import com.ruoyi.xkt.domain.StoreOrder;
|
||||
import com.ruoyi.xkt.enums.EProcessStatus;
|
||||
import com.ruoyi.xkt.manager.impl.AliPaymentMangerImpl;
|
||||
import com.ruoyi.xkt.service.IAlipayCallbackService;
|
||||
import com.ruoyi.xkt.service.IStoreOrderService;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -37,6 +38,8 @@ public class AlipayController extends XktBaseController {
|
|||
@Autowired
|
||||
private IStoreOrderService storeOrderService;
|
||||
@Autowired
|
||||
private IAlipayCallbackService alipayCallbackService;
|
||||
@Autowired
|
||||
private AliPaymentMangerImpl paymentManger;
|
||||
|
||||
/**
|
||||
|
|
@ -85,7 +88,25 @@ public class AlipayController extends XktBaseController {
|
|||
return FAILURE;
|
||||
}
|
||||
//5. 处理支付宝回调信息
|
||||
paymentManger.processAlipayCallback(alipayCallback);
|
||||
AlipayCallback info = alipayCallbackService.getByNotifyId(alipayCallback.getNotifyId());
|
||||
if (info == null) {
|
||||
//保存到数据库
|
||||
info = alipayCallback;
|
||||
alipayCallbackService.insertAlipayCallback(info);
|
||||
}
|
||||
if (!"TRADE_SUCCESS".equals(info.getTradeStatus())) {
|
||||
//非交易支付成功的回调不处理
|
||||
return SUCCESS;
|
||||
}
|
||||
if (info.getRefundFee() != null && !NumberUtil.equals(info.getRefundFee(), BigDecimal.ZERO)) {
|
||||
//如果有退款金额,可能是部分退款的回调,这里不做处理
|
||||
return SUCCESS;
|
||||
}
|
||||
if (EProcessStatus.INIT.getValue().equals(info.getProcessStatus())) {
|
||||
alipayCallbackService.processOrderPay(info);
|
||||
} else {
|
||||
logger.warn("支付回调重复请求处理: {}", info.getId());
|
||||
}
|
||||
return SUCCESS;
|
||||
} else {
|
||||
logger.info("支付宝验签未通过:{}", params);
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ import com.ruoyi.web.controller.xkt.vo.order.StoreOrderAddReqVO;
|
|||
import com.ruoyi.web.controller.xkt.vo.order.StoreOrderPayReqVO;
|
||||
import com.ruoyi.web.controller.xkt.vo.order.StoreOrderPayRespVO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddDTO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddResult;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayFrom;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
import com.ruoyi.xkt.manager.PaymentManager;
|
||||
import com.ruoyi.xkt.service.IStoreOrderService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
|
|
@ -26,6 +27,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
|
@ -44,28 +46,30 @@ public class StoreOrderController extends XktBaseController {
|
|||
|
||||
@PreAuthorize("@ss.hasPermi('system:order:add')")
|
||||
@Log(title = "订单", businessType = BusinessType.INSERT)
|
||||
@ApiOperation("创建订单并发起支付")
|
||||
@ApiOperation("创建订单")
|
||||
@PostMapping("create")
|
||||
public R<StoreOrderPayRespVO> create(@RequestBody StoreOrderAddReqVO vo) {
|
||||
public R<StoreOrderPayRespVO> create(@Valid @RequestBody StoreOrderAddReqVO vo) {
|
||||
StoreOrderAddDTO dto = BeanUtil.toBean(vo, StoreOrderAddDTO.class);
|
||||
dto.setOrderUserId(SecurityUtils.getUserId());
|
||||
//初始化订单
|
||||
StoreOrderInfo orderInfo = storeOrderService.createOrder(dto);
|
||||
//发起支付
|
||||
PaymentManager paymentManager = getPaymentManager(EPayChannel.of(vo.getPayChannel()));
|
||||
String rtnStr = paymentManager.payForOrder(orderInfo.getOrder().getId(), EPayFrom.of(vo.getPayFrom()));
|
||||
//创建订单并根据参数决定是否发起支付
|
||||
StoreOrderAddResult result = storeOrderService.createOrder(dto, vo.getBeginPay(),
|
||||
EPayChannel.of(vo.getPayChannel()), EPayPage.of(vo.getPayFrom()));
|
||||
//返回信息
|
||||
StoreOrderPayRespVO respVO = new StoreOrderPayRespVO(orderInfo.getOrder().getId(), rtnStr);
|
||||
StoreOrderPayRespVO respVO = new StoreOrderPayRespVO(result.getOrderInfo().getOrder().getId(),
|
||||
result.getPayRtnStr());
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('system:order:add')")
|
||||
@Log(title = "订单", businessType = BusinessType.OTHER)
|
||||
@ApiOperation("重新发起订单支付")
|
||||
@ApiOperation("支付订单")
|
||||
@PostMapping("pay")
|
||||
public R<StoreOrderPayRespVO> pay(@RequestBody StoreOrderPayReqVO vo) {
|
||||
public R<StoreOrderPayRespVO> pay(@Valid @RequestBody StoreOrderPayReqVO vo) {
|
||||
PaymentManager paymentManager = getPaymentManager(EPayChannel.of(vo.getPayChannel()));
|
||||
String rtnStr = paymentManager.payForOrder(vo.getStoreOrderId(), EPayFrom.of(vo.getPayFrom()));
|
||||
//订单支付状态->支付中
|
||||
StoreOrderInfo storeOrderInfo = storeOrderService.preparePayOrder(vo.getStoreOrderId());
|
||||
//调用支付
|
||||
String rtnStr = paymentManager.payOrder(storeOrderInfo, EPayPage.of(vo.getPayFrom()));
|
||||
StoreOrderPayRespVO respVO = new StoreOrderPayRespVO(vo.getStoreOrderId(), rtnStr);
|
||||
return success(respVO);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ import io.swagger.annotations.ApiModel;
|
|||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -17,6 +20,7 @@ public class StoreOrderAddReqVO {
|
|||
/**
|
||||
* 档口ID
|
||||
*/
|
||||
@NotNull(message = "档口ID不能为空")
|
||||
@ApiModelProperty(value = "档口ID")
|
||||
private Long storeId;
|
||||
/**
|
||||
|
|
@ -27,41 +31,49 @@ public class StoreOrderAddReqVO {
|
|||
/**
|
||||
* 物流ID
|
||||
*/
|
||||
@NotNull(message = "物流ID不能为空")
|
||||
@ApiModelProperty(value = "物流ID")
|
||||
private Long expressId;
|
||||
/**
|
||||
* 收货人-名称
|
||||
*/
|
||||
@NotEmpty(message = "收货人名称不能为空")
|
||||
@ApiModelProperty(value = "收货人-名称")
|
||||
private String destinationContactName;
|
||||
/**
|
||||
* 收货人-电话
|
||||
*/
|
||||
@NotEmpty(message = "收货人电话不能为空")
|
||||
@ApiModelProperty(value = "收货人-电话")
|
||||
private String destinationContactPhoneNumber;
|
||||
/**
|
||||
* 收货人-省编码
|
||||
*/
|
||||
@NotEmpty(message = "收货人省编码不能为空")
|
||||
@ApiModelProperty(value = "收货人-省编码")
|
||||
private String destinationProvinceCode;
|
||||
/**
|
||||
* 收货人-市编码
|
||||
*/
|
||||
@NotEmpty(message = "收货人市编码不能为空")
|
||||
@ApiModelProperty(value = "收货人-市编码")
|
||||
private String destinationCityCode;
|
||||
/**
|
||||
* 收货人-区县编码
|
||||
*/
|
||||
@NotEmpty(message = "收货人区县编码不能为空")
|
||||
@ApiModelProperty(value = "收货人-区县编码")
|
||||
private String destinationCountyCode;
|
||||
/**
|
||||
* 收货人-详细地址
|
||||
*/
|
||||
@NotEmpty(message = "收货人详细地址不能为空")
|
||||
@ApiModelProperty(value = "收货人-详细地址")
|
||||
private String destinationDetailAddress;
|
||||
/**
|
||||
* 发货方式[1:货其再发 2:有货先发]
|
||||
*/
|
||||
@NotNull(message = "发货方式不能为空")
|
||||
@ApiModelProperty(value = "发货方式[1:货其再发 2:有货先发]")
|
||||
private Integer deliveryType;
|
||||
/**
|
||||
|
|
@ -72,12 +84,20 @@ public class StoreOrderAddReqVO {
|
|||
/**
|
||||
* 明细列表
|
||||
*/
|
||||
@Valid
|
||||
@NotEmpty(message = "订单明细不能为空")
|
||||
@ApiModelProperty(value = "明细列表")
|
||||
private List<Detail> detailList;
|
||||
|
||||
@NotNull(message = "是否发起支付不能为空")
|
||||
@ApiModelProperty(value = "是否发起支付")
|
||||
private Boolean beginPay;
|
||||
|
||||
@NotNull(message = "支付渠道不能为空")
|
||||
@ApiModelProperty(value = "支付渠道[1:支付宝]")
|
||||
private Integer payChannel;
|
||||
|
||||
@NotNull(message = "支付来源不能为空")
|
||||
@ApiModelProperty(value = "支付来源[1:电脑网站 2:手机网站]")
|
||||
private Integer payFrom;
|
||||
|
||||
|
|
@ -85,9 +105,11 @@ public class StoreOrderAddReqVO {
|
|||
@Data
|
||||
public static class Detail {
|
||||
|
||||
@NotNull(message = "商品颜色尺码ID不能为空")
|
||||
@ApiModelProperty(value = "商品颜色尺码ID")
|
||||
private Long storeProdColorSizeId;
|
||||
|
||||
@NotNull(message = "商品数量不能为空")
|
||||
@ApiModelProperty(value = "商品数量")
|
||||
private Integer goodsQuantity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import io.swagger.annotations.ApiModel;
|
|||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-07 18:16
|
||||
|
|
@ -12,12 +14,15 @@ import lombok.Data;
|
|||
@Data
|
||||
public class StoreOrderPayReqVO {
|
||||
|
||||
@NotNull(message = "订单ID不能为空")
|
||||
@ApiModelProperty(value = "订单ID")
|
||||
private Long storeOrderId;
|
||||
|
||||
@NotNull(message = "支付渠道不能为空")
|
||||
@ApiModelProperty(value = "支付渠道[1:支付宝]")
|
||||
private Integer payChannel;
|
||||
|
||||
@NotNull(message = "支付来源不能为空")
|
||||
@ApiModelProperty(value = "支付来源[1:电脑网站 2:手机网站]")
|
||||
private Integer payFrom;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,27 @@
|
|||
package com.ruoyi.common.utils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import com.ruoyi.common.constant.Constants;
|
||||
import com.ruoyi.common.constant.HttpStatus;
|
||||
import com.ruoyi.common.core.domain.entity.SysRole;
|
||||
import com.ruoyi.common.core.domain.model.LoginUser;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 安全服务工具类
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Slf4j
|
||||
public class SecurityUtils
|
||||
{
|
||||
|
||||
|
|
@ -66,6 +70,25 @@ public class SecurityUtils
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户账户
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getUsernameSafe() {
|
||||
String username = null;
|
||||
try {
|
||||
Authentication auth = getAuthentication();
|
||||
if (auth != null) {
|
||||
LoginUser user = (LoginUser) auth.getPrincipal();
|
||||
username = Optional.ofNullable(user).map(LoginUser::getUsername).orElse(null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("获取用户账户异常", e);
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package com.ruoyi.xkt.dto.order;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-03 13:46
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class StoreOrderAddResult {
|
||||
/**
|
||||
* 订单信息
|
||||
*/
|
||||
private StoreOrderInfo orderInfo;
|
||||
/**
|
||||
* 三方支付返回信息
|
||||
*/
|
||||
private String payRtnStr;
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import lombok.Getter;
|
|||
public enum EOrderAction {
|
||||
|
||||
ADD_ORDER(1, "下单"),
|
||||
PAID_ORDER(2, "支付"),
|
||||
;
|
||||
|
||||
private final Integer value;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import lombok.Getter;
|
|||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum EPayFrom {
|
||||
public enum EPayPage {
|
||||
|
||||
WEB(1, "电脑网站"),
|
||||
WAP(2, "手机网站"),
|
||||
|
|
@ -18,8 +18,8 @@ public enum EPayFrom {
|
|||
private final Integer value;
|
||||
private final String label;
|
||||
|
||||
public static EPayFrom of(Integer value) {
|
||||
for (EPayFrom e : EPayFrom.values()) {
|
||||
public static EPayPage of(Integer value) {
|
||||
for (EPayPage e : EPayPage.values()) {
|
||||
if (e.getValue().equals(value)) {
|
||||
return e;
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
package com.ruoyi.xkt.manager;
|
||||
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayFrom;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
|
|
@ -18,10 +19,10 @@ public interface PaymentManager {
|
|||
/**
|
||||
* 订单支付
|
||||
*
|
||||
* @param storeOrderId
|
||||
* @param order
|
||||
* @param payFrom
|
||||
* @return 跳转页面数据/签名字符串/支付跳转链接/预支付交易会话标识(根据支付渠道&支付来源确定)
|
||||
*/
|
||||
String payForOrder(Long storeOrderId, EPayFrom payFrom);
|
||||
String payOrder(StoreOrderInfo order, EPayPage payFrom);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.ruoyi.xkt.manager.impl;
|
||||
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
|
|
@ -8,23 +7,18 @@ import com.alipay.api.DefaultAlipayClient;
|
|||
import com.alipay.api.request.AlipayTradePagePayRequest;
|
||||
import com.alipay.api.request.AlipayTradeWapPayRequest;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.xkt.domain.AlipayCallback;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.dto.finance.AlipayReqDTO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayFrom;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
import com.ruoyi.xkt.enums.EPayStatus;
|
||||
import com.ruoyi.xkt.manager.PaymentManager;
|
||||
import com.ruoyi.xkt.service.IAlipayCallbackService;
|
||||
import com.ruoyi.xkt.service.IStoreOrderService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
* @date 2025-04-06 19:36
|
||||
|
|
@ -33,6 +27,9 @@ import java.math.BigDecimal;
|
|||
@Getter
|
||||
@Component
|
||||
public class AliPaymentMangerImpl implements PaymentManager {
|
||||
|
||||
private static final String DEFAULT_FORMAT = "json";
|
||||
private static final String PAY_PRODUCT_CODE = "FAST_INSTANT_TRADE_PAY";
|
||||
/**
|
||||
* 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
|
||||
*/
|
||||
|
|
@ -74,29 +71,25 @@ public class AliPaymentMangerImpl implements PaymentManager {
|
|||
@Value("${alipay.gatewayUrl:https://openapi-sandbox.dl.alipaydev.com/gateway.do}")
|
||||
private String gatewayUrl;
|
||||
|
||||
@Autowired
|
||||
private IStoreOrderService storeOrderService;
|
||||
@Autowired
|
||||
private IAlipayCallbackService alipayCallbackService;
|
||||
|
||||
@Override
|
||||
public EPayChannel channel() {
|
||||
return EPayChannel.ALI_PAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String payForOrder(Long storeOrderId, EPayFrom payFrom) {
|
||||
Assert.notNull(storeOrderId);
|
||||
public String payOrder(StoreOrderInfo orderInfo, EPayPage payFrom) {
|
||||
Assert.notNull(orderInfo);
|
||||
Assert.notNull(payFrom);
|
||||
//订单状态更新为支付中
|
||||
StoreOrderInfo order = storeOrderService.preparePayOrder(storeOrderId);
|
||||
if (!EPayStatus.PAYING.getValue().equals(orderInfo.getOrder().getPayStatus())) {
|
||||
throw new ServiceException("订单[" + orderInfo.getOrder().getOrderNo() + "]支付状态异常");
|
||||
}
|
||||
AlipayReqDTO reqDTO = new AlipayReqDTO();
|
||||
reqDTO.setOutTradeNo(order.getOrder().getOrderNo());
|
||||
reqDTO.setTotalAmount(order.getOrder().getTotalAmount().toPlainString());
|
||||
reqDTO.setSubject("代发订单" + order.getOrder().getOrderNo());
|
||||
reqDTO.setProductCode("FAST_INSTANT_TRADE_PAY"); //这个是固定的
|
||||
reqDTO.setOutTradeNo(orderInfo.getOrder().getOrderNo());
|
||||
reqDTO.setTotalAmount(orderInfo.getOrder().getTotalAmount().toPlainString());
|
||||
reqDTO.setSubject("代发订单" + orderInfo.getOrder().getOrderNo());
|
||||
reqDTO.setProductCode(PAY_PRODUCT_CODE); //这个是固定的
|
||||
String reqStr = JSON.toJSONString(reqDTO);
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, privateKey, "json", charset,
|
||||
AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl, appId, privateKey, DEFAULT_FORMAT, charset,
|
||||
alipayPublicKey, signType);
|
||||
switch (payFrom) {
|
||||
case WEB:
|
||||
|
|
@ -126,19 +119,4 @@ public class AliPaymentMangerImpl implements PaymentManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void processAlipayCallback(AlipayCallback alipayCallback) {
|
||||
AlipayCallback info = alipayCallbackService.getByNotifyId(alipayCallback.getNotifyId());
|
||||
if (info == null) {
|
||||
//保存到数据库
|
||||
info = alipayCallback;
|
||||
alipayCallbackService.insertAlipayCallback(info);
|
||||
}
|
||||
if (info.getRefundFee() != null &&
|
||||
!NumberUtil.equals(info.getRefundFee(), BigDecimal.ZERO)) {
|
||||
//如果有退款金额,可能是部分退款的回调,这里不做处理
|
||||
return;
|
||||
}
|
||||
//TODO
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,4 +24,10 @@ public interface IAlipayCallbackService {
|
|||
*/
|
||||
int insertAlipayCallback(AlipayCallback alipayCallback);
|
||||
|
||||
/**
|
||||
* 处理订单支付结果
|
||||
*
|
||||
* @param info
|
||||
*/
|
||||
void processOrderPay(AlipayCallback info);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package com.ruoyi.xkt.service;
|
|||
|
||||
import com.ruoyi.xkt.domain.StoreOrder;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddDTO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddResult;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EPayPage;
|
||||
|
||||
/**
|
||||
* @author liangyq
|
||||
|
|
@ -12,10 +15,14 @@ public interface IStoreOrderService {
|
|||
/**
|
||||
* 创建订单
|
||||
*
|
||||
* @param storeOrderAddDTO
|
||||
* @param storeOrderAddDTO 订单信息
|
||||
* @param beginPay 是否发起支付
|
||||
* @param payChannel 支付渠道
|
||||
* @param payPage 支付来源
|
||||
* @return
|
||||
*/
|
||||
StoreOrderInfo createOrder(StoreOrderAddDTO storeOrderAddDTO);
|
||||
StoreOrderAddResult createOrder(StoreOrderAddDTO storeOrderAddDTO, boolean beginPay, EPayChannel payChannel,
|
||||
EPayPage payPage);
|
||||
|
||||
/**
|
||||
* 通过订单号获取订单
|
||||
|
|
@ -31,4 +38,13 @@ public interface IStoreOrderService {
|
|||
* @param storeOrderId
|
||||
*/
|
||||
StoreOrderInfo preparePayOrder(Long storeOrderId);
|
||||
|
||||
/**
|
||||
* 订单支付成果
|
||||
* TODO 更新扣除手续费后的金额
|
||||
*
|
||||
* @param storeOrderId
|
||||
* @return
|
||||
*/
|
||||
StoreOrderInfo paySuccess(Long storeOrderId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,14 @@ package com.ruoyi.xkt.service.impl;
|
|||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.ruoyi.xkt.domain.AlipayCallback;
|
||||
import com.ruoyi.xkt.domain.StoreOrder;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.enums.EPayChannel;
|
||||
import com.ruoyi.xkt.enums.EProcessStatus;
|
||||
import com.ruoyi.xkt.mapper.AlipayCallbackMapper;
|
||||
import com.ruoyi.xkt.service.IAlipayCallbackService;
|
||||
import com.ruoyi.xkt.service.IFinanceBillService;
|
||||
import com.ruoyi.xkt.service.IStoreOrderService;
|
||||
import io.jsonwebtoken.lang.Assert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
|
@ -18,6 +24,10 @@ public class AlipayCallbackServiceImpl implements IAlipayCallbackService {
|
|||
|
||||
@Autowired
|
||||
private AlipayCallbackMapper alipayCallbackMapper;
|
||||
@Autowired
|
||||
private IStoreOrderService storeOrderService;
|
||||
@Autowired
|
||||
private IFinanceBillService financeBillService;
|
||||
|
||||
|
||||
@Override
|
||||
|
|
@ -33,4 +43,18 @@ public class AlipayCallbackServiceImpl implements IAlipayCallbackService {
|
|||
Assert.notNull(alipayCallback);
|
||||
return alipayCallbackMapper.insert(alipayCallback);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void processOrderPay(AlipayCallback info) {
|
||||
//更新回调状态
|
||||
info.setProcessStatus(EProcessStatus.SUCCESS.getValue());
|
||||
alipayCallbackMapper.updateById(info);
|
||||
//更新订单状态
|
||||
StoreOrder order = storeOrderService.getByOrderNo(info.getOutTradeNo());
|
||||
Assert.notNull(order);
|
||||
StoreOrderInfo orderInfo = storeOrderService.paySuccess(order.getId());
|
||||
//创建收款单
|
||||
financeBillService.createCollectionBillAfterOrderPaid(orderInfo, info.getId(), EPayChannel.ALI_PAY);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ import com.ruoyi.common.utils.bean.BeanValidators;
|
|||
import com.ruoyi.xkt.domain.*;
|
||||
import com.ruoyi.xkt.dto.express.ExpressContactDTO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddDTO;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderAddResult;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderInfo;
|
||||
import com.ruoyi.xkt.dto.order.StoreOrderOperationRecordAddDTO;
|
||||
import com.ruoyi.xkt.enums.*;
|
||||
import com.ruoyi.xkt.manager.PaymentManager;
|
||||
import com.ruoyi.xkt.mapper.*;
|
||||
import com.ruoyi.xkt.service.IExpressService;
|
||||
import com.ruoyi.xkt.service.IOperationRecordService;
|
||||
|
|
@ -40,21 +42,24 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
@Autowired
|
||||
private StoreOrderDetailMapper storeOrderDetailMapper;
|
||||
@Autowired
|
||||
private IExpressService expressService;
|
||||
@Autowired
|
||||
private IOperationRecordService operationRecordService;
|
||||
@Autowired
|
||||
private StoreProductMapper storeProductMapper;
|
||||
@Autowired
|
||||
private StoreProductColorSizeMapper storeProductColorSizeMapper;
|
||||
@Autowired
|
||||
private StoreProductColorPriceMapper storeProductColorPriceMapper;
|
||||
@Autowired
|
||||
private IExpressService expressService;
|
||||
@Autowired
|
||||
private IOperationRecordService operationRecordService;
|
||||
@Autowired
|
||||
private IVoucherSequenceService voucherSequenceService;
|
||||
@Autowired
|
||||
private List<PaymentManager> paymentManagers;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public StoreOrderInfo createOrder(StoreOrderAddDTO storeOrderAddDTO) {
|
||||
public StoreOrderAddResult createOrder(StoreOrderAddDTO storeOrderAddDTO, boolean beginPay, EPayChannel payChannel,
|
||||
EPayPage payPage) {
|
||||
Long orderUserId = storeOrderAddDTO.getOrderUserId();
|
||||
Long storeId = storeOrderAddDTO.getStoreId();
|
||||
Long expressId = storeOrderAddDTO.getExpressId();
|
||||
|
|
@ -81,7 +86,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
orderDetail.setStoreProdColorSizeId(spcs.getId());
|
||||
orderDetail.setStoreProdId(spcs.getStoreProdId());
|
||||
orderDetail.setDetailStatus(EOrderStatus.PENDING_PAYMENT.getValue());
|
||||
orderDetail.setPayStatus(EPayStatus.INIT.getValue());
|
||||
orderDetail.setPayStatus(beginPay ? EPayStatus.PAYING.getValue() : EPayStatus.INIT.getValue());
|
||||
orderDetail.setExpressStatus(EExpressStatus.INIT.getValue());
|
||||
//计算明细费用
|
||||
BigDecimal goodsPrice = calcPrice(orderUserId, spcs);
|
||||
|
|
@ -122,7 +127,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
order.setOrderNo(orderNo);
|
||||
order.setOrderType(EOrderType.SALES_ORDER.getValue());
|
||||
order.setOrderStatus(EOrderStatus.PENDING_PAYMENT.getValue());
|
||||
order.setPayStatus(EPayStatus.INIT.getValue());
|
||||
order.setPayStatus(beginPay ? EPayStatus.PAYING.getValue() : EPayStatus.INIT.getValue());
|
||||
order.setOrderRemark(storeOrderAddDTO.getOrderRemark());
|
||||
order.setGoodsQuantity(orderGoodsQuantity);
|
||||
order.setGoodsAmount(orderGoodsAmount);
|
||||
|
|
@ -160,7 +165,14 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
});
|
||||
//操作记录
|
||||
addOperationRecords(orderId, orderDetailIdList, orderUserId, new Date(), EOrderAction.ADD_ORDER);
|
||||
return new StoreOrderInfo(order, orderDetailList);
|
||||
StoreOrderInfo orderInfo = new StoreOrderInfo(order, orderDetailList);
|
||||
String rtnStr = null;
|
||||
if (beginPay) {
|
||||
//发起支付
|
||||
PaymentManager paymentManager = getPaymentManager(payChannel);
|
||||
rtnStr = paymentManager.payOrder(orderInfo, payPage);
|
||||
}
|
||||
return new StoreOrderAddResult(orderInfo, rtnStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -178,33 +190,64 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
Assert.isTrue(EOrderType.SALES_ORDER.getValue().equals(order.getOrderType()),
|
||||
"非销售订单无法发起支付");
|
||||
Assert.isTrue(BeanValidators.exists(order), "订单不存在");
|
||||
checkPreparePayStatus(order.getPayStatus());
|
||||
order.setPayStatus(EPayStatus.PAYING.getValue());
|
||||
int orderSuccess = storeOrderMapper.updateById(order);
|
||||
if (orderSuccess == 0) {
|
||||
throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG);
|
||||
}
|
||||
List<StoreOrderDetail> orderDetails = storeOrderDetailMapper.selectList(
|
||||
Wrappers.lambdaQuery(StoreOrderDetail.class)
|
||||
.eq(StoreOrderDetail::getStoreOrderId, storeOrderId)
|
||||
.eq(SimpleEntity::getDelFlag, Constants.UNDELETED));
|
||||
checkPreparePayStatus(order.getPayStatus());
|
||||
StoreOrder updateOrder = new StoreOrder();
|
||||
updateOrder.setId(storeOrderId);
|
||||
updateOrder.setPayStatus(EPayStatus.PAYING.getValue());
|
||||
updateOrder.setVersion(order.getVersion());
|
||||
int orderSuccess = storeOrderMapper.updateById(updateOrder);
|
||||
if (orderSuccess == 0) {
|
||||
throw new ServiceException("系统繁忙请稍后再试");
|
||||
}
|
||||
for (StoreOrderDetail orderDetail : orderDetails) {
|
||||
checkPreparePayStatus(orderDetail.getPayStatus());
|
||||
StoreOrderDetail orderDetailUpdate = new StoreOrderDetail();
|
||||
orderDetailUpdate.setId(orderDetail.getId());
|
||||
orderDetailUpdate.setPayStatus(EPayStatus.PAYING.getValue());
|
||||
orderDetailUpdate.setVersion(orderDetail.getVersion());
|
||||
int orderDetailSuccess = storeOrderDetailMapper.updateById(orderDetailUpdate);
|
||||
orderDetail.setPayStatus(EPayStatus.PAYING.getValue());
|
||||
int orderDetailSuccess = storeOrderDetailMapper.updateById(orderDetail);
|
||||
if (orderDetailSuccess == 0) {
|
||||
throw new ServiceException("系统繁忙请稍后再试");
|
||||
throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG);
|
||||
}
|
||||
}
|
||||
return new StoreOrderInfo(order, orderDetails);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public StoreOrderInfo paySuccess(Long storeOrderId) {
|
||||
Assert.notNull(storeOrderId);
|
||||
StoreOrder order = storeOrderMapper.selectById(storeOrderId);
|
||||
Assert.isTrue(EOrderType.SALES_ORDER.getValue().equals(order.getOrderType()),
|
||||
"订单类型异常");
|
||||
Assert.isTrue(BeanValidators.exists(order), "订单不存在");
|
||||
Assert.isTrue(order.getPayStatus().equals(EPayStatus.PAYING.getValue()), "订单支付状态异常");
|
||||
order.setPayStatus(EPayStatus.PAID.getValue());
|
||||
//TODO 暂时使用总金额
|
||||
order.setRealTotalAmount(order.getTotalAmount());
|
||||
int orderSuccess = storeOrderMapper.updateById(order);
|
||||
if (orderSuccess == 0) {
|
||||
throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG);
|
||||
}
|
||||
List<StoreOrderDetail> orderDetails = storeOrderDetailMapper.selectList(
|
||||
Wrappers.lambdaQuery(StoreOrderDetail.class)
|
||||
.eq(StoreOrderDetail::getStoreOrderId, storeOrderId)
|
||||
.eq(SimpleEntity::getDelFlag, Constants.UNDELETED));
|
||||
List<Long> orderDetailIdList = new ArrayList<>(orderDetails.size());
|
||||
for (StoreOrderDetail orderDetail : orderDetails) {
|
||||
Assert.isTrue(orderDetail.getPayStatus().equals(EPayStatus.PAYING.getValue()),
|
||||
"订单明细支付状态异常");
|
||||
orderDetail.setPayStatus(EPayStatus.PAID.getValue());
|
||||
orderDetail.setRealTotalAmount(orderDetail.getTotalAmount());
|
||||
int orderDetailSuccess = storeOrderDetailMapper.updateById(orderDetail);
|
||||
if (orderDetailSuccess == 0) {
|
||||
throw new ServiceException(Constants.VERSION_LOCK_ERROR_COMMON_MSG);
|
||||
}
|
||||
orderDetailIdList.add(orderDetail.getId());
|
||||
}
|
||||
//操作记录
|
||||
addOperationRecords(storeOrderId, orderDetailIdList, null, new Date(), EOrderAction.PAID_ORDER);
|
||||
return new StoreOrderInfo(order, orderDetails);
|
||||
}
|
||||
|
||||
private void checkPreparePayStatus(Integer payStatus) {
|
||||
if (!EPayStatus.INIT.getValue().equals(payStatus) && !EPayStatus.PAYING.getValue().equals(payStatus)) {
|
||||
throw new ServiceException("订单状态异常无法发起支付");
|
||||
|
|
@ -328,4 +371,22 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
|
|||
}
|
||||
return spcsMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据支付渠道匹配支付类
|
||||
*
|
||||
* @param payChannel
|
||||
* @return
|
||||
*/
|
||||
private PaymentManager getPaymentManager(EPayChannel payChannel) {
|
||||
if (payChannel == null) {
|
||||
throw new ServiceException("请先选择支付渠道");
|
||||
}
|
||||
for (PaymentManager paymentManager : paymentManagers) {
|
||||
if (paymentManager.channel() == payChannel) {
|
||||
return paymentManager;
|
||||
}
|
||||
}
|
||||
throw new ServiceException("未知支付渠道");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue