Commit 333adc989fc185da3170684b8f3b803853d30527

Authored by YunaiV
1 parent 4d2ebcd8

pay:示例订单,接入支付回调逻辑

yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
@@ -57,4 +57,11 @@ public interface ErrorCodeConstants { @@ -57,4 +57,11 @@ public interface ErrorCodeConstants {
57 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); 57 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
58 ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除"); 58 ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除");
59 59
  60 +
  61 + // ========== 示例订单 1-007-900-000 ==========
  62 + ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在");
  63 + ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "示例订单更新支付状态失败,订单不是【未支付】状态");
  64 + ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "示例订单更新支付状态失败,支付单编号不匹配");
  65 + ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
  66 + ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "示例订单更新支付状态失败,支付单金额不匹配");
60 } 67 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo; @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.framework.common.pojo.PageParam; 4 import cn.iocoder.yudao.framework.common.pojo.PageParam;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  7 +import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
6 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 8 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
7 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; 9 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO;
8 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; 10 import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
@@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated; @@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
14 import org.springframework.web.bind.annotation.*; 16 import org.springframework.web.bind.annotation.*;
15 17
16 import javax.annotation.Resource; 18 import javax.annotation.Resource;
  19 +import javax.annotation.security.PermitAll;
17 import javax.validation.Valid; 20 import javax.validation.Valid;
18 21
19 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -41,4 +44,14 @@ public class PayDemoOrderController { @@ -41,4 +44,14 @@ public class PayDemoOrderController {
41 return success(PayDemoOrderConvert.INSTANCE.convertPage(pageResult)); 44 return success(PayDemoOrderConvert.INSTANCE.convertPage(pageResult));
42 } 45 }
43 46
  47 + @PostMapping("/update-paid")
  48 + @Operation(description = "更新示例订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
  49 + @PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
  50 + @OperateLog(enable = false) // 禁用操作日志,因为没有操作人
  51 + public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
  52 + payDemoOrderService.updateDemoOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
  53 + notifyReqDTO.getPayOrderId());
  54 + return success(true);
  55 + }
  56 +
44 } 57 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/demo/PayDemoOrderMapper.java
@@ -20,4 +20,9 @@ public interface PayDemoOrderMapper extends BaseMapperX&lt;PayDemoOrderDO&gt; { @@ -20,4 +20,9 @@ public interface PayDemoOrderMapper extends BaseMapperX&lt;PayDemoOrderDO&gt; {
20 .orderByDesc(PayDemoOrderDO::getId)); 20 .orderByDesc(PayDemoOrderDO::getId));
21 } 21 }
22 22
  23 + default int updateByIdAndPayed(Long id, boolean wherePayed, PayDemoOrderDO updateObj) {
  24 + return update(updateObj, new LambdaQueryWrapperX<PayDemoOrderDO>()
  25 + .eq(PayDemoOrderDO::getId, id).eq(PayDemoOrderDO::getPayed, wherePayed));
  26 + }
  27 +
23 } 28 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderService.java
@@ -39,4 +39,12 @@ public interface PayDemoOrderService { @@ -39,4 +39,12 @@ public interface PayDemoOrderService {
39 */ 39 */
40 PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO); 40 PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO);
41 41
  42 + /**
  43 + * 更新示例订单为已支付
  44 + *
  45 + * @param id 编号
  46 + * @param payOrderId 支付订单号
  47 + */
  48 + void updateDemoOrderPaid(Long id, Long payOrderId);
  49 +
42 } 50 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
1 package cn.iocoder.yudao.module.pay.service.demo; 1 package cn.iocoder.yudao.module.pay.service.demo;
2 2
3 import cn.hutool.core.lang.Assert; 3 import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.ObjectUtil;
  5 +import cn.iocoder.yudao.framework.common.core.KeyValue;
4 import cn.iocoder.yudao.framework.common.pojo.PageParam; 6 import cn.iocoder.yudao.framework.common.pojo.PageParam;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  8 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; 9 import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
7 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; 10 import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
  11 +import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
8 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; 12 import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
9 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; 13 import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
  14 +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
10 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; 15 import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
  16 +import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
  17 +import lombok.extern.slf4j.Slf4j;
11 import org.springframework.stereotype.Service; 18 import org.springframework.stereotype.Service;
12 import org.springframework.validation.annotation.Validated; 19 import org.springframework.validation.annotation.Validated;
13 20
14 import javax.annotation.Resource; 21 import javax.annotation.Resource;
15 import java.time.Duration; 22 import java.time.Duration;
  23 +import java.time.LocalDateTime;
16 import java.util.HashMap; 24 import java.util.HashMap;
17 import java.util.Map; 25 import java.util.Map;
18 26
  27 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; 28 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
20 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 29 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
  30 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
21 31
22 /** 32 /**
23 * 示例订单 Service 实现类 33 * 示例订单 Service 实现类
@@ -26,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli @@ -26,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli
26 */ 36 */
27 @Service 37 @Service
28 @Validated 38 @Validated
  39 +@Slf4j
29 public class PayDemoOrderServiceImpl implements PayDemoOrderService { 40 public class PayDemoOrderServiceImpl implements PayDemoOrderService {
30 41
31 /** 42 /**
@@ -67,7 +78,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -67,7 +78,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
67 // 1.2 插入 demo 订单 78 // 1.2 插入 demo 订单
68 PayDemoOrderDO demoOrder = new PayDemoOrderDO().setUserId(userId) 79 PayDemoOrderDO demoOrder = new PayDemoOrderDO().setUserId(userId)
69 .setSpuId(createReqVO.getSpuId()).setSpuName(spuName) 80 .setSpuId(createReqVO.getSpuId()).setSpuName(spuName)
70 - .setPayed(false).setRefundPrice(0); 81 + .setPrice(price).setPayed(false).setRefundPrice(0);
71 payDemoOrderMapper.insert(demoOrder); 82 payDemoOrderMapper.insert(demoOrder);
72 83
73 // 2.1 创建支付单 84 // 2.1 创建支付单
@@ -99,4 +110,74 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -99,4 +110,74 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
99 return payDemoOrderMapper.selectPage(pageReqVO); 110 return payDemoOrderMapper.selectPage(pageReqVO);
100 } 111 }
101 112
  113 + @Override
  114 + public void updateDemoOrderPaid(Long id, Long payOrderId) {
  115 + // 校验并获得支付订单(可支付)
  116 + PayOrderRespDTO payOrder = validateDemoOrderCanPaid(id, payOrderId);
  117 +
  118 + // 更新 PayDemoOrderDO 状态为已支付
  119 + int updateCount = payDemoOrderMapper.updateByIdAndPayed(id, false,
  120 + new PayDemoOrderDO().setPayed(true).setPayTime(LocalDateTime.now())
  121 + .setPayChannelCode(payOrder.getChannelCode()));
  122 + if (updateCount == 0) {
  123 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
  124 + }
  125 + }
  126 +
  127 + /**
  128 + * 校验交易订单满足被支付的条件
  129 + *
  130 + * 1. 交易订单未支付
  131 + * 2. 支付单已支付
  132 + *
  133 + * @param id 交易订单编号
  134 + * @param payOrderId 支付订单编号
  135 + * @return 交易订单
  136 + */
  137 + private PayOrderRespDTO validateDemoOrderCanPaid(Long id, Long payOrderId) {
  138 + // 校验订单是否存在
  139 + PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
  140 + if (order == null) {
  141 + throw exception(PAY_DEMO_ORDER_NOT_FOUND);
  142 + }
  143 + // 校验订单未支付
  144 + if (order.getPayed()) {
  145 + log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态,请进行处理!order 数据是:{}]",
  146 + id, JsonUtils.toJsonString(order));
  147 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
  148 + }
  149 + // 校验支付订单匹配
  150 + if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
  151 + log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!order 数据是:{}]",
  152 + id, payOrderId, JsonUtils.toJsonString(order));
  153 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
  154 + }
  155 +
  156 + // 校验支付单是否存在
  157 + PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
  158 + if (payOrder == null) {
  159 + log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
  160 + throw exception(PAY_ORDER_NOT_FOUND);
  161 + }
  162 + // 校验支付单已支付
  163 + if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
  164 + log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付,请进行处理!payOrder 数据是:{}]",
  165 + id, payOrderId, JsonUtils.toJsonString(payOrder));
  166 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
  167 + }
  168 + // 校验支付金额一致
  169 + if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPrice())) {
  170 + log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配,请进行处理!order 数据是:{},payOrder 数据是:{}]",
  171 + id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
  172 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
  173 + }
  174 + // 校验支付订单匹配(二次)
  175 + if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
  176 + log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({}),请进行处理!payOrder 数据是:{}]",
  177 + id, payOrderId, JsonUtils.toJsonString(payOrder));
  178 + throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
  179 + }
  180 + return payOrder;
  181 + }
  182 +
102 } 183 }