diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java index dfa64eeb0..2fd69d1f8 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AlipayController.java @@ -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); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java index 4a95e1fd5..9c87e2eab 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreOrderController.java @@ -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 create(@RequestBody StoreOrderAddReqVO vo) { + public R 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 pay(@RequestBody StoreOrderPayReqVO vo) { + public R 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); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAddReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAddReqVO.java index 48c40e3db..0aeb43165 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAddReqVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderAddReqVO.java @@ -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 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; } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPayReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPayReqVO.java index ce54b1c32..a1266b042 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPayReqVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/order/StoreOrderPayReqVO.java @@ -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; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java index 3898cfadf..b54873f95 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java @@ -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; + } + /** * 获取用户 **/ diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAddResult.java b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAddResult.java new file mode 100644 index 000000000..8505fce66 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/order/StoreOrderAddResult.java @@ -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; +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java b/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java index 330bda03a..375798e3e 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/EOrderAction.java @@ -12,6 +12,7 @@ import lombok.Getter; public enum EOrderAction { ADD_ORDER(1, "下单"), + PAID_ORDER(2, "支付"), ; private final Integer value; diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/EPayFrom.java b/xkt/src/main/java/com/ruoyi/xkt/enums/EPayPage.java similarity index 78% rename from xkt/src/main/java/com/ruoyi/xkt/enums/EPayFrom.java rename to xkt/src/main/java/com/ruoyi/xkt/enums/EPayPage.java index ac63e686f..37d7b495b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/EPayFrom.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/EPayPage.java @@ -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; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/PaymentManager.java b/xkt/src/main/java/com/ruoyi/xkt/manager/PaymentManager.java index 05d15e636..007fbf08a 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/PaymentManager.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/PaymentManager.java @@ -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); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/AliPaymentMangerImpl.java b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/AliPaymentMangerImpl.java index 2b856af7e..be90db924 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/manager/impl/AliPaymentMangerImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/impl/AliPaymentMangerImpl.java @@ -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 - } - } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IAlipayCallbackService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IAlipayCallbackService.java index c28aaaaf1..1cf25cd44 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IAlipayCallbackService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IAlipayCallbackService.java @@ -24,4 +24,10 @@ public interface IAlipayCallbackService { */ int insertAlipayCallback(AlipayCallback alipayCallback); + /** + * 处理订单支付结果 + * + * @param info + */ + void processOrderPay(AlipayCallback info); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java index eda5fe1c9..bac6d9af2 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreOrderService.java @@ -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); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AlipayCallbackServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AlipayCallbackServiceImpl.java index 50c7d0f1a..5ca98fb38 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AlipayCallbackServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AlipayCallbackServiceImpl.java @@ -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); + } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java index 63ef3c0bd..d839d711b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java @@ -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 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 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 orderDetails = storeOrderDetailMapper.selectList( + Wrappers.lambdaQuery(StoreOrderDetail.class) + .eq(StoreOrderDetail::getStoreOrderId, storeOrderId) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)); + List 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("未知支付渠道"); + } }