|  |  |  | 
|---|
|  |  |  | import com.mzl.flower.config.exception.ValidationException; | 
|---|
|  |  |  | import com.mzl.flower.config.security.SecurityUtils; | 
|---|
|  |  |  | import com.mzl.flower.constant.Constants; | 
|---|
|  |  |  | import com.mzl.flower.constant.LockConstants; | 
|---|
|  |  |  | import com.mzl.flower.dto.request.wallet.CreateWalletWithdrawRecordDTO; | 
|---|
|  |  |  | import com.mzl.flower.dto.request.wallet.QueryWalletDTO; | 
|---|
|  |  |  | import com.mzl.flower.dto.request.wallet.QueryWalletWithdrawDTO; | 
|---|
|  |  |  | import com.mzl.flower.dto.request.wallet.WalletWithdrawRecordDTO; | 
|---|
|  |  |  | import com.mzl.flower.dto.response.supplier.SupplierDTO; | 
|---|
|  |  |  | import com.mzl.flower.dto.response.wallet.WalletWithdrawRecordVO; | 
|---|
|  |  |  | 
|---|
|  |  |  | import com.mzl.flower.entity.wallet.WalletWithdrawRecordDO; | 
|---|
|  |  |  | import com.mzl.flower.mapper.wallet.WalletWithdrawRecordMapper; | 
|---|
|  |  |  | import com.mzl.flower.service.supplier.SupplierService; | 
|---|
|  |  |  | import com.mzl.flower.service.wallet.WalletBillRecordService; | 
|---|
|  |  |  | import com.mzl.flower.service.wallet.WalletService; | 
|---|
|  |  |  | import com.mzl.flower.service.wallet.WalletWithdrawRecordService; | 
|---|
|  |  |  | import lombok.RequiredArgsConstructor; | 
|---|
|  |  |  | import org.redisson.api.RLock; | 
|---|
|  |  |  | import org.redisson.api.RedissonClient; | 
|---|
|  |  |  | import org.springframework.beans.BeanUtils; | 
|---|
|  |  |  | import org.springframework.beans.factory.annotation.Autowired; | 
|---|
|  |  |  | import org.springframework.stereotype.Service; | 
|---|
|  |  |  | import org.springframework.transaction.annotation.Transactional; | 
|---|
|  |  |  | import org.springframework.util.StringUtils; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | import java.time.LocalDateTime; | 
|---|
|  |  |  | import java.util.List; | 
|---|
|  |  |  | import java.util.concurrent.TimeUnit; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /** | 
|---|
|  |  |  | * <p> | 
|---|
|  |  |  | 
|---|
|  |  |  | @Transactional | 
|---|
|  |  |  | @RequiredArgsConstructor | 
|---|
|  |  |  | public class WalletWithdrawRecordServiceImpl extends ServiceImpl<WalletWithdrawRecordMapper, WalletWithdrawRecordDO> implements WalletWithdrawRecordService { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private final WalletWithdrawRecordMapper walletWithdrawRecordMapper; | 
|---|
|  |  |  | private final WalletService walletService; | 
|---|
|  |  |  | private final SupplierService supplierService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | private final WalletBillRecordService walletBillRecordService; | 
|---|
|  |  |  |  | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Autowired | 
|---|
|  |  |  | RedissonClient redissonClient; | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Transactional | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public boolean create(CreateWalletWithdrawRecordDTO dto) { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | SupplierDTO supplierDTO = supplierService.getCurrentSupplier(); | 
|---|
|  |  |  | if (null == supplierDTO) { | 
|---|
|  |  |  | throw new ValidationException("供应商不能为空"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | final WalletDO walletDO = walletService.getBySupplierId(); | 
|---|
|  |  |  | WalletDO walletDO = walletService.getCurrentSupplier(); | 
|---|
|  |  |  | if (null == walletDO) { | 
|---|
|  |  |  | throw new ValidationException("钱包不能为空"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | 
|---|
|  |  |  | if (null != walletDO.getWithdrawableAmount() && null != dto.getAmount() && walletDO.getWithdrawableAmount().compareTo(dto.getAmount()) < 0) { | 
|---|
|  |  |  | throw new ValidationException("钱包金额不足"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | WalletWithdrawRecordDO withdrawRecordDO = new WalletWithdrawRecordDO(); | 
|---|
|  |  |  | withdrawRecordDO.setAmount(dto.getAmount()); | 
|---|
|  |  |  | withdrawRecordDO.setSupplierId(supplierDTO.getId()); | 
|---|
|  |  |  | withdrawRecordDO.setWithdrawState(Constants.WALLET_WITHDRAW_STATE.WAITING.name()); | 
|---|
|  |  |  | withdrawRecordDO.setMethod(Constants.WALLET_WITHDRAW_METHOD.WEIXIN.name()); | 
|---|
|  |  |  | withdrawRecordDO.create(SecurityUtils.getUserId()); | 
|---|
|  |  |  | return save(withdrawRecordDO); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | RLock lock = redissonClient.getLock(String.format(LockConstants.WALLET_ID_KEY, walletDO.getId())); | 
|---|
|  |  |  | // 获取锁,最多等待 10 秒,锁自动释放时间 30 秒 | 
|---|
|  |  |  | try { | 
|---|
|  |  |  | if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { | 
|---|
|  |  |  | try { | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 加锁了之后需要二次查询,防止未加锁之前 someone else 已经修改了 | 
|---|
|  |  |  | walletDO = walletService.getCurrentSupplier(); | 
|---|
|  |  |  | if (null == walletDO) { | 
|---|
|  |  |  | throw new ValidationException("钱包不能为空"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | // 查看钱包的金额是不是大于要提现的金额 | 
|---|
|  |  |  | if (null != walletDO.getWithdrawableAmount() && null != dto.getAmount() && walletDO.getWithdrawableAmount().compareTo(dto.getAmount()) < 0) { | 
|---|
|  |  |  | throw new ValidationException("钱包金额不足"); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 1.新增一条余额提现记录 | 
|---|
|  |  |  | WalletWithdrawRecordDO withdrawRecordDO = new WalletWithdrawRecordDO(); | 
|---|
|  |  |  | withdrawRecordDO.setAmount(dto.getAmount()); | 
|---|
|  |  |  | withdrawRecordDO.setSupplierId(supplierDTO.getId()); | 
|---|
|  |  |  | withdrawRecordDO.setWithdrawState(Constants.WALLET_WITHDRAW_STATE.WAITING.name()); | 
|---|
|  |  |  | withdrawRecordDO.setMethod(Constants.WALLET_WITHDRAW_METHOD.WEIXIN.name()); | 
|---|
|  |  |  | withdrawRecordDO.create(SecurityUtils.getUserId()); | 
|---|
|  |  |  | // 保存余额提现记录 | 
|---|
|  |  |  | save(withdrawRecordDO); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | /* | 
|---|
|  |  |  | // 2.新增一条账单明细 | 
|---|
|  |  |  | WalletBillRecordDO walletBillRecordDO=new WalletBillRecordDO(); | 
|---|
|  |  |  | walletBillRecordDO.setSupplierId(supplierDTO.getId()); | 
|---|
|  |  |  | walletBillRecordDO.setWalletId(walletDO.getId()); | 
|---|
|  |  |  | // 提现 | 
|---|
|  |  |  | walletBillRecordDO.setType(Constants.BILL_CHANGE_TYPE.withdraw.name()); | 
|---|
|  |  |  | walletBillRecordDO.setMethod(Constants.BILL_CHANGE_METHOD.add.name()); | 
|---|
|  |  |  | walletBillRecordDO.setOriginalAmount(walletDO.getWithdrawableAmount()); | 
|---|
|  |  |  | walletBillRecordDO.setChangeAmount(dto.getAmount()); | 
|---|
|  |  |  | walletBillRecordDO.setBalance(walletDO.getWithdrawableAmount().subtract(dto.getAmount())); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 保存账单明细 | 
|---|
|  |  |  | walletBillRecordService.save(walletBillRecordDO); | 
|---|
|  |  |  | */ | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 3. 钱包更新 | 
|---|
|  |  |  | // 钱包可提现的钱等于当前钱包可提现的钱-提现的钱 | 
|---|
|  |  |  | walletDO.setWithdrawableAmount(walletDO.getWithdrawableAmount().subtract(dto.getAmount())); | 
|---|
|  |  |  | // 提现中的钱等于原有可提现的钱+提现的钱 | 
|---|
|  |  |  | walletDO.setWithdrawingAmount(walletDO.getWithdrawingAmount().add(dto.getAmount())); | 
|---|
|  |  |  | walletDO.update(SecurityUtils.getUserId()); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | // 更新钱包 | 
|---|
|  |  |  | return walletService.updateById(walletDO); | 
|---|
|  |  |  |  | 
|---|
|  |  |  | } finally { | 
|---|
|  |  |  | lock.unlock(); | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } | 
|---|
|  |  |  | } catch (InterruptedException e) { | 
|---|
|  |  |  | throw new RuntimeException(e); | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | return false; | 
|---|
|  |  |  | } | 
|---|
|  |  |  |  | 
|---|
|  |  |  | @Override | 
|---|
|  |  |  | public Page<WalletWithdrawRecordVO> queryPage(QueryWalletDTO queryWalletDTO, Page page) { | 
|---|
|  |  |  | public Page<WalletWithdrawRecordVO> queryPage(QueryWalletWithdrawDTO queryWalletDTO, Page page) { | 
|---|
|  |  |  | List<WalletWithdrawRecordVO> list = walletWithdrawRecordMapper.queryPage(queryWalletDTO, page); | 
|---|
|  |  |  | page.setRecords(list); | 
|---|
|  |  |  | return page; | 
|---|