package com.iotechn.unimall.biz.service.order; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dobbinsoft.fw.core.exception.AppServiceException; import com.dobbinsoft.fw.core.exception.BizServiceException; import com.dobbinsoft.fw.core.exception.ServiceException; import com.dobbinsoft.fw.pay.enums.PayChannelType; import com.dobbinsoft.fw.pay.model.request.MatrixPayRefundRequest; import com.dobbinsoft.fw.pay.model.result.MatrixPayRefundResult; import com.dobbinsoft.fw.pay.service.pay.MatrixPayService; import com.dobbinsoft.fw.support.component.LockComponent; import com.dobbinsoft.fw.support.mq.DelayedMessageQueue; import com.dobbinsoft.fw.support.properties.FwWxAppProperties; import com.iotechn.unimall.data.constant.LockConst; import com.iotechn.unimall.data.domain.OrderDO; import com.iotechn.unimall.data.domain.OrderSkuDO; import com.iotechn.unimall.data.domain.UserDO; import com.iotechn.unimall.data.dto.order.OrderDTO; import com.iotechn.unimall.data.enums.DMQHandlerType; import com.iotechn.unimall.data.enums.OrderStatusType; import com.iotechn.unimall.data.enums.UserLoginType; import com.iotechn.unimall.data.exception.ExceptionDefinition; import com.iotechn.unimall.data.mapper.OrderMapper; import com.iotechn.unimall.data.mapper.OrderSkuMapper; import com.iotechn.unimall.data.mapper.UserMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import java.util.Date; import java.util.List; /** * Created by rize on 2019/7/10. */ @Service public class OrderBizService { private static final Logger logger = LoggerFactory.getLogger(OrderBizService.class); @Autowired private LockComponent lockComponent; @Autowired private OrderMapper orderMapper; @Autowired private OrderSkuMapper orderSkuMapper; @Autowired private UserMapper userMapper; @Autowired private MatrixPayService payService; @Autowired private DelayedMessageQueue delayedMessageQueue; @Autowired private FwWxAppProperties fwWxAppProperties; public List checkOrderExistByParentNo(String parentOrderNo, Long userId) throws ServiceException { QueryWrapper wrapper = new QueryWrapper().eq("parent_order_no", parentOrderNo); if (userId != null) { wrapper.eq("user_id", userId); } List orderDOS = orderMapper.selectList(wrapper); if (CollectionUtils.isEmpty(orderDOS)) { throw new AppServiceException(ExceptionDefinition.ORDER_NOT_EXIST); } return orderDOS; } public List checkOrderExistByNo(String orderNo, Long userId) throws ServiceException { QueryWrapper wrapper = new QueryWrapper().eq("order_no", orderNo); if (userId != null) { wrapper.eq("user_id", userId); } List orderDOS = orderMapper.selectList(wrapper); if (CollectionUtils.isEmpty(orderDOS)) { throw new AppServiceException(ExceptionDefinition.ORDER_NOT_EXIST); } return orderDOS; } public boolean changeOrderSubStatus(String orderNo, int nowStatus, OrderDO orderDO) throws ServiceException { String parentOrderNo = orderNo.substring(0, orderNo.indexOf('S') + 1); try { // 防止传入值为空,导致其余订单被改变 if(orderNo == null || orderDO == null){ throw new BizServiceException(ExceptionDefinition.ORDER_STATUS_CHANGE_FAILED); } // 同时拿到父单锁和子单锁,才能对子单进行操作 if (lockComponent.tryLock(LockConst.ORDER_SUB_STATUS_LOCK + orderNo, 30) && lockComponent.tryLock(LockConst.ORDER_PARENT_STATUS_LOCK + parentOrderNo, 30)) { if (orderMapper.update(orderDO, new QueryWrapper() .eq("order_no", orderNo) .eq("status", nowStatus)) > 0) { return true; } throw new BizServiceException(ExceptionDefinition.ORDER_STATUS_CHANGE_FAILED); } else { throw new BizServiceException(ExceptionDefinition.ORDER_SYSTEM_BUSY); } } catch (ServiceException e) { throw e; } catch (Exception e) { logger.error("[订单状态扭转] 异常", e); throw new BizServiceException(ExceptionDefinition.ORDER_UNKNOWN_EXCEPTION); } finally { lockComponent.release(LockConst.ORDER_SUB_STATUS_LOCK + orderNo); lockComponent.release(LockConst.ORDER_PARENT_STATUS_LOCK + parentOrderNo); } } public boolean changeOrderParentStatus(String parentOrderNo, int nowStatus, OrderDO orderDO, int length) throws ServiceException { try { // 防止传入值为空,导致其余订单被改变 if (parentOrderNo == null || orderDO == null) { throw new BizServiceException(ExceptionDefinition.ORDER_STATUS_CHANGE_FAILED); } if (lockComponent.tryLock(LockConst.ORDER_PARENT_STATUS_LOCK + parentOrderNo, 30)) { int updateRes = orderMapper.update(orderDO, new QueryWrapper() .eq("parent_order_no", parentOrderNo) .eq("status", nowStatus)); if (updateRes == length) { return true; } throw new BizServiceException(ExceptionDefinition.ORDER_STATUS_CHANGE_FAILED); } else { throw new BizServiceException(ExceptionDefinition.ORDER_SYSTEM_BUSY); } } catch (ServiceException e) { throw e; } catch (Exception e) { logger.error("[订单状态扭转] 异常", parentOrderNo, e); throw new BizServiceException(ExceptionDefinition.ORDER_UNKNOWN_EXCEPTION); } finally { lockComponent.release(LockConst.ORDER_PARENT_STATUS_LOCK + parentOrderNo); } } public OrderDTO getOrderDetail(Long orderId, Long userId) throws ServiceException { QueryWrapper wrapper = new QueryWrapper() .eq("id", orderId); if (userId != null) { wrapper.eq("user_id", userId); } List orderDOS = orderMapper.selectList(wrapper); if (CollectionUtils.isEmpty(orderDOS)) { throw new AppServiceException(ExceptionDefinition.ORDER_NOT_EXIST); } OrderDTO orderDTO = new OrderDTO(); BeanUtils.copyProperties(orderDOS.get(0), orderDTO); orderDTO.setSkuList(orderSkuMapper.selectList(new QueryWrapper().eq("order_id", orderId))); // 封装两个 自动取消 & 自动确认 剩余时间 if (orderDTO.getStatus().intValue() == OrderStatusType.UNPAY.getCode()) { Long taskTime = delayedMessageQueue.getTaskTime(DMQHandlerType.ORDER_AUTO_CANCEL.getCode(), orderDTO.getOrderNo()); if (taskTime != null && taskTime > 0) { orderDTO.setCancelSec(taskTime.intValue()); } } if (orderDTO.getStatus().intValue() == OrderStatusType.WAIT_CONFIRM.getCode()) { Long taskTime = delayedMessageQueue.getTaskTime(DMQHandlerType.ORDER_AUTO_CONFIRM.getCode(), orderDTO.getOrderNo()); if (taskTime != null && taskTime > 0) { orderDTO.setConfirmSec(taskTime.intValue()); } } return orderDTO; } // TODO 使用隔离级别 // @Transactional(rollbackFor = Exception.class) 外面加了事务 public String groupShopStatusRefund(String orderNo) throws ServiceException { if (lockComponent.tryLock(LockConst.ORDER_REFUND_LOCK + orderNo, 30)) { try { //1.校验订单状态是否处于团购状态中 OrderDO orderDO = checkOrderExistByNo(orderNo, null).get(0); if (orderDO.getStatus() != OrderStatusType.GROUP_SHOP_WAIT.getCode()) { throw new BizServiceException(ExceptionDefinition.ORDER_IS_NOT_GROUP_SHOP_STATUS); } //2.退款处理 //2.1.1 先流转状态 OrderDO updateOrderDO = new OrderDO(); updateOrderDO.setStatus(OrderStatusType.REFUNDED.getCode()); updateOrderDO.setGmtUpdate(new Date()); changeOrderSubStatus(orderNo, OrderStatusType.GROUP_SHOP_WAIT.getCode(), updateOrderDO); Long userId = orderDO.getUserId(); UserDO userDO = userMapper.selectById(userId); // TODO 现在已经取消loginType,应该从订单中取支付方式 Integer loginType = 1; // 根据不同的的支付方式,进行退款 if (PayChannelType.WX.getCode().equals(orderDO.getPayChannel())) { //2.1.2 向微信支付平台发送退款请求 // TODO 设置平台 MatrixPayRefundRequest payRefundRequest = new MatrixPayRefundRequest(); payRefundRequest.setAppid(loginType == UserLoginType.MP_WEIXIN.getCode() ? fwWxAppProperties.getMiniAppId() : fwWxAppProperties.getAppId()); payRefundRequest.setOutTradeNo(orderNo); payRefundRequest.setOutRefundNo("refund_" + orderNo); payRefundRequest.setRefundDesc("团购失败退款"); payRefundRequest.setTotalFee(orderDO.getPayPrice() - orderDO.getFreightPrice()); payRefundRequest.setRefundFee(orderDO.getPayPrice() - orderDO.getFreightPrice()); MatrixPayRefundResult payRefundResult = payService.refund(payRefundRequest); if (!payRefundResult.getReturnCode().equals("SUCCESS")) { logger.warn("[微信退款] 失败 : " + payRefundResult.getReturnMsg()); throw new BizServiceException(payRefundResult.getReturnMsg(), ExceptionDefinition.THIRD_PART_SERVICE_EXCEPTION.getCode()); } if (!payRefundResult.getResultCode().equals("SUCCESS")) { logger.warn("[微信退款] 失败 : " + payRefundResult.getReturnMsg()); throw new BizServiceException(payRefundResult.getReturnMsg(), ExceptionDefinition.THIRD_PART_SERVICE_EXCEPTION.getCode()); } return "ok"; } else if (PayChannelType.OFFLINE.getCode().equals(orderDO.getChannel())) { // 不需要退款 return "ok"; } else { throw new AppServiceException(ExceptionDefinition.ORDER_PAY_CHANNEL_NOT_SUPPORT_REFUND); } } catch (ServiceException e) { throw e; } catch (Exception e) { logger.error("[微信退款] 异常", e); throw new AppServiceException(ExceptionDefinition.ADMIN_UNKNOWN_EXCEPTION); } finally { lockComponent.release(LockConst.ORDER_REFUND_LOCK + orderNo); } } else { throw new AppServiceException(ExceptionDefinition.SYSTEM_BUSY); } } }