Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
F
fit-finance
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fitness-server
fit-finance
Commits
a25711b3
Commit
a25711b3
authored
May 10, 2024
by
程裕兵
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat:refund
parent
8fcbc3b2
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
311 additions
and
96 deletions
+311
-96
api/src/main/java/com/jiejing/fitness/finance/api/merchant/StudioMerchantApi.java
+3
-1
api/src/main/java/com/jiejing/fitness/finance/api/merchant/StudioMerchantApiFallback.java
+2
-1
api/src/main/java/com/jiejing/fitness/finance/api/merchant/vo/StudioMerchantRefundVO.java
+79
-0
app/src/main/java/com/jiejing/fitness/finance/app/controller/merchant/StudioMerchantController.java
+2
-1
repository/src/main/java/com/jiejing/fitness/finance/repository/mapper/StudioCashierRecordMapper.java
+2
-0
repository/src/main/java/com/jiejing/fitness/finance/repository/mapper/StudioCashierRecordMapper.xml
+9
-1
repository/src/main/java/com/jiejing/fitness/finance/repository/service/StudioCashierRecordRpService.java
+7
-1
service/src/main/java/com/jiejing/fitness/finance/service/enums/GlobalConfigEnums.java
+1
-0
service/src/main/java/com/jiejing/fitness/finance/service/global/ConfigService.java
+2
-0
service/src/main/java/com/jiejing/fitness/finance/service/global/dto/RefundConfigDTO.java
+37
-0
service/src/main/java/com/jiejing/fitness/finance/service/global/impl/ConfigServiceImpl.java
+8
-0
service/src/main/java/com/jiejing/fitness/finance/service/merchant/StudioMerchantService.java
+10
-1
service/src/main/java/com/jiejing/fitness/finance/service/merchant/impl/StudioMerchantServiceImpl.java
+2
-1
service/src/main/java/com/jiejing/fitness/finance/service/pay/RefundService.java
+10
-1
service/src/main/java/com/jiejing/fitness/finance/service/pay/convert/RefundConvert.java
+29
-0
service/src/main/java/com/jiejing/fitness/finance/service/pay/impl/RefundServiceImpl.java
+93
-12
service/src/main/java/com/jiejing/fitness/finance/service/utils/FeeUtil.java
+15
-76
No files found.
api/src/main/java/com/jiejing/fitness/finance/api/merchant/StudioMerchantApi.java
View file @
a25711b3
...
...
@@ -19,6 +19,7 @@ import com.jiejing.fitness.finance.api.merchant.request.UnbindStudioMerchantRequ
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantApplyVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantAuthSubChannelVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantBindXcxAppIdVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantVO
;
import
com.jiejing.paycenter.common.model.vo.PayVO
;
import
com.jiejing.paycenter.common.model.vo.RefundVO
;
...
...
@@ -98,6 +99,6 @@ public interface StudioMerchantApi {
@ApiOperation
(
value
=
"退款"
,
tags
=
{
TAG
})
@PostMapping
(
value
=
"/private/studioMerchant/refund"
)
JsonResult
<
RefundVO
>
refund
(
StudioMerchantRefundRequest
request
);
JsonResult
<
StudioMerchant
RefundVO
>
refund
(
StudioMerchantRefundRequest
request
);
}
\ No newline at end of file
api/src/main/java/com/jiejing/fitness/finance/api/merchant/StudioMerchantApiFallback.java
View file @
a25711b3
...
...
@@ -19,6 +19,7 @@ import com.jiejing.fitness.finance.api.merchant.request.UnbindStudioMerchantRequ
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantApplyVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantAuthSubChannelVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantBindXcxAppIdVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantVO
;
import
com.jiejing.paycenter.common.model.vo.PayVO
;
import
com.jiejing.paycenter.common.model.vo.RefundVO
;
...
...
@@ -116,7 +117,7 @@ public class StudioMerchantApiFallback implements FallbackFactory<StudioMerchant
}
@Override
public
JsonResult
<
RefundVO
>
refund
(
StudioMerchantRefundRequest
request
)
{
public
JsonResult
<
StudioMerchant
RefundVO
>
refund
(
StudioMerchantRefundRequest
request
)
{
return
JsonResult
.
rpcError
();
}
};
...
...
api/src/main/java/com/jiejing/fitness/finance/api/merchant/vo/StudioMerchantRefundVO.java
0 → 100644
View file @
a25711b3
package
com
.
jiejing
.
fitness
.
finance
.
api
.
merchant
.
vo
;
import
com.jiejing.common.swagger.EnumMapping
;
import
com.jiejing.paycenter.common.enums.common.TransStateEnums
;
import
com.jiejing.paycenter.common.enums.error.PayErrorEnums
;
import
io.swagger.annotations.ApiModel
;
import
io.swagger.annotations.ApiModelProperty
;
import
java.util.Arrays
;
import
java.util.Date
;
import
lombok.AllArgsConstructor
;
import
lombok.Builder
;
import
lombok.Data
;
import
lombok.Getter
;
import
lombok.NoArgsConstructor
;
/**
* @author chengyubing
* @since 2024/5/10 13:40
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel
(
description
=
"场馆商户退款VO"
)
public
class
StudioMerchantRefundVO
{
@ApiModelProperty
(
name
=
"退款单号"
)
private
String
transNo
;
@EnumMapping
(
enumClass
=
TransStateEnums
.
class
)
@ApiModelProperty
(
name
=
"退款状态"
)
private
String
refundState
;
@ApiModelProperty
(
name
=
"三方交易单号"
)
private
String
thirdTransNo
;
@ApiModelProperty
(
name
=
"失败原因"
)
private
String
failMessage
;
@ApiModelProperty
(
name
=
"完成时间"
)
private
Date
successTime
;
@EnumMapping
(
enumClass
=
CheckRefundCodeEnum
.
class
)
@ApiModelProperty
(
value
=
"具体的错误码"
,
notes
=
"退款校验或者退款失败时此code有值"
)
private
String
code
;
@Getter
@AllArgsConstructor
public
enum
CheckRefundCodeEnum
{
/**
* 退款校验CODE,退款失败CODE
*/
SUCCESS
(
"校验成功"
),
NOT_CURRENT_MERCHANT
(
"不是当前商户号收款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支"
),
DATE_LIMIT
(
"仅支持350天内交易进行退款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支"
),
TIME_LIMIT
(
"当前时间段不支持退款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支"
),
AMOUNT_LIMIT
(
"乐动收银可退金额不足"
),
OTHER_ERROR
(
"其他错误"
),
;
private
final
String
code
=
name
();
private
final
String
message
;
public
static
CheckRefundCodeEnum
getByCode
(
String
code
)
{
return
Arrays
.
stream
(
CheckRefundCodeEnum
.
values
()).
filter
(
e
->
e
.
getCode
().
equals
(
code
)).
findFirst
()
.
orElse
(
OTHER_ERROR
);
}
public
static
boolean
isSuccess
(
String
code
)
{
return
CheckRefundCodeEnum
.
SUCCESS
==
getByCode
(
code
);
}
public
static
boolean
isFail
(
String
code
)
{
return
!
isSuccess
(
code
);
}
}
}
app/src/main/java/com/jiejing/fitness/finance/app/controller/merchant/StudioMerchantController.java
View file @
a25711b3
...
...
@@ -21,6 +21,7 @@ import com.jiejing.fitness.finance.api.merchant.request.UnbindStudioMerchantRequ
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantApplyVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantAuthSubChannelVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantBindXcxAppIdVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantVO
;
import
com.jiejing.fitness.finance.service.merchant.StudioMerchantService
;
import
com.jiejing.fitness.finance.service.merchant.params.ApplyStudioMerchantParams
;
...
...
@@ -181,7 +182,7 @@ public class StudioMerchantController implements StudioMerchantApi {
@ApiOperation
(
value
=
"退款"
,
tags
=
{
TAG
})
@PostMapping
(
value
=
"/private/studioMerchant/refund"
)
@Override
public
JsonResult
<
RefundVO
>
refund
(
@RequestBody
@Valid
StudioMerchantRefundRequest
request
)
{
public
JsonResult
<
StudioMerchant
RefundVO
>
refund
(
@RequestBody
@Valid
StudioMerchantRefundRequest
request
)
{
StudioMerchantRefundParams
params
=
BeanUtil
.
map
(
request
,
StudioMerchantRefundParams
.
class
);
return
JsonResult
.
success
(
refundService
.
merchantRefund
(
params
));
}
...
...
repository/src/main/java/com/jiejing/fitness/finance/repository/mapper/StudioCashierRecordMapper.java
View file @
a25711b3
...
...
@@ -49,4 +49,6 @@ public interface StudioCashierRecordMapper extends XBaseMapper<StudioCashierReco
StudioCashierStatisticVO
statistic
(
@Param
(
"query"
)
PageBrandCashierRecordQuery
query
);
BigDecimal
sumRefundTransAmountByPayTransNo
(
@Param
(
"payTransNo"
)
String
payTransNo
);
}
repository/src/main/java/com/jiejing/fitness/finance/repository/mapper/StudioCashierRecordMapper.xml
View file @
a25711b3
...
...
@@ -25,7 +25,15 @@
from studio_cashier_record
where related_trans_no = #{payTransNo}
and trans_type = 'REFUND'
and trans_state in ('REFUNDING', 'REFUND_SUCCESS')
and trans_state in ('REFUND_INIT', 'REFUNDING', 'REFUND_SUCCESS')
</select>
<select
id=
"sumRefundTransAmountByPayTransNo"
resultType=
"java.math.BigDecimal"
>
select sum(trans_amount)
from studio_cashier_record
where related_trans_no = #{payTransNo}
and trans_type = 'REFUND'
and trans_state in ('REFUND_INIT', 'REFUNDING', 'REFUND_SUCCESS')
</select>
<select
id=
"sumMerchantPaySuccess"
resultType=
"java.math.BigDecimal"
>
...
...
repository/src/main/java/com/jiejing/fitness/finance/repository/service/StudioCashierRecordRpService.java
View file @
a25711b3
...
...
@@ -47,7 +47,13 @@ public class StudioCashierRecordRpService extends
MapperRepoService
<
Long
,
StudioCashierRecord
,
StudioCashierRecordMapper
>
{
public
BigDecimal
sumRefundActualAmountByPayTransNo
(
String
payTransNo
)
{
return
this
.
baseMapper
.
sumRefundActualAmountByPayTransNo
(
payTransNo
);
return
Optional
.
ofNullable
(
this
.
baseMapper
.
sumRefundActualAmountByPayTransNo
(
payTransNo
))
.
orElse
(
BigDecimal
.
ZERO
);
}
public
BigDecimal
sumRefundTransAmountByPayTransNo
(
String
payTransNo
)
{
return
Optional
.
ofNullable
(
this
.
baseMapper
.
sumRefundTransAmountByPayTransNo
(
payTransNo
))
.
orElse
(
BigDecimal
.
ZERO
);
}
public
List
<
StudioCashierRecord
>
listByOrderNo
(
String
orderNo
)
{
...
...
service/src/main/java/com/jiejing/fitness/finance/service/enums/GlobalConfigEnums.java
View file @
a25711b3
...
...
@@ -18,6 +18,7 @@ public enum GlobalConfigEnums {
BRAND_MERCHANT_SUB_CHANNELS
(
"BRAND_MERCHANT_SUB_CHANNELS"
,
"品牌商户默认开通的子渠道以及对应费率"
),
CASHIER_APP_IDS
(
"CASHIER_APP_IDS"
,
"收银所需的appId"
),
CASHIER_ALI_INFO
(
"CASHIER_ALI_INFO"
,
"收银所需支付宝信息"
),
CASHIER_REFUND_CONFIG
(
"CASHIER_REFUND_CONFIG"
,
"退款所需配置"
),
;
@EnumValue
...
...
service/src/main/java/com/jiejing/fitness/finance/service/global/ConfigService.java
View file @
a25711b3
package
com
.
jiejing
.
fitness
.
finance
.
service
.
global
;
import
com.jiejing.fitness.finance.service.global.dto.RefundConfigDTO
;
import
com.jiejing.fitness.finance.service.global.dto.SubChannelInfoDTO
;
/**
...
...
@@ -11,5 +12,6 @@ public interface ConfigService {
SubChannelInfoDTO
getDefaultBrandSubChannelInfo
();
RefundConfigDTO
getRefundConfig
();
}
service/src/main/java/com/jiejing/fitness/finance/service/global/dto/RefundConfigDTO.java
0 → 100644
View file @
a25711b3
package
com
.
jiejing
.
fitness
.
finance
.
service
.
global
.
dto
;
import
java.util.List
;
import
lombok.Data
;
/**
* @author chengyubing
* @since 2024/5/10 14:24
*/
@Data
public
class
RefundConfigDTO
{
/**
* 最大天数
*/
private
Long
maxDate
;
/**
* 拒绝时间区间
*/
private
List
<
RefuseTime
>
refuseTimeList
;
@Data
public
static
class
RefuseTime
{
/**
* 开始分钟
*/
private
Integer
start
;
/**
* 结束分钟
*/
private
Integer
end
;
}
}
service/src/main/java/com/jiejing/fitness/finance/service/global/impl/ConfigServiceImpl.java
View file @
a25711b3
...
...
@@ -7,6 +7,7 @@ import com.jiejing.fitness.finance.repository.service.GlobalConfigRpService;
import
com.jiejing.fitness.finance.service.enums.FinanceErrorEnums
;
import
com.jiejing.fitness.finance.service.enums.GlobalConfigEnums
;
import
com.jiejing.fitness.finance.service.global.ConfigService
;
import
com.jiejing.fitness.finance.service.global.dto.RefundConfigDTO
;
import
com.jiejing.fitness.finance.service.global.dto.SubChannelInfoDTO
;
import
javax.annotation.Resource
;
import
org.springframework.stereotype.Service
;
...
...
@@ -29,4 +30,11 @@ public class ConfigServiceImpl implements ConfigService {
return
JSON
.
parseObject
(
config
.
getConfigValue
(),
SubChannelInfoDTO
.
class
);
}
@Override
public
RefundConfigDTO
getRefundConfig
()
{
GlobalConfig
config
=
globalConfigRpService
.
getById
(
GlobalConfigEnums
.
CASHIER_REFUND_CONFIG
.
getCode
())
.
orElseThrow
(()
->
new
BizException
(
FinanceErrorEnums
.
NOT_EXIST
));
return
JSON
.
parseObject
(
config
.
getConfigValue
(),
RefundConfigDTO
.
class
);
}
}
service/src/main/java/com/jiejing/fitness/finance/service/merchant/StudioMerchantService.java
View file @
a25711b3
...
...
@@ -5,6 +5,7 @@ import com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantApplyVO;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantAuthSubChannelVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantBindXcxAppIdVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantVO
;
import
com.jiejing.fitness.finance.repository.entity.PartyToMerchant
;
import
com.jiejing.fitness.finance.service.merchant.params.ApplyStudioMerchantParams
;
import
com.jiejing.fitness.finance.service.merchant.params.PageStudioMerchantApplyParams
;
import
com.jiejing.paycenter.common.enums.merchant.SubChannelAuthTypeEnums
;
...
...
@@ -106,6 +107,14 @@ public interface StudioMerchantService {
StudioMerchantBindXcxAppIdVO
bindXcxAppId
(
Long
studioId
,
String
appId
);
/**
* 获取关联关系
*
* @param studioId 场馆ID
* @return 关联关系
*/
PartyToMerchant
getRelation
(
Long
studioId
);
/**
* 授权子渠道
*
* @param studioId 场馆ID
...
...
@@ -138,7 +147,7 @@ public interface StudioMerchantService {
/**
* 解绑前置校验
*
* @param studioId
场馆ID
* @param studioId 场馆ID
* @return true:绑定过其他场馆;false-没有绑定过
*/
List
<
String
>
checkUnbind
(
Long
studioId
);
...
...
service/src/main/java/com/jiejing/fitness/finance/service/merchant/impl/StudioMerchantServiceImpl.java
View file @
a25711b3
...
...
@@ -242,7 +242,8 @@ public class StudioMerchantServiceImpl implements StudioMerchantService {
.
build
();
}
private
PartyToMerchant
getRelation
(
Long
studioId
)
{
@Override
public
PartyToMerchant
getRelation
(
Long
studioId
)
{
List
<
PartyToMerchant
>
relations
=
partyToMerchantRpService
.
listByParty
(
studioId
,
PartyTypeEnum
.
STUDIO
,
config
.
getCashier
());
if
(
CollectionUtil
.
isEmpty
(
relations
))
{
...
...
service/src/main/java/com/jiejing/fitness/finance/service/pay/RefundService.java
View file @
a25711b3
package
com
.
jiejing
.
fitness
.
finance
.
service
.
pay
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams
;
import
com.jiejing.paycenter.common.event.RefundEvent
;
import
com.jiejing.paycenter.common.model.vo.RefundVO
;
...
...
@@ -11,12 +12,20 @@ import com.jiejing.paycenter.common.model.vo.RefundVO;
public
interface
RefundService
{
/**
* 退款前检查
*
* @param params 参数
* @return 结果
*/
StudioMerchantRefundVO
checkBeforeMerchantRefund
(
StudioMerchantRefundParams
params
);
/**
* 商户退款
*
* @param params 参数
* @return 结果
*/
RefundVO
merchantRefund
(
StudioMerchantRefundParams
params
);
StudioMerchant
RefundVO
merchantRefund
(
StudioMerchantRefundParams
params
);
/**
* 退款回调
...
...
service/src/main/java/com/jiejing/fitness/finance/service/pay/convert/RefundConvert.java
View file @
a25711b3
...
...
@@ -3,6 +3,8 @@ package com.jiejing.fitness.finance.service.pay.convert;
import
com.baomidou.mybatisplus.core.toolkit.IdWorker
;
import
com.jiejing.common.utils.convert.BeanUtil
;
import
com.jiejing.fitness.enums.finance.BrandCashierTransStateEnum
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO.CheckRefundCodeEnum
;
import
com.jiejing.fitness.finance.repository.entity.StudioCashierRecord
;
import
com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams
;
import
com.jiejing.fitness.finance.service.utils.FeeUtil
;
...
...
@@ -82,4 +84,31 @@ public class RefundConvert {
return
null
;
}
}
public
static
StudioCashierRecord
convertRefundFail
(
StudioCashierRecord
record
,
StudioMerchantRefundVO
checkResult
)
{
return
StudioCashierRecord
.
builder
()
.
id
(
record
.
getId
())
.
transState
(
BrandCashierTransStateEnum
.
REFUND_FAIL
.
getCode
())
.
failMessage
(
checkResult
.
getFailMessage
())
.
updateTime
(
new
Date
())
.
build
();
}
public
static
StudioMerchantRefundVO
convertRefundVO
(
StudioCashierRecord
refund
,
RefundVO
vo
)
{
return
StudioMerchantRefundVO
.
builder
()
.
thirdTransNo
(
vo
.
getThirdTransNo
())
.
transNo
(
refund
.
getTransNo
())
.
failMessage
(
vo
.
getFailMessage
())
.
refundState
(
vo
.
getRefundState
())
.
successTime
(
vo
.
getSuccessTime
())
.
code
(
TransStateEnums
.
FAIL
==
TransStateEnums
.
getByCode
(
vo
.
getRefundState
())
?
CheckRefundCodeEnum
.
OTHER_ERROR
.
getCode
()
:
null
)
.
build
();
}
public
static
StudioMerchantRefundVO
convertRefundVO
(
CheckRefundCodeEnum
code
)
{
return
StudioMerchantRefundVO
.
builder
().
code
(
code
.
getCode
()).
failMessage
(
code
.
getMessage
()).
build
();
}
}
service/src/main/java/com/jiejing/fitness/finance/service/pay/impl/RefundServiceImpl.java
View file @
a25711b3
...
...
@@ -4,18 +4,27 @@ import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import
com.google.common.collect.Lists
;
import
com.jiejing.common.exception.BizException
;
import
com.jiejing.common.utils.collection.CollectionUtil
;
import
com.jiejing.common.utils.time.TimeUtil
;
import
com.jiejing.fitness.enums.auth.AuthDomainEnum
;
import
com.jiejing.fitness.enums.finance.BrandCashierTransStateEnum
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO
;
import
com.jiejing.fitness.finance.api.merchant.vo.StudioMerchantRefundVO.CheckRefundCodeEnum
;
import
com.jiejing.fitness.finance.repository.entity.PartyToMerchant
;
import
com.jiejing.fitness.finance.repository.entity.StudioCashierRecord
;
import
com.jiejing.fitness.finance.repository.service.StudioCashierRecordRpService
;
import
com.jiejing.fitness.finance.service.config.AppUrlProperties
;
import
com.jiejing.fitness.finance.service.enums.FinanceErrorEnums
;
import
com.jiejing.fitness.finance.service.global.ConfigService
;
import
com.jiejing.fitness.finance.service.global.dto.RefundConfigDTO
;
import
com.jiejing.fitness.finance.service.global.dto.RefundConfigDTO.RefuseTime
;
import
com.jiejing.fitness.finance.service.merchant.StudioMerchantService
;
import
com.jiejing.fitness.finance.service.pay.RefundService
;
import
com.jiejing.fitness.finance.service.pay.convert.RefundConvert
;
import
com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams
;
import
com.jiejing.fitness.finance.service.rpc.PayRpcService
;
import
com.jiejing.fitness.finance.service.rpc.PermissionRpcService
;
import
com.jiejing.fitness.finance.service.rpc.StudioRpcService
;
import
com.jiejing.fitness.finance.service.utils.MoneyUtil
;
import
com.jiejing.message.enums.MsgChannelEnum
;
import
com.jiejing.message.event.SendCommonMsgEvent
;
import
com.jiejing.paycenter.api.pay.request.RefundPayRequest
;
...
...
@@ -24,9 +33,13 @@ import com.jiejing.paycenter.common.event.RefundEvent;
import
com.jiejing.paycenter.common.model.vo.RefundVO
;
import
com.xiaomai.event.EventAgent
;
import
java.math.BigDecimal
;
import
java.time.temporal.ChronoUnit
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
import
java.util.concurrent.Executor
;
import
java.util.stream.Collectors
;
import
javax.annotation.Resource
;
...
...
@@ -46,6 +59,9 @@ public class RefundServiceImpl implements RefundService {
private
PayRpcService
payRpcService
;
@Resource
private
StudioMerchantService
studioMerchantService
;
@Resource
private
StudioCashierRecordRpService
studioCashierRecordRpService
;
@Resource
...
...
@@ -60,30 +76,55 @@ public class RefundServiceImpl implements RefundService {
@Resource
private
AppUrlProperties
appUrlProperties
;
@Resource
private
ConfigService
configService
;
@Resource
(
name
=
"financeThreadPool"
)
private
Executor
executor
;
@Override
public
RefundVO
merchantRefund
(
StudioMerchantRefundParams
params
)
{
StudioCashierRecord
refund
=
transactionTemplate
.
execute
(
action
->
{
Long
payId
=
Long
.
parseLong
(
params
.
getPayTransNo
());
StudioCashierRecord
pay
=
studioCashierRecordRpService
.
getById
(
payId
)
.
orElseThrow
(()
->
new
BizException
(
FinanceErrorEnums
.
NOT_EXIST
));
public
StudioMerchantRefundVO
checkBeforeMerchantRefund
(
StudioMerchantRefundParams
params
)
{
Long
payId
=
Long
.
parseLong
(
params
.
getPayTransNo
());
StudioCashierRecord
pay
=
studioCashierRecordRpService
.
getById
(
payId
)
.
orElseThrow
(()
->
new
BizException
(
FinanceErrorEnums
.
NOT_EXIST
));
RefundConfigDTO
config
=
configService
.
getRefundConfig
();
// 不是当前商户号收款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支
if
(!
this
.
isCurrentMerchant
(
params
.
getStudioId
(),
pay
.
getMerchantId
()))
{
return
RefundConvert
.
convertRefundVO
(
CheckRefundCodeEnum
.
NOT_CURRENT_MERCHANT
);
}
// 仅支持350天内交易进行退款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支
if
(
this
.
isDateLimit
(
pay
.
getSuccessTime
(),
config
.
getMaxDate
()))
{
return
RefundConvert
.
convertRefundVO
(
CheckRefundCodeEnum
.
DATE_LIMIT
);
}
// 当前时间段不支持退款,金额无法线上原路退回。如仍需退款请私下处理,系统会产生新的收支
if
(
this
.
isTimeLimit
(
new
Date
(),
config
.
getRefuseTimeList
()))
{
return
RefundConvert
.
convertRefundVO
(
CheckRefundCodeEnum
.
TIME_LIMIT
);
}
// 乐动收银可退金额不足
if
(
this
.
isAmountLimit
(
params
.
getTransAmount
(),
pay
))
{
return
RefundConvert
.
convertRefundVO
(
CheckRefundCodeEnum
.
AMOUNT_LIMIT
);
}
return
RefundConvert
.
convertRefundVO
(
CheckRefundCodeEnum
.
SUCCESS
);
}
BigDecimal
historyRefundActualAmount
=
studioCashierRecordRpService
.
sumRefundActualAmountByPayTransNo
(
params
.
getPayTransNo
());
@Override
public
StudioMerchantRefundVO
merchantRefund
(
StudioMerchantRefundParams
params
)
{
StudioCashierRecord
record
=
RefundConvert
.
convertRefundInit
(
params
,
pay
,
historyRefundActualAmount
);
studioCashierRecordRpService
.
insert
(
record
);
return
record
;
});
StudioCashierRecord
refund
=
this
.
initRefundRecord
(
params
);
StudioMerchantRefundVO
checkResult
=
this
.
checkBeforeMerchantRefund
(
params
);
if
(
CheckRefundCodeEnum
.
isFail
(
checkResult
.
getCode
()))
{
StudioCashierRecord
toModify
=
RefundConvert
.
convertRefundFail
(
refund
,
checkResult
);
studioCashierRecordRpService
.
updateById
(
toModify
);
return
checkResult
;
}
RefundPayRequest
request
=
RefundConvert
.
convert
(
params
,
refund
);
RefundVO
vo
=
payRpcService
.
refund
(
request
);
StudioCashierRecord
toModify
=
RefundConvert
.
convertRefund
(
refund
,
vo
);
studioCashierRecordRpService
.
updateById
(
toModify
);
return
vo
;
return
RefundConvert
.
convertRefundVO
(
refund
,
vo
)
;
}
@Override
...
...
@@ -154,4 +195,44 @@ public class RefundServiceImpl implements RefundService {
Lists
.
newArrayList
(
"FitSeeXmPay"
,
"FitManageXmPay"
),
false
);
}
private
StudioCashierRecord
initRefundRecord
(
StudioMerchantRefundParams
params
)
{
return
transactionTemplate
.
execute
(
action
->
{
Long
payId
=
Long
.
parseLong
(
params
.
getPayTransNo
());
StudioCashierRecord
pay
=
studioCashierRecordRpService
.
getById
(
payId
)
.
orElseThrow
(()
->
new
BizException
(
FinanceErrorEnums
.
NOT_EXIST
));
BigDecimal
historyRefundActualAmount
=
studioCashierRecordRpService
.
sumRefundActualAmountByPayTransNo
(
params
.
getPayTransNo
());
StudioCashierRecord
record
=
RefundConvert
.
convertRefundInit
(
params
,
pay
,
historyRefundActualAmount
);
studioCashierRecordRpService
.
insert
(
record
);
return
record
;
});
}
private
boolean
isCurrentMerchant
(
Long
studioId
,
Long
merchantId
)
{
PartyToMerchant
merchant
=
studioMerchantService
.
getRelation
(
studioId
);
if
(
null
==
merchant
)
{
return
false
;
}
return
merchant
.
getMerchantId
().
equals
(
merchantId
);
}
private
boolean
isDateLimit
(
Date
successTime
,
Long
maxDate
)
{
return
TimeUtil
.
local
().
diff
(
new
Date
(),
successTime
,
ChronoUnit
.
DAYS
)
>
maxDate
;
}
private
boolean
isTimeLimit
(
Date
now
,
List
<
RefuseTime
>
refuseTimeList
)
{
int
minute
=
TimeUtil
.
local
().
getMinuteOfDay
(
now
);
return
refuseTimeList
.
stream
().
anyMatch
(
refuseTime
->
minute
>=
refuseTime
.
getStart
()
&&
minute
<=
refuseTime
.
getEnd
());
}
private
boolean
isAmountLimit
(
BigDecimal
refundAmount
,
StudioCashierRecord
pay
)
{
BigDecimal
historyRefundAmount
=
studioCashierRecordRpService
.
sumRefundTransAmountByPayTransNo
(
pay
.
getTransNo
());
BigDecimal
leftTransAmount
=
MoneyUtil
.
subtract
(
pay
.
getTransAmount
(),
historyRefundAmount
);
return
refundAmount
.
compareTo
(
leftTransAmount
)
>
0
;
}
}
service/src/main/java/com/jiejing/fitness/finance/service/utils/FeeUtil.java
View file @
a25711b3
...
...
@@ -2,7 +2,6 @@ package com.jiejing.fitness.finance.service.utils;
import
java.math.BigDecimal
;
import
java.math.RoundingMode
;
import
java.util.Objects
;
/**
* @author chengyubing
...
...
@@ -14,7 +13,7 @@ public class FeeUtil {
* 【支付】计算支付手续费,保留小数点后两位,四舍五入
*
* @param feeRate 费率(%)
* @param amount 支付金额
* @param amount 支付金额
(元)
* @return 手续费
*/
public
static
BigDecimal
calPayFee
(
BigDecimal
feeRate
,
BigDecimal
amount
)
{
...
...
@@ -24,23 +23,23 @@ public class FeeUtil {
}
/**
* 【退款】计算退款手续费
* 【退款】计算退款手续费
(元)
*
* <p>实退手续费计算公式:退款手续费=向下取整(退款金额*原交易手续费金额/原交易金额)</p>
*
* @param refundTransAmount 退款申请金额
* @param payTransAmount 原支付交易金额
* @param payActualAmount 用户实收金额
* @param payFee 平台实收手续费
* @param historyRefundActualAmount 历史实退金额
* @return 本次退款应退手续费
* @param refundTransAmount 退款申请金额
(元)
* @param payTransAmount 原支付交易金额
(元)
* @param payActualAmount 用户实收金额
(元)
* @param payFee 平台实收手续费
(元)
* @param historyRefundActualAmount 历史实退金额
(元)
* @return 本次退款应退手续费
(元)
*/
public
static
BigDecimal
calculateRefundFee
(
BigDecimal
refundTransAmount
,
BigDecimal
payTransAmount
,
BigDecimal
payActualAmount
,
BigDecimal
payFee
,
BigDecimal
historyRefundActualAmount
)
{
// 机构剩余实收金额
BigDecimal
leftPayActualAmount
=
MoneyUtil
.
subtract
(
payActualAmount
,
historyRefundActualAmount
);
// 试算手续费
BigDecimal
trialFee
=
MoneyUtil
.
divide
(
refundTransAmount
.
multiply
(
payFee
),
payTransAmount
,
0
,
// 试算手续费
:向下取整(退款金额/原交易金额*原支付交易手续费金额)
BigDecimal
trialFee
=
MoneyUtil
.
divide
(
refundTransAmount
.
multiply
(
payFee
),
payTransAmount
,
2
,
RoundingMode
.
FLOOR
);
// 试算实退金额
BigDecimal
trialActualAmount
=
MoneyUtil
.
subtract
(
refundTransAmount
,
trialFee
);
...
...
@@ -49,77 +48,17 @@ public class FeeUtil {
:
MoneyUtil
.
add
(
trialFee
,
MoneyUtil
.
subtract
(
trialActualAmount
,
leftPayActualAmount
));
}
/**
* 计算补贴回退金额(向上取整ceil)
*
* @param refundTransAmount 退款申请金额
* @param payTransAmount 原支付交易金额
* @param subsidyAmount 补贴金额
* @param historyBackAmount 历史补贴回退金额
* @return 补贴回退金额
*/
public
static
BigDecimal
calculateSubsidyBackAmount
(
BigDecimal
refundTransAmount
,
BigDecimal
payTransAmount
,
BigDecimal
subsidyAmount
,
BigDecimal
historyBackAmount
)
{
if
(
Objects
.
isNull
(
subsidyAmount
))
{
return
BigDecimal
.
ZERO
;
}
// 剩余可回退补贴金额
BigDecimal
leftSubsidyBackAmount
=
MoneyUtil
.
subtract
(
subsidyAmount
,
historyBackAmount
);
// 试算补贴回退金额
BigDecimal
trialAmount
=
MoneyUtil
.
divide
(
refundTransAmount
.
multiply
(
subsidyAmount
),
payTransAmount
,
0
,
RoundingMode
.
CEILING
);
return
leftSubsidyBackAmount
.
compareTo
(
trialAmount
)
>=
0
?
trialAmount
:
leftSubsidyBackAmount
;
}
public
static
BigDecimal
calculateAdvanceAmount
(
BigDecimal
refundAmount
,
BigDecimal
qyqbhTransitBalance
,
BigDecimal
yxyjhTransitBalance
)
{
BigDecimal
transitBalance
=
MoneyUtil
.
subtract
(
qyqbhTransitBalance
,
yxyjhTransitBalance
);
if
(
refundAmount
.
compareTo
(
transitBalance
)
<=
0
)
{
// 若:退款金额 <= 业务钱包入账中余额,则无需佣金垫付记录记账
return
null
;
}
// 若:退款金额 > 业务钱包入账中余额,则添加佣金垫付记录记账
// 垫付金额 = (退款金额 - 业务入帐中金额) > 佣金入账中 ? 佣金入账中 : (退款金额 - 入帐中金额)
BigDecimal
advanceAmount
=
MoneyUtil
.
subtract
(
refundAmount
,
transitBalance
);
if
(
advanceAmount
.
compareTo
(
yxyjhTransitBalance
)
>
0
)
{
advanceAmount
=
yxyjhTransitBalance
;
}
return
advanceAmount
;
}
public
static
void
main
(
String
[]
args
)
{
// 1. 首次退款
// BigDecimal refundTransAmount = new BigDecimal("498");
// BigDecimal payTransAmount = new BigDecimal("500");
// BigDecimal payActualAmount = new BigDecimal("498");
// BigDecimal payFee = new BigDecimal("2");
// BigDecimal historyRefundActualAmount = new BigDecimal("0");
// 预计输出:1
// 实退金额:497, 实退手续费:1。剩余可退金额:2(剩余实退金额:1,剩余实退手续费:1),历史实退金额:497,历史实退手续费:1
// 2. 二次退款
// BigDecimal refundTransAmount = new BigDecimal("1");
// BigDecimal payTransAmount = new BigDecimal("500");
// BigDecimal payActualAmount = new BigDecimal("498");
// BigDecimal payFee = new BigDecimal("2");
// BigDecimal historyRefundActualAmount = new BigDecimal("497");
// 预计输出:0
// 实退金额:1,实退手续费:0。剩余可退金额:1(剩余实退金额:0,剩余实退手续费:1),历史实退金额:498,历史实退手续费:1
// 3. 三次退款
BigDecimal
refundTransAmount
=
new
BigDecimal
(
"40"
);
BigDecimal
payTransAmount
=
new
BigDecimal
(
"10000"
);
BigDecimal
payActualAmount
=
new
BigDecimal
(
"9943"
);
BigDecimal
payFee
=
new
BigDecimal
(
"57"
);
BigDecimal
historyRefundActualAmount
=
new
BigDecimal
(
"9904"
);
BigDecimal
refundTransAmount
=
new
BigDecimal
(
"100"
);
BigDecimal
payTransAmount
=
new
BigDecimal
(
"100"
);
BigDecimal
payActualAmount
=
new
BigDecimal
(
"99.43"
);
BigDecimal
payFee
=
new
BigDecimal
(
"0.57"
);
BigDecimal
historyRefundActualAmount
=
new
BigDecimal
(
"99.43"
);
// 预计输出:1
// 实退金额:0,实退手续费:1。剩余可退金额:0,历史实退金额:498,历史实退手续费:2
System
.
out
.
println
(
FeeUtil
.
calculateRefundFee
(
refundTransAmount
,
payTransAmount
,
payActualAmount
,
payFee
,
historyRefundActualAmount
));
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment