mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-23 23:45:08 +08:00
pay: PayNotifyJob 增加多租户的支持
This commit is contained in:
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.pay.api.notify.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 支付单的通知 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayOrderNotifyReqDTO {
|
||||
|
||||
/**
|
||||
* 商户订单编号
|
||||
*/
|
||||
@NotEmpty(message = "商户订单号不能为空")
|
||||
private String merchantOrderId;
|
||||
|
||||
/**
|
||||
* 支付订单编号
|
||||
*/
|
||||
@NotNull(message = "支付订单编号不能为空")
|
||||
private Long payOrderId;
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package cn.iocoder.yudao.module.pay.api.notify.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 退款单的通知 Request DTO
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayRefundNotifyReqDTO {
|
||||
|
||||
/**
|
||||
* 商户退款单编号
|
||||
*/
|
||||
@NotEmpty(message = "商户退款单编号不能为空")
|
||||
private String merchantOrderId;
|
||||
|
||||
/**
|
||||
* 支付退款编号
|
||||
*/
|
||||
@NotNull(message = "支付退款编号不能为空")
|
||||
private Long payRefundId;
|
||||
|
||||
/**
|
||||
* 退款状态
|
||||
*
|
||||
* (成功,失败) TODO 芋艿:枚举
|
||||
*/
|
||||
@NotNull(message = "退款状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* 占位符,无特殊作用
|
||||
*/
|
||||
package cn.iocoder.yudao.module.pay.api.notify;
|
@ -15,8 +15,8 @@ import javax.annotation.Resource;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Component
|
||||
@TenantJob // 多租户
|
||||
@Slf4j
|
||||
@TenantJob
|
||||
public class PayNotifyJob implements JobHandler {
|
||||
|
||||
@Resource
|
||||
|
@ -2,8 +2,8 @@
|
||||
* pay 模块,我们放支付业务,提供业务的支付能力。
|
||||
* 例如说:商户、应用、支付、退款等等
|
||||
*
|
||||
* 1. Controller URL:以 /member/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 member_ 开头,方便在数据库中区分
|
||||
* 1. Controller URL:以 /pay/ 开头,避免和其它 Module 冲突
|
||||
* 2. DataObject 表名:以 pay_ 开头,方便在数据库中区分
|
||||
*
|
||||
* 注意,由于 Pay 模块和 Trade 模块,容易重名,所以类名都加载 Pay 的前缀~
|
||||
*/
|
||||
|
@ -2,7 +2,13 @@ package cn.iocoder.yudao.module.pay.service.notify;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
|
||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
|
||||
@ -13,11 +19,8 @@ import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
|
||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.vo.PayNotifyOrderReqVO;
|
||||
import cn.iocoder.yudao.module.pay.service.notify.vo.PayRefundOrderReqVO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
|
||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -30,7 +33,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -164,8 +169,9 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
||||
// 校验,当前任务是否已经被通知过
|
||||
// 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。
|
||||
PayNotifyTaskDO dbTask = payNotifyTaskCoreMapper.selectById(task.getId());
|
||||
if (DateUtils.afterNow(dbTask.getNextNotifyTime())) {
|
||||
log.info("[executeNotify][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]", JsonUtils.toJsonString(dbTask));
|
||||
if (LocalDateTimeUtils.afterNow(dbTask.getNextNotifyTime())) {
|
||||
log.info("[executeNotifySync][dbTask({}) 任务被忽略,原因是未到达下次通知时间,可能是因为并发执行了]",
|
||||
JsonUtils.toJsonString(dbTask));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -185,11 +191,12 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
||||
invokeException = e;
|
||||
}
|
||||
|
||||
// 处理
|
||||
Integer newStatus = this.processNotifyResult(task, invokeResult, invokeException);
|
||||
// 处理结果
|
||||
Integer newStatus = processNotifyResult(task, invokeResult, invokeException);
|
||||
|
||||
// 记录 PayNotifyLog 日志
|
||||
String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : JsonUtils.toJsonString(invokeResult);
|
||||
String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) :
|
||||
JsonUtils.toJsonString(invokeResult);
|
||||
payNotifyLogCoreMapper.insert(PayNotifyLogDO.builder().taskId(task.getId())
|
||||
.notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build());
|
||||
}
|
||||
@ -201,22 +208,28 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
||||
* @return HTTP 响应
|
||||
*/
|
||||
private CommonResult<?> executeNotifyInvoke(PayNotifyTaskDO task) {
|
||||
// 拼接参数
|
||||
// 拼接 body 参数
|
||||
Object request;
|
||||
if (Objects.equals(task.getType(), PayNotifyTypeEnum.ORDER.getType())) {
|
||||
request = PayNotifyOrderReqVO.builder().merchantOrderId(task.getMerchantOrderId())
|
||||
request = PayOrderNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
|
||||
.payOrderId(task.getDataId()).build();
|
||||
} else if (Objects.equals(task.getType(), PayNotifyTypeEnum.REFUND.getType())) {
|
||||
request = PayRefundOrderReqVO.builder().merchantOrderId(task.getMerchantOrderId())
|
||||
request = PayRefundNotifyReqDTO.builder().merchantOrderId(task.getMerchantOrderId())
|
||||
.payRefundId(task.getDataId()).build();
|
||||
} else {
|
||||
throw new RuntimeException("未知的通知任务类型:" + JsonUtils.toJsonString(task));
|
||||
}
|
||||
// 请求地址
|
||||
String response = HttpUtil.post(task.getNotifyUrl(), JsonUtils.toJsonString(request),
|
||||
(int) NOTIFY_TIMEOUT_MILLIS);
|
||||
// 解析结果
|
||||
return JsonUtils.parseObject(response, CommonResult.class);
|
||||
// 拼接 header 参数
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
TenantUtils.addTenantHeader(headers);
|
||||
|
||||
// 发起请求
|
||||
try (HttpResponse response = HttpUtil.createPost(task.getNotifyUrl())
|
||||
.body(JsonUtils.toJsonString(request)).addHeaders(headers)
|
||||
.timeout((int) NOTIFY_TIMEOUT_MILLIS).execute()) {
|
||||
// 解析结果
|
||||
return JsonUtils.parseObject(response.body(), CommonResult.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,28 +0,0 @@
|
||||
package cn.iocoder.yudao.module.pay.service.notify.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel(value = "支付单的通知 Request VO", description = "业务方接入支付回调时,使用该 VO 对象")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayNotifyOrderReqVO {
|
||||
|
||||
@ApiModelProperty(value = "商户订单编号", required = true, example = "10")
|
||||
@NotEmpty(message = "商户订单号不能为空")
|
||||
private String merchantOrderId;
|
||||
|
||||
@ApiModelProperty(value = "支付订单编号", required = true, example = "20")
|
||||
@NotNull(message = "支付订单编号不能为空")
|
||||
private Long payOrderId;
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
package cn.iocoder.yudao.module.pay.service.notify.vo;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ApiModel(value = "退款单的通知 Request VO", description = "业务方接入退款回调时,使用该 VO 对象")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PayRefundOrderReqVO {
|
||||
|
||||
@ApiModelProperty(value = "商户退款单编号", required = true, example = "10")
|
||||
@NotEmpty(message = "商户退款单编号不能为空")
|
||||
private String merchantOrderId;
|
||||
|
||||
@ApiModelProperty(value = "支付退款编号", required = true, example = "20")
|
||||
@NotNull(message = "支付退款编号不能为空")
|
||||
private Long payRefundId;
|
||||
|
||||
@ApiModelProperty(value = "退款状态(成功,失败)", required = true, example = "10")
|
||||
private Integer status;
|
||||
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
/**
|
||||
* 这里的 VO 包有点特殊,是提供给接入支付模块的业务,提供回调接口时,可以直接使用 VO
|
||||
*
|
||||
* 例如说,支付单的回调,使用 TODO 芋艿:想下怎么优化下
|
||||
*/
|
||||
package cn.iocoder.yudao.module.pay.service.notify.vo;
|
@ -1 +0,0 @@
|
||||
package cn.iocoder.yudao.module.pay.service;
|
Reference in New Issue
Block a user