Commit b4cde69ddbba3d5c1b2ad2860943ca7880c7e26e

Authored by sfmind
2 parents 49fe926c 73d847ae

Merge remote-tracking branch 'origin/feature/1.8.0-uniapp' into feature/1.8.0-uniapp

yudao-framework/yudao-spring-boot-starter-biz-pay/src/test-integration/java/cn/iocoder/yudao/framework/core/client/impl/PayClientFactoryImplTest.java renamed to yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn.iocoder.yudao.framework.pay.core.client.impl/PayClientFactoryImplIntegrationTest.java
1 -package cn.iocoder.yudao.framework.core.client.impl; 1 +package cn.iocoder.yudao.framework.pay.core.client.impl;
2 2
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
4 import cn.hutool.core.util.RandomUtil; 4 import cn.hutool.core.util.RandomUtil;
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
7 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 7 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
8 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
9 -import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;  
10 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; 9 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
11 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient; 10 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient;
12 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient; 11 import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayWapPayClient;
@@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; @@ -14,6 +13,7 @@ import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
14 import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient; 13 import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient;
15 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 14 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
16 import com.alipay.api.response.AlipayTradePrecreateResponse; 15 import com.alipay.api.response.AlipayTradePrecreateResponse;
  16 +import org.junit.jupiter.api.Disabled;
17 import org.junit.jupiter.api.Test; 17 import org.junit.jupiter.api.Test;
18 18
19 import java.io.FileInputStream; 19 import java.io.FileInputStream;
@@ -24,7 +24,8 @@ import java.io.FileNotFoundException; @@ -24,7 +24,8 @@ import java.io.FileNotFoundException;
24 * 24 *
25 * @author 芋道源码 25 * @author 芋道源码
26 */ 26 */
27 -public class PayClientFactoryImplTest { 27 +@Disabled
  28 +public class PayClientFactoryImplIntegrationTest {
28 29
29 private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl(); 30 private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl();
30 31
@@ -91,7 +92,7 @@ public class PayClientFactoryImplTest { @@ -91,7 +92,7 @@ public class PayClientFactoryImplTest {
91 PayClient client = payClientFactory.getPayClient(channelId); 92 PayClient client = payClientFactory.getPayClient(channelId);
92 // 发起支付 93 // 发起支付
93 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO(); 94 PayOrderUnifiedReqDTO reqDTO = buildPayOrderUnifiedReqDTO();
94 - reqDTO.setNotifyUrl("http://niubi.natapp1.cc/api/pay/order/notify/alipay-qr/1"); // TODO @tina: 这里改成你的 natapp 回调地址 95 + reqDTO.setNotifyUrl("http://yunai.natapp1.cc/admin-api/pay/notify/callback/18"); // TODO @tina: 这里改成你的 natapp 回调地址
95 CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO); 96 CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO);
96 System.out.println(JsonUtils.toJsonString(result)); 97 System.out.println(JsonUtils.toJsonString(result));
97 System.out.println(result.getData().getQrCode()); 98 System.out.println(result.getData().getQrCode());
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/TradeAfterSaleController.java
@@ -83,7 +83,7 @@ public class TradeAfterSaleController { @@ -83,7 +83,7 @@ public class TradeAfterSaleController {
83 return success(true); 83 return success(true);
84 } 84 }
85 85
86 - @PutMapping("/receive") 86 + @PutMapping("/refuse")
87 @ApiOperation("确认收货") 87 @ApiOperation("确认收货")
88 @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") 88 @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1")
89 @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')") 89 @PreAuthorize("@ss.hasPermission('trade:after-sale:receive')")
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.pay.controller.admin.notify;
  2 +
  3 +import cn.iocoder.yudao.framework.pay.core.client.PayClient;
  4 +import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
  5 +import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;
  6 +import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
  7 +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
  8 +import io.swagger.annotations.Api;
  9 +import io.swagger.annotations.ApiOperation;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.validation.annotation.Validated;
  12 +import org.springframework.web.bind.annotation.*;
  13 +
  14 +import javax.annotation.Resource;
  15 +import javax.annotation.security.PermitAll;
  16 +import java.util.Map;
  17 +
  18 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  19 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_CHANNEL_CLIENT_NOT_FOUND;
  20 +
  21 +@Api(tags = "管理后台 - 支付通知")
  22 +@RestController
  23 +@RequestMapping("/pay/notify")
  24 +@Validated
  25 +@Slf4j
  26 +public class PayNotifyController {
  27 +
  28 + @Resource
  29 + private PayOrderService orderService;
  30 + @Resource
  31 + private PayRefundService refundService;
  32 +
  33 + @Resource
  34 + private PayClientFactory payClientFactory;
  35 +
  36 + /**
  37 + * 统一的跳转页面,支付宝跳转参数说明
  38 + *
  39 + * <a href="https://opendocs.alipay.com/open/203/105285#前台回跳参数说明">支付宝 - 前台回跳参数说明</a>
  40 + *
  41 + * @param channelId 渠道编号
  42 + * @return 返回跳转页面
  43 + */
  44 + @GetMapping(value = "/return/{channelId}")
  45 + @ApiOperation("渠道统一的支付成功返回地址")
  46 + @Deprecated // TODO yunai:如果是 way 的情况,应该是跳转回前端地址
  47 + public String returnCallback(@PathVariable("channelId") Long channelId,
  48 + @RequestParam Map<String, String> params) {
  49 + log.info("[returnCallback][app_id({}) 跳转]", params.get("app_id"));
  50 + return String.format("渠道[%s]支付成功", channelId);
  51 + }
  52 +
  53 + /**
  54 + * 统一的渠道支付回调,支付宝的退款回调
  55 + *
  56 + * @param channelId 渠道编号
  57 + * @param params form 参数
  58 + * @param body request body
  59 + * @return 成功返回 "success"
  60 + */
  61 + @PostMapping(value = "/callback/{channelId}")
  62 + @ApiOperation(value = "支付渠道的统一回调接口", notes = "包括支付回调,退款回调")
  63 + @PermitAll
  64 + public String notifyCallback(@PathVariable("channelId") Long channelId,
  65 + @RequestParam Map<String, String> params,
  66 + @RequestBody String body) throws Exception {
  67 + // 校验支付渠道是否存在
  68 + PayClient payClient = payClientFactory.getPayClient(channelId);
  69 + if (payClient == null) {
  70 + log.error("[notifyCallback][渠道编号({}) 找不到对应的支付客户端]", channelId);
  71 + throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
  72 + }
  73 + // 校验通知数据是否合法
  74 + PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(body).build();
  75 + payClient.verifyNotifyData(notifyData);
  76 +
  77 + // 情况一:如果是退款,则发起退款通知
  78 + if (payClient.isRefundNotify(notifyData)) {
  79 + refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(body).build());
  80 + return "success";
  81 + }
  82 +
  83 + // 情况二:如果非退款,则发起支付通知
  84 + orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(body).build());
  85 + return "success";
  86 + }
  87 +
  88 +
  89 +}
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
@@ -2,29 +2,25 @@ package cn.iocoder.yudao.module.pay.controller.app.order; @@ -2,29 +2,25 @@ package cn.iocoder.yudao.module.pay.controller.app.order;
2 2
3 import cn.hutool.core.bean.BeanUtil; 3 import cn.hutool.core.bean.BeanUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 -import cn.iocoder.yudao.framework.pay.core.client.PayClient;  
6 -import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;  
7 -import cn.iocoder.yudao.framework.pay.core.client.dto.PayNotifyDataDTO;  
8 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; 5 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO;
9 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; 6 import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO;
10 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; 7 import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
11 import cn.iocoder.yudao.module.pay.service.order.PayOrderService; 8 import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
12 import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; 9 import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO;
13 import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; 10 import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO;
14 -import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;  
15 import io.swagger.annotations.Api; 11 import io.swagger.annotations.Api;
16 import io.swagger.annotations.ApiOperation; 12 import io.swagger.annotations.ApiOperation;
17 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
18 import org.springframework.validation.annotation.Validated; 14 import org.springframework.validation.annotation.Validated;
19 -import org.springframework.web.bind.annotation.*; 15 +import org.springframework.web.bind.annotation.PostMapping;
  16 +import org.springframework.web.bind.annotation.RequestBody;
  17 +import org.springframework.web.bind.annotation.RequestMapping;
  18 +import org.springframework.web.bind.annotation.RestController;
20 19
21 import javax.annotation.Resource; 20 import javax.annotation.Resource;
22 -import java.util.Map;  
23 21
24 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
25 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
26 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 23 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
27 -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;  
28 24
29 @Api(tags = "用户 APP - 支付订单") 25 @Api(tags = "用户 APP - 支付订单")
30 @RestController 26 @RestController
@@ -35,11 +31,6 @@ public class AppPayOrderController { @@ -35,11 +31,6 @@ public class AppPayOrderController {
35 31
36 @Resource 32 @Resource
37 private PayOrderService orderService; 33 private PayOrderService orderService;
38 - @Resource  
39 - private PayRefundService refundService;  
40 -  
41 - @Resource  
42 - private PayClientFactory payClientFactory;  
43 34
44 @PostMapping("/submit") 35 @PostMapping("/submit")
45 @ApiOperation("提交支付订单") 36 @ApiOperation("提交支付订单")
@@ -59,64 +50,4 @@ public class AppPayOrderController { @@ -59,64 +50,4 @@ public class AppPayOrderController {
59 return success(AppPayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build()); 50 return success(AppPayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build());
60 } 51 }
61 52
62 - // ========== 支付渠道的回调 ==========  
63 - // TODO @芋艿:是不是放到 notify 模块更合适  
64 - //TODO 芋道源码 换成了统一的地址了 /notify/{channelId},测试通过可以删除  
65 - @PostMapping("/notify/wx-pub/{channelId}")  
66 - @ApiOperation("通知微信公众号支付的结果")  
67 - public String notifyWxPayOrder(@PathVariable("channelId") Long channelId,  
68 - @RequestBody String xmlData) throws Exception {  
69 - orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().body(xmlData).build());  
70 - return "success";  
71 - }  
72 -  
73 - /**  
74 - * 统一的跳转页面, 支付宝跳转参数说明  
75 - * https://opendocs.alipay.com/open/203/105285#%E5%89%8D%E5%8F%B0%E5%9B%9E%E8%B7%B3%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E  
76 - * @param channelId 渠道id  
77 - * @return 返回跳转页面  
78 - */  
79 - @GetMapping(value = "/return/{channelId}")  
80 - @ApiOperation("渠道统一的支付成功返回地址")  
81 - public String returnAliPayOrder(@PathVariable("channelId") Long channelId, @RequestParam Map<String, String> params){  
82 - //TODO 可以根据渠道和 app_id 返回不同的页面  
83 - log.info("app_id is {}", params.get("app_id"));  
84 - return String.format("渠道[%s]支付成功", channelId);  
85 - }  
86 -  
87 - /**  
88 - * 统一的渠道支付回调,支付宝的退款回调  
89 - *  
90 - * @param channelId 渠道编号  
91 - * @param params form 参数  
92 - * @param originData http request body  
93 - * @return 成功返回 "success"  
94 - */  
95 - @PostMapping(value = "/notify/{channelId}")  
96 - @ApiOperation("渠道统一的支付成功,或退款成功 通知url")  
97 - public String notifyChannelPay(@PathVariable("channelId") Long channelId,  
98 - @RequestParam Map<String, String> params,  
99 - @RequestBody String originData) throws Exception {  
100 - // 校验支付渠道是否存在  
101 - PayClient payClient = payClientFactory.getPayClient(channelId);  
102 - if (payClient == null) {  
103 - log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channelId);  
104 - throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);  
105 - }  
106 -  
107 - // 校验通知数据是否合法  
108 - PayNotifyDataDTO notifyData = PayNotifyDataDTO.builder().params(params).body(originData).build();  
109 - payClient.verifyNotifyData(notifyData);  
110 -  
111 - // 如果是退款,则发起退款通知  
112 - if (payClient.isRefundNotify(notifyData)) {  
113 - refundService.notifyPayRefund(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());  
114 - return "success";  
115 - }  
116 -  
117 - // 如果非退款,则发起支付通知  
118 - orderService.notifyPayOrder(channelId, PayNotifyDataDTO.builder().params(params).body(originData).build());  
119 - return "success";  
120 - }  
121 -  
122 } 53 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/merchant/PayChannelDO.java
1 package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; 1 package cn.iocoder.yudao.module.pay.dal.dataobject.merchant;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;  
5 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 4 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
6 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 5 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
  6 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
7 import com.baomidou.mybatisplus.annotation.KeySequence; 7 import com.baomidou.mybatisplus.annotation.KeySequence;
8 import com.baomidou.mybatisplus.annotation.TableField; 8 import com.baomidou.mybatisplus.annotation.TableField;
9 import com.baomidou.mybatisplus.annotation.TableName; 9 import com.baomidou.mybatisplus.annotation.TableName;
@@ -26,7 +26,7 @@ import lombok.*; @@ -26,7 +26,7 @@ import lombok.*;
26 @Builder 26 @Builder
27 @NoArgsConstructor 27 @NoArgsConstructor
28 @AllArgsConstructor 28 @AllArgsConstructor
29 -public class PayChannelDO extends BaseDO { 29 +public class PayChannelDO extends TenantBaseDO {
30 30
31 /** 31 /**
32 * 渠道编号,数据库自增 32 * 渠道编号,数据库自增
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -211,7 +211,7 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -211,7 +211,7 @@ public class PayOrderServiceImpl implements PayOrderService {
211 211
212 @Override 212 @Override
213 @Transactional 213 @Transactional
214 - public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception { 214 + public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception {
215 // TODO 芋艿,记录回调日志 215 // TODO 芋艿,记录回调日志
216 log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); 216 log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody());
217 217
yudao-server/src/main/resources/application.yaml
@@ -117,7 +117,7 @@ yudao: @@ -117,7 +117,7 @@ yudao:
117 - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 117 - /admin-api/system/captcha/check # 校验图片验证码,和租户无关
118 - /admin-api/infra/file/*/get/** # 获取图片,和租户无关 118 - /admin-api/infra/file/*/get/** # 获取图片,和租户无关
119 - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 119 - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
120 - - /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号 120 + - /admin-api/pay/notify/callback/* # 支付回调通知,不携带租户编号
121 - /jmreport/* # 积木报表,无法携带租户编号 121 - /jmreport/* # 积木报表,无法携带租户编号
122 ignore-tables: 122 ignore-tables:
123 - system_tenant 123 - system_tenant