Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
liuxu0511
jeepay
提交
9e8d51da
jeepay
项目概览
liuxu0511
/
jeepay
与 Fork 源项目一致
Fork自
计全科技 / jeepay
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
jeepay
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
9e8d51da
编写于
6月 17, 2021
作者:
terrfly
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
添加退款补单和超时关闭; 添加查单控制器
上级
7e119aa2
变更
19
隐藏空白更改
内联
并排
Showing
19 changed file
with
582 addition
and
17 deletion
+582
-17
docs/sql/init.sql
docs/sql/init.sql
+2
-1
jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/RefundOrder.java
...main/java/com/jeequan/jeepay/core/entity/RefundOrder.java
+7
-1
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IRefundService.java
...n/java/com/jeequan/jeepay/pay/channel/IRefundService.java
+3
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/alipay/AlipayKit.java
...java/com/jeequan/jeepay/pay/channel/alipay/AlipayKit.java
+1
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/alipay/AlipayRefundService.java
...eequan/jeepay/pay/channel/alipay/AlipayRefundService.java
+35
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/QueryOrderController.java
...eequan/jeepay/pay/ctrl/payorder/QueryOrderController.java
+2
-2
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/refund/QueryRefundOrderController.java
...an/jeepay/pay/ctrl/refund/QueryRefundOrderController.java
+67
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/refund/RefundOrderController.java
...jeequan/jeepay/pay/ctrl/refund/RefundOrderController.java
+8
-4
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/QueryPayOrderRQ.java
...com/jeequan/jeepay/pay/rqrs/payorder/QueryPayOrderRQ.java
+3
-2
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/payorder/QueryPayOrderRS.java
...com/jeequan/jeepay/pay/rqrs/payorder/QueryPayOrderRS.java
+3
-2
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRQ.java
...om/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRQ.java
+37
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRS.java
...om/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRS.java
+128
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/RefundOrderRS.java
...ava/com/jeequan/jeepay/pay/rqrs/refund/RefundOrderRS.java
+0
-2
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/ChannelOrderReissueService.java
...eequan/jeepay/pay/service/ChannelOrderReissueService.java
+58
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java
...a/com/jeequan/jeepay/pay/service/PayMchNotifyService.java
+65
-3
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/task/RefundOrderExpiredTask.java
...a/com/jeequan/jeepay/pay/task/RefundOrderExpiredTask.java
+46
-0
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/task/RefundOrderReissueTask.java
...a/com/jeequan/jeepay/pay/task/RefundOrderReissueTask.java
+88
-0
jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java
...a/com/jeequan/jeepay/service/impl/RefundOrderService.java
+28
-0
jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/RefundOrderMapper.xml
...a/com/jeequan/jeepay/service/mapper/RefundOrderMapper.xml
+1
-0
未找到文件。
docs/sql/init.sql
浏览文件 @
9e8d51da
...
...
@@ -360,7 +360,7 @@ CREATE TABLE `t_refund_order` (
`pay_amount`
BIGINT
(
20
)
NOT
NULL
COMMENT
'支付金额,单位分'
,
`refund_amount`
BIGINT
(
20
)
NOT
NULL
COMMENT
'退款金额,单位分'
,
`currency`
VARCHAR
(
3
)
NOT
NULL
DEFAULT
'cny'
COMMENT
'三位货币代码,人民币:cny'
,
`state`
TINYINT
(
6
)
NOT
NULL
DEFAULT
'0'
COMMENT
'退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败'
,
`state`
TINYINT
(
6
)
NOT
NULL
DEFAULT
'0'
COMMENT
'退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败
,4-退款任务关闭
'
,
`client_ip`
VARCHAR
(
32
)
DEFAULT
NULL
COMMENT
'客户端IP'
,
`refund_reason`
VARCHAR
(
256
)
NOT
NULL
COMMENT
'退款原因'
,
`channel_order_no`
VARCHAR
(
32
)
DEFAULT
NULL
COMMENT
'渠道订单号'
,
...
...
@@ -370,6 +370,7 @@ CREATE TABLE `t_refund_order` (
`notify_url`
VARCHAR
(
128
)
DEFAULT
NULL
COMMENT
'通知地址'
,
`ext_param`
VARCHAR
(
64
)
DEFAULT
NULL
COMMENT
'扩展参数'
,
`success_time`
DATETIME
DEFAULT
NULL
COMMENT
'订单退款成功时间'
,
`expired_time`
DATETIME
DEFAULT
NULL
COMMENT
'退款失效时间(失效后系统更改为退款任务关闭状态)'
,
`created_at`
TIMESTAMP
(
6
)
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
(
6
)
COMMENT
'创建时间'
,
`updated_at`
TIMESTAMP
(
6
)
NOT
NULL
DEFAULT
CURRENT_TIMESTAMP
(
6
)
ON
UPDATE
CURRENT_TIMESTAMP
(
6
)
COMMENT
'更新时间'
,
PRIMARY
KEY
(
`refund_order_id`
),
...
...
jeepay-core/src/main/java/com/jeequan/jeepay/core/entity/RefundOrder.java
浏览文件 @
9e8d51da
...
...
@@ -43,6 +43,7 @@ public class RefundOrder extends BaseModel {
public
static
final
byte
STATE_ING
=
1
;
//退款中
public
static
final
byte
STATE_SUCCESS
=
2
;
//退款成功
public
static
final
byte
STATE_FAIL
=
3
;
//退款失败
public
static
final
byte
STATE_CLOSED
=
4
;
//退款任务关闭
public
static
final
LambdaQueryWrapper
<
RefundOrder
>
gw
(){
return
new
LambdaQueryWrapper
<>();
...
...
@@ -122,7 +123,7 @@ public class RefundOrder extends BaseModel {
private
String
currency
;
/**
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败
,4-退款任务关闭
*/
private
Byte
state
;
...
...
@@ -171,6 +172,11 @@ public class RefundOrder extends BaseModel {
*/
private
Date
successTime
;
/**
* 退款失效时间(失效后系统更改为退款任务关闭状态)
*/
private
Date
expiredTime
;
/**
* 创建时间
*/
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/IRefundService.java
浏览文件 @
9e8d51da
...
...
@@ -39,4 +39,7 @@ public interface IRefundService {
/** 调起退款接口,并响应数据; 内部处理普通商户和服务商模式 **/
ChannelRetMsg
refund
(
RefundOrderRQ
bizRQ
,
RefundOrder
refundOrder
,
PayOrder
payOrder
,
MchAppConfigContext
mchAppConfigContext
)
throws
Exception
;
/** 退款查单接口 **/
ChannelRetMsg
query
(
RefundOrder
refundOrder
,
MchAppConfigContext
mchAppConfigContext
)
throws
Exception
;
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/alipay/AlipayKit.java
浏览文件 @
9e8d51da
...
...
@@ -56,6 +56,7 @@ public class AlipayKit {
else
if
(
req
instanceof
AlipayTradeWapPayRequest
)
((
AlipayTradeWapPayRequest
)
req
).
putOtherTextParam
(
"app_auth_token"
,
isvsubMchParams
.
getAppAuthToken
());
else
if
(
req
instanceof
AlipayTradeQueryRequest
)
((
AlipayTradeQueryRequest
)
req
).
putOtherTextParam
(
"app_auth_token"
,
isvsubMchParams
.
getAppAuthToken
());
else
if
(
req
instanceof
AlipayTradeRefundRequest
)
((
AlipayTradeRefundRequest
)
req
).
putOtherTextParam
(
"app_auth_token"
,
isvsubMchParams
.
getAppAuthToken
());
else
if
(
req
instanceof
AlipayTradeFastpayRefundQueryRequest
)
((
AlipayTradeFastpayRefundQueryRequest
)
req
).
putOtherTextParam
(
"app_auth_token"
,
isvsubMchParams
.
getAppAuthToken
());
// 服务商信息
ExtendParams
extendParams
=
new
ExtendParams
();
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/channel/alipay/AlipayRefundService.java
浏览文件 @
9e8d51da
...
...
@@ -15,8 +15,11 @@
*/
package
com.jeequan.jeepay.pay.channel.alipay
;
import
com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel
;
import
com.alipay.api.domain.AlipayTradeRefundModel
;
import
com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest
;
import
com.alipay.api.request.AlipayTradeRefundRequest
;
import
com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse
;
import
com.alipay.api.response.AlipayTradeRefundResponse
;
import
com.jeequan.jeepay.core.constants.CS
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
...
...
@@ -82,5 +85,37 @@ public class AlipayRefundService extends AbstractRefundService {
return
channelRetMsg
;
}
@Override
public
ChannelRetMsg
query
(
RefundOrder
refundOrder
,
MchAppConfigContext
mchAppConfigContext
)
throws
Exception
{
AlipayTradeFastpayRefundQueryRequest
request
=
new
AlipayTradeFastpayRefundQueryRequest
();
AlipayTradeFastpayRefundQueryModel
model
=
new
AlipayTradeFastpayRefundQueryModel
();
model
.
setTradeNo
(
refundOrder
.
getChannelPayOrderNo
());
model
.
setOutTradeNo
(
refundOrder
.
getPayOrderId
());
model
.
setOutRequestNo
(
refundOrder
.
getRefundOrderId
());
request
.
setBizModel
(
model
);
//统一放置 isv接口必传信息
AlipayKit
.
putApiIsvInfo
(
mchAppConfigContext
,
request
,
model
);
AlipayTradeFastpayRefundQueryResponse
response
=
mchAppConfigContext
.
getAlipayClientWrapper
().
execute
(
request
);
ChannelRetMsg
channelRetMsg
=
new
ChannelRetMsg
();
channelRetMsg
.
setChannelAttach
(
response
.
getBody
());
channelRetMsg
.
setChannelOrderId
(
response
.
getTradeNo
());
// 调用成功 & 金额相等 (传入不存在的outRequestNo支付宝仍然返回响应成功只是数据不存在, 调用isSuccess() 仍是成功, 此处需判断金额是否相等)
Long
channelRefundAmount
=
response
.
getRefundAmount
()
==
null
?
null
:
Long
.
parseLong
(
AmountUtil
.
convertDollar2Cent
(
response
.
getRefundAmount
()));
if
(
response
.
isSuccess
()
&&
refundOrder
.
getRefundAmount
().
equals
(
channelRefundAmount
)){
channelRetMsg
.
setChannelState
(
ChannelRetMsg
.
ChannelState
.
CONFIRM_SUCCESS
);
}
else
{
channelRetMsg
.
setChannelState
(
ChannelRetMsg
.
ChannelState
.
WAITING
);
//认为是处理中
}
return
channelRetMsg
;
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/payorder/QueryOrderController.java
浏览文件 @
9e8d51da
...
...
@@ -19,8 +19,8 @@ import com.jeequan.jeepay.core.entity.PayOrder;
import
com.jeequan.jeepay.core.exception.BizException
;
import
com.jeequan.jeepay.core.model.ApiRes
;
import
com.jeequan.jeepay.pay.ctrl.ApiController
;
import
com.jeequan.jeepay.pay.rqrs.QueryPayOrderRQ
;
import
com.jeequan.jeepay.pay.rqrs.QueryPayOrderRS
;
import
com.jeequan.jeepay.pay.rqrs.
payorder.
QueryPayOrderRQ
;
import
com.jeequan.jeepay.pay.rqrs.
payorder.
QueryPayOrderRS
;
import
com.jeequan.jeepay.pay.service.ConfigContextService
;
import
com.jeequan.jeepay.service.impl.PayOrderService
;
import
lombok.extern.slf4j.Slf4j
;
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/refund/QueryRefundOrderController.java
0 → 100644
浏览文件 @
9e8d51da
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.ctrl.refund
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.core.exception.BizException
;
import
com.jeequan.jeepay.core.model.ApiRes
;
import
com.jeequan.jeepay.pay.ctrl.ApiController
;
import
com.jeequan.jeepay.pay.rqrs.refund.QueryRefundOrderRQ
;
import
com.jeequan.jeepay.pay.rqrs.refund.QueryRefundOrderRS
;
import
com.jeequan.jeepay.pay.service.ConfigContextService
;
import
com.jeequan.jeepay.service.impl.RefundOrderService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* 商户退款单查询controller
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/17 15:20
*/
@Slf4j
@RestController
public
class
QueryRefundOrderController
extends
ApiController
{
@Autowired
private
RefundOrderService
refundOrderService
;
@Autowired
private
ConfigContextService
configContextService
;
/**
* 查单接口
* **/
@RequestMapping
(
"/api/refund/query"
)
public
ApiRes
queryRefundOrder
(){
//获取参数 & 验签
QueryRefundOrderRQ
rq
=
getRQByWithMchSign
(
QueryRefundOrderRQ
.
class
);
if
(
StringUtils
.
isAllEmpty
(
rq
.
getMchRefundNo
(),
rq
.
getRefundOrderId
())){
throw
new
BizException
(
"mchRefundNo 和 refundOrderId不能同时为空"
);
}
RefundOrder
refundOrder
=
refundOrderService
.
queryMchOrder
(
rq
.
getMchNo
(),
rq
.
getMchRefundNo
(),
rq
.
getRefundOrderId
());
if
(
refundOrder
==
null
){
throw
new
BizException
(
"订单不存在"
);
}
QueryRefundOrderRS
bizRes
=
QueryRefundOrderRS
.
buildByRefundOrder
(
refundOrder
);
return
ApiRes
.
okWithSign
(
bizRes
,
configContextService
.
getMchAppConfigContext
(
rq
.
getMchNo
(),
rq
.
getAppId
()).
getMchApp
().
getAppSecret
());
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/ctrl/refund/RefundOrderController.java
浏览文件 @
9e8d51da
...
...
@@ -15,6 +15,7 @@
*/
package
com.jeequan.jeepay.pay.ctrl.refund
;
import
cn.hutool.core.date.DateUtil
;
import
com.jeequan.jeepay.core.entity.MchApp
;
import
com.jeequan.jeepay.core.entity.MchInfo
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
...
...
@@ -32,6 +33,7 @@ import com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg;
import
com.jeequan.jeepay.pay.rqrs.refund.RefundOrderRQ
;
import
com.jeequan.jeepay.pay.rqrs.refund.RefundOrderRS
;
import
com.jeequan.jeepay.pay.service.ConfigContextService
;
import
com.jeequan.jeepay.pay.service.PayMchNotifyService
;
import
com.jeequan.jeepay.service.impl.PayOrderService
;
import
com.jeequan.jeepay.service.impl.RefundOrderService
;
import
lombok.extern.slf4j.Slf4j
;
...
...
@@ -56,6 +58,7 @@ public class RefundOrderController extends ApiController {
@Autowired
private
PayOrderService
payOrderService
;
@Autowired
private
RefundOrderService
refundOrderService
;
@Autowired
private
ConfigContextService
configContextService
;
@Autowired
private
PayMchNotifyService
payMchNotifyService
;
/** 申请退款 **/
@PostMapping
(
"/api/refund/refundOrder"
)
...
...
@@ -69,7 +72,6 @@ public class RefundOrderController extends ApiController {
try
{
if
(
StringUtils
.
isAllEmpty
(
rq
.
getMchOrderNo
(),
rq
.
getPayOrderId
())){
throw
new
BizException
(
"mchOrderNo 和 payOrderId不能同时为空"
);
}
...
...
@@ -174,6 +176,7 @@ public class RefundOrderController extends ApiController {
private
RefundOrder
genRefundOrder
(
RefundOrderRQ
rq
,
PayOrder
payOrder
,
MchInfo
mchInfo
,
MchApp
mchApp
){
Date
nowTime
=
new
Date
();
RefundOrder
refundOrder
=
new
RefundOrder
();
refundOrder
.
setRefundOrderId
(
SeqKit
.
genPayOrderId
());
//退款订单号
refundOrder
.
setPayOrderId
(
payOrder
.
getPayOrderId
());
//支付订单号
...
...
@@ -198,8 +201,9 @@ public class RefundOrderController extends ApiController {
refundOrder
.
setChannelExtra
(
rq
.
getChannelExtra
());
//特定渠道发起时额外参数
refundOrder
.
setNotifyUrl
(
rq
.
getNotifyUrl
());
//通知地址
refundOrder
.
setExtParam
(
rq
.
getExtParam
());
//扩展参数
refundOrder
.
setExpiredTime
(
DateUtil
.
offsetHour
(
nowTime
,
2
));
//订单超时关闭时间 默认两个小时
refundOrder
.
setSuccessTime
(
null
);
//订单退款成功时间
refundOrder
.
setCreatedAt
(
n
ew
Date
()
);
//创建时间
refundOrder
.
setCreatedAt
(
n
owTime
);
//创建时间
return
refundOrder
;
}
...
...
@@ -219,7 +223,7 @@ public class RefundOrderController extends ApiController {
if
(
ChannelRetMsg
.
ChannelState
.
CONFIRM_SUCCESS
==
channelRetMsg
.
getChannelState
())
{
this
.
updateInitOrderStateThrowException
(
RefundOrder
.
STATE_SUCCESS
,
refundOrder
,
channelRetMsg
);
// payMchNotifyService.payOrderNotify(pay
Order);
payMchNotifyService
.
refundOrderNotify
(
refund
Order
);
//明确失败
}
else
if
(
ChannelRetMsg
.
ChannelState
.
CONFIRM_FAIL
==
channelRetMsg
.
getChannelState
())
{
...
...
@@ -235,7 +239,7 @@ public class RefundOrderController extends ApiController {
this
.
updateInitOrderStateThrowException
(
RefundOrder
.
STATE_ING
,
refundOrder
,
channelRetMsg
);
// 系统异常: 退款单不再处理。 为: 生成状态
}
else
if
(
ChannelRetMsg
.
ChannelState
.
SYS_ERROR
==
channelRetMsg
.
getChannelState
()){
}
else
if
(
ChannelRetMsg
.
ChannelState
.
SYS_ERROR
==
channelRetMsg
.
getChannelState
()
){
}
else
{
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/QueryPayOrderRQ.java
→
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/
payorder/
QueryPayOrderRQ.java
浏览文件 @
9e8d51da
...
...
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.rqrs
;
package
com.jeequan.jeepay.pay.rqrs
.payorder
;
import
com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ
;
import
lombok.Data
;
import
javax.validation.constraints.NotBlank
;
...
...
@@ -27,7 +28,7 @@ import javax.validation.constraints.NotBlank;
* @date 2021/6/8 17:40
*/
@Data
public
class
QueryPayOrderRQ
extends
AbstractMchAppRQ
{
public
class
QueryPayOrderRQ
extends
AbstractMchAppRQ
{
/** 商户订单号 **/
private
String
mchOrderNo
;
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/QueryPayOrderRS.java
→
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/
payorder/
QueryPayOrderRS.java
浏览文件 @
9e8d51da
...
...
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.rqrs
;
package
com.jeequan.jeepay.pay.rqrs
.payorder
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
import
com.jeequan.jeepay.pay.rqrs.AbstractRS
;
import
lombok.Data
;
import
org.springframework.beans.BeanUtils
;
...
...
@@ -27,7 +28,7 @@ import org.springframework.beans.BeanUtils;
* @date 2021/6/8 17:40
*/
@Data
public
class
QueryPayOrderRS
extends
AbstractRS
{
public
class
QueryPayOrderRS
extends
AbstractRS
{
/**
* 支付订单号
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRQ.java
0 → 100644
浏览文件 @
9e8d51da
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.rqrs.refund
;
import
com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ
;
import
lombok.Data
;
/*
* 查询退款单请求参数对象
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/17 14:07
*/
@Data
public
class
QueryRefundOrderRQ
extends
AbstractMchAppRQ
{
/** 商户退款单号 **/
private
String
mchRefundNo
;
/** 支付系统退款订单号 **/
private
String
refundOrderId
;
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/QueryRefundOrderRS.java
0 → 100644
浏览文件 @
9e8d51da
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.rqrs.refund
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.pay.rqrs.AbstractRS
;
import
lombok.Data
;
import
org.springframework.beans.BeanUtils
;
/*
* 查询退款单 响应参数
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/17 14:08
*/
@Data
public
class
QueryRefundOrderRS
extends
AbstractRS
{
/**
* 退款订单号(支付系统生成订单号)
*/
private
String
refundOrderId
;
/**
* 支付订单号(与t_pay_order对应)
*/
private
String
payOrderId
;
/**
* 商户号
*/
private
String
mchNo
;
/**
* 应用ID
*/
private
String
appId
;
/**
* 商户退款单号(商户系统的订单号)
*/
private
String
mchRefundNo
;
/**
* 支付金额,单位分
*/
private
Long
payAmount
;
/**
* 退款金额,单位分
*/
private
Long
refundAmount
;
/**
* 三位货币代码,人民币:cny
*/
private
String
currency
;
/**
* 退款状态:0-订单生成,1-退款中,2-退款成功,3-退款失败
*/
private
Byte
state
;
/**
* 渠道订单号
*/
private
String
channelOrderNo
;
/**
* 渠道错误码
*/
private
String
channelErrCode
;
/**
* 渠道错误描述
*/
private
String
channelErrMsg
;
/**
* 特定渠道发起时额外参数
*/
private
String
channelExtra
;
/**
* 扩展参数
*/
private
String
extParam
;
/**
* 订单退款成功时间
*/
private
Long
successTime
;
/**
* 创建时间
*/
private
Long
createdAt
;
public
static
QueryRefundOrderRS
buildByRefundOrder
(
RefundOrder
refundOrder
){
if
(
refundOrder
==
null
){
return
null
;
}
QueryRefundOrderRS
result
=
new
QueryRefundOrderRS
();
BeanUtils
.
copyProperties
(
refundOrder
,
result
);
result
.
setSuccessTime
(
refundOrder
.
getSuccessTime
()
==
null
?
null
:
refundOrder
.
getSuccessTime
().
getTime
());
result
.
setCreatedAt
(
refundOrder
.
getCreatedAt
()
==
null
?
null
:
refundOrder
.
getCreatedAt
().
getTime
());
return
result
;
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/rqrs/refund/RefundOrderRS.java
浏览文件 @
9e8d51da
...
...
@@ -15,10 +15,8 @@
*/
package
com.jeequan.jeepay.pay.rqrs.refund
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.pay.rqrs.AbstractRS
;
import
com.jeequan.jeepay.pay.rqrs.QueryPayOrderRS
;
import
lombok.Data
;
import
org.springframework.beans.BeanUtils
;
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/ChannelOrderReissueService.java
浏览文件 @
9e8d51da
...
...
@@ -16,11 +16,14 @@
package
com.jeequan.jeepay.pay.service
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.core.utils.SpringBeansUtil
;
import
com.jeequan.jeepay.pay.channel.IPayOrderQueryService
;
import
com.jeequan.jeepay.pay.channel.IRefundService
;
import
com.jeequan.jeepay.pay.model.MchAppConfigContext
;
import
com.jeequan.jeepay.pay.rqrs.msg.ChannelRetMsg
;
import
com.jeequan.jeepay.service.impl.PayOrderService
;
import
com.jeequan.jeepay.service.impl.RefundOrderService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
...
@@ -33,12 +36,14 @@ import org.springframework.stereotype.Service;
* @site https://www.jeepay.vip
* @date 2021/6/8 17:40
*/
@Service
@Slf4j
public
class
ChannelOrderReissueService
{
@Autowired
private
ConfigContextService
configContextService
;
@Autowired
private
PayOrderService
payOrderService
;
@Autowired
private
RefundOrderService
refundOrderService
;
@Autowired
private
PayMchNotifyService
payMchNotifyService
;
...
...
@@ -95,5 +100,58 @@ public class ChannelOrderReissueService {
}
/** 处理退款订单 **/
public
ChannelRetMsg
processRefundOrder
(
RefundOrder
refundOrder
){
try
{
String
refundOrderId
=
refundOrder
.
getRefundOrderId
();
//查询支付接口是否存在
IRefundService
queryService
=
SpringBeansUtil
.
getBean
(
refundOrder
.
getIfCode
()
+
"RefundService"
,
IRefundService
.
class
);
// 支付通道接口实现不存在
if
(
queryService
==
null
){
log
.
error
(
"退款补单:{} interface not exists!"
,
refundOrder
.
getIfCode
());
return
null
;
}
//查询出商户应用的配置信息
MchAppConfigContext
mchAppConfigContext
=
configContextService
.
getMchAppConfigContext
(
refundOrder
.
getMchNo
(),
refundOrder
.
getAppId
());
ChannelRetMsg
channelRetMsg
=
queryService
.
query
(
refundOrder
,
mchAppConfigContext
);
if
(
channelRetMsg
==
null
){
log
.
error
(
"退款补单:channelRetMsg is null"
);
return
null
;
}
log
.
info
(
"退款补单:[{}]查询结果为:{}"
,
refundOrderId
,
channelRetMsg
);
// 查询成功
if
(
channelRetMsg
.
getChannelState
()
==
ChannelRetMsg
.
ChannelState
.
CONFIRM_SUCCESS
)
{
if
(
refundOrderService
.
updateIng2Success
(
refundOrderId
,
channelRetMsg
.
getChannelOrderId
()))
{
// 通知商户系统
if
(
StringUtils
.
isNotEmpty
(
refundOrder
.
getNotifyUrl
())){
payMchNotifyService
.
refundOrderNotify
(
refundOrderService
.
getById
(
refundOrderId
));
}
}
}
else
if
(
channelRetMsg
.
getChannelState
()
==
ChannelRetMsg
.
ChannelState
.
CONFIRM_FAIL
){
//确认失败
//1. 更新支付订单表为失败状态
refundOrderService
.
updateIng2Fail
(
refundOrderId
,
channelRetMsg
.
getChannelOrderId
(),
channelRetMsg
.
getChannelErrCode
(),
channelRetMsg
.
getChannelErrMsg
());
}
return
channelRetMsg
;
}
catch
(
Exception
e
)
{
//继续下一次迭代查询
log
.
error
(
"退款补单:error refundOrderId = {}"
,
refundOrder
.
getRefundOrderId
(),
e
);
return
null
;
}
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/service/PayMchNotifyService.java
浏览文件 @
9e8d51da
...
...
@@ -16,14 +16,14 @@
package
com.jeequan.jeepay.pay.service
;
import
com.alibaba.fastjson.JSONObject
;
import
com.jeequan.jeepay.core.entity.MchInfo
;
import
com.jeequan.jeepay.core.entity.MchNotifyRecord
;
import
com.jeequan.jeepay.core.entity.PayOrder
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.core.utils.JeepayKit
;
import
com.jeequan.jeepay.core.utils.StringKit
;
import
com.jeequan.jeepay.pay.mq.queue.MqQueue4PayOrderMchNotify
;
import
com.jeequan.jeepay.pay.rqrs.QueryPayOrderRS
;
import
com.jeequan.jeepay.
service.impl.MchInfoService
;
import
com.jeequan.jeepay.pay.rqrs.
payorder.
QueryPayOrderRS
;
import
com.jeequan.jeepay.
pay.rqrs.refund.QueryRefundOrderRS
;
import
com.jeequan.jeepay.service.impl.MchNotifyRecordService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -91,6 +91,51 @@ public class PayMchNotifyService {
}
}
/** 商户通知信息,退款成功的发送通知 **/
public
void
refundOrderNotify
(
RefundOrder
dbRefundOrder
){
try
{
// 通知地址为空
if
(
StringUtils
.
isEmpty
(
dbRefundOrder
.
getNotifyUrl
())){
return
;
}
//获取到通知对象
MchNotifyRecord
mchNotifyRecord
=
mchNotifyRecordService
.
findByRefundOrder
(
dbRefundOrder
.
getRefundOrderId
());
if
(
mchNotifyRecord
!=
null
){
log
.
info
(
"当前已存在通知消息, 不再发送。"
);
return
;
}
//商户app私钥
String
appSecret
=
configContextService
.
getMchAppConfigContext
(
dbRefundOrder
.
getMchNo
(),
dbRefundOrder
.
getAppId
()).
getMchApp
().
getAppSecret
();
// 封装通知url
String
notifyUrl
=
createNotifyUrl
(
dbRefundOrder
,
appSecret
);
mchNotifyRecord
=
new
MchNotifyRecord
();
mchNotifyRecord
.
setOrderId
(
dbRefundOrder
.
getRefundOrderId
());
mchNotifyRecord
.
setOrderType
(
MchNotifyRecord
.
TYPE_REFUND_ORDER
);
mchNotifyRecord
.
setMchNo
(
dbRefundOrder
.
getMchNo
());
mchNotifyRecord
.
setMchOrderNo
(
dbRefundOrder
.
getMchRefundNo
());
//商户订单号
mchNotifyRecord
.
setIsvNo
(
dbRefundOrder
.
getIsvNo
());
mchNotifyRecord
.
setAppId
(
dbRefundOrder
.
getAppId
());
mchNotifyRecord
.
setNotifyUrl
(
notifyUrl
);
mchNotifyRecord
.
setResResult
(
""
);
mchNotifyRecord
.
setNotifyCount
(
0
);
mchNotifyRecord
.
setState
(
MchNotifyRecord
.
STATE_ING
);
// 通知中
mchNotifyRecordService
.
save
(
mchNotifyRecord
);
//推送到MQ
Long
notifyId
=
mchNotifyRecord
.
getNotifyId
();
mqPayOrderMchNotifyQueue
.
send
(
notifyId
+
""
);
}
catch
(
Exception
e
)
{
log
.
error
(
"推送失败!"
,
e
);
}
}
/**
* 创建响应URL
...
...
@@ -109,6 +154,23 @@ public class PayMchNotifyService {
}
/**
* 创建响应URL
*/
public
String
createNotifyUrl
(
RefundOrder
refundOrder
,
String
appSecret
)
{
QueryRefundOrderRS
queryPayOrderRS
=
QueryRefundOrderRS
.
buildByRefundOrder
(
refundOrder
);
JSONObject
jsonObject
=
(
JSONObject
)
JSONObject
.
toJSON
(
queryPayOrderRS
);
jsonObject
.
put
(
"reqTime"
,
System
.
currentTimeMillis
());
//添加请求时间
// 报文签名
jsonObject
.
put
(
"sign"
,
JeepayKit
.
getSign
(
jsonObject
,
appSecret
));
// 生成通知
return
StringKit
.
appendUrlQuery
(
refundOrder
.
getNotifyUrl
(),
jsonObject
);
}
/**
* 创建响应URL
*/
...
...
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/task/RefundOrderExpiredTask.java
0 → 100644
浏览文件 @
9e8d51da
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.task
;
import
com.jeequan.jeepay.service.impl.PayOrderService
;
import
com.jeequan.jeepay.service.impl.RefundOrderService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
/*
* 退款订单过期定时任务
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/17 14:36
*/
@Slf4j
@Component
public
class
RefundOrderExpiredTask
{
@Autowired
private
RefundOrderService
refundOrderService
;
@Scheduled
(
cron
=
"0 0/1 * * * ?"
)
// 每分钟执行一次
public
void
start
()
{
int
updateCount
=
refundOrderService
.
updateOrderExpired
();
log
.
info
(
"处理退款订单超时{}条."
,
updateCount
);
}
}
jeepay-payment/src/main/java/com/jeequan/jeepay/pay/task/RefundOrderReissueTask.java
0 → 100644
浏览文件 @
9e8d51da
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
com.jeequan.jeepay.pay.task
;
import
cn.hutool.core.date.DateUtil
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
com.jeequan.jeepay.core.entity.RefundOrder
;
import
com.jeequan.jeepay.pay.service.ChannelOrderReissueService
;
import
com.jeequan.jeepay.service.impl.RefundOrderService
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
java.util.Date
;
/*
* 补单定时任务(退款单)
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/6/17 14:22
*/
@Slf4j
@Component
public
class
RefundOrderReissueTask
{
private
static
final
int
QUERY_PAGE_SIZE
=
100
;
//每次查询数量
@Autowired
private
RefundOrderService
refundOrderService
;
@Autowired
private
ChannelOrderReissueService
channelOrderReissueService
;
@Scheduled
(
cron
=
"0 0/1 * * * ?"
)
// 每分钟执行一次
public
void
start
()
{
//当前时间 减去10分钟。
Date
offsetDate
=
DateUtil
.
offsetMinute
(
new
Date
(),
-
10
);
//查询条件: 支付中的订单 & ( 订单创建时间 + 10分钟 >= 当前时间 )
LambdaQueryWrapper
<
RefundOrder
>
lambdaQueryWrapper
=
RefundOrder
.
gw
().
eq
(
RefundOrder:
:
getState
,
RefundOrder
.
STATE_ING
).
le
(
RefundOrder:
:
getCreatedAt
,
offsetDate
);
int
currentPageIndex
=
1
;
//当前页码
while
(
true
){
try
{
IPage
<
RefundOrder
>
refundOrderIPage
=
refundOrderService
.
page
(
new
Page
(
currentPageIndex
,
QUERY_PAGE_SIZE
),
lambdaQueryWrapper
);
if
(
refundOrderIPage
==
null
||
refundOrderIPage
.
getRecords
().
isEmpty
()){
//本次查询无结果, 不再继续查询;
break
;
}
for
(
RefundOrder
refundOrder:
refundOrderIPage
.
getRecords
()){
channelOrderReissueService
.
processRefundOrder
(
refundOrder
);
}
//已经到达页码最大量,无需再次查询
if
(
refundOrderIPage
.
getPages
()
<=
currentPageIndex
){
break
;
}
currentPageIndex
++;
}
catch
(
Exception
e
)
{
//出现异常,直接退出,避免死循环。
log
.
error
(
"error"
,
e
);
break
;
}
}
}
}
jeepay-service/src/main/java/com/jeequan/jeepay/service/impl/RefundOrderService.java
浏览文件 @
9e8d51da
...
...
@@ -21,10 +21,12 @@ import com.jeequan.jeepay.core.entity.RefundOrder;
import
com.jeequan.jeepay.core.exception.BizException
;
import
com.jeequan.jeepay.service.mapper.PayOrderMapper
;
import
com.jeequan.jeepay.service.mapper.RefundOrderMapper
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
java.util.Arrays
;
import
java.util.Date
;
/**
...
...
@@ -40,6 +42,18 @@ public class RefundOrderService extends ServiceImpl<RefundOrderMapper, RefundOrd
@Autowired
private
PayOrderMapper
payOrderMapper
;
/** 查询商户订单 **/
public
RefundOrder
queryMchOrder
(
String
mchNo
,
String
mchRefundNo
,
String
refundOrderId
){
if
(
StringUtils
.
isNotEmpty
(
refundOrderId
)){
return
getOne
(
RefundOrder
.
gw
().
eq
(
RefundOrder:
:
getMchNo
,
mchNo
).
eq
(
RefundOrder:
:
getRefundOrderId
,
refundOrderId
));
}
else
if
(
StringUtils
.
isNotEmpty
(
mchRefundNo
)){
return
getOne
(
RefundOrder
.
gw
().
eq
(
RefundOrder:
:
getMchNo
,
mchNo
).
eq
(
RefundOrder:
:
getMchRefundNo
,
mchRefundNo
));
}
else
{
return
null
;
}
}
/** 更新退款单状态 【退款单生成】 --》 【退款中】 **/
public
boolean
updateInit2Ing
(
String
refundOrderId
){
...
...
@@ -108,4 +122,18 @@ public class RefundOrderService extends ServiceImpl<RefundOrderMapper, RefundOrd
}
/** 更新退款单为 关闭状态 **/
public
Integer
updateOrderExpired
(){
RefundOrder
refundOrder
=
new
RefundOrder
();
refundOrder
.
setState
(
RefundOrder
.
STATE_CLOSED
);
return
baseMapper
.
update
(
refundOrder
,
RefundOrder
.
gw
()
.
in
(
RefundOrder:
:
getState
,
Arrays
.
asList
(
RefundOrder
.
STATE_INIT
,
RefundOrder
.
STATE_ING
))
.
le
(
RefundOrder:
:
getExpiredTime
,
new
Date
())
);
}
}
jeepay-service/src/main/java/com/jeequan/jeepay/service/mapper/RefundOrderMapper.xml
浏览文件 @
9e8d51da
...
...
@@ -28,6 +28,7 @@
<result
column=
"notify_url"
property=
"notifyUrl"
/>
<result
column=
"ext_param"
property=
"extParam"
/>
<result
column=
"success_time"
property=
"successTime"
/>
<result
column=
"expired_time"
property=
"expiredTime"
/>
<result
column=
"created_at"
property=
"createdAt"
/>
<result
column=
"updated_at"
property=
"updatedAt"
/>
</resultMap>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录