mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 17:21:53 +08:00
增加支付回调地址的配置
This commit is contained in:
parent
1b0aaec9ab
commit
20628987c9
@ -2,6 +2,7 @@ package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
|||||||
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayOrderCoreConvert;
|
import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayOrderCoreConvert;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
|
||||||
@ -19,6 +20,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmit
|
|||||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import cn.iocoder.yudao.framework.pay.config.PayProperties;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
|
||||||
@ -43,6 +45,9 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU
|
|||||||
@Slf4j
|
@Slf4j
|
||||||
public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private PayProperties payProperties;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private PayAppCoreService payAppCoreService;
|
private PayAppCoreService payAppCoreService;
|
||||||
@Resource
|
@Resource
|
||||||
@ -125,7 +130,7 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
|||||||
// 商户相关字段
|
// 商户相关字段
|
||||||
unifiedOrderReqDTO.setMerchantOrderId(order.getMerchantOrderId())
|
unifiedOrderReqDTO.setMerchantOrderId(order.getMerchantOrderId())
|
||||||
.setSubject(order.getSubject()).setBody(order.getBody())
|
.setSubject(order.getSubject()).setBody(order.getBody())
|
||||||
.setNotifyUrl(app.getPayNotifyUrl());
|
.setNotifyUrl(genChannelPayNotifyUrl(reqDTO.getChannelCode()));
|
||||||
// 订单相关字段
|
// 订单相关字段
|
||||||
unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime());
|
unifiedOrderReqDTO.setAmount(order.getAmount()).setExpireTime(order.getExpireTime());
|
||||||
CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO);
|
CommonResult<?> unifiedOrderResult = client.unifiedOrder(unifiedOrderReqDTO);
|
||||||
@ -137,6 +142,17 @@ public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
|||||||
.setInvokeResponse(unifiedOrderResult.getData());
|
.setInvokeResponse(unifiedOrderResult.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据支付渠道的编码,生成支付渠道的回调地址
|
||||||
|
*
|
||||||
|
* @param channelCode 支付渠道的编码
|
||||||
|
* @return 支付渠道的回调地址
|
||||||
|
*/
|
||||||
|
private String genChannelPayNotifyUrl(String channelCode) {
|
||||||
|
// _ 转化为 - 的原因,是因为 URL 我们统一采用中划线的原则
|
||||||
|
return payProperties.getPayNotifyUrl() + "/" + StrUtil.replace(channelCode, "_", "-");
|
||||||
|
}
|
||||||
|
|
||||||
private String generateOrderExtensionNo() {
|
private String generateOrderExtensionNo() {
|
||||||
// wx
|
// wx
|
||||||
// 2014
|
// 2014
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
package cn.iocoder.yudao.framework.pay.config;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.URL;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "yudao.pay")
|
||||||
|
@Validated
|
||||||
|
@Data
|
||||||
|
public class PayProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付回调地址
|
||||||
|
* 注意,支付渠道统一回调到 payNotifyUrl 地址,由支付模块统一处理;然后,自己的支付模块,在回调 PayAppDO.payNotifyUrl 地址
|
||||||
|
*/
|
||||||
|
@NotEmpty(message = "支付回调地址不能为空")
|
||||||
|
@URL(message = "支付回调地址的格式必须是 URL")
|
||||||
|
private String payNotifyUrl;
|
||||||
|
/**
|
||||||
|
* 退款回调地址
|
||||||
|
* 注意点,同 {@link #payNotifyUrl} 属性
|
||||||
|
*/
|
||||||
|
@NotNull(message = "短信发送频率不能为空")
|
||||||
|
@URL(message = "退款回调地址的格式必须是 URL")
|
||||||
|
private String refundNotifyUrl;
|
||||||
|
|
||||||
|
}
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.config;
|
|||||||
|
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
import cn.iocoder.yudao.framework.pay.core.client.impl.PayClientFactoryImpl;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@EnableConfigurationProperties(PayProperties.class)
|
||||||
public class YudaoPayAutoConfiguration {
|
public class YudaoPayAutoConfiguration {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -8,6 +8,7 @@ import javax.validation.constraints.DecimalMin;
|
|||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 统一下单 Request DTO
|
* 统一下单 Request DTO
|
||||||
@ -63,6 +64,11 @@ public class PayOrderUnifiedReqDTO {
|
|||||||
private Date expireTime;
|
private Date expireTime;
|
||||||
|
|
||||||
// ========== 拓展参数 ==========
|
// ========== 拓展参数 ==========
|
||||||
// TODO 芋艿:待完善
|
/**
|
||||||
|
* 支付渠道的额外参数
|
||||||
|
*
|
||||||
|
* 例如说,微信公众号需要传递 openid 参数
|
||||||
|
*/
|
||||||
|
private Map<String, String> channelExtras;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
|
|||||||
|
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.date.DateUtil;
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
@ -94,7 +95,7 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
|
|||||||
.totalFee(reqDTO.getAmount().intValue()) // 单位分
|
.totalFee(reqDTO.getAmount().intValue()) // 单位分
|
||||||
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"))
|
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"))
|
||||||
.spbillCreateIp(reqDTO.getUserIp())
|
.spbillCreateIp(reqDTO.getUserIp())
|
||||||
.openid("ockUAwIZ-0OeMZl9ogcZ4ILrGba0") // TODO 芋艿:先随便写死
|
.openid(getOpenid(reqDTO))
|
||||||
.notifyUrl(reqDTO.getNotifyUrl())
|
.notifyUrl(reqDTO.getNotifyUrl())
|
||||||
.build();
|
.build();
|
||||||
// 执行请求
|
// 执行请求
|
||||||
@ -109,11 +110,20 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
|
|||||||
request.setDescription(reqDTO.getBody());
|
request.setDescription(reqDTO.getBody());
|
||||||
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
|
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
|
||||||
request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"));
|
request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"));
|
||||||
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid("ockUAwIZ-0OeMZl9ogcZ4ILrGba0")); // TODO 芋艿:先随便写死
|
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
|
||||||
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
|
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
|
||||||
request.setNotifyUrl(reqDTO.getNotifyUrl());
|
request.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||||
// 执行请求
|
// 执行请求
|
||||||
return client.createOrderV3(TradeTypeEnum.JSAPI, request);
|
return client.createOrderV3(TradeTypeEnum.JSAPI, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {
|
||||||
|
String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");
|
||||||
|
if (StrUtil.isEmpty(openid)) {
|
||||||
|
throw new IllegalArgumentException("支付请求的 openid 不能为空!");
|
||||||
|
}
|
||||||
|
return openid;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ public class PayOrderController {
|
|||||||
@PostMapping("/submit")
|
@PostMapping("/submit")
|
||||||
@ApiOperation("提交支付订单")
|
@ApiOperation("提交支付订单")
|
||||||
// @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好
|
// @PreAuthenticated // TODO 暂时不加登陆验证,前端暂时没做好
|
||||||
public CommonResult<PayOrderSubmitRespVO> submit(@RequestBody PayOrderSubmitReqVO reqVO) {
|
public CommonResult<PayOrderSubmitRespVO> submitPayOrder(@RequestBody PayOrderSubmitReqVO reqVO) {
|
||||||
// 获得订单
|
// 获得订单
|
||||||
PayOrderDO payOrder = payOrderCoreService.getPayOrder(reqVO.getId());
|
PayOrderDO payOrder = payOrderCoreService.getPayOrder(reqVO.getId());
|
||||||
|
|
||||||
@ -47,4 +47,13 @@ public class PayOrderController {
|
|||||||
return success(PayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build());
|
return success(PayOrderSubmitRespVO.builder().invokeResponse(respDTO.getInvokeResponse()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 支付渠道的回调 ==========
|
||||||
|
|
||||||
|
@PostMapping("/notify/wx-pub")
|
||||||
|
@ApiOperation("通知微信公众号的结果")
|
||||||
|
public String notifyWxPayOrder(@RequestBody String xmlData) {
|
||||||
|
System.out.println(xmlData);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,3 +138,6 @@ yudao:
|
|||||||
- ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
|
- ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
|
||||||
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
|
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
|
||||||
demo: true # 开启演示模式
|
demo: true # 开启演示模式
|
||||||
|
pay:
|
||||||
|
pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
|
||||||
|
refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
|
||||||
|
@ -152,3 +152,6 @@ yudao:
|
|||||||
- ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
|
- ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
|
||||||
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
|
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
|
||||||
demo: false # 关闭演示模式
|
demo: false # 关闭演示模式
|
||||||
|
pay:
|
||||||
|
pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
|
||||||
|
refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
let payOrderId = undefined;
|
let payOrderId = undefined;
|
||||||
// let server = 'http://127.0.0.1:28080';
|
// let server = 'http://127.0.0.1:28080';
|
||||||
let server = 'http://niubi.natapp1.cc';
|
let server = 'http://niubi.natapp1.cc';
|
||||||
|
// TODO openid
|
||||||
|
let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0";
|
||||||
$(function() {
|
$(function() {
|
||||||
// 获得 JsapiTicket
|
// 获得 JsapiTicket
|
||||||
// 参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档
|
// 参考 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html 文档
|
||||||
@ -73,6 +75,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 提交支付
|
// 提交支付
|
||||||
|
// 参考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6 文档
|
||||||
|
// 参考 https://segmentfault.com/a/1190000020704650 文档
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: server + "/api/pay/order/submit",
|
url: server + "/api/pay/order/submit",
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -81,6 +85,9 @@
|
|||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
"id": payOrderId,
|
"id": payOrderId,
|
||||||
"channelCode": 'wx_pub',
|
"channelCode": 'wx_pub',
|
||||||
|
"channelExtras": {
|
||||||
|
"openid": openid
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
success: function( result ) {
|
success: function( result ) {
|
||||||
if (result.code !== 0) {
|
if (result.code !== 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user