GiftCardOrderServiceImpl.java 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. package com.ylx.giftCard.service.impl;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import cn.hutool.core.util.RandomUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  6. import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
  7. import com.ylx.common.core.domain.model.WxLoginUser;
  8. import com.ylx.common.exception.ServiceException;
  9. import com.ylx.common.utils.DateUtils;
  10. import com.ylx.giftCard.domain.GiftCard;
  11. import com.ylx.giftCard.domain.GiftCardOrder;
  12. import com.ylx.giftCard.enums.GiftCardOrderStatusEnum;
  13. import com.ylx.giftCard.mapper.GiftCardOrderMapper;
  14. import com.ylx.giftCard.service.IGiftCardOrderService;
  15. import com.ylx.massage.domain.TJs;
  16. import com.ylx.massage.domain.TWxUser;
  17. import com.ylx.massage.service.TJsService;
  18. import com.ylx.massage.service.TWxUserService;
  19. import com.ylx.shopingfundsdetail.domain.vo.ShoppingFundsDetailAddDto;
  20. import com.ylx.shopingfundsdetail.enums.ShoppingFundsExpenseTypeEnum;
  21. import com.ylx.shopingfundsdetail.service.ShoppingFundsDetailService;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.springframework.stereotype.Service;
  24. import org.springframework.transaction.annotation.Transactional;
  25. import javax.annotation.Resource;
  26. import java.math.BigDecimal;
  27. import java.math.RoundingMode;
  28. @Slf4j // 添加日志注解
  29. @Service
  30. public class GiftCardOrderServiceImpl extends ServiceImpl<GiftCardOrderMapper, GiftCardOrder> implements IGiftCardOrderService {
  31. @Resource
  32. private TJsService jsService;
  33. @Resource
  34. private TWxUserService wxUserService;
  35. @Resource
  36. private ShoppingFundsDetailService shoppingFundsDetailService;
  37. @Override
  38. @Transactional(rollbackFor = Exception.class)
  39. public GiftCardOrder buildOrder(GiftCard card, Integer quantity, String merchantId, WxLoginUser wxLoginUser) {
  40. // 1. 参数校验
  41. if (ObjectUtil.isNull(card)) {
  42. throw new ServiceException("购物卡信息不能为空");
  43. }
  44. if (ObjectUtil.isNull(quantity) || quantity <= 0) {
  45. throw new ServiceException("购买数量必须大于0");
  46. }
  47. // 2. 创建订单对象
  48. GiftCardOrder order = new GiftCardOrder();
  49. // 4. 生成唯一订单号(使用更安全的方式)
  50. String orderNo = generateUniqueOrderNo();
  51. order.setOrderNo(orderNo);
  52. // 5. 设置购物卡信息
  53. setGiftCardInfo(order, card);
  54. // 6. 设置用户信息
  55. setUserInfo(order, wxLoginUser);
  56. // 7. 设置商户信息
  57. setMerchantInfo(order, merchantId);
  58. // 8. 计算金额
  59. calculateAmount(order, card, quantity);
  60. order.setPurchaseQuantity(quantity);
  61. // 9. 设置订单状态和时间
  62. order.setStatus(GiftCardOrderStatusEnum.WAIT_PAY.getCode()); // 待支付
  63. order.setCreateTime(DateUtils.getNowDate());
  64. order.setUpdateTime(order.getCreateTime());
  65. int rowsAffected = this.baseMapper.insert(order);
  66. if (rowsAffected <= 0) {
  67. log.warn("购物卡订单创建失败,购物卡ID: {},下单人ID: {}", card.getId(), wxLoginUser.getId());
  68. return null;
  69. }
  70. return order;
  71. }
  72. @Override
  73. @Transactional(rollbackFor = Exception.class)
  74. public void cancelOrder(Long id) {
  75. // 1. 查询订单
  76. GiftCardOrder order = this.getById(id);
  77. if (ObjectUtil.isNull(order)) {
  78. throw new ServiceException("订单不存在");
  79. }
  80. // 仅待支付订单可取消
  81. if (!GiftCardOrderStatusEnum.PAID.getCode().equals(order.getStatus())) {
  82. throw new ServiceException("当前订单状态不支持取消");
  83. }
  84. // 2. 修改订单状态为已取消
  85. order.setStatus(GiftCardOrderStatusEnum.CANCEL.getCode());
  86. order.setUpdateTime(DateUtils.getNowDate());
  87. boolean update = this.updateById(order);
  88. if (!update) {
  89. log.error("订单取消失败,订单号:{}", order.getOrderNo());
  90. throw new ServiceException("订单取消失败");
  91. }
  92. log.info("订单取消成功,订单号:{},购物卡ID:{}", order.getOrderNo(), order.getGiftCardId());
  93. }
  94. @Transactional(rollbackFor = Exception.class)
  95. public void processGiftCardPayment(WxPayOrderNotifyV3Result.DecryptNotifyResult result, TWxUser wxUser,GiftCardOrder cardOrder) {
  96. // 更新订单状态
  97. this.lambdaUpdate()
  98. .set(GiftCardOrder::getStatus, GiftCardOrderStatusEnum.PAID.getCode())
  99. .eq(GiftCardOrder::getId, cardOrder.getId())
  100. .update();
  101. // 计算充值金额
  102. Integer totalCent = result.getAmount().getTotal();
  103. BigDecimal payAmount = new BigDecimal(totalCent).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP);
  104. // 更新用户余额
  105. BigDecimal oldBalance = wxUser.getdBalance();
  106. BigDecimal newBalance = oldBalance.add(payAmount);
  107. this.wxUserService.lambdaUpdate()
  108. .set(TWxUser::getdBalance, newBalance)
  109. .eq(TWxUser::getId, wxUser.getId())
  110. .update();
  111. // 记录购物金明细
  112. ShoppingFundsDetailAddDto dto = new ShoppingFundsDetailAddDto();
  113. dto.setUserId(wxUser.getId());
  114. dto.setAmount(payAmount);
  115. dto.setOrderNo(result.getOutTradeNo());
  116. dto.setExpenseType(ShoppingFundsExpenseTypeEnum.RECHARGE.getCode());
  117. dto.setBalance(newBalance);
  118. dto.setGiftCardId(cardOrder.getGiftCardId());
  119. shoppingFundsDetailService.addShoppingFundsDetail(dto);
  120. }
  121. /**
  122. * 生成唯一订单号
  123. */
  124. private String generateUniqueOrderNo() {
  125. // 使用时间戳 + 随机数 + 更多信息避免冲突
  126. long timestamp = System.currentTimeMillis();
  127. String randomNum = RandomUtil.randomNumbers(6);
  128. // 可以加入用户ID后几位、线程ID等进一步降低冲突概率
  129. String suffix = String.valueOf(timestamp % 1000000).substring(0, 3); // 取时间戳后3位
  130. return "GC" + timestamp + randomNum + suffix;
  131. }
  132. /**
  133. * 设置购物卡信息
  134. */
  135. private void setGiftCardInfo(GiftCardOrder order, GiftCard card) {
  136. order.setGiftCardId(card.getId());
  137. order.setGiftCardName(card.getName());
  138. order.setGiftCardAmount(card.getAmount());
  139. order.setCommissionRate(card.getCommissionRate());
  140. }
  141. /**
  142. * 设置用户信息
  143. */
  144. private void setUserInfo(GiftCardOrder order, WxLoginUser wxLoginUser) {
  145. order.setUserId(wxLoginUser.getId());
  146. order.setUserName(wxLoginUser.getUsername());
  147. order.setUserPhone(wxLoginUser.getCPhone());
  148. }
  149. /**
  150. * 设置商户信息
  151. */
  152. private void setMerchantInfo(GiftCardOrder order, String merchantId) {
  153. if (StrUtil.isEmpty(merchantId)) {
  154. log.warn("商户ID为空,跳过商户信息查询");
  155. return;
  156. }
  157. TJs merchant = this.jsService.getById(merchantId);
  158. if (ObjectUtil.isNotNull(merchant)) {
  159. order.setMerchantId(merchantId);
  160. order.setMerchantName(merchant.getcName());
  161. order.setMerchantNickName(merchant.getcNickName());
  162. // 注意:如果 TJs 表有收款账号字段,可以在这里设置
  163. // order.setMerchantAccount(merchant.getAccount());
  164. }
  165. }
  166. /**
  167. * 计算金额
  168. */
  169. private void calculateAmount(GiftCardOrder order, GiftCard card, Integer quantity) {
  170. BigDecimal payAmount = card.getAmount()
  171. .multiply(new BigDecimal(quantity))
  172. .setScale(2, RoundingMode.HALF_UP); // 保留两位小数
  173. order.setPayAmount(payAmount);
  174. BigDecimal commissionAmount = payAmount
  175. .multiply(card.getCommissionRate())
  176. .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
  177. order.setCommissionAmount(commissionAmount);
  178. }
  179. }