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

This commit is contained in:
YunaiV 2023-02-15 09:58:20 +08:00
parent 4d2ebcd898
commit 333adc989f
5 changed files with 115 additions and 1 deletions

View File

@ -57,4 +57,11 @@ public interface ErrorCodeConstants {
ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除"); ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除");
// ========== 示例订单 1-007-900-000 ==========
ErrorCode PAY_DEMO_ORDER_NOT_FOUND = new ErrorCode(100790000, "示例订单不存在");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID = new ErrorCode(1011000013, "示例订单更新支付状态失败,订单不是【未支付】状态");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR = new ErrorCode(1011000014, "示例订单更新支付状态失败,支付单编号不匹配");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS = new ErrorCode(1011000015, "示例订单更新支付状态失败,支付单状态不是【支付成功】状态");
ErrorCode PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1011000016, "示例订单更新支付状态失败,支付单金额不匹配");
} }

View File

@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.pay.controller.admin.demo;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderRespVO;
import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert; import cn.iocoder.yudao.module.pay.convert.demo.PayDemoOrderConvert;
@ -14,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid; import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -41,4 +44,14 @@ public class PayDemoOrderController {
return success(PayDemoOrderConvert.INSTANCE.convertPage(pageResult)); return success(PayDemoOrderConvert.INSTANCE.convertPage(pageResult));
} }
@PostMapping("/update-paid")
@Operation(description = "更新示例订单为已支付") // pay-module 支付服务进行回调可见 PayNotifyJob
@PermitAll // 无需登录安全由 PayDemoOrderService 内部校验实现
@OperateLog(enable = false) // 禁用操作日志因为没有操作人
public CommonResult<Boolean> updateDemoOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
payDemoOrderService.updateDemoOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
notifyReqDTO.getPayOrderId());
return success(true);
}
} }

View File

@ -20,4 +20,9 @@ public interface PayDemoOrderMapper extends BaseMapperX<PayDemoOrderDO> {
.orderByDesc(PayDemoOrderDO::getId)); .orderByDesc(PayDemoOrderDO::getId));
} }
default int updateByIdAndPayed(Long id, boolean wherePayed, PayDemoOrderDO updateObj) {
return update(updateObj, new LambdaQueryWrapperX<PayDemoOrderDO>()
.eq(PayDemoOrderDO::getId, id).eq(PayDemoOrderDO::getPayed, wherePayed));
}
} }

View File

@ -39,4 +39,12 @@ public interface PayDemoOrderService {
*/ */
PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO); PageResult<PayDemoOrderDO> getDemoOrderPage(PageParam pageReqVO);
/**
* 更新示例订单为已支付
*
* @param id 编号
* @param payOrderId 支付订单号
*/
void updateDemoOrderPaid(Long id, Long payOrderId);
} }

View File

@ -1,23 +1,33 @@
package cn.iocoder.yudao.module.pay.service.demo; package cn.iocoder.yudao.module.pay.service.demo;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO; import cn.iocoder.yudao.module.pay.controller.admin.demo.vo.PayDemoOrderCreateReqVO;
import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.demo.PayDemoOrderDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper; import cn.iocoder.yudao.module.pay.dal.mysql.demo.PayDemoOrderMapper;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.Duration; import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
/** /**
* 示例订单 Service 实现类 * 示例订单 Service 实现类
@ -26,6 +36,7 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli
*/ */
@Service @Service
@Validated @Validated
@Slf4j
public class PayDemoOrderServiceImpl implements PayDemoOrderService { public class PayDemoOrderServiceImpl implements PayDemoOrderService {
/** /**
@ -67,7 +78,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
// 1.2 插入 demo 订单 // 1.2 插入 demo 订单
PayDemoOrderDO demoOrder = new PayDemoOrderDO().setUserId(userId) PayDemoOrderDO demoOrder = new PayDemoOrderDO().setUserId(userId)
.setSpuId(createReqVO.getSpuId()).setSpuName(spuName) .setSpuId(createReqVO.getSpuId()).setSpuName(spuName)
.setPayed(false).setRefundPrice(0); .setPrice(price).setPayed(false).setRefundPrice(0);
payDemoOrderMapper.insert(demoOrder); payDemoOrderMapper.insert(demoOrder);
// 2.1 创建支付单 // 2.1 创建支付单
@ -99,4 +110,74 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
return payDemoOrderMapper.selectPage(pageReqVO); return payDemoOrderMapper.selectPage(pageReqVO);
} }
@Override
public void updateDemoOrderPaid(Long id, Long payOrderId) {
// 校验并获得支付订单可支付
PayOrderRespDTO payOrder = validateDemoOrderCanPaid(id, payOrderId);
// 更新 PayDemoOrderDO 状态为已支付
int updateCount = payDemoOrderMapper.updateByIdAndPayed(id, false,
new PayDemoOrderDO().setPayed(true).setPayTime(LocalDateTime.now())
.setPayChannelCode(payOrder.getChannelCode()));
if (updateCount == 0) {
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
}
}
/**
* 校验交易订单满足被支付的条件
*
* 1. 交易订单未支付
* 2. 支付单已支付
*
* @param id 交易订单编号
* @param payOrderId 支付订单编号
* @return 交易订单
*/
private PayOrderRespDTO validateDemoOrderCanPaid(Long id, Long payOrderId) {
// 校验订单是否存在
PayDemoOrderDO order = payDemoOrderMapper.selectById(id);
if (order == null) {
throw exception(PAY_DEMO_ORDER_NOT_FOUND);
}
// 校验订单未支付
if (order.getPayed()) {
log.error("[validateDemoOrderCanPaid][order({}) 不处于待支付状态请进行处理order 数据是:{}]",
id, JsonUtils.toJsonString(order));
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
}
// 校验支付订单匹配
if (ObjectUtil.notEqual(order.getPayOrderId(), payOrderId)) { // 支付单号
log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({})请进行处理order 数据是:{}]",
id, payOrderId, JsonUtils.toJsonString(order));
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
}
// 校验支付单是否存在
PayOrderRespDTO payOrder = payOrderApi.getOrder(payOrderId);
if (payOrder == null) {
log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 不存在,请进行处理!]", id, payOrderId);
throw exception(PAY_ORDER_NOT_FOUND);
}
// 校验支付单已支付
if (!PayOrderStatusEnum.isSuccess(payOrder.getStatus())) {
log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 未支付请进行处理payOrder 数据是:{}]",
id, payOrderId, JsonUtils.toJsonString(payOrder));
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_STATUS_NOT_SUCCESS);
}
// 校验支付金额一致
if (ObjectUtil.notEqual(payOrder.getAmount(), order.getPrice())) {
log.error("[validateDemoOrderCanPaid][order({}) payOrder({}) 支付金额不匹配请进行处理order 数据是:{}payOrder 数据是:{}]",
id, payOrderId, JsonUtils.toJsonString(order), JsonUtils.toJsonString(payOrder));
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_PRICE_NOT_MATCH);
}
// 校验支付订单匹配二次
if (ObjectUtil.notEqual(payOrder.getMerchantOrderId(), id.toString())) {
log.error("[validateDemoOrderCanPaid][order({}) 支付单不匹配({})请进行处理payOrder 数据是:{}]",
id, payOrderId, JsonUtils.toJsonString(payOrder));
throw exception(PAY_DEMO_ORDER_UPDATE_PAID_FAIL_PAY_ORDER_ID_ERROR);
}
return payOrder;
}
} }