Commit b4cde69ddbba3d5c1b2ad2860943ca7880c7e26e
Merge remote-tracking branch 'origin/feature/1.8.0-uniapp' into feature/1.8.0-uniapp
Showing
7 changed files
with
103 additions
and
82 deletions
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 | 3 | import cn.hutool.core.io.IoUtil; |
| 4 | 4 | import cn.hutool.core.util.RandomUtil; |
| ... | ... | @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 7 | 7 | import cn.iocoder.yudao.framework.pay.core.client.PayClient; |
| 8 | 8 | import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; |
| 9 | -import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl; | |
| 10 | 9 | import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; |
| 11 | 10 | import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayQrPayClient; |
| 12 | 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 | 13 | import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPubPayClient; |
| 15 | 14 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 16 | 15 | import com.alipay.api.response.AlipayTradePrecreateResponse; |
| 16 | +import org.junit.jupiter.api.Disabled; | |
| 17 | 17 | import org.junit.jupiter.api.Test; |
| 18 | 18 | |
| 19 | 19 | import java.io.FileInputStream; |
| ... | ... | @@ -24,7 +24,8 @@ import java.io.FileNotFoundException; |
| 24 | 24 | * |
| 25 | 25 | * @author 芋道源码 |
| 26 | 26 | */ |
| 27 | -public class PayClientFactoryImplTest { | |
| 27 | +@Disabled | |
| 28 | +public class PayClientFactoryImplIntegrationTest { | |
| 28 | 29 | |
| 29 | 30 | private final PayClientFactoryImpl payClientFactory = new PayClientFactoryImpl(); |
| 30 | 31 | |
| ... | ... | @@ -91,7 +92,7 @@ public class PayClientFactoryImplTest { |
| 91 | 92 | PayClient client = payClientFactory.getPayClient(channelId); |
| 92 | 93 | // 发起支付 |
| 93 | 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 | 96 | CommonResult<AlipayTradePrecreateResponse> result = (CommonResult<AlipayTradePrecreateResponse>) client.unifiedOrder(reqDTO); |
| 96 | 97 | System.out.println(JsonUtils.toJsonString(result)); |
| 97 | 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 | 83 | return success(true); |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | - @PutMapping("/receive") | |
| 86 | + @PutMapping("/refuse") | |
| 87 | 87 | @ApiOperation("确认收货") |
| 88 | 88 | @ApiImplicitParam(name = "id", value = "售后编号", required = true, example = "1") |
| 89 | 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 | 2 | |
| 3 | 3 | import cn.hutool.core.bean.BeanUtil; |
| 4 | 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 | 5 | import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; |
| 9 | 6 | import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; |
| 10 | 7 | import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; |
| 11 | 8 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 12 | 9 | import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitReqDTO; |
| 13 | 10 | import cn.iocoder.yudao.module.pay.service.order.dto.PayOrderSubmitRespDTO; |
| 14 | -import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | |
| 15 | 11 | import io.swagger.annotations.Api; |
| 16 | 12 | import io.swagger.annotations.ApiOperation; |
| 17 | 13 | import lombok.extern.slf4j.Slf4j; |
| 18 | 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 | 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 | 22 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 26 | 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 | 25 | @Api(tags = "用户 APP - 支付订单") |
| 30 | 26 | @RestController |
| ... | ... | @@ -35,11 +31,6 @@ public class AppPayOrderController { |
| 35 | 31 | |
| 36 | 32 | @Resource |
| 37 | 33 | private PayOrderService orderService; |
| 38 | - @Resource | |
| 39 | - private PayRefundService refundService; | |
| 40 | - | |
| 41 | - @Resource | |
| 42 | - private PayClientFactory payClientFactory; | |
| 43 | 34 | |
| 44 | 35 | @PostMapping("/submit") |
| 45 | 36 | @ApiOperation("提交支付订单") |
| ... | ... | @@ -59,64 +50,4 @@ public class AppPayOrderController { |
| 59 | 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 | 1 | package cn.iocoder.yudao.module.pay.dal.dataobject.merchant; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | |
| 5 | 4 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 6 | 5 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 6 | +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; | |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 8 | 8 | import com.baomidou.mybatisplus.annotation.TableField; |
| 9 | 9 | import com.baomidou.mybatisplus.annotation.TableName; |
| ... | ... | @@ -26,7 +26,7 @@ import lombok.*; |
| 26 | 26 | @Builder |
| 27 | 27 | @NoArgsConstructor |
| 28 | 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 | 211 | |
| 212 | 212 | @Override |
| 213 | 213 | @Transactional |
| 214 | - public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception { | |
| 214 | + public void notifyPayOrder(Long channelId, PayNotifyDataDTO notifyData) throws Exception { | |
| 215 | 215 | // TODO 芋艿,记录回调日志 |
| 216 | 216 | log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getBody()); |
| 217 | 217 | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -117,7 +117,7 @@ yudao: |
| 117 | 117 | - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 |
| 118 | 118 | - /admin-api/infra/file/*/get/** # 获取图片,和租户无关 |
| 119 | 119 | - /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号 |
| 120 | - - /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号 | |
| 120 | + - /admin-api/pay/notify/callback/* # 支付回调通知,不携带租户编号 | |
| 121 | 121 | - /jmreport/* # 积木报表,无法携带租户编号 |
| 122 | 122 | ignore-tables: |
| 123 | 123 | - system_tenant | ... | ... |