Commit 2c60a3aafa8f37b3fbbf6592c721bc811702b88b

Authored by jason
1 parent aa77eb02

支付宝手机网站支付

Showing 14 changed files with 204 additions and 21 deletions
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/PayOrderCoreService.java
1 package cn.iocoder.yudao.coreservice.modules.pay.service.order; 1 package cn.iocoder.yudao.coreservice.modules.pay.service.order;
2 2
3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; 3 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
  4 +
4 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; 5 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
5 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; 6 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
6 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; 7 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
  8 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
7 9
8 import javax.validation.Valid; 10 import javax.validation.Valid;
9 11
@@ -46,6 +48,6 @@ public interface PayOrderCoreService { @@ -46,6 +48,6 @@ public interface PayOrderCoreService {
46 * @param channelCode 渠道编码 48 * @param channelCode 渠道编码
47 * @param notifyData 通知数据 49 * @param notifyData 通知数据
48 */ 50 */
49 - void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception; 51 + void notifyPayOrder(Long channelId, String channelCode, NotifyDataDTO notifyData) throws Exception;
50 52
51 } 53 }
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/service/order/impl/PayOrderCoreServiceImpl.java
@@ -18,6 +18,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreS @@ -18,6 +18,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayChannelCoreS
18 import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService; 18 import cn.iocoder.yudao.coreservice.modules.pay.service.notify.PayNotifyCoreService;
19 import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; 19 import cn.iocoder.yudao.coreservice.modules.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
20 import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService; 20 import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
  21 +
21 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO; 22 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
22 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; 23 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
23 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; 24 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
@@ -26,6 +27,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -26,6 +27,7 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
26 import cn.iocoder.yudao.framework.pay.config.PayProperties; 27 import cn.iocoder.yudao.framework.pay.config.PayProperties;
27 import cn.iocoder.yudao.framework.pay.core.client.PayClient; 28 import cn.iocoder.yudao.framework.pay.core.client.PayClient;
28 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; 29 import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
  30 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
29 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; 31 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
30 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 32 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
31 import lombok.extern.slf4j.Slf4j; 33 import lombok.extern.slf4j.Slf4j;
@@ -135,9 +137,11 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @@ -135,9 +137,11 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
135 // 调用三方接口 137 // 调用三方接口
136 PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO); 138 PayOrderUnifiedReqDTO unifiedOrderReqDTO = PayOrderCoreConvert.INSTANCE.convert2(reqDTO);
137 // 商户相关字段 139 // 商户相关字段
  140 + //TODO jason @芋艿 是否加一个属性 如tradeNo 支付订单号, 用这个merchantOrderId让人迷糊
138 unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性! 141 unifiedOrderReqDTO.setMerchantOrderId(orderExtension.getNo()) // 注意,此处使用的是 PayOrderExtensionDO.no 属性!
139 .setSubject(order.getSubject()).setBody(order.getBody()) 142 .setSubject(order.getSubject()).setBody(order.getBody())
140 - .setNotifyUrl(genChannelPayNotifyUrl(channel)); 143 + .setNotifyUrl(genChannelPayNotifyUrl(channel))
  144 + .setReturnUrl(genChannelReturnUrl(channel));
141 // 订单相关字段 145 // 订单相关字段
142 unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime()); 146 unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime());
143 CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO); 147 CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO);
@@ -150,6 +154,16 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @@ -150,6 +154,16 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
150 } 154 }
151 155
152 /** 156 /**
  157 + * 根据支付渠道的编码,生成支付渠道的返回地址
  158 + * @param channel
  159 + * @return
  160 + */
  161 + private String genChannelReturnUrl(PayChannelDO channel) {
  162 + return payProperties.getReturnUrl() + "/" + StrUtil.replace(channel.getCode(), "_", "-")
  163 + + "/" + channel.getId();
  164 + }
  165 +
  166 + /**
153 * 根据支付渠道的编码,生成支付渠道的回调地址 167 * 根据支付渠道的编码,生成支付渠道的回调地址
154 * 168 *
155 * @param channel 支付渠道 169 * @param channel 支付渠道
@@ -181,9 +195,9 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @@ -181,9 +195,9 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
181 195
182 @Override 196 @Override
183 @Transactional 197 @Transactional
184 - public void notifyPayOrder(Long channelId, String channelCode, String notifyData) throws Exception { 198 + public void notifyPayOrder(Long channelId, String channelCode, NotifyDataDTO notifyData) throws Exception {
185 // TODO 芋艿,记录回调日志 199 // TODO 芋艿,记录回调日志
186 - log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData); 200 + log.info("[notifyPayOrder][channelId({}) 回调数据({})]", channelId, notifyData.getOrigData());
187 201
188 // 校验支付渠道是否有效 202 // 校验支付渠道是否有效
189 PayChannelDO channel = payChannelCoreService.validPayChannel(channelId); 203 PayChannelDO channel = payChannelCoreService.validPayChannel(channelId);
@@ -193,6 +207,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @@ -193,6 +207,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
193 log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId()); 207 log.error("[notifyPayOrder][渠道编号({}) 找不到对应的支付客户端]", channel.getId());
194 throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND); 208 throw exception(PAY_CHANNEL_CLIENT_NOT_FOUND);
195 } 209 }
  210 + //TODO @jason 校验 是否支付宝调用。 使用 支付宝publickey 或者payclient 加一个校验方法
196 // 解析支付结果 211 // 解析支付结果
197 PayOrderNotifyRespDTO notifyRespDTO = client.parseOrderNotify(notifyData); 212 PayOrderNotifyRespDTO notifyRespDTO = client.parseOrderNotify(notifyData);
198 213
@@ -207,9 +222,10 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService { @@ -207,9 +222,10 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
207 throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); 222 throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
208 } 223 }
209 // 1.2 更新 PayOrderExtensionDO 224 // 1.2 更新 PayOrderExtensionDO
  225 + //TODO @jason notifyRespDTO.getTradeStatus() 需要根据不同的状态更新成不同的值 PayOrderStatusEnum
210 int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(), 226 int updateCounts = payOrderExtensionCoreMapper.updateByIdAndStatus(orderExtension.getId(),
211 PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId()) 227 PayOrderStatusEnum.WAITING.getStatus(), PayOrderExtensionDO.builder().id(orderExtension.getId())
212 - .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData).build()); 228 + .status(PayOrderStatusEnum.SUCCESS.getStatus()).channelNotifyData(notifyData.getOrigData()).build());
213 if (updateCounts == 0) { // 校验状态,必须是待支付 229 if (updateCounts == 0) { // 校验状态,必须是待支付
214 throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING); 230 throw exception(PAY_ORDER_EXTENSION_STATUS_IS_NOT_WAITING);
215 } 231 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/PayProperties.java
@@ -29,4 +29,11 @@ public class PayProperties { @@ -29,4 +29,11 @@ public class PayProperties {
29 @URL(message = "退款回调地址的格式必须是 URL") 29 @URL(message = "退款回调地址的格式必须是 URL")
30 private String refundNotifyUrl; 30 private String refundNotifyUrl;
31 31
  32 +
  33 + /**
  34 + * 支付完成的返回地址
  35 + */
  36 + @URL(message = "支付返回的地址的格式必须是 URL")
  37 + private String returnUrl;
  38 +
32 } 39 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
1 package cn.iocoder.yudao.framework.pay.core.client; 1 package cn.iocoder.yudao.framework.pay.core.client;
2 2
  3 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
3 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; 4 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
4 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 5 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
5 6
@@ -32,6 +33,6 @@ public interface PayClient { @@ -32,6 +33,6 @@ public interface PayClient {
32 * @return 解析结果 33 * @return 解析结果
33 * @throws Exception 解析失败,抛出异常 34 * @throws Exception 解析失败,抛出异常
34 */ 35 */
35 - PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception; 36 + PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception;
36 37
37 } 38 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/NotifyDataDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.pay.core.client.dto;
  2 +
  3 +import lombok.Builder;
  4 +import lombok.Data;
  5 +import lombok.ToString;
  6 +
  7 +import java.util.Map;
  8 +
  9 +@Data
  10 +@ToString
  11 +@Builder
  12 +public class NotifyDataDTO {
  13 +
  14 + private String origData;
  15 + //1:xml 2:form
  16 + private int format;
  17 +
  18 + //form 格式的 data;
  19 + private Map<String,String> params;
  20 +}
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderNotifyRespDTO.java
@@ -42,4 +42,14 @@ public class PayOrderNotifyRespDTO { @@ -42,4 +42,14 @@ public class PayOrderNotifyRespDTO {
42 */ 42 */
43 private String data; 43 private String data;
44 44
  45 +
  46 + /**
  47 + * TODO @jason 结合其他的渠道定义成枚举,
  48 + * alipay
  49 + * TRADE_CLOSED,未付款交易超时关闭,或支付完成后全额退款。
  50 + * TRADE_SUCCESS, 交易支付成功
  51 + * TRADE_FINISHED 交易结束,不可退款。
  52 + */
  53 + private String tradeStatus;
  54 +
45 } 55 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/PayOrderUnifiedReqDTO.java
@@ -50,6 +50,9 @@ public class PayOrderUnifiedReqDTO { @@ -50,6 +50,9 @@ public class PayOrderUnifiedReqDTO {
50 @URL(message = "支付结果的回调地址必须是 URL 格式") 50 @URL(message = "支付结果的回调地址必须是 URL 格式")
51 private String notifyUrl; 51 private String notifyUrl;
52 52
  53 + @URL(message = "支付结果的return 必须是 URL 格式")
  54 + private String returnUrl;
  55 +
53 // ========== 订单相关字段 ========== 56 // ========== 订单相关字段 ==========
54 57
55 /** 58 /**
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayCodeMapping.java
@@ -18,6 +18,10 @@ public class AlipayPayCodeMapping extends AbstractPayCodeMapping { @@ -18,6 +18,10 @@ public class AlipayPayCodeMapping extends AbstractPayCodeMapping {
18 if (Objects.equals(apiCode, "10000")) { 18 if (Objects.equals(apiCode, "10000")) {
19 return GlobalErrorCodeConstants.SUCCESS; 19 return GlobalErrorCodeConstants.SUCCESS;
20 } 20 }
  21 + // alipay wap api code 返回为null, 暂时定为-9999
  22 + if(Objects.equals(apiCode, "-9999")){
  23 + return GlobalErrorCodeConstants.SUCCESS;
  24 + }
21 return null; 25 return null;
22 } 26 }
23 27
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClient.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2
3 import cn.hutool.core.bean.BeanUtil; 3 import cn.hutool.core.bean.BeanUtil;
4 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; 4 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
  5 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
5 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; 6 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
6 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
7 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 8 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@@ -68,7 +69,7 @@ public class AlipayQrPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt; @@ -68,7 +69,7 @@ public class AlipayQrPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt;
68 } 69 }
69 70
70 @Override 71 @Override
71 - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception { 72 + public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception {
72 // TODO 芋艿:待完成 73 // TODO 芋艿:待完成
73 return null; 74 return null;
74 } 75 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayWapPayClient.java
1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; 1 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2
3 import cn.hutool.core.bean.BeanUtil; 3 import cn.hutool.core.bean.BeanUtil;
  4 +import cn.hutool.core.date.DateUtil;
4 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; 5 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
  6 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
5 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; 7 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
6 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 8 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
7 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 9 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@@ -14,6 +16,9 @@ import com.alipay.api.request.AlipayTradeWapPayRequest; @@ -14,6 +16,9 @@ import com.alipay.api.request.AlipayTradeWapPayRequest;
14 import com.alipay.api.response.AlipayTradeWapPayResponse; 16 import com.alipay.api.response.AlipayTradeWapPayResponse;
15 import lombok.SneakyThrows; 17 import lombok.SneakyThrows;
16 18
  19 +import java.util.Map;
  20 +import java.util.Objects;
  21 +
17 /** 22 /**
18 * 支付宝【手机网站】的 PayClient 实现类 23 * 支付宝【手机网站】的 PayClient 实现类
19 * 文档:https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay 24 * 文档:https://opendocs.alipay.com/apis/api_1/alipay.trade.wap.pay
@@ -45,12 +50,15 @@ public class AlipayWapPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt; @@ -45,12 +50,15 @@ public class AlipayWapPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt;
45 model.setBody(reqDTO.getBody()); 50 model.setBody(reqDTO.getBody());
46 model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString()); 51 model.setTotalAmount(calculateAmount(reqDTO.getAmount()).toString());
47 model.setProductCode("QUICK_WAP_PAY"); // TODO 芋艿:这里咋整 52 model.setProductCode("QUICK_WAP_PAY"); // TODO 芋艿:这里咋整
48 - model.setSellerId("2088102147948060"); // TODO 芋艿:这里咋整  
49 - // TODO 芋艿:userIp + expireTime 53 + //TODO 芋艿:这里咋整 jason @芋艿 可以去掉吧,
  54 + //model.setSellerId("2088102147948060");
  55 + model.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(),"yyyy-MM-dd HH:mm:ss"));
  56 + // TODO 芋艿:userIp
50 // 构建 AlipayTradeWapPayRequest 57 // 构建 AlipayTradeWapPayRequest
51 AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest(); 58 AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
52 request.setBizModel(model); 59 request.setBizModel(model);
53 - 60 + request.setNotifyUrl(reqDTO.getNotifyUrl());
  61 + request.setReturnUrl(reqDTO.getReturnUrl());
54 // 执行请求 62 // 执行请求
55 AlipayTradeWapPayResponse response; 63 AlipayTradeWapPayResponse response;
56 try { 64 try {
@@ -58,13 +66,30 @@ public class AlipayWapPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt; @@ -58,13 +66,30 @@ public class AlipayWapPayClient extends AbstractPayClient&lt;AlipayPayClientConfig&gt;
58 } catch (AlipayApiException e) { 66 } catch (AlipayApiException e) {
59 return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping); 67 return PayCommonResult.build(e.getErrCode(), e.getErrMsg(), null, codeMapping);
60 } 68 }
61 -// TODO 芋艿:sub Code  
62 - return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping); 69 +
  70 + // TODO 芋艿:sub Code
  71 + if(response.isSuccess() && Objects.isNull(response.getCode()) && Objects.nonNull(response.getBody())){
  72 + //成功alipay wap 成功 code 为 null , body 为form 表单
  73 + return PayCommonResult.build("-9999", "Success", response, codeMapping);
  74 + }else {
  75 + return PayCommonResult.build(response.getCode(), response.getMsg(), response, codeMapping);
  76 + }
63 } 77 }
64 78
  79 +
  80 + /**
  81 + * //https://opendocs.alipay.com/open/203/105286
  82 + * @param data 通知结果
  83 + * @return
  84 + * @throws Exception
  85 + */
65 @Override 86 @Override
66 - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws Exception {  
67 - // TODO 芋艿:待完成  
68 - return null; 87 + public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws Exception {
  88 + Map<String, String> params = data.getParams();
  89 + return PayOrderNotifyRespDTO.builder().orderExtensionNo(params.get("out_trade_no"))
  90 + .channelOrderNo(params.get("trade_no")).channelUserId(params.get("seller_id"))
  91 + .tradeStatus(params.get("trade_status"))
  92 + .successTime(DateUtil.parse(params.get("notify_time"), "yyyy-MM-dd HH:mm:ss"))
  93 + .data(data.getOrigData()).build();
69 } 94 }
70 } 95 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPubPayClient.java
@@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil; @@ -8,6 +8,7 @@ import cn.hutool.core.util.StrUtil;
8 import cn.iocoder.yudao.framework.common.util.io.FileUtils; 8 import cn.iocoder.yudao.framework.common.util.io.FileUtils;
9 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; 9 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
10 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult; 10 import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
  11 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
11 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO; 12 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderNotifyRespDTO;
12 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO; 13 import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
13 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; 14 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@@ -131,14 +132,14 @@ public class WXPubPayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; { @@ -131,14 +132,14 @@ public class WXPubPayClient extends AbstractPayClient&lt;WXPayClientConfig&gt; {
131 } 132 }
132 133
133 @Override 134 @Override
134 - public PayOrderNotifyRespDTO parseOrderNotify(String data) throws WxPayException {  
135 - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data); 135 + public PayOrderNotifyRespDTO parseOrderNotify(NotifyDataDTO data) throws WxPayException {
  136 + WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getOrigData());
136 Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); 137 Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");
137 // 转换结果 138 // 转换结果
138 return PayOrderNotifyRespDTO.builder().orderExtensionNo(notifyResult.getOutTradeNo()) 139 return PayOrderNotifyRespDTO.builder().orderExtensionNo(notifyResult.getOutTradeNo())
139 .channelOrderNo(notifyResult.getTransactionId()).channelUserId(notifyResult.getOpenid()) 140 .channelOrderNo(notifyResult.getTransactionId()).channelUserId(notifyResult.getOpenid())
140 .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) 141 .successTime(DateUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))
141 - .data(data).build(); 142 + .data(data.getOrigData()).build();
142 } 143 }
143 144
144 } 145 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/pay/controller/order/PayOrderController.java
@@ -6,17 +6,21 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreServic @@ -6,17 +6,21 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreServic
6 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO; 6 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
7 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO; 7 import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
8 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 8 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  9 +import cn.iocoder.yudao.framework.pay.core.client.dto.NotifyDataDTO;
9 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 10 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
10 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO; 11 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitReqVO;
11 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO; 12 import cn.iocoder.yudao.userserver.modules.pay.controller.order.vo.PayOrderSubmitRespVO;
12 import io.swagger.annotations.Api; 13 import io.swagger.annotations.Api;
13 import io.swagger.annotations.ApiOperation; 14 import io.swagger.annotations.ApiOperation;
14 import lombok.extern.slf4j.Slf4j; 15 import lombok.extern.slf4j.Slf4j;
  16 +import org.springframework.http.MediaType;
15 import org.springframework.validation.annotation.Validated; 17 import org.springframework.validation.annotation.Validated;
16 import org.springframework.web.bind.annotation.*; 18 import org.springframework.web.bind.annotation.*;
17 19
18 import javax.annotation.Resource; 20 import javax.annotation.Resource;
19 21
  22 +import java.util.Map;
  23 +
20 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
21 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 25 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
22 26
@@ -54,7 +58,7 @@ public class PayOrderController { @@ -54,7 +58,7 @@ public class PayOrderController {
54 @ApiOperation("通知微信公众号支付的结果") 58 @ApiOperation("通知微信公众号支付的结果")
55 public String notifyWxPayOrder(@PathVariable("channelId") Long channelId, 59 public String notifyWxPayOrder(@PathVariable("channelId") Long channelId,
56 @RequestBody String xmlData) throws Exception { 60 @RequestBody String xmlData) throws Exception {
57 - payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.WX_PUB.getCode(), xmlData); 61 + payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.WX_PUB.getCode(), NotifyDataDTO.builder().origData(xmlData).build());
58 return "success"; 62 return "success";
59 } 63 }
60 64
@@ -72,4 +76,27 @@ public class PayOrderController { @@ -72,4 +76,27 @@ public class PayOrderController {
72 return "success"; 76 return "success";
73 } 77 }
74 78
  79 + @PostMapping(value = "/notify/alipay-wap/{channelId}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
  80 + @ApiOperation("支付宝wap页面回调")
  81 + public String notifyAliPayWapPayOrder(@PathVariable("channelId") Long channelId,
  82 + @RequestParam Map<String, String> params,
  83 + @RequestBody String originData) throws Exception {
  84 + //TODO @jason 校验 是否支付宝调用。 使用 支付宝publickey payclient 或许加一个校验方法
  85 + payOrderCoreService.notifyPayOrder(channelId, PayChannelEnum.ALIPAY_WAP.getCode(), NotifyDataDTO.builder().params(params).origData(originData).build());
  86 + return "success";
  87 + }
  88 +
  89 + /**
  90 + * 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
  91 + * @param channelId
  92 + * @return
  93 + * @throws Exception
  94 + */
  95 + @GetMapping(value = "/return/alipay-wap/{channelId}")
  96 + @ApiOperation("支付宝wap页面回跳")
  97 + public String returnAliPayWapPayOrder(@PathVariable("channelId") Long channelId){
  98 + //TODO @jason 校验 是否支付宝调用。 支付宝publickey 可以根据 appId 跳转不同的页面
  99 + return "支付成功";
  100 + }
  101 +
75 } 102 }
yudao-user-server/src/main/resources/application-local.yaml
@@ -153,5 +153,6 @@ yudao: @@ -153,5 +153,6 @@ yudao:
153 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 153 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
154 demo: false # 关闭演示模式 154 demo: false # 关闭演示模式
155 pay: 155 pay:
156 - pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify  
157 - refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify 156 + pay-notify-url: http://jg6rde.natappfree.cc/api/pay/order/notify
  157 + refund-notify-url: http://jg6rde.natappfree.cc/api/pay/refund/notify
  158 + return-url: http://jg6rde.natappfree.cc/api/pay/order/return
yudao-user-server/src/main/resources/static/pay_alipay_wap.html 0 → 100644
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
  6 + <title>支付测试页</title>
  7 + <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
  8 +</head>
  9 +<body>
  10 +<div>点击如下按钮,发起支付的测试</div>
  11 +<div>
  12 + <button id="alipay_wap">支付宝h5</button>
  13 +</div>
  14 +<div id="dynamic_form"></div>
  15 +</body>
  16 +<script>
  17 + let shopOrderId = undefined;
  18 + let payOrderId = undefined;
  19 + let server = 'http://127.0.0.1:28080';
  20 + //let server = 'http://niubi.natapp1.cc';
  21 + // TODO openid
  22 + //let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0";
  23 + $(function() {
  24 + // 自动发起商城订单编号
  25 + $.ajax({
  26 + url: server + "/api/shop/order/create",
  27 + method: 'POST',
  28 + success: function( result ) {
  29 + if (result.code !== 0) {
  30 + alert('创建商城订单失败,原因:' + result.msg)
  31 + return;
  32 + }
  33 + shopOrderId = result.data.id;
  34 + payOrderId = result.data.payOrderId;
  35 + console.log("商城订单:" + shopOrderId)
  36 + console.log("支付订单:" + payOrderId)
  37 + }
  38 + })
  39 + });
  40 + // 微信公众号
  41 + $( "#alipay_wap").on( "click", function() {
  42 + // 提交支付
  43 + $.ajax({
  44 + url: server + "/api/pay/order/submit",
  45 + method: 'POST',
  46 + dataType: "json",
  47 + contentType: "application/json",
  48 + data: JSON.stringify({
  49 + "id": payOrderId,
  50 + "channelCode": 'alipay_wap'
  51 + }),
  52 + success: function( result ) {
  53 + if (result.code !== 0) {
  54 + alert('提交支付订单失败,原因:' + result.msg)
  55 + return;
  56 + }
  57 + alert('点击确定,开始支付');
  58 + // 开始调用微信支付
  59 + let data = result.data.invokeResponse;
  60 + $("#dynamic_form").html(data.body);
  61 + }
  62 + })
  63 + });
  64 +</script>
  65 +</html>