Commit 8dfa0c1e authored by shiyu's avatar shiyu

保证金缴纳

parent e9b58bb7
...@@ -48,6 +48,11 @@ public interface CommConsts { ...@@ -48,6 +48,11 @@ public interface CommConsts {
*/ */
public static final String AUCTION_LOCK_KEY_PRE = "AUCTION:OFFER:"; public static final String AUCTION_LOCK_KEY_PRE = "AUCTION:OFFER:";
/**
* 拍卖保证金额度更新的锁
*/
public static final String EARNEST_ACCOUNT_LOCK = "EARNEST:ACCOUNT:";
public static final Long SYSTEM_ACCOUNT = 8888888888L; public static final Long SYSTEM_ACCOUNT = 8888888888L;
...@@ -156,6 +161,12 @@ public interface CommConsts { ...@@ -156,6 +161,12 @@ public interface CommConsts {
public final static String EARNEST_REBATE = "0.05"; public final static String EARNEST_REBATE = "0.05";
/**
* 每个用户赠送50元初始保证金额度
*/
public final static Long GIFT_EARNEST_AMOUNT = 5000L;
/** /**
* 平台收货地址 * 平台收货地址
*/ */
......
...@@ -12,6 +12,7 @@ public interface EarnestOrderDao { ...@@ -12,6 +12,7 @@ public interface EarnestOrderDao {
*/ */
boolean insert(EarnestOrder earnestOrder); boolean insert(EarnestOrder earnestOrder);
boolean update(EarnestOrder earnestOrder);
EarnestOrder findByOrderId(String orderId); EarnestOrder findByOrderId(String orderId);
} }
package com.wwdz.ch.db.domain.openShop; package com.wwdz.ch.db.domain.openShop;
import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import com.xxdxxs.entity.Entity;
import lombok.Data; import lombok.Data;
/** /**
...@@ -11,7 +11,7 @@ import lombok.Data; ...@@ -11,7 +11,7 @@ import lombok.Data;
* @date 2024/11/06 * @date 2024/11/06
*/ */
@Data @Data
public class UserAccount implements Serializable { public class UserAccount implements Entity {
private Long id; private Long id;
/** /**
......
...@@ -19,6 +19,13 @@ public class EarnestOrderDaoImpl implements EarnestOrderDao { ...@@ -19,6 +19,13 @@ public class EarnestOrderDaoImpl implements EarnestOrderDao {
return earnestOrderMapper.insert(earnestOrder) > 0; return earnestOrderMapper.insert(earnestOrder) > 0;
} }
@Override
public boolean update(EarnestOrder earnestOrder) {
EarnestOrderExample example = new EarnestOrderExample();
EarnestOrderExample.Criteria criteria = example.createCriteria();
criteria.andEarnestOrderIdEqualTo(earnestOrder.getEarnestOrderId());
return earnestOrderMapper.updateByExampleSelective(earnestOrder, example) > 0;
}
@Override @Override
public EarnestOrder findByOrderId(String orderId) { public EarnestOrder findByOrderId(String orderId) {
......
...@@ -28,6 +28,7 @@ public class EarnestRecordDaoImpl implements EarnestRecordDao { ...@@ -28,6 +28,7 @@ public class EarnestRecordDaoImpl implements EarnestRecordDao {
EarnestRecordExample.Criteria criteria = example.createCriteria(); EarnestRecordExample.Criteria criteria = example.createCriteria();
criteria.andUserIdEqualTo(earnestRecord.getUserId()); criteria.andUserIdEqualTo(earnestRecord.getUserId());
criteria.andItemIdEqualTo(earnestRecord.getItemId()); criteria.andItemIdEqualTo(earnestRecord.getItemId());
JdbcHelper.ifPresent(earnestRecord.getType(), criteria::andTypeEqualTo);
return earnestRecordMapper.updateByExampleSelective(earnestRecord, example) > 0; return earnestRecordMapper.updateByExampleSelective(earnestRecord, example) > 0;
} }
......
...@@ -2,11 +2,14 @@ package com.wwdz.ch.db.impl.openShop; ...@@ -2,11 +2,14 @@ package com.wwdz.ch.db.impl.openShop;
import com.wwdz.ch.db.dao.openShop.UserAccountDao; import com.wwdz.ch.db.dao.openShop.UserAccountDao;
import com.wwdz.ch.db.domain.openShop.UserAccount; import com.wwdz.ch.db.domain.openShop.UserAccount;
import com.wwdz.ch.db.domain.openShop.UserAccountExample;
import com.wwdz.ch.db.mapper.UserMapper; import com.wwdz.ch.db.mapper.UserMapper;
import com.wwdz.ch.db.mapper.openShop.UserAccountMapper; import com.wwdz.ch.db.mapper.openShop.UserAccountMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.Date;
@Repository @Repository
public class UserAccountDaoImpl implements UserAccountDao { public class UserAccountDaoImpl implements UserAccountDao {
...@@ -21,7 +24,11 @@ public class UserAccountDaoImpl implements UserAccountDao { ...@@ -21,7 +24,11 @@ public class UserAccountDaoImpl implements UserAccountDao {
@Override @Override
public boolean update(UserAccount userAccount) { public boolean update(UserAccount userAccount) {
return false; UserAccountExample example = new UserAccountExample();
UserAccountExample.Criteria criteria = example.createCriteria();
criteria.andUserIdEqualTo(userAccount.getUserId());
userAccount.setUpdateTime(new Date());
return userAccountMapper.updateByExampleSelective(userAccount, example) > 0;
} }
@Override @Override
......
...@@ -3,8 +3,11 @@ package com.wwdz.ch.db.mapper.openShop; ...@@ -3,8 +3,11 @@ package com.wwdz.ch.db.mapper.openShop;
import com.wwdz.ch.db.domain.openShop.UserAccount; import com.wwdz.ch.db.domain.openShop.UserAccount;
import com.wwdz.ch.db.domain.openShop.UserAccountExample; import com.wwdz.ch.db.domain.openShop.UserAccountExample;
import java.util.List; import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
@Mapper
public interface UserAccountMapper { public interface UserAccountMapper {
long countByExample(UserAccountExample example); long countByExample(UserAccountExample example);
......
...@@ -18,14 +18,10 @@ import com.wwdz.ch.core.util.RedisUtils; ...@@ -18,14 +18,10 @@ import com.wwdz.ch.core.util.RedisUtils;
import com.wwdz.ch.core.util.TimeUtil; import com.wwdz.ch.core.util.TimeUtil;
import com.wwdz.ch.db.dao.CollectorWhiteListDao; import com.wwdz.ch.db.dao.CollectorWhiteListDao;
import com.wwdz.ch.db.dao.distribution.*; import com.wwdz.ch.db.dao.distribution.*;
import com.wwdz.ch.db.dao.openShop.GuaranteeMoneyRecordDao; import com.wwdz.ch.db.dao.openShop.*;
import com.wwdz.ch.db.dao.openShop.OpenShopApplyOrderDao;
import com.wwdz.ch.db.dao.openShop.OpenShopCostRecordDao;
import com.wwdz.ch.db.domain.CollectorWhiteList; import com.wwdz.ch.db.domain.CollectorWhiteList;
import com.wwdz.ch.db.domain.distribution.*; import com.wwdz.ch.db.domain.distribution.*;
import com.wwdz.ch.db.domain.openShop.GuaranteeMoneyRecord; import com.wwdz.ch.db.domain.openShop.*;
import com.wwdz.ch.db.domain.openShop.OpenShopApplyOrder;
import com.wwdz.ch.db.domain.openShop.OpenShopCostRecord;
import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto; import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto;
import com.wwdz.ch.core.entity.DistributionOrderNoticeMsg; import com.wwdz.ch.core.entity.DistributionOrderNoticeMsg;
import com.wwdz.ch.core.entity.PayNoticeMsg; import com.wwdz.ch.core.entity.PayNoticeMsg;
...@@ -35,6 +31,8 @@ import com.wwdz.ch.wx.service.distribution.*; ...@@ -35,6 +31,8 @@ import com.wwdz.ch.wx.service.distribution.*;
import com.xxdxxs.utils.DateUtils; import com.xxdxxs.utils.DateUtils;
import com.xxdxxs.utils.JsonUtils; import com.xxdxxs.utils.JsonUtils;
import com.xxdxxs.utils.StringUtils; import com.xxdxxs.utils.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -56,6 +54,7 @@ import java.time.temporal.TemporalUnit; ...@@ -56,6 +54,7 @@ import java.time.temporal.TemporalUnit;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit;
/** /**
* 微信支付回调通知 * 微信支付回调通知
...@@ -138,6 +137,15 @@ public class WxPayCallbackController { ...@@ -138,6 +137,15 @@ public class WxPayCallbackController {
@Autowired @Autowired
CollectorWhiteListDao collectorWhiteListDao; CollectorWhiteListDao collectorWhiteListDao;
@Autowired
EarnestOrderDao earnestOrderDao;
@Autowired
UserAccountDao userAccountDao;
@Autowired
RedissonClient redissonClient;
@RequestMapping(value ="/getPayNotify") @RequestMapping(value ="/getPayNotify")
public String payNotify(HttpServletRequest request) throws IOException { public String payNotify(HttpServletRequest request) throws IOException {
logger.info("------------------ 收到微信支付回调通知 ------------------"); logger.info("------------------ 收到微信支付回调通知 ------------------");
...@@ -201,7 +209,11 @@ public class WxPayCallbackController { ...@@ -201,7 +209,11 @@ public class WxPayCallbackController {
} else if (systemOrderId.startsWith(CommConsts.GUARANTEE_MONEY_ORDER_PREFIX)) { } else if (systemOrderId.startsWith(CommConsts.GUARANTEE_MONEY_ORDER_PREFIX)) {
//质保金缴纳订单 //质保金缴纳订单
handleOrderOfGuaranteeMoney(transaction); handleOrderOfGuaranteeMoney(transaction);
} else if (systemOrderId.startsWith(CommConsts.DISTRIBUTION_ORDER_PREFIX)) { } else if (systemOrderId.startsWith(CommConsts.AUCTION_EARNEST_ORDER_PREFIX)) {
//拍卖保证金缴纳订单
handleOrderOfEarnest(transaction);
}
else if (systemOrderId.startsWith(CommConsts.DISTRIBUTION_ORDER_PREFIX)) {
//查询系统中订单现在的状态,避免重复更新 //查询系统中订单现在的状态,避免重复更新
DistributionOrder distributionOrder = distributionOrderDao.findById(systemOrderId); DistributionOrder distributionOrder = distributionOrderDao.findById(systemOrderId);
if (distributionOrder.getState() == DistributionEnum.DistributionOrderStateEnum.PRE_PAY.getCode()) { if (distributionOrder.getState() == DistributionEnum.DistributionOrderStateEnum.PRE_PAY.getCode()) {
...@@ -631,6 +643,58 @@ public class WxPayCallbackController { ...@@ -631,6 +643,58 @@ public class WxPayCallbackController {
return Result.failed(); return Result.failed();
} }
/**
* 拍卖保证金订单回调
* @param transaction
* @return
*/
public Result handleOrderOfEarnest(Transaction transaction) {
//商户订单号,分销订单号
String systemOrderId = transaction.getOutTradeNo();
//微信支付交易id
String transactionId = transaction.getTransactionId();
//支付成功时间
String payTime = transaction.getSuccessTime();
EarnestOrder oldEarnestOrder = earnestOrderDao.findByOrderId(systemOrderId);
long userId = oldEarnestOrder.getUserId();
long amount = oldEarnestOrder.getAmount();
String lockKey = CommConsts.EARNEST_ACCOUNT_LOCK + userId;
RLock lock = redissonClient.getLock(lockKey);
try {
if (!lock.tryLock(5, 5, TimeUnit.SECONDS)) {
return Result.failed("未获取到锁");
}
//支付成功,更新订单状态为待发货
EarnestOrder earnestOrder = new EarnestOrder();
earnestOrder.setEarnestOrderId(systemOrderId);
earnestOrder.setTransactionId(transactionId);
earnestOrder.setPayTime(TimeUtil.wxTimeConvertToDate(payTime));
earnestOrder.setState(EarnestEnum.EarnestOrderStateEnum.PAYED.getCode());
earnestOrder.setUpdateTime(new Date());
earnestOrderDao.update(earnestOrder);
//用户账户,更新保证金额度
UserAccount userAccount = userAccountDao.findByUserId(userId);
long earnestUsableAmount = userAccount.getEarnestUsableAmount();
long newEarnestUsableAmount = earnestUsableAmount + amount;
UserAccount newUserAccount = new UserAccount();
newUserAccount.setUserId(userId);
newUserAccount.setEarnestAmount(userAccount.getEarnestAmount() + amount);
newUserAccount.setEarnestUsableAmount(newEarnestUsableAmount);
userAccountDao.update(newUserAccount);
logger.info(">>>>>>>>>>>> 拍卖保证金订单,微信支付回调通知处理成功 <<<<<<<<<<<<");
return Result.success();
} catch (Exception e) {
logger.error(">>>>>>>>>>>> 拍卖保证金订单,微信支付回调通知处理失败 error :{}", e);
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
return Result.failed();
}
/** /**
* 获取请求体 * 获取请求体
......
...@@ -16,6 +16,8 @@ import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto; ...@@ -16,6 +16,8 @@ import com.wwdz.ch.db.dto.request.distribution.DistributionOrderRequestDto;
import com.wwdz.ch.db.dto.request.openShop.EarnestOrderRequestDto; import com.wwdz.ch.db.dto.request.openShop.EarnestOrderRequestDto;
import com.wwdz.ch.db.dto.request.openShop.EarnestRecordRequestDto; import com.wwdz.ch.db.dto.request.openShop.EarnestRecordRequestDto;
import com.wwdz.ch.wx.service.openShop.AuctionEarnestService; import com.wwdz.ch.wx.service.openShop.AuctionEarnestService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -25,6 +27,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport; ...@@ -25,6 +27,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.concurrent.TimeUnit;
@Service @Service
public class AuctionEarnestServiceImpl implements AuctionEarnestService { public class AuctionEarnestServiceImpl implements AuctionEarnestService {
...@@ -43,6 +46,9 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService { ...@@ -43,6 +46,9 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService {
@Autowired @Autowired
UserAccountDao userAccountDao; UserAccountDao userAccountDao;
@Autowired
RedissonClient redissonClient;
@Override @Override
public Result payEarnest(EarnestOrderRequestDto dto) { public Result payEarnest(EarnestOrderRequestDto dto) {
try { try {
...@@ -87,15 +93,31 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService { ...@@ -87,15 +93,31 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService {
} }
@Override
public Result checkEnoughEarnest(EarnestRecordRequestDto dto) {
try {
return Result.success();
} catch (Exception e) {
logger.error("检查是否有足够的保证金失败 error : {}", e);
}
return Result.failed();
}
@Transactional @Transactional
@Override @Override
public Result occupyEarnest(EarnestRecordRequestDto dto) { public Result occupyEarnest(EarnestRecordRequestDto dto) {
String lockKey = CommConsts.EARNEST_ACCOUNT_LOCK + dto.getUserId();
RLock lock = redissonClient.getLock(lockKey);
try { try {
if (!lock.tryLock(5, 5, TimeUnit.SECONDS)) {
return Result.failed("操作过快,稍后再试");
}
EarnestRecord earnestRecord = new EarnestRecord(); EarnestRecord earnestRecord = new EarnestRecord();
long auctionPrice = dto.getAuctionPrice(); long auctionPrice = dto.getAuctionPrice();
BigDecimal earnestAmount = new BigDecimal(String.valueOf(auctionPrice)).multiply(new BigDecimal(CommConsts.EARNEST_REBATE)); BigDecimal earnestAmount = new BigDecimal(String.valueOf(auctionPrice)).multiply(new BigDecimal(CommConsts.EARNEST_REBATE));
//换算成对应占用的保证金 //换算成对应占用的保证金
long occupyAmount = earnestAmount.longValue(); long occupyAmount = earnestAmount.longValue();
earnestRecord.setUserId(dto.getUserId());
earnestRecord.setAmount(earnestAmount.longValue()); earnestRecord.setAmount(earnestAmount.longValue());
earnestRecord.setItemId(dto.getItemId()); earnestRecord.setItemId(dto.getItemId());
earnestRecord.setSpecialPerformanceId(dto.getSpecialPerformanceId()); earnestRecord.setSpecialPerformanceId(dto.getSpecialPerformanceId());
...@@ -106,26 +128,75 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService { ...@@ -106,26 +128,75 @@ public class AuctionEarnestServiceImpl implements AuctionEarnestService {
earnestRecord.setState(EarnestEnum.StateEnum.VALID.getCode()); earnestRecord.setState(EarnestEnum.StateEnum.VALID.getCode());
earnestRecordDao.insert(earnestRecord); earnestRecordDao.insert(earnestRecord);
//用户账户,更新保证金额度 //用户账户,更新保证金额度
UserAccount userAccount = new UserAccount(); UserAccount userAccount = userAccountDao.findByUserId(dto.getUserId());
userAccount.setUserId(dto.getUserId()); long earnestUsableAmount = userAccount.getEarnestUsableAmount();
long newEarnestUsableAmount = earnestUsableAmount - occupyAmount;
UserAccount newUserAccount = new UserAccount();
newUserAccount.setUserId(dto.getUserId());
newUserAccount.setEarnestUsableAmount(newEarnestUsableAmount);
userAccountDao.update(newUserAccount);
return Result.success(); return Result.success();
} catch (Exception e) { } catch (Exception e) {
logger.error("占用保证金失败 error : {}", e); logger.error("占用保证金失败 error : {}", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
return Result.failed(); return Result.failed();
} }
@Transactional @Transactional
@Override @Override
public Result releaseEarnest(EarnestRecordRequestDto dto) { public Result releaseEarnest(EarnestRecordRequestDto dto) {
String itemIdKey = CommConsts.EARNEST_ACCOUNT_LOCK + dto.getUserId();
RLock lock = redissonClient.getLock(itemIdKey);
try { try {
if (!lock.tryLock(5, 5, TimeUnit.SECONDS)) {
return Result.failed("操作过快,稍后再试");
}
long auctionPrice = dto.getAuctionPrice();
BigDecimal earnestAmount = new BigDecimal(String.valueOf(auctionPrice)).multiply(new BigDecimal(CommConsts.EARNEST_REBATE));
//换算成对应占用的保证金
long occupyAmount = earnestAmount.longValue();
EarnestRecord earnestRecord = new EarnestRecord();
earnestRecord.setUserId(dto.getUserId());
earnestRecord.setAmount(earnestAmount.longValue());
earnestRecord.setItemId(dto.getItemId());
earnestRecord.setSpecialPerformanceId(dto.getSpecialPerformanceId());
earnestRecord.setEntryType(EarnestEnum.EntryEnum.INCREASE.getCode());
earnestRecord.setCreateTime(new Date());
earnestRecord.setUpdateTime(new Date());
earnestRecord.setType(EarnestEnum.TypeEnum.RELEASE.getCode());
earnestRecord.setState(EarnestEnum.StateEnum.VALID.getCode());
earnestRecordDao.insert(earnestRecord);
//把上一次的占用记录状态更改为已释放
EarnestRecord newEarnestRecord = new EarnestRecord();
newEarnestRecord.setUserId(dto.getUserId());
newEarnestRecord.setItemId(dto.getItemId());
newEarnestRecord.setType(EarnestEnum.TypeEnum.OCCUPY.getCode());
earnestRecordDao.update(newEarnestRecord);
//更新用户账户,更新保证金额度
UserAccount userAccount = userAccountDao.findByUserId(dto.getUserId());
long earnestUsableAmount = userAccount.getEarnestUsableAmount();
long newEarnestUsableAmount = earnestUsableAmount + occupyAmount;
UserAccount newUserAccount = new UserAccount();
newUserAccount.setUserId(dto.getUserId());
newUserAccount.setEarnestUsableAmount(newEarnestUsableAmount);
userAccountDao.update(newUserAccount);
return Result.success();
} catch (Exception e) { } catch (Exception e) {
logger.error("释放保证金失败 error : {}", e); logger.error("释放保证金失败 error : {}", e);
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
} finally {
if (lock != null && lock.isHeldByCurrentThread()) {
lock.unlock();
}
} }
return Result.failed(); return Result.failed();
} }
......
...@@ -21,6 +21,13 @@ public interface AuctionEarnestService { ...@@ -21,6 +21,13 @@ public interface AuctionEarnestService {
*/ */
Result getPayParam(EarnestOrderRequestDto dto); Result getPayParam(EarnestOrderRequestDto dto);
/**
* 检查是否有足够的保证金出价
* @param dto
* @return
*/
Result checkEnoughEarnest(EarnestRecordRequestDto dto);
/** /**
* 占用保证金 * 占用保证金
* @return * @return
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment