mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-16 20:15:06 +08:00
完成支付回调的逻辑
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.infra.convert.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@ -10,6 +10,6 @@ public interface InfApiAccessLogCoreConvert {
|
||||
|
||||
InfApiAccessLogCoreConvert INSTANCE = Mappers.getMapper(InfApiAccessLogCoreConvert.class);
|
||||
|
||||
InfApiAccessLogDO convert(ApiAccessLogCreateDTO bean);
|
||||
InfApiAccessLogDO convert(ApiAccessLogCreateReqDTO bean);
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.infra.convert.logger;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
@ -10,6 +10,6 @@ public interface InfApiErrorLogCoreConvert {
|
||||
|
||||
InfApiErrorLogCoreConvert INSTANCE = Mappers.getMapper(InfApiErrorLogCoreConvert.class);
|
||||
|
||||
InfApiErrorLogDO convert(ApiErrorLogCreateDTO bean);
|
||||
InfApiErrorLogDO convert(ApiErrorLogCreateReqDTO bean);
|
||||
|
||||
}
|
||||
|
@ -1,18 +1,16 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.convert.logger.InfApiAccessLogCoreConvert;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiAccessLogCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.service.logger.InfApiAccessLogCoreService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* API 访问日志 Service 实现类
|
||||
@ -29,7 +27,7 @@ public class InfApiAccessLogCoreServiceImpl implements InfApiAccessLogCoreServic
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) {
|
||||
public void createApiAccessLogAsync(ApiAccessLogCreateReqDTO createDTO) {
|
||||
InfApiAccessLogDO apiAccessLog = InfApiAccessLogCoreConvert.INSTANCE.convert(createDTO);
|
||||
apiAccessLogMapper.insert(apiAccessLog);
|
||||
}
|
||||
|
@ -5,15 +5,13 @@ import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiEr
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiErrorLogCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.service.logger.InfApiErrorLogCoreService;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.AsyncResult;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* API 错误日志 Service 实现类
|
||||
@ -30,7 +28,7 @@ public class InfApiErrorLogCoreServiceImpl implements InfApiErrorLogCoreService
|
||||
|
||||
@Override
|
||||
@Async
|
||||
public void createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) {
|
||||
public void createApiErrorLogAsync(ApiErrorLogCreateReqDTO createDTO) {
|
||||
InfApiErrorLogDO apiErrorLog = InfApiErrorLogCoreConvert.INSTANCE.convert(createDTO);
|
||||
apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus());
|
||||
apiErrorLogMapper.insert(apiErrorLog);
|
||||
|
@ -0,0 +1,51 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 商户支付、退款等的通知 Log
|
||||
* 每次通知时,都会在该表中,记录一次 Log,方便排查问题
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("pay_notify_log")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class PayNotifyLogDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 日志编号,自增
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 通知编号
|
||||
*
|
||||
* 关联 {@link PayNotifyTaskDO#getId()}
|
||||
*/
|
||||
private Long notifyId;
|
||||
/**
|
||||
* 当前通知次数
|
||||
*/
|
||||
private Integer notifyTimes;
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private String request;
|
||||
/**
|
||||
* 响应结果
|
||||
*/
|
||||
private String response;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 外键 {@link PayNotifyStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 商户支付、退款等的通知
|
||||
* 在支付系统收到支付渠道的支付、退款的结果后,需要不断的通知到业务系统,直到成功。
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@TableName("pay_notify_task")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
public class PayNotifyTaskDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 通知频率,单位为秒。
|
||||
*
|
||||
* 算上首次的通知,实际是一共 1 + 8 = 9 次。
|
||||
*/
|
||||
public static final Integer[] NOTIFY_FREQUENCY = new Integer[]{
|
||||
15, 15, 30, 180,
|
||||
1800, 1800, 1800, 3600
|
||||
};
|
||||
|
||||
/**
|
||||
* 编号,自增
|
||||
*/
|
||||
private Long id;
|
||||
/**
|
||||
* 商户编号
|
||||
*
|
||||
* 关联 {@link PayMerchantDO#getId()}
|
||||
*/
|
||||
private Long merchantId;
|
||||
/**
|
||||
* 应用编号
|
||||
*
|
||||
* 关联 {@link PayAppDO#getId()}
|
||||
*/
|
||||
private Long appId;
|
||||
/**
|
||||
* 通知类型
|
||||
*
|
||||
* 外键 {@link PayNotifyTypeEnum}
|
||||
*/
|
||||
private Integer type;
|
||||
/**
|
||||
* 数据编号,根据不同 type 进行关联:
|
||||
*
|
||||
* 1. {@link PayNotifyTypeEnum#ORDER} 时,关联 {@link PayOrderDO#getId()}
|
||||
* 2. {@link PayNotifyTypeEnum#REFUND} 时,关联 {@link PayRefundDO#getId()}
|
||||
*/
|
||||
private Long dataId;
|
||||
/**
|
||||
* 商户订单编号
|
||||
*/
|
||||
private String merchantOrderId;
|
||||
/**
|
||||
* 通知状态
|
||||
*
|
||||
* 外键 {@link PayNotifyStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 下一次通知时间
|
||||
*/
|
||||
private Date nextNotifyTime;
|
||||
/**
|
||||
* 最后一次执行时间
|
||||
*/
|
||||
private Date lastExecuteTime;
|
||||
/**
|
||||
* 当前通知次数
|
||||
*/
|
||||
private Integer notifyTimes;
|
||||
/**
|
||||
* 最大可通知次数
|
||||
*/
|
||||
private Integer maxNotifyTimes;
|
||||
/**
|
||||
* 通知地址
|
||||
*/
|
||||
private String notifyUrl;
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 商户支付、退款等的通知
|
||||
* 在支付系统收到支付渠道的支付、退款的结果后,需要不断的通知到业务系统,直到成功。
|
||||
* TODO 芋艿:待完善
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
public class PayNotifyDO extends BaseDO {
|
||||
}
|
@ -1 +0,0 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject;
|
@ -0,0 +1,10 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PayNotifyTaskCoreMapper extends BaseMapperX<PayNotifyTaskDO> {
|
||||
}
|
@ -8,8 +8,8 @@ import org.apache.ibatis.annotations.Mapper;
|
||||
@Mapper
|
||||
public interface PayOrderExtensionCoreMapper extends BaseMapperX<PayOrderExtensionDO> {
|
||||
|
||||
default PayOrderExtensionDO selectByOrderExtensionNo(String orderExtensionNo) {
|
||||
return selectOne("order_extension_no", orderExtensionNo);
|
||||
default PayOrderExtensionDO selectByNo(String no) {
|
||||
return selectOne("no", no);
|
||||
}
|
||||
|
||||
default int updateByIdAndStatus(Long id, Integer status, PayOrderExtensionDO update) {
|
||||
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.enums.notify;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 支付通知状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PayNotifyStatusEnum {
|
||||
|
||||
WAITING(1, "等待通知"),
|
||||
SUCCESS(2, "通知成功"),
|
||||
FAILURE(3, "通知失败"), // 多次尝试,彻底失败
|
||||
REQUEST_SUCCESS(4, "请求成功,但是结果失败"),
|
||||
REQUEST_FAILURE(5, "请求失败"),
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final Integer status;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.enums.notify;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 支付通知类型
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PayNotifyTypeEnum {
|
||||
|
||||
ORDER(1, "支付单"),
|
||||
REFUND(2, "退款单"),
|
||||
;
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
}
|
@ -15,6 +15,16 @@ public interface PayChannelCoreService {
|
||||
*/
|
||||
void initPayClients();
|
||||
|
||||
/**
|
||||
* 支付渠道的合法性
|
||||
*
|
||||
* 如果不合法,抛出 {@link ServiceException} 业务异常
|
||||
*
|
||||
* @param id 渠道编号
|
||||
* @return 渠道信息
|
||||
*/
|
||||
PayChannelDO validPayChannel(Long id);
|
||||
|
||||
/**
|
||||
* 支付渠道的合法性
|
||||
*
|
||||
|
@ -95,16 +95,27 @@ public class PayChannelCoreServiceImpl implements PayChannelCoreService {
|
||||
return payChannelCoreMapper.selectList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayChannelDO validPayChannel(Long id) {
|
||||
PayChannelDO channel = payChannelCoreMapper.selectById(id);
|
||||
this.validPayChannel(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayChannelDO validPayChannel(Long appId, String code) {
|
||||
PayChannelDO channel = payChannelCoreMapper.selectByAppIdAndCode(appId, code);
|
||||
this.validPayChannel(channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
private void validPayChannel(PayChannelDO channel) {
|
||||
if (channel == null) {
|
||||
throw exception(PAY_CHANNEL_NOT_FOUND);
|
||||
}
|
||||
if (CommonStatusEnum.DISABLE.getStatus().equals(channel.getStatus())) {
|
||||
throw exception(PayErrorCodeCoreConstants.PAY_CHANNEL_IS_DISABLE);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.notify;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 支付通知 Core Service 接口
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface PayNotifyCoreService {
|
||||
|
||||
/**
|
||||
* 创建支付通知任务
|
||||
*
|
||||
* @param reqDTO 任务信息
|
||||
*/
|
||||
void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 执行支付通知
|
||||
*
|
||||
* 注意,该方法提供给定时任务调用。目前是 yudao-admin-server 进行调用
|
||||
*/
|
||||
void executeNotify();
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 支付通知创建 DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayNotifyTaskCreateReqDTO {
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
@NotNull(message = "类型不能为空")
|
||||
private Integer type;
|
||||
/**
|
||||
* 数据编号
|
||||
*/
|
||||
@NotNull(message = "数据编号不能为空")
|
||||
private Long dataId;
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.notify.impl;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.notify.PayNotifyTaskDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.notify.PayNotifyTaskCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付通知 Core Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Valid
|
||||
@Slf4j
|
||||
public class PayNotifyCoreServiceImpl implements PayNotifyCoreService {
|
||||
|
||||
@Resource
|
||||
@Lazy // 循环依赖,避免报错
|
||||
private PayOrderCoreService payOrderCoreService;
|
||||
|
||||
@Resource
|
||||
private PayNotifyTaskCoreMapper payNotifyTaskCoreMapper;
|
||||
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿:未来提供独立的线程池
|
||||
|
||||
@Override
|
||||
public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) {
|
||||
PayNotifyTaskDO task = new PayNotifyTaskDO();
|
||||
task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId());
|
||||
task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(new Date())
|
||||
.setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1);
|
||||
// 补充 merchantId + appId + notifyUrl 字段
|
||||
if (Objects.equals(task.getType(), PayNotifyTypeEnum.ORDER.getType())) {
|
||||
PayOrderDO order = payOrderCoreService.getPayOrder(task.getDataId()); // 不进行非空判断,有问题直接异常
|
||||
task.setMerchantId(order.getMerchantId()).setAppId(order.getAppId()).
|
||||
setMerchantOrderId(order.getMerchantOrderId()).setNotifyUrl(order.getNotifyUrl());
|
||||
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) {
|
||||
// TODO 芋艿,需要实现下哈
|
||||
throw new UnsupportedOperationException("需要实现");
|
||||
}
|
||||
|
||||
// 执行插入
|
||||
payNotifyTaskCoreMapper.insert(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeNotify() {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -10,10 +10,13 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderExtensionCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderNotifyStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
@ -27,6 +30,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
|
||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -53,6 +57,8 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
private PayAppCoreService payAppCoreService;
|
||||
@Resource
|
||||
private PayChannelCoreService payChannelCoreService;
|
||||
@Resource
|
||||
private PayNotifyCoreService payNotifyCoreService;
|
||||
|
||||
@Resource
|
||||
private PayClientFactory payClientFactory;
|
||||
@ -129,7 +135,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
// 调用三方接口
|
||||
PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO);
|
||||
// 商户相关字段
|
||||
unifiedOrderReqDTO.setMerchantOrderId(order.getMerchantOrderId())
|
||||
unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
|
||||
.setSubject(order.getSubject()).setBody(order.getBody())
|
||||
.setNotifyUrl(genChannelPayNotifyUrl(channel));
|
||||
// 订单相关字段
|
||||
@ -174,12 +180,13 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception {
|
||||
// TODO 芋艿,记录回调日志
|
||||
log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData);
|
||||
|
||||
// 校验支付渠道是否有效
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(channelId, channelCode);
|
||||
PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
|
||||
// 校验支付客户端是否正确初始化
|
||||
PayClient client = payClientFactory.getPayClient(channel.getId());
|
||||
if (client == null) {
|
||||
@ -191,7 +198,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
|
||||
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
|
||||
// 1.1 查询 PayOrderExtensionDO
|
||||
PayOrderExtensionDO orderExtension = payOrderExtensionCoreMapper.selectByOrderExtensionNo(
|
||||
PayOrderExtensionDO orderExtension = payOrderExtensionCoreMapper.selectByNo(
|
||||
notifyRespDTO.getOrderExtensionNo());
|
||||
if (orderExtension == null) {
|
||||
throw exception(PAY_ORDER_EXTENSION_NOT_FOUND);
|
||||
@ -200,7 +207,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
// 1.2 更新 PayOrderExtensionDO
|
||||
int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getOrderId(),
|
||||
int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(),
|
||||
PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId())
|
||||
.status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData).build());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
@ -219,15 +226,17 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
// 2.2 更新 PayOrderDO
|
||||
updateCounts = payOrderCoreMapper.updateByIdAndStatus(order.getId(), PayOrderStatusEnum.WAITING.getStatus(),
|
||||
PayOrderDO.builder().status(PayOrderStatusEnum.SUCCESS.getStatus()).channelId(channelId).channelCode(channelCode)
|
||||
.successTime(notifyRespDTO.getSuccessTime()).notifyTime(new Date())
|
||||
.successExtensionId(orderExtension.getId()).build());
|
||||
.successTime(notifyRespDTO.getSuccessTime()).successExtensionId(orderExtension.getId())
|
||||
.channelOrderNo(notifyRespDTO.getChannelOrderNo()).channelUserId(notifyRespDTO.getChannelUserId())
|
||||
.notifyTime(new Date()).build());
|
||||
if (updateCounts == 0) { // 校验状态,必须是待支付
|
||||
throw exception(PAY_ORDER_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
log.info("[notifyPayOrder][支付订单({}) 更新为已支付]", order.getId());
|
||||
|
||||
// 3. 插入支付通知记录
|
||||
// payNotifyService.addPayTransactionNotifyTask(order, orderExtension);
|
||||
payNotifyCoreService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
||||
.type(PayNotifyTypeEnum.ORDER.getType()).dataId(order.getId()).build());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,14 +5,13 @@ import cn.iocoder.yudao.coreservice.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiAccessLogCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl.InfApiAccessLogCoreServiceImpl;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
@ -32,7 +31,7 @@ public class InfApiAccessLogCoreServiceTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testCreateApiAccessLogAsync() {
|
||||
// 准备参数
|
||||
ApiAccessLogCreateDTO createDTO = RandomUtils.randomPojo(ApiAccessLogCreateDTO.class,
|
||||
ApiAccessLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiAccessLogCreateReqDTO.class,
|
||||
dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()));
|
||||
|
||||
// 调用
|
||||
|
@ -5,7 +5,7 @@ import cn.iocoder.yudao.coreservice.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.dal.mysql.logger.InfApiErrorLogCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.infra.service.logger.impl.InfApiErrorLogCoreServiceImpl;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO;
|
||||
import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@ -31,7 +31,7 @@ public class InfApiErrorLogCoreServiceTest extends BaseDbUnitTest {
|
||||
@Test
|
||||
public void testCreateApiErrorLogAsync() {
|
||||
// 准备参数
|
||||
ApiErrorLogCreateDTO createDTO = RandomUtils.randomPojo(ApiErrorLogCreateDTO.class,
|
||||
ApiErrorLogCreateReqDTO createDTO = RandomUtils.randomPojo(ApiErrorLogCreateReqDTO.class,
|
||||
dto -> dto.setUserType(RandomUtil.randomEle(UserTypeEnum.values()).getValue()));
|
||||
|
||||
// 调用
|
||||
|
Reference in New Issue
Block a user