diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index 5c57dd009..121aeb087 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -5,6 +5,8 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClient; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.*; +import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClient; +import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.*; import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; import lombok.extern.slf4j.Slf4j; @@ -68,6 +70,8 @@ public class PayClientFactoryImpl implements PayClientFactory { case ALIPAY_APP: return (AbstractPayClient) new AlipayAppPayClient(channelId, (AlipayPayClientConfig) config); case ALIPAY_PC: return (AbstractPayClient) new AlipayPcPayClient(channelId, (AlipayPayClientConfig) config); case ALIPAY_BAR: return (AbstractPayClient) new AlipayBarPayClient(channelId, (AlipayPayClientConfig) config); + // 其它支付 + case MOCK: return (AbstractPayClient) new MockPayClient(channelId, (MockPayClientConfig) config); } // 创建失败,错误日志 + 抛出异常 log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config); diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java new file mode 100644 index 000000000..1d3f4d48b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java @@ -0,0 +1,66 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.mock; + +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; +import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; +import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; +import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; + +import java.time.LocalDateTime; +import java.util.Map; + +/** + * 模拟支付的 PayClient 实现类 + * + * 模拟支付返回结果都是成功,方便大家日常流畅 + * + * @author jason + */ +public class MockPayClient extends AbstractPayClient { + + private static final String MOCK_RESP_SUCCESS_DATA = "MOCK_SUCCESS"; + + public MockPayClient(Long channelId, MockPayClientConfig config) { + super(channelId, PayChannelEnum.MOCK.getCode(), config); + } + + @Override + protected void doInit() { + } + + @Override + protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { + return PayOrderRespDTO.successOf("MOCK-P-" + reqDTO.getOutTradeNo(), "", LocalDateTime.now(), + reqDTO.getOutTradeNo(), MOCK_RESP_SUCCESS_DATA); + } + + @Override + protected PayOrderRespDTO doGetOrder(String outTradeNo) { + return PayOrderRespDTO.successOf("MOCK-P-" + outTradeNo, "", LocalDateTime.now(), + outTradeNo, MOCK_RESP_SUCCESS_DATA); + } + + @Override + protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) { + return PayRefundRespDTO.successOf("MOCK-R-" + reqDTO.getOutRefundNo(), LocalDateTime.now(), + reqDTO.getOutRefundNo(), MOCK_RESP_SUCCESS_DATA); + } + + @Override + protected PayRefundRespDTO doGetRefund(String outTradeNo, String outRefundNo) { + return PayRefundRespDTO.successOf("MOCK-R-" + outRefundNo, LocalDateTime.now(), + outRefundNo, MOCK_RESP_SUCCESS_DATA); + } + + @Override + protected PayRefundRespDTO doParseRefundNotify(Map params, String body) { + throw new UnsupportedOperationException("模拟支付无退款回调"); + } + + @Override + protected PayOrderRespDTO doParseOrderNotify(Map params, String body) { + throw new UnsupportedOperationException("模拟支付无支付回调"); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java new file mode 100644 index 000000000..3e35c52dc --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClientConfig.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.framework.pay.core.client.impl.mock; + +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; +import lombok.Data; + +import javax.validation.Validator; + +/** + * 模拟支付的 PayClientConfig 实现类 + * + * @author jason + */ +@Data +public class MockPayClientConfig implements PayClientConfig { + + /** + * 配置名称 + * + * 如果不加任何属性,JsonUtils.parseObject2 解析会报错,所以暂时加个名称 + */ + private String name; + + @Override + public void validate(Validator validator) { + // 模拟支付配置无需校验 + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java index 78bb85f1a..073b17f3c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/channel/PayChannelEnum.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.pay.core.enums.channel; import cn.hutool.core.util.ArrayUtil; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; +import cn.iocoder.yudao.framework.pay.core.client.impl.mock.MockPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.weixin.WxPayClientConfig; import lombok.AllArgsConstructor; import lombok.Getter; @@ -26,7 +27,9 @@ public enum PayChannelEnum { ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class), ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class), ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class), - ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class); + ALIPAY_BAR("alipay_bar", "支付宝条码支付", AlipayPayClientConfig.class), + + MOCK("mock", "模拟支付", MockPayClientConfig.class); /** * 编码 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 9db3bba30..7458e84eb 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,5 +1,6 @@ package cn.iocoder.yudao.module.pay.controller.admin.notify; +import cn.hutool.core.collection.CollUtil; 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; @@ -82,8 +83,8 @@ public class PayNotifyController { @PermitAll @OperateLog(enable = false) // 回调地址,无需记录操作日志 public String notifyRefund(@PathVariable("channelId") Long channelId, - @RequestParam(required = false) Map params, - @RequestBody(required = false) String body) { + @RequestParam(required = false) Map params, + @RequestBody(required = false) String body) { log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body); // 1. 校验支付渠道是否存在 PayClient payClient = payClientFactory.getPayClient(channelId); @@ -118,6 +119,9 @@ public class PayNotifyController { @PreAuthorize("@ss.hasPermission('pay:notify:query')") public CommonResult> getNotifyTaskPage(@Valid PayNotifyTaskPageReqVO pageVO) { PageResult pageResult = notifyService.getNotifyTaskPage(pageVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty()); + } // 拼接返回 Map appMap = appService.getAppMap(convertList(pageResult.getList(), PayNotifyTaskDO::getAppId)); return success(PayNotifyTaskConvert.INSTANCE.convertPage(pageResult, appMap));