From 654b70c514819eefabf1faa9dbddff02e2d5e5fc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 20 Jul 2023 22:48:06 +0800 Subject: [PATCH] =?UTF-8?q?mall=20+=20pay=EF=BC=9A=201.=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=80=9A=E7=9F=A5=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/notify/PayNotifyController.java | 51 +++- .../admin/notify/vo/PayNotifyTaskBaseVO.java | 45 ++++ .../notify/vo/PayNotifyTaskDetailRespVO.java | 54 +++++ .../notify/vo/PayNotifyTaskPageReqVO.java | 39 ++++ .../admin/notify/vo/PayNotifyTaskRespVO.java | 22 ++ .../convert/notify/PayNotifyTaskConvert.java | 43 ++++ .../dataobject/notify/PayNotifyTaskDO.java | 2 +- .../dal/mysql/notify/PayNotifyLogMapper.java | 7 + .../dal/mysql/notify/PayNotifyTaskMapper.java | 26 ++- .../pay/service/notify/PayNotifyService.java | 35 ++- .../service/notify/PayNotifyServiceImpl.java | 39 +++- yudao-ui-admin/src/api/pay/notify.js | 18 ++ yudao-ui-admin/src/utils/dict.js | 3 +- yudao-ui-admin/src/views/pay/notify/index.vue | 221 ++++++++++++++++++ yudao-ui-admin/src/views/pay/order/index.vue | 2 +- yudao-ui-admin/src/views/pay/refund/index.vue | 4 +- 16 files changed, 584 insertions(+), 27 deletions(-) create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskBaseVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java create mode 100644 yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/notify/PayNotifyTaskConvert.java create mode 100644 yudao-ui-admin/src/api/pay/notify.js create mode 100644 yudao-ui-admin/src/views/pay/notify/index.vue diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java index 04c080843..9db3bba30 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java @@ -1,25 +1,43 @@ package cn.iocoder.yudao.module.pay.controller.admin.notify; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; +import cn.iocoder.yudao.module.pay.convert.notify.PayNotifyTaskConvert; +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; +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.service.app.PayAppService; +import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; import cn.iocoder.yudao.module.pay.service.order.PayOrderService; import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.annotation.security.PermitAll; +import javax.validation.Valid; +import java.util.List; import java.util.Map; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.CHANNEL_NOT_FOUND; -@Tag(name = "管理后台 - 支付通知") +@Tag(name = "管理后台 - 回调通知") @RestController @RequestMapping("/pay/notify") @Validated @@ -30,6 +48,10 @@ public class PayNotifyController { private PayOrderService orderService; @Resource private PayRefundService refundService; + @Resource + private PayNotifyService notifyService; + @Resource + private PayAppService appService; @Resource private PayClientFactory payClientFactory; @@ -76,4 +98,29 @@ public class PayNotifyController { return "success"; } + @GetMapping("/get-detail") + @Operation(summary = "获得回调通知的明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('pay:notify:query')") + public CommonResult getNotifyTaskDetail(@RequestParam("id") Long id) { + PayNotifyTaskDO task = notifyService.getNotifyTask(id); + if (task == null) { + return success(null); + } + // 拼接返回 + PayAppDO app = appService.getApp(task.getAppId()); + List logs = notifyService.getNotifyLogList(id); + return success(PayNotifyTaskConvert.INSTANCE.convert(task, app, logs)); + } + + @GetMapping("/page") + @Operation(summary = "获得回调通知分页") + @PreAuthorize("@ss.hasPermission('pay:notify:query')") + public CommonResult> getNotifyTaskPage(@Valid PayNotifyTaskPageReqVO pageVO) { + PageResult pageResult = notifyService.getNotifyTaskPage(pageVO); + // 拼接返回 + Map appMap = appService.getAppMap(convertList(pageResult.getList(), PayNotifyTaskDO::getAppId)); + return success(PayNotifyTaskConvert.INSTANCE.convertPage(pageResult, appMap)); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskBaseVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskBaseVO.java new file mode 100644 index 000000000..1e623751b --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskBaseVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 回调通知 Base VO,提供给添加、修改、详细的子 VO 使用 + * 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成 + */ +@Data +public class PayNotifyTaskBaseVO { + + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10636") + private Long appId; + + @Schema(description = "通知类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + private Byte type; + + @Schema(description = "数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "6722") + private Long dataId; + + @Schema(description = "通知状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Byte status; + + @Schema(description = "商户订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26697") + private String merchantOrderId; + + @Schema(description = "下一次通知时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime nextNotifyTime; + + @Schema(description = "最后一次执行时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime lastExecuteTime; + + @Schema(description = "当前通知次数", requiredMode = Schema.RequiredMode.REQUIRED) + private Byte notifyTimes; + + @Schema(description = "最大可通知次数", requiredMode = Schema.RequiredMode.REQUIRED) + private Byte maxNotifyTimes; + + @Schema(description = "异步通知地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn") + private String notifyUrl; + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java new file mode 100644 index 000000000..7c75613e2 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java @@ -0,0 +1,54 @@ + +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 回调通知的明细 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PayNotifyTaskDetailRespVO extends PayNotifyTaskBaseVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3380") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime updateTime; + + @Schema(description = "应用名称", example = "wx_pay") + private String appName; + + @Schema(description = "回调日志列表") + private List logs; + + @Schema(description = "管理后台 - 回调日志") + @Data + public static class Log { + + @Schema(description = "日志编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8848") + private Long id; + + @Schema(description = "通知状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Byte status; + + @Schema(description = "当前通知次数", requiredMode = Schema.RequiredMode.REQUIRED) + private Byte notifyTimes; + + @Schema(description = "HTTP 响应结果", requiredMode = Schema.RequiredMode.REQUIRED) + private String response; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + } + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java new file mode 100644 index 000000000..5697d0d87 --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - 回调通知分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PayNotifyTaskPageReqVO extends PageParam { + + @Schema(description = "应用编号", example = "10636") + private Long appId; + + @Schema(description = "通知类型", example = "2") + private Byte type; + + @Schema(description = "数据编号", example = "6722") + private Long dataId; + + @Schema(description = "通知状态", example = "1") + private Byte status; + + @Schema(description = "商户订单编号", example = "26697") + private String merchantOrderId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java new file mode 100644 index 000000000..d7f7fe6fb --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.pay.controller.admin.notify.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - 回调通知 Response VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class PayNotifyTaskRespVO extends PayNotifyTaskBaseVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3380") + private Long id; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + + @Schema(description = "应用名称", example = "wx_pay") + private String appName; + +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/notify/PayNotifyTaskConvert.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/notify/PayNotifyTaskConvert.java new file mode 100644 index 000000000..d0b8e36ff --- /dev/null +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/notify/PayNotifyTaskConvert.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.pay.convert.notify; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskDetailRespVO; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskRespVO; +import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; +import java.util.Map; + +/** + * 支付通知 Convert + * + * @author 芋道源码 + */ +@Mapper +public interface PayNotifyTaskConvert { + + PayNotifyTaskConvert INSTANCE = Mappers.getMapper(PayNotifyTaskConvert.class); + + PayNotifyTaskRespVO convert(PayNotifyTaskDO bean); + + default PageResult convertPage(PageResult page, Map appMap){ + PageResult result = convertPage(page); + result.getList().forEach(order -> MapUtils.findAndThen(appMap, order.getAppId(), app -> order.setAppName(app.getName()))); + return result; + } + PageResult convertPage(PageResult page); + + default PayNotifyTaskDetailRespVO convert(PayNotifyTaskDO task, PayAppDO app, List logs) { + PayNotifyTaskDetailRespVO respVO = convert(task, logs); + if (app != null) { + respVO.setAppName(app.getName()); + } + return respVO; + } + PayNotifyTaskDetailRespVO convert(PayNotifyTaskDO task, List logs); +} diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 6bc60dc3a..bbcf105b4 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -15,7 +15,7 @@ import lombok.experimental.Accessors; import java.time.LocalDateTime; /** - * 商户支付、退款等的通知 + * 支付通知 * 在支付系统收到支付渠道的支付、退款的结果后,需要不断的通知到业务系统,直到成功。 * * @author 芋道源码 diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java index 34a7b6249..8b586dff2 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyLogMapper.java @@ -4,6 +4,13 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + @Mapper public interface PayNotifyLogMapper extends BaseMapperX { + + default List selectListByTaskId(Long taskId) { + return selectList(PayNotifyLogDO::getTaskId, taskId); + } + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java index 37ec65a3a..cc7701271 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.pay.dal.mysql.notify; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; import java.time.LocalDateTime; @@ -21,10 +24,21 @@ public interface PayNotifyTaskMapper extends BaseMapperX { * @return PayTransactionNotifyTaskDO 数组 */ default List selectListByNotify() { - return selectList(new QueryWrapper() - .in("status", PayNotifyStatusEnum.WAITING.getStatus(), PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus(), - PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()) - .le("next_notify_time", LocalDateTime.now())); + return selectList(new LambdaQueryWrapper() + .in(PayNotifyTaskDO::getStatus, PayNotifyStatusEnum.WAITING.getStatus(), + PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus(), PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()) + .le(PayNotifyTaskDO::getNextNotifyTime, LocalDateTime.now())); + } + + default PageResult selectPage(PayNotifyTaskPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(PayNotifyTaskDO::getAppId, reqVO.getAppId()) + .eqIfPresent(PayNotifyTaskDO::getType, reqVO.getType()) + .eqIfPresent(PayNotifyTaskDO::getDataId, reqVO.getDataId()) + .eqIfPresent(PayNotifyTaskDO::getStatus, reqVO.getStatus()) + .eqIfPresent(PayNotifyTaskDO::getMerchantOrderId, reqVO.getMerchantOrderId()) + .betweenIfPresent(PayNotifyTaskDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(PayNotifyTaskDO::getId)); } } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java index 8b6aba199..fa302e782 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java @@ -1,29 +1,58 @@ package cn.iocoder.yudao.module.pay.service.notify; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; +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.service.notify.dto.PayNotifyTaskCreateReqDTO; import javax.validation.Valid; +import java.util.List; /** - * 支付通知 Service 接口 + * 回调通知 Service 接口 * * @author 芋道源码 */ public interface PayNotifyService { /** - * 创建支付通知任务 + * 创建回调通知任务 * * @param reqDTO 任务信息 */ void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO); /** - * 执行支付通知 + * 执行回调通知 * * 注意,该方法提供给定时任务调用。目前是 yudao-server 进行调用 * @return 通知数量 */ int executeNotify() throws InterruptedException; + /** + * 获得回调通知 + * + * @param id 编号 + * @return 回调通知 + */ + PayNotifyTaskDO getNotifyTask(Long id); + + /** + * 获得回调通知分页 + * + * @param pageReqVO 分页查询 + * @return 回调通知分页 + */ + PageResult getNotifyTaskPage(PayNotifyTaskPageReqVO pageReqVO); + + /** + * 获得回调日志列表 + * + * @param taskId 任务编号 + * @return 日志列表 + */ + List getNotifyLogList(Long taskId); + } diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java index f38c3c0d7..2503e1118 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java @@ -6,11 +6,13 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; 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.controller.admin.notify.vo.PayNotifyTaskPageReqVO; 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; @@ -72,15 +74,15 @@ public class PayNotifyServiceImpl implements PayNotifyService { private PayRefundService refundService; @Resource - private PayNotifyTaskMapper payNotifyTaskMapper; + private PayNotifyTaskMapper notifyTaskMapper; @Resource - private PayNotifyLogMapper payNotifyLogMapper; + private PayNotifyLogMapper notifyLogMapper; @Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR) private ThreadPoolTaskExecutor threadPoolTaskExecutor; @Resource - private PayNotifyLockRedisDAO payNotifyLockCoreRedisDAO; + private PayNotifyLockRedisDAO notifyLockCoreRedisDAO; @Resource @Lazy // 循环依赖(自己依赖自己),避免报错 @@ -105,7 +107,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { } // 执行插入 - payNotifyTaskMapper.insert(task); + notifyTaskMapper.insert(task); // 必须在事务提交后,在发起任务,否则 PayNotifyTaskDO 还没入库,就提前回调接入的业务 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @@ -119,7 +121,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { @Override public int executeNotify() throws InterruptedException { // 获得需要通知的任务 - List tasks = payNotifyTaskMapper.selectListByNotify(); + List tasks = notifyTaskMapper.selectListByNotify(); if (CollUtil.isEmpty(tasks)) { return 0; } @@ -164,11 +166,11 @@ public class PayNotifyServiceImpl implements PayNotifyService { */ public void executeNotify(PayNotifyTaskDO task) { // 分布式锁,避免并发问题 - payNotifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { + notifyLockCoreRedisDAO.lock(task.getId(), NOTIFY_TIMEOUT_MILLIS, () -> { // 校验,当前任务是否已经被通知过 // 虽然已经通过分布式加锁,但是可能同时满足通知的条件,然后都去获得锁。此时,第一个执行完后,第二个还是能拿到锁,然后会再执行一次。 // 因此,此处我们通过第 notifyTimes 通知次数是否匹配来判断 - PayNotifyTaskDO dbTask = payNotifyTaskMapper.selectById(task.getId()); + PayNotifyTaskDO dbTask = notifyTaskMapper.selectById(task.getId()); if (ObjectUtil.notEqual(task.getNotifyTimes(), dbTask.getNotifyTimes())) { log.warn("[executeNotifySync][task({}) 任务被忽略,原因是它的通知不是第 ({}) 次,可能是因为并发执行了]", JsonUtils.toJsonString(task), dbTask.getNotifyTimes()); @@ -197,7 +199,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { // 记录 PayNotifyLog 日志 String response = invokeException != null ? ExceptionUtil.getRootCauseMessage(invokeException) : JsonUtils.toJsonString(invokeResult); - payNotifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) + notifyLogMapper.insert(PayNotifyLogDO.builder().taskId(task.getId()) .notifyTimes(task.getNotifyTimes() + 1).status(newStatus).response(response).build()); } @@ -250,22 +252,37 @@ public class PayNotifyServiceImpl implements PayNotifyService { // 情况一:调用成功 if (invokeResult != null && invokeResult.isSuccess()) { updateTask.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()); - payNotifyTaskMapper.updateById(updateTask); + notifyTaskMapper.updateById(updateTask); return updateTask.getStatus(); } // 情况二:调用失败、调用异常 // 2.1 超过最大回调次数 if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { updateTask.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()); - payNotifyTaskMapper.updateById(updateTask); + notifyTaskMapper.updateById(updateTask); return updateTask.getStatus(); } // 2.2 未超过最大回调次数 updateTask.setNextNotifyTime(addTime(Duration.ofSeconds(PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()]))); updateTask.setStatus(invokeException != null ? PayNotifyStatusEnum.REQUEST_FAILURE.getStatus() : PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()); - payNotifyTaskMapper.updateById(updateTask); + notifyTaskMapper.updateById(updateTask); return updateTask.getStatus(); } + @Override + public PayNotifyTaskDO getNotifyTask(Long id) { + return notifyTaskMapper.selectById(id); + } + + @Override + public PageResult getNotifyTaskPage(PayNotifyTaskPageReqVO pageReqVO) { + return notifyTaskMapper.selectPage(pageReqVO); + } + + @Override + public List getNotifyLogList(Long taskId) { + return notifyLogMapper.selectListByTaskId(taskId); + } + } diff --git a/yudao-ui-admin/src/api/pay/notify.js b/yudao-ui-admin/src/api/pay/notify.js new file mode 100644 index 000000000..4cb6e20c1 --- /dev/null +++ b/yudao-ui-admin/src/api/pay/notify.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 获得支付通知明细 +export function getNotifyTaskDetail(id) { + return request({ + url: '/pay/notify/get-detail?id=' + id, + method: 'get' + }) +} + +// 获得支付通知分页 +export function getNotifyTaskPage(query) { + return request({ + url: '/pay/notify/page', + method: 'get', + params: query + }) +} diff --git a/yudao-ui-admin/src/utils/dict.js b/yudao-ui-admin/src/utils/dict.js index 4f20c890b..8abbe2093 100644 --- a/yudao-ui-admin/src/utils/dict.js +++ b/yudao-ui-admin/src/utils/dict.js @@ -56,9 +56,10 @@ export const DICT_TYPE = { PAY_CHANNEL_ALIPAY_SERVER_TYPE: 'pay_channel_alipay_server_type', // 支付宝网关地址 PAY_CHANNEL_CODE: 'pay_channel_code', // 支付渠道编码类型 - PAY_NOTIFY_STATUS: 'pay_notify_status', // 商户支付回调状态 PAY_ORDER_STATUS: 'pay_order_status', // 商户支付订单状态 PAY_REFUND_STATUS: 'pay_refund_status', // 退款订单状态 + PAY_NOTIFY_STATUS: 'pay_notify_status', // 商户支付回调状态 + PAY_NOTIFY_TYPE: 'pay_notify_type', // 商户支付回调状态 // ========== MP 模块 ========== MP_AUTO_REPLY_REQUEST_MATCH: 'mp_auto_reply_request_match', // 自动回复请求匹配类型 diff --git a/yudao-ui-admin/src/views/pay/notify/index.vue b/yudao-ui-admin/src/views/pay/notify/index.vue new file mode 100644 index 000000000..3c9e7d578 --- /dev/null +++ b/yudao-ui-admin/src/views/pay/notify/index.vue @@ -0,0 +1,221 @@ + + + diff --git a/yudao-ui-admin/src/views/pay/order/index.vue b/yudao-ui-admin/src/views/pay/order/index.vue index 1ceb52918..6d7be5014 100755 --- a/yudao-ui-admin/src/views/pay/order/index.vue +++ b/yudao-ui-admin/src/views/pay/order/index.vue @@ -121,7 +121,7 @@ @pagination="getList"/> - + {{ orderDetail.merchantOrderId }} diff --git a/yudao-ui-admin/src/views/pay/refund/index.vue b/yudao-ui-admin/src/views/pay/refund/index.vue index 3ea674531..2149f16ed 100755 --- a/yudao-ui-admin/src/views/pay/refund/index.vue +++ b/yudao-ui-admin/src/views/pay/refund/index.vue @@ -128,7 +128,7 @@ @pagination="getList"/> - + {{ refundDetail.merchantRefundId }} @@ -180,7 +180,7 @@ {{ refundDetail.notifyUrl }} - + {{refundDetail.channelErrorCode}} {{refundDetail.channelErrorMsg}}