| | |
| | | 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.sh.domain.Order; |
| | | import com.oying.modules.pc.store.domain.Store; |
| | | import com.oying.modules.pc.store.domain.enums.StoreStatusEnum; |
| | | 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.UserAddressService; |
| | | import com.oying.utils.FileUtil; |
| | | 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.service.OrderService; |
| | | 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 com.oying.utils.PageUtil; |
| | | |
| | | 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; |
| | | |
| | | import com.oying.utils.PageResult; |
| | | |
| | | /** |
| | | * @author lixin |
| | |
| | | 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<Order> queryAll(OrderQueryCriteria criteria, Page<Object> page) { |
| | | return PageUtil.toPage(orderMapper.findAll(criteria, page)); |
| | | criteria.setOffset(page.offset()); |
| | | List<Order> list = orderMapper.findAll(criteria, criteria.getBlurry()); |
| | | Long total = orderMapper.countAll(criteria, criteria.getBlurry()); |
| | | return PageUtil.toPage(list, total); |
| | | } |
| | | |
| | | @Override |
| | | public List<Order> queryAll(OrderQueryCriteria criteria) { |
| | | return orderMapper.findAll(criteria); |
| | | } |
| | | |
| | | @Override |
| | | public Order submitOrder(SubmitOrder submit) { |
| | | return null; |
| | | return orderMapper.findAll(criteria, criteria.getBlurry()); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public OrderInfo generatorOrder(GeneratorOrder criteria) { |
| | | public synchronized Order submitOrder(SubmitOrder submit, HttpServletRequest request) { |
| | | switch (submit.getPayType()) { |
| | | case HWC: |
| | | case HWC2: |
| | | break; |
| | | default: |
| | | throw new BadRequestException("支付类型暂未开放"); |
| | | } |
| | | GeneratorOrder generator = new GeneratorOrder(); |
| | | generator.setProducts(submit.getProducts()); |
| | | generator.setStoreId(submit.getStoreId()); |
| | | OrderInfo info = generatorOrder(generator); |
| | | Store store = info.getStore(); |
| | | UserAddress address = userAddressService.getById(submit.getAddressId(), store.getLongitude(), store.getLatitude()); |
| | | if (address == null) { |
| | | throw new BadRequestException("没找到用户地址"); |
| | | } |
| | | if (!(address.getDistance().compareTo(BigDecimal.valueOf(store.getRadius())) <= 0)) { |
| | | throw new BadRequestException("超出配送范围"); |
| | | } |
| | | String orderNum = redisUtils.generateOrderSn(GenerateEnum.ORDER.getKey()); |
| | | // 总金额 |
| | | BigDecimal amount = BigDecimal.ZERO; |
| | | // 商品快照 |
| | | List<OrderProductSnapshot> 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错误"); |
| | | } |
| | | // 订单信息 |
| | | 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)); |
| | | } |
| | | |
| | | 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) { |
| | | // 门店信息 |
| | | Store store = storeService.getById(criteria.getStoreId()); |
| | | if (!store.getBusinessStatus().equals(StoreStatusEnum.OPEN.getValue())) { |
| | | throw new BadRequestException("停止营业"); |
| | | } |
| | | List<ProductInfo> products = new ArrayList<>(); |
| | | BigDecimal amount = BigDecimal.ZERO; |
| | | for (ProductOrder productOrder : criteria.getProducts()) { |
| | |
| | | if (product == null) { |
| | | throw new BadRequestException("商品不存在"); |
| | | } |
| | | if (product.getStoreId().equals(criteria.getStoreId())) { |
| | | 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.getProductCount() > product.getStockQuantity()) { |
| | | if (productOrder.getCount() > product.getStockQuantity()) { |
| | | throw new BadRequestException("商品库存不足"); |
| | | } |
| | | if (productOrder.getProductCount() < product.getMinPurchaseQuantity()) { |
| | | if (productOrder.getCount() < product.getMinPurchaseQuantity()) { |
| | | throw new BadRequestException("起售数量不足"); |
| | | } |
| | | ProductInfo info = new ProductInfo(); |
| | | info.setProduct(product); |
| | | info.setProductLabels(product.getLabels()); |
| | | info.setCount(productOrder.getProductCount()); |
| | | info.setCount(productOrder.getCount()); |
| | | products.add(info); |
| | | amount = amount.add(product.getPrice().multiply(BigDecimal.valueOf(productOrder.getProductCount()))); |
| | | amount = BigDecimalUtils.add(amount, BigDecimalUtils.multiply(product.getPrice(), productOrder.getCount())); |
| | | } |
| | | if (!(amount.compareTo(store.getDeliveryMinimum()) >= 0)) { |
| | | throw new BadRequestException("起送金额:" + store.getDeliveryMinimum()); |
| | | } |
| | | OrderInfo info = new OrderInfo(); |
| | | info.setStore(store); |
| | | info.setProducts(products); |
| | | info.setAmount(amount); |
| | | info.setPayAmount(amount); |
| | | info.setPromotionAmount(BigDecimal.ZERO); |
| | | info.setUserAddresses(userAddressService.queryUserAddress()); |
| | | info.setUserAddresses(userAddressService.queryUserAddress(store.getLongitude(), store.getLatitude())); |
| | | 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, cardName); |
| | | } |
| | | |
| | | @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 synchronized void cancel(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 |
| | |
| | | map.put("消息", order.getPayMessage()); |
| | | map.put("支付类型", order.getPayType()); |
| | | map.put("支付时间", order.getPayTime()); |
| | | map.put("订单失效时间RFC3339", order.getExpireTime()); |
| | | map.put("订单失效时间", order.getExpireTime()); |
| | | map.put("openid", order.getOpenid()); |
| | | map.put("APPID", order.getAppId()); |
| | | map.put("创建人", order.getCreateBy()); |