package com.oying.modules.sh.service.impl; import com.alibaba.fastjson2.JSONObject; import com.oying.exception.BadRequestException; import com.oying.modules.hwc.domain.HwcResponse; import com.oying.modules.hwc.service.SwiftPassService; import com.oying.modules.pc.product.domain.Product; import com.oying.modules.pc.product.domain.enums.ProductStatusEnum; import com.oying.modules.pc.product.service.ProductService; import com.oying.modules.pc.store.domain.Store; import com.oying.modules.pc.store.service.StoreService; import com.oying.modules.sh.domain.*; import com.oying.modules.sh.domain.request.GeneratorOrder; import com.oying.modules.sh.domain.request.ProductOrder; import com.oying.modules.sh.domain.request.StatusOrder; import com.oying.modules.sh.domain.request.SubmitOrder; import com.oying.modules.sh.domain.vo.OrderInfo; import com.oying.modules.sh.domain.vo.OrderResponse; import com.oying.modules.sh.domain.vo.ProductInfo; import com.oying.modules.sh.service.*; import com.oying.utils.*; import com.oying.utils.enums.*; import lombok.RequiredArgsConstructor; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.oying.modules.sh.domain.dto.OrderQueryCriteria; import com.oying.modules.sh.mapper.OrderMapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.sql.Timestamp; import java.util.*; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @author lixin * @description 服务实现 * @date 2025-06-11 **/ @Service @RequiredArgsConstructor public class OrderServiceImpl extends ServiceImpl implements OrderService { private final OrderMapper orderMapper; private final UserAddressService userAddressService; private final ProductService productService; private final SwiftPassService swiftPassService; private final OrderProductSnapshotService productSnapshotService; private final OrderAddressSnapshotService addressSnapshotService; private final RedisUtils redisUtils; private final StoreService storeService; private final OrderOperationLogService operationLogService; private final static String DESCRIBE = "哦应:"; @Override public PageResult queryAll(OrderQueryCriteria criteria, Page page) { criteria.setOffset(page.offset()); List list = orderMapper.findAll(criteria, criteria.getBlurry()); Long total = orderMapper.countAll(criteria, criteria.getBlurry()); return PageUtil.toPage(list, total); } @Override public List queryAll(OrderQueryCriteria criteria) { return orderMapper.findAll(criteria, criteria.getBlurry()); } @Override @Transactional(rollbackFor = Exception.class) public synchronized Order submitOrder(SubmitOrder submit, HttpServletRequest request) { switch (submit.getPayType()) { case HWC: case HWC2: break; default: throw new BadRequestException("支付类型暂未开放"); } String orderNum = redisUtils.generateOrderSn(GenerateEnum.ORDER.getKey()); // 总金额 BigDecimal amount = BigDecimal.ZERO; GeneratorOrder generator = new GeneratorOrder(); generator.setProducts(submit.getProducts()); generator.setStoreId(submit.getStoreId()); OrderInfo info = generatorOrder(generator); // 商品快照 List snapshots = new ArrayList<>(); for (ProductInfo productInfo : info.getProducts()) { Product product = productInfo.getProduct(); OrderProductSnapshot snapshot = new OrderProductSnapshot(); snapshot.setOrderNum(orderNum); snapshot.setStoreId(submit.getStoreId()); snapshot.setProductId(product.getProductId()); snapshot.setProductBarcode(product.getBarcode()); snapshot.setProductName(product.getName()); snapshot.setProductTitle(product.getTitle()); snapshot.setProductMainImage(product.getMainImageUrl()); snapshot.setParamData(JSONObject.toJSONString(productInfo.getProductLabels())); snapshot.setUnitPrice(product.getPrice()); snapshot.setDetailCount(productInfo.getCount()); snapshot.setOriginalPrice(product.getPrice()); snapshot.setPaidPrice(product.getPrice()); BigDecimal decimal = BigDecimalUtils.multiply(product.getPrice(), productInfo.getCount()); amount = BigDecimalUtils.add(amount, decimal); snapshot.setActuallyPayPrice(decimal); snapshot.setPayState(PayStateEnum.NOTPAY.getKey()); snapshots.add(snapshot); } Timestamp now = DateUtil.getTimeStamp(); // 下单后30分钟失效 Timestamp time = DateUtil.addMinute(now, 30); String expire = DateUtil.localDateTimeFormat(time.toLocalDateTime(), DateUtil.SDF_YMDHMS); String openid = SecurityUtils.getCurrentOpenid(); if (openid == null || openid.isEmpty()) { throw new BadRequestException("OPENID错误"); } // 门店信息 Store store = storeService.getById(submit.getStoreId()); if (amount.compareTo(store.getDeliveryMinimum()) >= 0) { throw new BadRequestException("起送金额:" + store.getDeliveryMinimum()); } // 订单信息 Order order = new Order(); order.setOrderNum(orderNum); order.setOrderStoreNum(redisUtils.generateOrderSn(Math.toIntExact(submit.getStoreId())).substring(orderNum.length() - 4)); order.setOrderStatus(OrderStatusEnum.ZERO.getKey()); order.setOrderStatusDescribe(OrderStatusEnum.ZERO.getValue()); order.setOrderRemark(submit.getRemark() != null ? submit.getRemark() : ""); order.setOrderTime(submit.getDateTime()); order.setSendPrice(store.getDeliveryFee()); order.setSendType(SendTypeEnum.LY.getKey()); order.setUserId(SecurityUtils.getCurrentUserId()); order.setUsername(SecurityUtils.getCurrentUsername()); order.setStoreId(submit.getStoreId()); order.setStoreName(store.getStoreName()); order.setStoreLogo(store.getLogoImageUrl()); order.setStoreAddress(store.getAddress()); order.setStoreLongitude(BigDecimal.valueOf(store.getLongitude())); order.setStoreLatitude(BigDecimal.valueOf(store.getLatitude())); order.setOrderDescribe(DESCRIBE + submit.getStoreId()); order.setOriginalPrice(amount); order.setPaidPrice(amount); order.setActuallyPayPrice(amount); order.setOpenid(openid); order.setPayType(submit.getPayType().getKey()); order.setExpireTime(expire); order.setOpenid(openid); Long total = BigDecimalUtils.yuanToCents(amount); if (total > 0) { HwcResponse response = swiftPassService.pay(StringUtils.getIp(request), total.toString(), expire, DESCRIBE + submit.getStoreId(), openid, orderNum, submit.getPayType()); //微信支付下单放回值 order.setAppId(response.getAppId()); order.setTimestamp(response.getTimeStamp()); order.setNonceStr(response.getNonceStr()); order.setPackageVal(response.getPackageVal()); order.setSignType(response.getSignType()); order.setPaySign(response.getPaySign()); order.setPayState(PayStateEnum.NOTPAY.getKey()); order.setPayMessage(PayStateEnum.NOTPAY.getValue()); order.setPayTime(null); } else { order.setPayState(PayStateEnum.SUCCESS.getKey()); order.setPayMessage(PayStateEnum.SUCCESS.getValue()); order.setPayTime(DateUtil.localDateTimeFormat(now.toLocalDateTime(), DateUtil.SDF_YMDHMS)); } UserAddress address = userAddressService.getById(submit.getAddressId()); OrderAddressSnapshot addressSnapshot = getOrderAddressSnapshot(orderNum, address); addressSnapshotService.save(addressSnapshot); orderMapper.insert(order); productSnapshotService.saveBatch(snapshots); order.setProductSnapshots(new HashSet<>(snapshots)); OrderResponse response = new OrderResponse(order, addressSnapshot, null); operationLogService.create(response, OrderStatusEnum.ZERO, null); return order; } private static OrderAddressSnapshot getOrderAddressSnapshot(String orderNum, UserAddress address) { OrderAddressSnapshot snapshot = new OrderAddressSnapshot(); snapshot.setOrderNum(orderNum); snapshot.setReceiverName(address.getReceiverName()); snapshot.setReceiverPhone(address.getReceiverPhone()); snapshot.setProvince(address.getProvince() != null ? address.getProvince() : ""); snapshot.setCity(address.getCity() != null ? address.getCity() : ""); snapshot.setDistrict(address.getDistrict() != null ? address.getDistrict() : ""); snapshot.setStreet(address.getStreet() != null ? address.getStreet() : ""); snapshot.setShortAddress(address.getShortAddress()); snapshot.setDetail(address.getDetail()); snapshot.setLongitude(address.getLongitude()); snapshot.setLatitude(address.getLatitude()); snapshot.setTag(address.getTag()); return snapshot; } @Override @Transactional(rollbackFor = Exception.class) public synchronized OrderInfo generatorOrder(GeneratorOrder criteria) { List products = new ArrayList<>(); BigDecimal amount = BigDecimal.ZERO; for (ProductOrder productOrder : criteria.getProducts()) { Product product = productService.getById(productOrder.getProductId()); if (product == null) { throw new BadRequestException("商品不存在"); } if (!product.getStoreId().equals(criteria.getStoreId())) { throw new BadRequestException("不支持跨门店下单"); } if (!product.getStatus().equals(ProductStatusEnum.AVAILABLE.getValue())) { ProductStatusEnum statusEnum = ProductStatusEnum.get(product.getStatus()); throw new BadRequestException(product.getName() + ":" + (statusEnum != null ? statusEnum.getReasonPhrase() : "状态")); } if (productOrder.getCount() > product.getStockQuantity()) { throw new BadRequestException("商品库存不足"); } if (productOrder.getCount() < product.getMinPurchaseQuantity()) { throw new BadRequestException("起售数量不足"); } ProductInfo info = new ProductInfo(); info.setProduct(product); info.setProductLabels(product.getLabels()); info.setCount(productOrder.getCount()); products.add(info); amount = BigDecimalUtils.add(amount, BigDecimalUtils.multiply(product.getPrice(), productOrder.getCount())); } OrderInfo info = new OrderInfo(); info.setProducts(products); info.setAmount(amount); info.setPayAmount(amount); info.setPromotionAmount(BigDecimal.ZERO); info.setUserAddresses(userAddressService.queryUserAddress()); return info; } @Override @Transactional(rollbackFor = Exception.class) public void statusOrder(StatusOrder statusOrder) { operationLog(getByOrderNum(statusOrder.getOrderNum()), statusOrder.getStatus(), null); } @Override @Transactional(rollbackFor = Exception.class) public OrderResponse getByOrderNum(String orderNum) { return new OrderResponse(orderMapper.getByOrderNum(orderNum), addressSnapshotService.queryByOrderNum(orderNum), operationLogService.getByOrderNum(orderNum)); } @Override @Transactional(rollbackFor = Exception.class) public void operationLog(OrderResponse order, OrderStatusEnum stateEnum, String cardName) { operationLogService.create(order, stateEnum, null); } @Override @Transactional(rollbackFor = Exception.class) public void updatePayStatus(String orderNum, PayStateEnum payState, String payMessage, String payTime) { orderMapper.updatePayStatus(orderNum, payState.getKey(), payMessage, payTime); } @Override @Transactional(rollbackFor = Exception.class) public void closeOrder(String orderNum) { OrderResponse response = getByOrderNum(orderNum); Order order = response.getOrder(); if (order == null) { throw new BadRequestException("订单不存在"); } if (!SecurityUtils.getCurrentUserId().equals(order.getUserId())) { throw new BadRequestException("不能修改他人订单"); } if (!order.getPayState().equals(PayStateEnum.NOTPAY.getKey())) { throw new BadRequestException(PayStateEnum.getValue(order.getPayState())); } PayTypeEnum anEnum = PayTypeEnum.find(order.getPayType()); switch (anEnum) { case HWC: case HWC2: JSONObject object = swiftPassService.query(orderNum, anEnum); if (object.getString("trade_state").equals(PayStateEnum.NOTPAY.getKey())) { throw new BadRequestException(PayStateEnum.getValue(order.getPayState())); } swiftPassService.closeOrder(orderNum, anEnum); break; } operationLogService.create(response, OrderStatusEnum.NINE, null); orderMapper.updateCloseStatus(orderNum, PayStateEnum.CLOSED.getKey(), PayStateEnum.CLOSED.getValue()); } @Override @Transactional(rollbackFor = Exception.class) public void create(Order resources) { orderMapper.insert(resources); throw new BadRequestException("未开放"); } @Override @Transactional(rollbackFor = Exception.class) public void update(Order resources) { Order order = getById(resources.getOrderId()); order.copy(resources); orderMapper.updateById(order); } @Override @Transactional(rollbackFor = Exception.class) public void deleteAll(List ids) { orderMapper.deleteBatchIds(ids); } @Override public void download(List all, HttpServletResponse response) throws IOException { List> list = new ArrayList<>(); for (Order order : all) { Map map = new LinkedHashMap<>(); map.put("订单号", order.getOrderNum()); map.put("用户id", order.getUserId()); map.put("门店ID", order.getStoreId()); map.put("门店", order.getStoreName()); map.put("描述", order.getOrderDescribe()); map.put("原金额", order.getOriginalPrice()); map.put("折扣价", order.getPaidPrice()); map.put("实付金额", order.getActuallyPayPrice()); map.put("支付状态", order.getPayState()); map.put("消息", order.getPayMessage()); map.put("支付类型", order.getPayType()); map.put("支付时间", order.getPayTime()); map.put("订单失效时间RFC3339", order.getExpireTime()); map.put("openid", order.getOpenid()); map.put("APPID", order.getAppId()); map.put("创建人", order.getCreateBy()); map.put("创建时间", order.getCreateTime()); map.put("修改者", order.getUpdateBy()); map.put("修改时间", order.getUpdateTime()); list.add(map); } FileUtil.downloadExcel(list, response); } }