| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- package com.ylx.giftCard.service.impl;
- import cn.hutool.core.bean.BeanUtil;
- import cn.hutool.core.collection.CollectionUtil;
- import cn.hutool.core.util.ObjectUtil;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.ylx.common.core.domain.model.WxLoginUser;
- import com.ylx.common.exception.ServiceException;
- import com.ylx.common.utils.SecurityUtils;
- import com.ylx.common.weixinPay.service.WxPayV3Service;
- import com.ylx.giftCard.domain.GiftCard;
- import com.ylx.giftCard.domain.GiftCardOrder;
- import com.ylx.giftCard.domain.dto.GiftCardPurchaseDTO;
- import com.ylx.giftCard.domain.vo.GiftCardDetailVO;
- import com.ylx.giftCard.domain.vo.GiftCardVO;
- import com.ylx.giftCard.mapper.GiftCardMapper;
- import com.ylx.giftCard.service.IGiftCardOrderService;
- import com.ylx.giftCard.service.IGiftCardService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import javax.annotation.Resource;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
- @Slf4j
- @Service
- public class GiftCardServiceImpl extends ServiceImpl<GiftCardMapper, GiftCard> implements IGiftCardService {
- @Resource
- private IGiftCardOrderService giftCardOrderService;
- @Resource
- private WxPayV3Service wxPayV3Service;
- private static final int NOT_DELETE = 0;
- private static final int PUBLISHED = 1;
- @Override
- public Page<GiftCardVO> getGiftCardPage(Page<GiftCard> page) {
- LambdaQueryWrapper<GiftCard> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(GiftCard::getIsDelete, NOT_DELETE);
- wrapper.eq(GiftCard::getIsPublished, PUBLISHED);
- wrapper.orderByDesc(GiftCard::getCreateTime);
- Page<GiftCard> giftCardPage = this.baseMapper.selectPage(page, wrapper);
- Page<GiftCardVO> pageData = new Page<>(
- giftCardPage.getCurrent(),
- giftCardPage.getSize(),
- giftCardPage.getTotal()
- );
- if (CollectionUtil.isNotEmpty(giftCardPage.getRecords())) {
- List<GiftCardVO> voList = giftCardPage.getRecords().stream()
- .map(GiftCardVO::new)
- .collect(Collectors.toList());
- pageData.setRecords(voList);
- }
- return pageData;
- }
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> purchaseGiftCard(GiftCardPurchaseDTO dto) {
- // 1. 获取当前用户
- WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
- if (ObjectUtil.isNull(wxLoginUser)) {
- log.warn("用户未登录,无法创建订单");
- throw new ServiceException("用户未登录");
- }
- Long id = dto.getId();
- Integer quantity = dto.getQuantity();
- String merchantId = dto.getMerchantId();
- // 2. 查询并校验购物卡
- GiftCard card = this.getById(id);
- validateGiftCard(card, quantity);
- // 3. 乐观锁扣减库存(增加状态校验,防止无效更新)
- int rowsAffected = deductStockOptimisticLock(card.getId(), dto.getQuantity());
- if (rowsAffected <= 0) {
- log.warn("购买失败,库存不足或商品不存在,购物卡ID: {}", id);
- throw new ServiceException("库存不足或商品状态异常");
- }
- log.info("购买成功,购物卡ID: {}, 数量: {}", id, quantity);
- // 4. 创建订单
- GiftCardOrder order = this.giftCardOrderService.buildOrder(card, quantity, merchantId, wxLoginUser);
- // 5. 调用微信支付
- return createWxPayOrder(order, wxLoginUser);
- }
- @Override
- public GiftCardDetailVO getGiftCardDetail(Long id) {
- LambdaQueryWrapper<GiftCard> wrapper = new LambdaQueryWrapper<>();
- wrapper.eq(GiftCard::getId, id)
- .eq(GiftCard::getIsDelete, NOT_DELETE)
- .eq(GiftCard::getIsPublished, PUBLISHED);
- GiftCard card = this.getOne(wrapper);
- if (ObjectUtil.isNull(card)) {
- return null;
- }
- GiftCardDetailVO vo = new GiftCardDetailVO();
- BeanUtil.copyProperties(card, vo);
- return vo;
- }
- /**
- * 校验购物卡有效性
- */
- private void validateGiftCard(GiftCard card, Integer quantity) {
- if (ObjectUtil.isNull(card)) {
- throw new ServiceException("商品不存在");
- }
- if (card.getIsDelete() != NOT_DELETE) {
- log.warn("购买失败,购物卡已删除,ID: {}", card.getId());
- throw new ServiceException("购物卡已删除");
- }
- if (card.getIsPublished() != PUBLISHED) {
- log.warn("购买失败,购物卡未上架,ID: {}", card.getId());
- throw new ServiceException("购物卡未上架");
- }
- if (card.getStock() < quantity) {
- log.warn("购买失败,库存不足,ID: {},库存: {},需求数量: {}", card.getId(), card.getStock(), quantity);
- throw new ServiceException("库存不足");
- }
- }
- /**
- * 乐观锁扣减库存(增加状态条件,确保只更新有效记录)
- */
- private int deductStockOptimisticLock(Long cardId, Integer quantity) {
- LambdaUpdateWrapper<GiftCard> wrapper = new LambdaUpdateWrapper<>();
- wrapper.eq(GiftCard::getId, cardId)
- .eq(GiftCard::getIsDelete, NOT_DELETE)
- .eq(GiftCard::getIsPublished, PUBLISHED)
- .ge(GiftCard::getStock, quantity) // 库存充足时才更新
- .setSql("stock = stock - " + quantity + ", sales = sales + " + quantity);
- return baseMapper.update(null, wrapper);
- }
- /**
- * 补偿回滚库存
- */
- private void recoverStock(Long cardId, Integer num) {
- GiftCard updateEntity = new GiftCard();
- LambdaUpdateWrapper<GiftCard> updateWrapper = new LambdaUpdateWrapper<>();
- updateWrapper.eq(GiftCard::getId, cardId)
- .eq(GiftCard::getIsDelete, NOT_DELETE);
- updateWrapper.setSql("stock = stock + #{num}, sales = sales - #{num}");
- // 数据放到实体里
- updateEntity.setStock(num);
- baseMapper.update(updateEntity, updateWrapper);
- }
- /**
- * 创建微信支付订单(事务外执行,减少事务时长)
- */
- private Map<String, Object> createWxPayOrder(GiftCardOrder order, WxLoginUser wxLoginUser) {
- try {
- return wxPayV3Service.createV3JsapiOrder(
- order.getOrderNo(),
- order.getPayAmount(),
- "购物卡购买",
- wxLoginUser.getCOpenid()
- );
- } catch (Exception e) {
- log.error("微信支付下单失败,订单号: {}", order.getOrderNo(), e);
- // 支付失败:恢复库存、修改订单为取消
- recoverStock(order.getGiftCardId(), order.getPurchaseQuantity());
- this.giftCardOrderService.cancelOrder(order.getId());
- throw new ServiceException("支付服务异常,请稍后重试");
- }
- }
- }
|