package com.ruoyi.system.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.system.config.ICBCConfig; import com.ruoyi.system.dto.PhysicalGoodsPlaceOrderDTO; import com.ruoyi.system.enums.PhysicalGoodsOrderStatusEnum; import com.ruoyi.system.mapper.TPhysicalGoodsMapper; import com.ruoyi.system.mapper.TPhysicalGoodsOrderMapper; import com.ruoyi.system.model.TCompany; import com.ruoyi.system.model.TPhysicalGoods; import com.ruoyi.system.model.TPhysicalGoodsOrder; import com.ruoyi.system.query.BigGiftPackageQuery; import com.ruoyi.system.service.TAppUserService; import com.ruoyi.system.service.TPhysicalGoodsOrderService; import com.ruoyi.system.utils.ICBCPayUtil; import com.ruoyi.system.utils.OrderCodeGenerator; import com.ruoyi.system.vo.PlaceOrderVO; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; /** *

* 实物商品订单 服务实现类 *

* * @author xiaochen * @since 2025-12-08 */ @Slf4j @Service public class TPhysicalGoodsOrderServiceImpl extends ServiceImpl implements TPhysicalGoodsOrderService { @Resource private TPhysicalGoodsMapper physicalGoodsMapper; @Resource private ICBCPayUtil icbcPayUtil; @Autowired private ICBCConfig icbcConfig; @Autowired private RedisTemplate redisTemplate; @Autowired private TAppUserService appUserService; /** * 实物商品支付参数 Redis Key 前缀 */ private static final String PHYSICAL_ORDER_PAY_PARAMS_KEY = "physical_order_pay_params:"; /** * 支付参数缓存过期时间(24小时) */ private static final long PAY_PARAMS_EXPIRE_HOURS = 60; @Override public Page pageList(BigGiftPackageQuery query) { Page page = new Page<>(query.getPageNum(), query.getPageSize()); return this.baseMapper.pageList(page, query); } @Override public List export(BigGiftPackageQuery query) { return this.baseMapper.export(query); } @Override @Transactional(rollbackFor = Exception.class) public PlaceOrderVO placeOrder(PhysicalGoodsPlaceOrderDTO dto, Integer appUserId, String openid) { // 1. 校验商品是否存在 TPhysicalGoods physicalGoods = physicalGoodsMapper.selectById(dto.getPhysicalGoodsId()); if (physicalGoods == null) { throw new ServiceException("商品不存在"); } // 2. 创建订单 TPhysicalGoodsOrder order = new TPhysicalGoodsOrder(); String orderCode = OrderCodeGenerator.generatePhysicalGoodsOrderCode(); order.setCode(orderCode); order.setAppUserId(appUserId); order.setCreateTime(LocalDateTime.now()); order.setPhysicalGoodsId(dto.getPhysicalGoodsId()); order.setPhysicalGoods(JSON.toJSONString(physicalGoods)); order.setOrderPrice(physicalGoods.getTotalPrice()); order.setPaymentPrice(physicalGoods.getTotalPrice()); // 支付方式:1=微信 order.setPaymentMethod(1); // 订单状态:1=待付款 order.setStatus(PhysicalGoodsOrderStatusEnum.PENDING_PAYMENT.getCode()); order.setDelFlag(0); //查询用户所属公司,获取经销商商户号 TCompany company = appUserService.getUserCompany(appUserId); order.setCompanyId(company.getId()); this.save(order); // 3. 更新商品销量 Integer currentSales = physicalGoods.getSales() == null ? 0 : physicalGoods.getSales(); physicalGoods.setSales(currentSales + 1); physicalGoodsMapper.updateById(physicalGoods); // 4. 调用工行支付 log.info("实物商品下单,订单号:{},支付金额:{},用户ID:{}", orderCode, physicalGoods.getTotalPrice(), appUserId); JSONObject paymentParams = icbcPayUtil.wechatPay(orderCode, physicalGoods.getTotalPrice(), physicalGoods.getName(), openid,icbcConfig.getNotifyUrl()+"/physical/pay-notify", company.getMerchantNumber(), company.getMerchantOpenid()); // 5. 缓存支付参数到 Redis(用于立即支付) String redisKey = PHYSICAL_ORDER_PAY_PARAMS_KEY + order.getId(); redisTemplate.opsForValue().set(redisKey, paymentParams.toJSONString(), PAY_PARAMS_EXPIRE_HOURS, TimeUnit.MINUTES); log.info("实物商品支付参数已缓存,订单ID:{},Redis Key:{}", order.getId(), redisKey); // 6. 构建返回结果 PlaceOrderVO vo = new PlaceOrderVO(); vo.setOrderIds(Collections.singletonList(order.getId())); vo.setOrderCodes(Collections.singletonList(orderCode)); vo.setPaymentParams(paymentParams); return vo; } @Override public PlaceOrderVO payNow(Integer orderId, Integer appUserId) { // 1. 查询订单 TPhysicalGoodsOrder order = this.getById(orderId); if (order == null) { throw new ServiceException("订单不存在"); } // 2. 校验订单所属用户 if (!order.getAppUserId().equals(appUserId)) { throw new ServiceException("无权操作此订单"); } // 3. 校验订单状态(必须是待付款) if (!PhysicalGoodsOrderStatusEnum.PENDING_PAYMENT.getCode().equals(order.getStatus())) { throw new ServiceException("订单状态不正确,无法支付"); } // 4. 从 Redis 获取缓存的支付参数 String redisKey = PHYSICAL_ORDER_PAY_PARAMS_KEY + orderId; Object cachedParams = redisTemplate.opsForValue().get(redisKey); if (cachedParams == null) { throw new ServiceException("支付参数已过期,请重新下单"); } // 5. 构建返回结果 PlaceOrderVO vo = new PlaceOrderVO(); vo.setOrderIds(Collections.singletonList(order.getId())); vo.setOrderCodes(Collections.singletonList(order.getCode())); vo.setPaymentParams(JSON.parseObject(cachedParams.toString())); log.info("实物商品立即支付,订单ID:{},用户ID:{}", orderId, appUserId); return vo; } }