支付优化
This commit is contained in:
@ -22,9 +22,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
@ -52,6 +50,8 @@ public class AmountServiceImpl implements AmountService {
|
||||
@Resource
|
||||
private RechargeLogMapper rechargeLogMapper;
|
||||
|
||||
public final static Map<String, Object> userLocks = new WeakHashMap<>();
|
||||
|
||||
@Override
|
||||
public void operateAmount(Long userId, BigDecimal money, BigDecimal cashAmount, BigDecimal giftAmount, BigDecimal wxAmount) {
|
||||
synchronized (userId) {
|
||||
|
@ -23,6 +23,8 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock;
|
||||
|
||||
/**
|
||||
* 现金充值 Service 实现类
|
||||
*
|
||||
@ -62,7 +64,7 @@ public class CashRechargeServiceImpl implements CashRechargeService{
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewAmount;
|
||||
|
||||
synchronized (userId){
|
||||
synchronized (getUserLock(userId)){
|
||||
MemberUserDO memberUserDO = userMapper.selectById(userId);
|
||||
//金额变动
|
||||
memberUserDO.setMoney(memberUserDO.getMoney().add(money));
|
||||
|
@ -31,4 +31,9 @@ public interface DeductionService {
|
||||
* 减免
|
||||
*/
|
||||
void reduction(Long userId, BigDecimal money, BigDecimal giftAmount, BigDecimal cashAmount, BigDecimal wxAmount);
|
||||
|
||||
/**
|
||||
* 超市扣款
|
||||
*/
|
||||
BigDecimal storeDeduction(BigDecimal total, Long userId);
|
||||
}
|
||||
|
@ -18,17 +18,20 @@ import cn.iocoder.yudao.module.member.service.order.OrderService;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
import cn.iocoder.yudao.module.member.util.MemberConstants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.sun.istack.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.CASH_AMOUNT_NOT_ENOUGH;
|
||||
import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock;
|
||||
|
||||
|
||||
/**
|
||||
@ -58,9 +61,9 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
BigDecimal changeMoney;
|
||||
BigDecimal wxNewMoney;
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewAmount;
|
||||
BigDecimal cashNewMoney;
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
|
||||
//新的总价
|
||||
@ -142,7 +145,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
newMoney = user.getMoney();
|
||||
wxNewMoney = user.getWxAmount();
|
||||
giftNewMoney = user.getGiftAmount();
|
||||
cashNewAmount = user.getCashAmount();
|
||||
cashNewMoney = user.getCashAmount();
|
||||
changeMoney = total;
|
||||
}
|
||||
|
||||
@ -154,7 +157,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
cardDO.setChangeMoney(changeMoney);
|
||||
cardDO.setFlag(CardDO.MINUS);
|
||||
cardDO.setMoney(newMoney);
|
||||
cardDO.setCashAmount(cashNewAmount);
|
||||
cardDO.setCashAmount(cashNewMoney);
|
||||
cardDO.setWxAmount(wxNewMoney);
|
||||
cardDO.setGiftAmount(giftNewMoney);
|
||||
|
||||
@ -184,9 +187,9 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
BigDecimal newMoney;
|
||||
BigDecimal wxNewMoney;
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewAmount;
|
||||
BigDecimal cashNewMoney;
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
if (ObjectUtil.isEmpty(user) || user.getCashAmount().compareTo(BigDecimal.ZERO) < 1
|
||||
|| money.compareTo(user.getCashAmount()) > 0) {
|
||||
@ -198,7 +201,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
newMoney = user.getMoney();
|
||||
wxNewMoney = user.getWxAmount();
|
||||
giftNewMoney = user.getGiftAmount();
|
||||
cashNewAmount = user.getCashAmount();
|
||||
cashNewMoney = user.getCashAmount();
|
||||
}
|
||||
|
||||
CardDO cardDO = new CardDO();
|
||||
@ -209,7 +212,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
cardDO.setWxAmount(wxNewMoney);
|
||||
cardDO.setGiftAmount(giftNewMoney);
|
||||
cardDO.setMoney(newMoney);
|
||||
cardDO.setCashAmount(cashNewAmount);
|
||||
cardDO.setCashAmount(cashNewMoney);
|
||||
cardService.insertOne(cardDO);
|
||||
}
|
||||
|
||||
@ -219,10 +222,10 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
BigDecimal newMoney;
|
||||
BigDecimal wxNewMoney;
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewAmount;
|
||||
BigDecimal cashNewMoney;
|
||||
BigDecimal changeMoney = new BigDecimal(amount).divide(new BigDecimal("100"));
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
user.setWxAmount(user.getWxAmount().subtract(changeMoney));
|
||||
user.setMoney(user.getMoney().subtract(changeMoney));
|
||||
@ -230,7 +233,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
newMoney = user.getMoney();
|
||||
wxNewMoney = user.getWxAmount();
|
||||
giftNewMoney = user.getGiftAmount();
|
||||
cashNewAmount = user.getCashAmount();
|
||||
cashNewMoney = user.getCashAmount();
|
||||
}
|
||||
|
||||
|
||||
@ -244,7 +247,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
cardDO.setWxAmount(wxNewMoney);
|
||||
cardDO.setGiftAmount(giftNewMoney);
|
||||
cardDO.setMoney(newMoney);
|
||||
cardDO.setCashAmount(cashNewAmount);
|
||||
cardDO.setCashAmount(cashNewMoney);
|
||||
cardService.insertOne(cardDO);
|
||||
}
|
||||
|
||||
@ -254,9 +257,9 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
BigDecimal newMoney2;
|
||||
BigDecimal wxNewMoney;
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewAmount;
|
||||
BigDecimal cashNewMoney;
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
BigDecimal oldMoney = user.getMoney();
|
||||
|
||||
@ -305,7 +308,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
newMoney2 = user.getMoney();
|
||||
wxNewMoney = user.getWxAmount();
|
||||
giftNewMoney = user.getGiftAmount();
|
||||
cashNewAmount = user.getCashAmount();
|
||||
cashNewMoney = user.getCashAmount();
|
||||
|
||||
}
|
||||
|
||||
@ -317,7 +320,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
cardDO.setWxAmount(wxNewMoney);
|
||||
cardDO.setGiftAmount(giftNewMoney);
|
||||
cardDO.setMoney(newMoney2);
|
||||
cardDO.setCashAmount(cashNewAmount);
|
||||
cardDO.setCashAmount(cashNewMoney);
|
||||
|
||||
cardService.insertOne(cardDO);
|
||||
}
|
||||
@ -325,12 +328,12 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
@Override
|
||||
public void reduction(Long userId, BigDecimal money, BigDecimal giftAmount, BigDecimal cashAmount, BigDecimal wxAmount) {
|
||||
|
||||
BigDecimal NewMoney;
|
||||
BigDecimal newMoney;
|
||||
BigDecimal giftNewAmount;
|
||||
BigDecimal cashNewAmount;
|
||||
BigDecimal wxNewAmount;
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
user.setMoney(user.getMoney().add(money));
|
||||
user.setCashAmount(user.getCashAmount().add(cashAmount));
|
||||
@ -338,7 +341,7 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
user.setWxAmount(user.getWxAmount().add(wxAmount));
|
||||
userService.updateById(user);
|
||||
|
||||
NewMoney = user.getMoney();
|
||||
newMoney = user.getMoney();
|
||||
wxNewAmount = user.getWxAmount();
|
||||
giftNewAmount = user.getGiftAmount();
|
||||
cashNewAmount = user.getCashAmount();
|
||||
@ -348,11 +351,62 @@ public class DeductionServiceImpl implements DeductionService {
|
||||
cardDO.setFlag(CardDO.ADD);
|
||||
cardDO.setChangeMoney(money);
|
||||
cardDO.setType(CostTypeEnum.REFUND.getCode());
|
||||
cardDO.setMoney(NewMoney);
|
||||
cardDO.setMoney(newMoney);
|
||||
cardDO.setWxAmount(wxNewAmount);
|
||||
cardDO.setCashAmount(cashNewAmount);
|
||||
cardDO.setGiftAmount(giftNewAmount);
|
||||
cardService.insertOne(cardDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigDecimal storeDeduction(BigDecimal total, @NotNull Long userId) {
|
||||
|
||||
BigDecimal newMoney;
|
||||
BigDecimal wxNewMoney;
|
||||
BigDecimal giftNewMoney;
|
||||
BigDecimal cashNewMoney;
|
||||
synchronized (getUserLock(userId)) {
|
||||
MemberUserDO user = userService.getUser(userId);
|
||||
BigDecimal money = user.getMoney();
|
||||
if (total.compareTo(money) > 0){
|
||||
return money.subtract(total);
|
||||
}
|
||||
BigDecimal wxAmount = user.getWxAmount();
|
||||
BigDecimal giftAmount = user.getGiftAmount();
|
||||
BigDecimal cashAmount = user.getCashAmount();
|
||||
user.setMoney(money.subtract(total));
|
||||
|
||||
//计算金额
|
||||
if (total.compareTo(cashAmount) <= 0) {
|
||||
user.setCashAmount(cashAmount.subtract(total));
|
||||
} else {
|
||||
user.setCashAmount(BigDecimal.ZERO);
|
||||
BigDecimal total1 = total.subtract(cashAmount);
|
||||
if (total1.compareTo(giftAmount) <= 0) {
|
||||
user.setGiftAmount(giftAmount.subtract(total1));
|
||||
} else {
|
||||
user.setGiftAmount(BigDecimal.ZERO);
|
||||
BigDecimal total2 = total1.subtract(giftAmount);
|
||||
user.setWxAmount(wxAmount.subtract(total2));
|
||||
}
|
||||
}
|
||||
userService.updateById(user);
|
||||
newMoney = user.getMoney();
|
||||
wxNewMoney = user.getWxAmount();
|
||||
giftNewMoney = user.getGiftAmount();
|
||||
cashNewMoney = user.getCashAmount();
|
||||
}
|
||||
|
||||
CardDO cardDO = new CardDO();
|
||||
cardDO.setUserId(userId);
|
||||
cardDO.setChangeMoney(total);
|
||||
cardDO.setFlag(CardDO.MINUS);
|
||||
cardService.insertOne(cardDO);
|
||||
cardDO.setMoney(newMoney);
|
||||
cardDO.setWxAmount(wxNewMoney);
|
||||
cardDO.setCashAmount(cashNewMoney);
|
||||
cardDO.setGiftAmount(giftNewMoney);
|
||||
return cardDO.getMoney();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
package cn.iocoder.yudao.module.member.service.amount;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LockManager {
|
||||
|
||||
private static final ConcurrentHashMap<Long, WeakReference<Object>> userLocks = new ConcurrentHashMap<>();
|
||||
|
||||
private static final ConcurrentHashMap<Long, Object> storeLocks = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public static Object getUserLock(Long userId) {
|
||||
// 从 Map 中获取 WeakReference 对象
|
||||
WeakReference<Object> lockRef = userLocks.get(userId);
|
||||
Object lock = (lockRef != null) ? lockRef.get() : null;
|
||||
|
||||
if (lock == null) {
|
||||
// 如果锁对象不存在或者已被回收,创建新的锁对象
|
||||
lock = new Object();
|
||||
WeakReference<Object> newLockRef = new WeakReference<>(lock);
|
||||
// 使用 putIfAbsent 确保线程安全
|
||||
WeakReference<Object> existingLockRef = userLocks.putIfAbsent(userId, newLockRef);
|
||||
if (existingLockRef != null) {
|
||||
lock = existingLockRef.get();
|
||||
if (lock == null) {
|
||||
// 如果弱引用对象已经被 GC 回收,更新锁对象
|
||||
userLocks.put(userId, newLockRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
|
||||
public static Object getStoreLock(Long storeId) {
|
||||
// 对每个 userId 生成独立的锁对象,并发地存储在 ConcurrentHashMap 中
|
||||
return storeLocks.computeIfAbsent(storeId, k -> new Object());
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.module.member.service.amount.LockManager.getUserLock;
|
||||
|
||||
|
||||
/**
|
||||
@ -56,7 +57,7 @@ public class WxRechargeServiceImpl implements WxRechargeService {
|
||||
BigDecimal cashNewAmount;
|
||||
|
||||
|
||||
synchronized (userId) {
|
||||
synchronized (getUserLock(userId)) {
|
||||
//获取最新余额
|
||||
MemberUserDO memberUserDO = userMapper.selectById(userId);
|
||||
|
||||
|
@ -42,6 +42,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.member.service.amount.LockManager.getStoreLock;
|
||||
|
||||
/**
|
||||
* 营业统计 Service 实现类
|
||||
@ -105,7 +106,7 @@ public class BusinessServiceImpl implements BusinessService {
|
||||
|
||||
@Override
|
||||
public void updateStatistics(StatisticsVo vo) {
|
||||
synchronized(vo.getCarteenId()){
|
||||
synchronized(getStoreLock(vo.getCarteenId())){
|
||||
// 获取今天的开始时间
|
||||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
|
||||
// 获取今天的结束时间 (23:59:59.999)
|
||||
|
@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.member.dal.dataobject.storeorderdetail.StoreOrder
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.storeorder.StoreOrderMapper;
|
||||
import cn.iocoder.yudao.module.member.enums.CostTypeEnum;
|
||||
import cn.iocoder.yudao.module.member.service.amount.DeductionService;
|
||||
import cn.iocoder.yudao.module.member.service.card.CardService;
|
||||
import cn.iocoder.yudao.module.member.service.storeorderdetail.StoreOrderDetailService;
|
||||
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
|
||||
@ -59,6 +60,11 @@ public class StoreOrderServiceImpl implements StoreOrderService {
|
||||
@Resource
|
||||
private MemberUserService userService;
|
||||
|
||||
@Resource
|
||||
private DeductionService deductionService;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Integer createStoreOrder(StoreOrderSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
@ -200,45 +206,7 @@ public class StoreOrderServiceImpl implements StoreOrderService {
|
||||
}
|
||||
|
||||
public BigDecimal compute(BigDecimal total, Long userId) {
|
||||
//新的总价
|
||||
CardDO cardDO = new CardDO();
|
||||
cardDO.setType(CostTypeEnum.SHOPPING.getCode());
|
||||
CardDO oldCardDO = cardService.getCardDoByUserId(userId);
|
||||
|
||||
|
||||
BigDecimal money = oldCardDO.getMoney();
|
||||
|
||||
if (total.compareTo(money) > 0) {
|
||||
return money.subtract(total);
|
||||
}
|
||||
|
||||
|
||||
BigDecimal wxAmount = oldCardDO.getWxAmount();
|
||||
BigDecimal giftAmount = oldCardDO.getGiftAmount();
|
||||
BigDecimal cashAmount = oldCardDO.getCashAmount();
|
||||
cardDO.setMoney(money.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
|
||||
//计算金额
|
||||
if (total.compareTo(cashAmount) <= 0) {
|
||||
cardDO.setCashAmount(cashAmount.subtract(total).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
} else {
|
||||
cardDO.setCashAmount(BigDecimal.ZERO);
|
||||
BigDecimal total1 = total.subtract(cashAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
if (total1.compareTo(giftAmount) <= 0) {
|
||||
cardDO.setGiftAmount(giftAmount.subtract(total1).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
} else {
|
||||
cardDO.setGiftAmount(BigDecimal.ZERO);
|
||||
BigDecimal total2 = total1.subtract(giftAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
|
||||
cardDO.setWxAmount(wxAmount.subtract(total2).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
}
|
||||
}
|
||||
|
||||
cardDO.setUserId(userId);
|
||||
cardDO.setChangeMoney(total);
|
||||
cardDO.setFlag(CardDO.MINUS);
|
||||
cardService.insertOne(cardDO);
|
||||
|
||||
return cardDO.getMoney();
|
||||
return deductionService.storeDeduction(total, userId);
|
||||
}
|
||||
|
||||
public void test(){
|
||||
|
Reference in New Issue
Block a user