Commit 2c60a3aafa8f37b3fbbf6592c721bc811702b88b
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<AlipayPayClientConfig> | @@ -68,7 +69,7 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig> | ||
| 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<AlipayPayClientConfig> | @@ -45,12 +50,15 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig> | ||
| 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<AlipayPayClientConfig> | @@ -58,13 +66,30 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig> | ||
| 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<WXPayClientConfig> { | @@ -131,14 +132,14 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> { | ||
| 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> |