记得上下班打卡 | git大法好,push需谨慎
Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liquidnet-bus-v1
Project
Project
Details
Activity
Releases
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
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
董敬伟
liquidnet-bus-v1
Commits
9ca7ab4f
Commit
9ca7ab4f
authored
Jul 10, 2026
by
wangyifan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加退款锁
parent
0d43204a
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
325 additions
and
90 deletions
+325
-90
GoblinRedisConst.java
...m/liquidnet/service/goblin/constant/GoblinRedisConst.java
+6
-0
RedisKeyExpireConst.java
.../liquidnet/service/base/constant/RedisKeyExpireConst.java
+10
-0
GoblinSqbServiceImpl.java
...net/service/goblin/service/impl/GoblinSqbServiceImpl.java
+173
-32
GoblinSqbRedisUtils.java
...om/liquidnet/service/goblin/util/GoblinSqbRedisUtils.java
+21
-0
GoblinSqbOrderServiceImpl.java
...service/order/service/impl/GoblinSqbOrderServiceImpl.java
+93
-58
GoblinSqbRedisUtils.java
...om/liquidnet/service/order/utils/GoblinSqbRedisUtils.java
+22
-0
No files found.
liquidnet-bus-api/liquidnet-service-goblin-api/src/main/java/com/liquidnet/service/goblin/constant/GoblinRedisConst.java
View file @
9ca7ab4f
...
@@ -461,6 +461,12 @@ public class GoblinRedisConst {
...
@@ -461,6 +461,12 @@ public class GoblinRedisConst {
*/
*/
public
static
final
String
REFUND_ORDER_LOCK
=
PREFIX
.
concat
(
"refund:lock:"
);
public
static
final
String
REFUND_ORDER_LOCK
=
PREFIX
.
concat
(
"refund:lock:"
);
/**
* 收钱吧退款库存已归还标记(防回调重复还库存)
* {goblin:sqb:refund:stock:${orderId}}
*/
public
static
final
String
SQB_REFUND_STOCK_FLAG
=
PREFIX
.
concat
(
"sqb:refund:stock:"
);
/**
/**
* 收钱吧 用户订单列表
* 收钱吧 用户订单列表
*/
*/
...
...
liquidnet-bus-common/liquidnet-common-service-base/src/main/java/com/liquidnet/service/base/constant/RedisKeyExpireConst.java
View file @
9ca7ab4f
...
@@ -67,6 +67,16 @@ public class RedisKeyExpireConst {
...
@@ -67,6 +67,16 @@ public class RedisKeyExpireConst {
*/
*/
public
static
final
long
SQB_ORDER_LOCK_EXPIRE
=
10
;
public
static
final
long
SQB_ORDER_LOCK_EXPIRE
=
10
;
/**
* 收钱吧退款锁过期时间 (60秒,覆盖调收钱吧退款 API)
*/
public
static
final
long
SQB_REFUND_LOCK_EXPIRE
=
60
;
/**
* 收钱吧退款库存归还标记过期时间 (30天)
*/
public
static
final
long
SQB_REFUND_STOCK_FLAG_EXPIRE
=
30
*
24
*
60
*
60
;
// 已发布状态徽章过期时间:30天
// 已发布状态徽章过期时间:30天
public
static
final
long
CAOMEI_BADGE_PUBLISHED_EXPIRE
=
30
*
24
*
60
*
60
;
public
static
final
long
CAOMEI_BADGE_PUBLISHED_EXPIRE
=
30
*
24
*
60
*
60
;
}
}
liquidnet-bus-service/liquidnet-service-goblin/liquidnet-service-goblin-impl/src/main/java/com/liquidnet/service/goblin/service/impl/GoblinSqbServiceImpl.java
View file @
9ca7ab4f
This diff is collapsed.
Click to expand it.
liquidnet-bus-service/liquidnet-service-goblin/liquidnet-service-goblin-impl/src/main/java/com/liquidnet/service/goblin/util/GoblinSqbRedisUtils.java
View file @
9ca7ab4f
...
@@ -90,6 +90,27 @@ public class GoblinSqbRedisUtils {
...
@@ -90,6 +90,27 @@ public class GoblinSqbRedisUtils {
redisUtil
.
uLock
(
key
);
redisUtil
.
uLock
(
key
);
}
}
/* ---------------------------------------- 退款锁 / 库存归还幂等 ---------------------------------------- */
/**
* 尝试获取收钱吧退款锁(发起退款与退款回调共用,按 orderId)
*/
public
boolean
tryRefundLock
(
String
orderId
)
{
String
key
=
GoblinRedisConst
.
REFUND_ORDER_LOCK
.
concat
(
orderId
);
return
redisUtil
.
lock
(
key
,
1
,
RedisKeyExpireConst
.
SQB_REFUND_LOCK_EXPIRE
);
}
public
void
releaseRefundLock
(
String
orderId
)
{
redisUtil
.
uLock
(
GoblinRedisConst
.
REFUND_ORDER_LOCK
.
concat
(
orderId
));
}
/**
* 标记退款库存已归还。首次标记成功返回 true(应执行 incrSkuStock),已标记过返回 false。
*/
public
boolean
tryMarkRefundStockRestored
(
String
orderId
)
{
String
key
=
GoblinRedisConst
.
SQB_REFUND_STOCK_FLAG
.
concat
(
orderId
);
return
redisUtil
.
lock
(
key
,
1
,
RedisKeyExpireConst
.
SQB_REFUND_STOCK_FLAG_EXPIRE
);
}
// 获取 收钱吧订单id列表
// 获取 收钱吧订单id列表
public
List
<
String
>
getSqbOrderList
(
String
uid
)
{
public
List
<
String
>
getSqbOrderList
(
String
uid
)
{
...
...
liquidnet-bus-service/liquidnet-service-order/liquidnet-service-order-impl/src/main/java/com/liquidnet/service/order/service/impl/GoblinSqbOrderServiceImpl.java
View file @
9ca7ab4f
...
@@ -257,8 +257,10 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -257,8 +257,10 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
orderSkuVo
.
setSkuImage
(
skuImg
);
orderSkuVo
.
setSkuImage
(
skuImg
);
orderSkuVo
.
setSkuSpecs
(
"[]"
);
orderSkuVo
.
setSkuSpecs
(
"[]"
);
orderSkuVo
.
setPriceVoucher
(
BigDecimal
.
ZERO
);
orderSkuVo
.
setPriceVoucher
(
BigDecimal
.
ZERO
);
orderSkuVo
.
setPriceRefund
(
BigDecimal
.
ZERO
);
orderSkuVo
.
setCreatedAt
(
now
);
orderSkuVo
.
setCreatedAt
(
now
);
// 特殊标识类型:33
// 待支付;特殊标识类型:33
orderSkuVo
.
setStatus
(
GoblinStatusConst
.
Status
.
ORDER_STATUS_0
.
getValue
());
orderSkuVo
.
setSkuType
(
33
);
orderSkuVo
.
setSkuType
(
33
);
// 存入 Redis 并绑定关系
// 存入 Redis 并绑定关系
...
@@ -519,7 +521,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -519,7 +521,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
/**
/**
* 退款完成回调(targetState=20)。
* 退款完成回调(targetState=20)。
* 主单 status→6(退款通过) + priceRefund→实付金额,子单 status→6 + priceRefund→实付金额,
* 主单 status→6(退款通过) + priceRefund→实付金额,子单 status→6 + priceRefund→实付金额,
* 恢复库存,主单/子单/扩展单批量落库 MySQL。
* 恢复库存
(幂等)
,主单/子单/扩展单批量落库 MySQL。
*/
*/
@Override
@Override
public
ResponseDto
<
String
>
handleRefundCallback
(
RefundCallbackContent
refundCallbackContent
)
{
public
ResponseDto
<
String
>
handleRefundCallback
(
RefundCallbackContent
refundCallbackContent
)
{
...
@@ -536,6 +538,12 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -536,6 +538,12 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
final
String
orderId
=
goblinSqbRedisUtils
.
getOrderIdBySqbOrderSn
(
sqbOrderSn
);
final
String
orderId
=
goblinSqbRedisUtils
.
getOrderIdBySqbOrderSn
(
sqbOrderSn
);
if
(
StringUtil
.
isBlank
(
orderId
))
return
ResponseDto
.
failure
(
"订单不存在"
);
if
(
StringUtil
.
isBlank
(
orderId
))
return
ResponseDto
.
failure
(
"订单不存在"
);
if
(!
tryAcquireRefundLock
(
orderId
))
{
log
.
warn
(
"[收钱吧退款回调] 获取退款锁失败,稍后重试 orderId={}"
,
orderId
);
return
ResponseDto
.
failure
(
"退款处理中"
);
}
try
{
GoblinSqbOrderVo
orderVo
=
goblinSqbRedisUtils
.
getSqbOrder
(
orderId
);
GoblinSqbOrderVo
orderVo
=
goblinSqbRedisUtils
.
getSqbOrder
(
orderId
);
if
(
orderVo
==
null
)
return
ResponseDto
.
failure
(
"订单不存在"
);
if
(
orderVo
==
null
)
return
ResponseDto
.
failure
(
"订单不存在"
);
GoblinStoreOrderVo
storeOrderVo
=
goblinRedisUtils
.
getGoblinOrder
(
orderId
);
GoblinStoreOrderVo
storeOrderVo
=
goblinRedisUtils
.
getGoblinOrder
(
orderId
);
...
@@ -574,8 +582,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -574,8 +582,14 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
goblinRedisUtils
.
setGoblinOrder
(
orderId
,
storeOrderVo
);
goblinRedisUtils
.
setGoblinOrder
(
orderId
,
storeOrderVo
);
goblinMongoUtils
.
updateGoblinStoreOrderVo
(
orderId
,
storeOrderVo
);
goblinMongoUtils
.
updateGoblinStoreOrderVo
(
orderId
,
storeOrderVo
);
// 恢复库存
// 恢复库存(SETNX 幂等,防重复回调双还)
if
(
goblinSqbRedisUtils
.
tryMarkRefundStockRestored
(
orderId
))
{
goblinRedisUtils
.
incrSkuStock
(
null
,
orderVo
.
getSkuId
(),
orderVo
.
getQuantity
());
goblinRedisUtils
.
incrSkuStock
(
null
,
orderVo
.
getSkuId
(),
orderVo
.
getQuantity
());
log
.
info
(
"[收钱吧退款回调] 库存已归还 orderId={}, skuId={}, qty={}"
,
orderId
,
orderVo
.
getSkuId
(),
orderVo
.
getQuantity
());
}
else
{
log
.
info
(
"[收钱吧退款回调] 库存已归还过,跳过 orderId={}"
,
orderId
);
}
// 批量落库 MySQL
// 批量落库 MySQL
LinkedList
<
String
>
sqls
=
new
LinkedList
<>();
LinkedList
<
String
>
sqls
=
new
LinkedList
<>();
...
@@ -606,6 +620,9 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -606,6 +620,9 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
log
.
info
(
"[收钱吧退款回调] targetState=20 更新退款状态成功,orderId={}"
,
orderId
);
log
.
info
(
"[收钱吧退款回调] targetState=20 更新退款状态成功,orderId={}"
,
orderId
);
return
ResponseDto
.
success
(
"success"
);
return
ResponseDto
.
success
(
"success"
);
}
finally
{
goblinSqbRedisUtils
.
releaseRefundLock
(
orderId
);
}
}
}
@Override
@Override
...
@@ -892,6 +909,24 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
...
@@ -892,6 +909,24 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
return
0
;
return
0
;
}
}
/**
* 退款回调抢锁:与发起退款共用 orderId 锁;短暂重试,避免发起侧刚释放前回调直接失败。
*/
private
boolean
tryAcquireRefundLock
(
String
orderId
)
{
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
if
(
goblinSqbRedisUtils
.
tryRefundLock
(
orderId
))
{
return
true
;
}
try
{
Thread
.
sleep
(
200L
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
return
false
;
}
}
return
false
;
}
/**
/**
* 将收钱吧内部状态码映射为商城主单 status,同步 Redis / MongoDB / MySQL。
* 将收钱吧内部状态码映射为商城主单 status,同步 Redis / MongoDB / MySQL。
*/
*/
...
...
liquidnet-bus-service/liquidnet-service-order/liquidnet-service-order-impl/src/main/java/com/liquidnet/service/order/utils/GoblinSqbRedisUtils.java
View file @
9ca7ab4f
...
@@ -88,6 +88,28 @@ public class GoblinSqbRedisUtils {
...
@@ -88,6 +88,28 @@ public class GoblinSqbRedisUtils {
redisUtil
.
uLock
(
key
);
redisUtil
.
uLock
(
key
);
}
}
/* ---------------------------------------- 退款锁 / 库存归还幂等 ---------------------------------------- */
/**
* 尝试获取收钱吧退款锁(发起退款与退款回调共用,按 orderId)
*/
public
boolean
tryRefundLock
(
String
orderId
)
{
String
key
=
GoblinRedisConst
.
REFUND_ORDER_LOCK
.
concat
(
orderId
);
return
redisUtil
.
lock
(
key
,
1
,
RedisKeyExpireConst
.
SQB_REFUND_LOCK_EXPIRE
);
}
public
void
releaseRefundLock
(
String
orderId
)
{
redisUtil
.
uLock
(
GoblinRedisConst
.
REFUND_ORDER_LOCK
.
concat
(
orderId
));
}
/**
* 标记退款库存已归还。首次标记成功返回 true(应执行 incrSkuStock),已标记过返回 false。
*/
public
boolean
tryMarkRefundStockRestored
(
String
orderId
)
{
String
key
=
GoblinRedisConst
.
SQB_REFUND_STOCK_FLAG
.
concat
(
orderId
);
return
redisUtil
.
lock
(
key
,
1
,
RedisKeyExpireConst
.
SQB_REFUND_STOCK_FLAG_EXPIRE
);
}
/**
/**
* 添加用户 收钱吧订单列表
* 添加用户 收钱吧订单列表
*
*
...
...
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