Commit 333adc989fc185da3170684b8f3b803853d30527
1 parent
4d2ebcd8
pay:示例订单,接入支付回调逻辑
Showing
5 changed files
with
115 additions
and
1 deletions
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<PayDemoOrderDO> { | @@ -20,4 +20,9 @@ public interface PayDemoOrderMapper extends BaseMapperX<PayDemoOrderDO> { | ||
| 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 | } |