Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
T
travel-cloud
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
cloud
travel-cloud
Commits
21c4dadf
提交
21c4dadf
authored
12月 31, 2024
作者:
hzh
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
微信退款功能部分实现
上级
df38e8f4
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
227 行增加
和
26 行删除
+227
-26
WechatPayConfiguration.java
...org/dromara/common/pay/config/WechatPayConfiguration.java
+5
-0
JsapiRefundNotifyModel.java
...org/dromara/common/pay/domain/JsapiRefundNotifyModel.java
+14
-0
IWxPayService.java
...in/java/org/dromara/common/pay/service/IWxPayService.java
+21
-1
WxPayServiceImpl.java
...org/dromara/common/pay/service/impl/WxPayServiceImpl.java
+57
-2
OrderController.java
...in/java/org/dromara/order/controller/OrderController.java
+69
-23
IOrderPayService.java
...main/java/org/dromara/order/service/IOrderPayService.java
+17
-0
WeChatOrderPayServiceImpl.java
...dromara/order/service/impl/WeChatOrderPayServiceImpl.java
+44
-0
没有找到文件。
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/config/WechatPayConfiguration.java
浏览文件 @
21c4dadf
...
@@ -53,5 +53,10 @@ public class WechatPayConfiguration {
...
@@ -53,5 +53,10 @@ public class WechatPayConfiguration {
* 回调函数的接口路径
* 回调函数的接口路径
*/
*/
private
String
notify
;
private
String
notify
;
/**
* 退款回调函数的接口路径
*/
private
String
refundNotify
;
}
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/domain/JsapiRefundNotifyModel.java
0 → 100644
浏览文件 @
21c4dadf
package
org
.
dromara
.
common
.
pay
.
domain
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
/**
* @author hzh
* @date 2024-12-31
* @desc jsapi退款回调模型
**/
@Data
@Accessors
(
chain
=
true
)
public
class
JsapiRefundNotifyModel
{
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/service/IWxPayService.java
浏览文件 @
21c4dadf
...
@@ -3,6 +3,7 @@ package org.dromara.common.pay.service;
...
@@ -3,6 +3,7 @@ package org.dromara.common.pay.service;
import
com.ijpay.wxpay.model.v3.RefundModel
;
import
com.ijpay.wxpay.model.v3.RefundModel
;
import
com.ijpay.wxpay.model.v3.UnifiedOrderModel
;
import
com.ijpay.wxpay.model.v3.UnifiedOrderModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiRefundNotifyModel
;
/**
/**
* @author wenhe
* @author wenhe
...
@@ -55,13 +56,32 @@ public interface IWxPayService {
...
@@ -55,13 +56,32 @@ public interface IWxPayService {
*/
*/
JsapiNotifyModel
notify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
);
JsapiNotifyModel
notify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
);
/**
* 退款回调
*
* @param timestamp 时间搓
* @param nonce nonce
* @param serialNo serialNo
* @param signature 签名
* @param result 支付通知密文
* @return 退款通知明文
*/
JsapiRefundNotifyModel
refundNotify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
);
/**
/**
* 退款
* 退款
*
* @param model model
* @param model model
* @return 退款结果
* @return 退款结果
* @throws Exception 异常
* @throws Exception 异常
*/
*/
org
.
dromara
.
common
.
pay
.
domain
.
RefundModel
refund
(
RefundModel
model
)
throws
Exception
;
org
.
dromara
.
common
.
pay
.
domain
.
RefundModel
refund
(
RefundModel
model
)
throws
Exception
;
/**
* 退款查询
*
* @param outRefundNo 退款单号
* @return 退款结果
*/
JsapiRefundNotifyModel
refundQuery
(
String
outRefundNo
);
}
}
ruoyi-common/ruoyi-common-pay/src/main/java/org/dromara/common/pay/service/impl/WxPayServiceImpl.java
浏览文件 @
21c4dadf
...
@@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
...
@@ -25,6 +25,7 @@ import lombok.extern.slf4j.Slf4j;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.dromara.common.pay.config.WechatPayConfiguration
;
import
org.dromara.common.pay.config.WechatPayConfiguration
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiRefundNotifyModel
;
import
org.dromara.common.pay.service.IWxPayService
;
import
org.dromara.common.pay.service.IWxPayService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
...
@@ -228,6 +229,29 @@ public class WxPayServiceImpl implements IWxPayService {
...
@@ -228,6 +229,29 @@ public class WxPayServiceImpl implements IWxPayService {
}
}
}
}
@Override
public
JsapiRefundNotifyModel
refundNotify
(
String
timestamp
,
String
nonce
,
String
serialNo
,
String
signature
,
String
result
)
{
log
.
info
(
"timestamp:{} nonce:{} serialNo:{} signature:{}"
,
timestamp
,
nonce
,
serialNo
,
signature
);
log
.
info
(
"退款通知密文 {}"
,
result
);
try
{
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
String
plainText
=
WxPayKit
.
verifyNotify
(
serialNo
,
result
,
signature
,
nonce
,
timestamp
,
config
.
getApiKey3
(),
config
.
getPlatformCertPath
()
);
log
.
info
(
"退款通知明文 {}"
,
plainText
);
return
JSON
.
parseObject
(
plainText
,
JsapiRefundNotifyModel
.
class
);
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
throw
new
RuntimeException
(
"系统异常!"
);
}
}
@Override
@Override
public
JsapiNotifyModel
query
(
String
outTradeNo
)
{
public
JsapiNotifyModel
query
(
String
outTradeNo
)
{
try
{
try
{
...
@@ -262,6 +286,37 @@ public class WxPayServiceImpl implements IWxPayService {
...
@@ -262,6 +286,37 @@ public class WxPayServiceImpl implements IWxPayService {
}
}
}
}
@Override
public
JsapiRefundNotifyModel
refundQuery
(
String
outRefundNo
)
{
try
{
log
.
info
(
"退款订单查询,退款单号:{}"
,
outRefundNo
);
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
RequestMethodEnum
.
GET
,
WxDomainEnum
.
CHINA
.
toString
(),
String
.
format
(
BasePayApiEnum
.
REFUND_QUERY_BY_OUT_REFUND_NO
.
toString
(),
outRefundNo
),
config
.
getMchId
(),
getSerialNumber
(),
null
,
config
.
getKeyPath
(),
Collections
.
emptyMap
());
log
.
info
(
"查询退款单:{} 查询响应 {}"
,
outRefundNo
,
response
);
if
(
response
.
getStatus
()
==
IJPayConstants
.
CODE_200
)
{
// 根据证书序列号查询对应的证书来验证签名结果
boolean
verifySignature
=
WxPayKit
.
verifySignature
(
response
,
config
.
getPlatformCertPath
());
log
.
info
(
"verifySignature: {}"
,
verifySignature
);
//验签成功
if
(
verifySignature
)
{
JSONObject
result
=
JSONUtil
.
parseObj
(
response
.
getBody
());
return
JSON
.
parseObject
(
JSON
.
toJSONString
(
result
),
JsapiRefundNotifyModel
.
class
);
}
}
throw
new
RuntimeException
(
"退款单:"
+
outRefundNo
+
"查询失败!"
);
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
throw
new
RuntimeException
(
"退款单:"
+
outRefundNo
+
"查询失败!"
);
}
}
@Override
@Override
public
Boolean
close
(
String
outTradeNo
)
{
public
Boolean
close
(
String
outTradeNo
)
{
try
{
try
{
...
@@ -280,7 +335,7 @@ public class WxPayServiceImpl implements IWxPayService {
...
@@ -280,7 +335,7 @@ public class WxPayServiceImpl implements IWxPayService {
JSONUtil
.
toJsonStr
(
params
));
JSONUtil
.
toJsonStr
(
params
));
log
.
info
(
"关闭订单:{} 查询响应 {}"
,
outTradeNo
,
response
);
log
.
info
(
"关闭订单:{} 查询响应 {}"
,
outTradeNo
,
response
);
if
(
response
.
getStatus
()
==
IJPayConstants
.
CODE_204
)
{
if
(
response
.
getStatus
()
==
IJPayConstants
.
CODE_204
)
{
return
true
;
return
true
;
}
}
throw
new
RuntimeException
(
"订单:"
+
outTradeNo
+
"关闭失败!"
);
throw
new
RuntimeException
(
"订单:"
+
outTradeNo
+
"关闭失败!"
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
...
@@ -291,7 +346,7 @@ public class WxPayServiceImpl implements IWxPayService {
...
@@ -291,7 +346,7 @@ public class WxPayServiceImpl implements IWxPayService {
@Override
@Override
public
org
.
dromara
.
common
.
pay
.
domain
.
RefundModel
refund
(
RefundModel
model
)
throws
Exception
{
public
org
.
dromara
.
common
.
pay
.
domain
.
RefundModel
refund
(
RefundModel
model
)
throws
Exception
{
model
.
setNotify_url
(
config
.
getNotify
());
model
.
setNotify_url
(
config
.
get
Domain
()
+
config
.
getRefund
Notify
());
log
.
info
(
"统一退款参数 {}"
,
JSONUtil
.
toJsonStr
(
model
));
log
.
info
(
"统一退款参数 {}"
,
JSONUtil
.
toJsonStr
(
model
));
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
IJPayHttpResponse
response
=
WxPayApi
.
v3
(
RequestMethodEnum
.
POST
,
RequestMethodEnum
.
POST
,
...
...
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/controller/OrderController.java
浏览文件 @
21c4dadf
...
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
...
@@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RestController;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.RequestContextHolder
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
org.springframework.web.context.request.ServletRequestAttributes
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.charset.StandardCharsets
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -50,33 +51,78 @@ public class OrderController extends BaseController {
...
@@ -50,33 +51,78 @@ public class OrderController extends BaseController {
Map
<
String
,
String
>
map
=
new
HashMap
<>(
12
);
Map
<
String
,
String
>
map
=
new
HashMap
<>(
12
);
try
{
try
{
log
.
info
(
"微信回调开始"
);
log
.
info
(
"微信
支付
回调开始"
);
jakarta
.
servlet
.
http
.
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
currentRequestAttributes
()).
getRequest
();
//获取请求参数
ImmutableMap
<
String
,
String
>
builder
=
getParams
();
ImmutableMap
<
String
,
String
>
builder
=
ImmutableMap
.<
String
,
String
>
builder
()
.
put
(
"timestamp"
,
request
.
getHeader
(
"Wechatpay-Timestamp"
))
.
put
(
"nonce"
,
request
.
getHeader
(
"Wechatpay-Nonce"
))
.
put
(
"serialNo"
,
request
.
getHeader
(
"Wechatpay-Serial"
))
.
put
(
"signature"
,
request
.
getHeader
(
"Wechatpay-Signature"
))
.
put
(
"result"
,
CustomHttpKit
.
readData
(
request
))
.
build
();
boolean
result
=
orderPayService
.
notify
(
JSON
.
toJSONString
(
new
HashMap
<>(
builder
)));
boolean
result
=
orderPayService
.
notify
(
JSON
.
toJSONString
(
new
HashMap
<>(
builder
)));
if
(
result
)
{
//设置响应参数
response
.
setStatus
(
200
);
setResponse
(
result
,
response
,
map
);
map
.
put
(
"code"
,
"SUCCESS"
);
}
catch
(
Exception
e
)
{
map
.
put
(
"message"
,
"SUCCESS"
);
log
.
error
(
"系统异常"
,
e
);
}
else
{
}
response
.
setStatus
(
500
);
}
map
.
put
(
"code"
,
"ERROR"
);
map
.
put
(
"message"
,
"签名错误"
);
/**
}
* 获取请求参数
*
response
.
setHeader
(
"Content-type"
,
ContentType
.
JSON
.
toString
());
* @return ImmutableMap<String, String> 请求参数
response
.
getOutputStream
().
write
(
JSONUtil
.
toJsonStr
(
map
).
getBytes
(
StandardCharsets
.
UTF_8
));
*/
response
.
flushBuffer
();
private
ImmutableMap
<
String
,
String
>
getParams
()
{
jakarta
.
servlet
.
http
.
HttpServletRequest
request
=
((
ServletRequestAttributes
)
RequestContextHolder
.
currentRequestAttributes
()).
getRequest
();
return
ImmutableMap
.<
String
,
String
>
builder
()
.
put
(
"timestamp"
,
request
.
getHeader
(
"Wechatpay-Timestamp"
))
.
put
(
"nonce"
,
request
.
getHeader
(
"Wechatpay-Nonce"
))
.
put
(
"serialNo"
,
request
.
getHeader
(
"Wechatpay-Serial"
))
.
put
(
"signature"
,
request
.
getHeader
(
"Wechatpay-Signature"
))
.
put
(
"result"
,
CustomHttpKit
.
readData
(
request
))
.
build
();
}
/**
* 设置响应参数
*
* @param result result
* @param response response
* @param map map
* @throws IOException IOException 异常信息
*/
private
void
setResponse
(
boolean
result
,
HttpServletResponse
response
,
Map
<
String
,
String
>
map
)
throws
IOException
{
if
(
result
)
{
response
.
setStatus
(
200
);
map
.
put
(
"code"
,
"SUCCESS"
);
map
.
put
(
"message"
,
"SUCCESS"
);
}
else
{
response
.
setStatus
(
500
);
map
.
put
(
"code"
,
"ERROR"
);
map
.
put
(
"message"
,
"签名错误"
);
}
response
.
setHeader
(
"Content-type"
,
ContentType
.
JSON
.
toString
());
response
.
getOutputStream
().
write
(
JSONUtil
.
toJsonStr
(
map
).
getBytes
(
StandardCharsets
.
UTF_8
));
response
.
flushBuffer
();
}
/**
* 退款函数
*
* @param response response
*/
@RequestMapping
(
value
=
"/v3/refundNotify"
,
method
=
{
RequestMethod
.
POST
,
RequestMethod
.
GET
})
public
void
refundNotify
(
HttpServletResponse
response
)
{
Map
<
String
,
String
>
map
=
new
HashMap
<>(
12
);
try
{
log
.
info
(
"微信退款回调开始"
);
//获取请求参数
ImmutableMap
<
String
,
String
>
builder
=
getParams
();
boolean
result
=
orderPayService
.
refundNotify
(
JSON
.
toJSONString
(
new
HashMap
<>(
builder
)));
setResponse
(
result
,
response
,
map
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
log
.
error
(
"系统异常"
,
e
);
}
}
...
...
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/IOrderPayService.java
浏览文件 @
21c4dadf
package
org
.
dromara
.
order
.
service
;
package
org
.
dromara
.
order
.
service
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiRefundNotifyModel
;
/**
/**
* @author hzh
* @author hzh
...
@@ -16,11 +17,27 @@ public interface IOrderPayService {
...
@@ -16,11 +17,27 @@ public interface IOrderPayService {
*/
*/
boolean
notify
(
String
body
);
boolean
notify
(
String
body
);
/**
* 退款回调
*
* @param body 回调参数
* @return 回调结果
*/
boolean
refundNotify
(
String
body
);
/**
/**
* 微信支付查询
* 微信支付查询
*
* @param outTradeNo 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* @param outTradeNo 【商户订单号】 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* @return 支付结果
* @return 支付结果
*/
*/
JsapiNotifyModel
query
(
String
outTradeNo
);
JsapiNotifyModel
query
(
String
outTradeNo
);
/**
* 退款查询
* @param outRefundNo 商户申请退款时传入的商户系统内部退款单号。
* @return 退款结果
*/
JsapiRefundNotifyModel
refundQuery
(
String
outRefundNo
);
}
}
ruoyi-modules/ruoyi-order/src/main/java/org/dromara/order/service/impl/WeChatOrderPayServiceImpl.java
浏览文件 @
21c4dadf
...
@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
...
@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.dubbo.config.annotation.DubboReference
;
import
org.apache.dubbo.config.annotation.DubboReference
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiNotifyModel
;
import
org.dromara.common.pay.domain.JsapiRefundNotifyModel
;
import
org.dromara.common.pay.service.IWxPayService
;
import
org.dromara.common.pay.service.IWxPayService
;
import
org.dromara.order.api.enums.OrderStatus
;
import
org.dromara.order.api.enums.OrderStatus
;
import
org.dromara.order.constant.WechatTradeState
;
import
org.dromara.order.constant.WechatTradeState
;
...
@@ -70,6 +71,40 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
...
@@ -70,6 +71,40 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
}
}
}
}
@GlobalTransactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
boolean
refundNotify
(
String
body
)
{
log
.
info
(
"微信退款回调参数:{}"
,
body
);
JSONObject
bodyJson
=
JSONObject
.
parseObject
(
body
);
try
{
JsapiRefundNotifyModel
model
=
wxPayService
.
refundNotify
(
bodyJson
.
getString
(
"timestamp"
),
bodyJson
.
getString
(
"nonce"
),
bodyJson
.
getString
(
"serialNo"
),
bodyJson
.
getString
(
"signature"
),
bodyJson
.
getString
(
"result"
)
);
//处理订单
dealRefundOrder
(
model
);
return
true
;
}
catch
(
Exception
e
)
{
log
.
error
(
"系统异常"
,
e
);
return
false
;
}
}
/**
* 处理退款订单
*
* @param model 退款回调参数
*/
private
void
dealRefundOrder
(
JsapiRefundNotifyModel
model
)
{
}
@GlobalTransactional
(
rollbackFor
=
Exception
.
class
)
@GlobalTransactional
(
rollbackFor
=
Exception
.
class
)
@Override
@Override
public
JsapiNotifyModel
query
(
String
outTradeNo
)
{
public
JsapiNotifyModel
query
(
String
outTradeNo
)
{
...
@@ -79,6 +114,15 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
...
@@ -79,6 +114,15 @@ public class WeChatOrderPayServiceImpl implements IOrderPayService {
return
model
;
return
model
;
}
}
@GlobalTransactional
(
rollbackFor
=
Exception
.
class
)
@Override
public
JsapiRefundNotifyModel
refundQuery
(
String
outRefundNo
)
{
JsapiRefundNotifyModel
model
=
wxPayService
.
refundQuery
(
outRefundNo
);
//处理退款订单
dealRefundOrder
(
model
);
return
model
;
}
private
void
dealOrder
(
JsapiNotifyModel
model
)
{
private
void
dealOrder
(
JsapiNotifyModel
model
)
{
//支付订单号
//支付订单号
String
orderPayNo
=
model
.
getOut_trade_no
();
String
orderPayNo
=
model
.
getOut_trade_no
();
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论