支付优化

This commit is contained in:
seesaw
2024-10-22 14:35:28 +08:00
parent f26bf709b5
commit dbe0c9a61b
8 changed files with 136 additions and 65 deletions

View File

@ -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) {

View File

@ -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));

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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(){