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;
|
|
/**
|
* <p>
|
* 实物商品订单 服务实现类
|
* </p>
|
*
|
* @author xiaochen
|
* @since 2025-12-08
|
*/
|
@Slf4j
|
@Service
|
public class TPhysicalGoodsOrderServiceImpl extends ServiceImpl<TPhysicalGoodsOrderMapper, TPhysicalGoodsOrder> 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<TPhysicalGoodsOrder> pageList(BigGiftPackageQuery query) {
|
Page<TPhysicalGoodsOrder> page = new Page<>(query.getPageNum(), query.getPageSize());
|
return this.baseMapper.pageList(page, query);
|
}
|
|
@Override
|
public List<TPhysicalGoodsOrder> 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;
|
}
|
}
|