|  | @@ -0,0 +1,267 @@
 | 
	
		
			
				|  |  | +package com.yonge.cooleshow.biz.dal.service.impl;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import com.alibaba.fastjson.JSONObject;
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.core.metadata.IPage;
 | 
	
		
			
				|  |  | +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.constant.SysConfigConstant;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.dto.req.OrderPayReq;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.entity.UserOrderDetail;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.entity.UserOrder;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.entity.UserOrderPayment;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.enums.PayChannelEnum;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.sdk.PaymentSdk;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.sdk.req.DeviceInfo;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.sdk.req.PaymentReq;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.service.*;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.vo.res.OrderCheckRes;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.vo.res.OrderPayRes;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.entity.HttpResponseResult;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.common.exception.BizException;
 | 
	
		
			
				|  |  | +import com.yonge.toolset.utils.collection.MapUtil;
 | 
	
		
			
				|  |  | +import org.apache.commons.beanutils.BeanUtils;
 | 
	
		
			
				|  |  | +import org.slf4j.Logger;
 | 
	
		
			
				|  |  | +import org.slf4j.LoggerFactory;
 | 
	
		
			
				|  |  | +import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  | +import org.springframework.stereotype.Service;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
 | 
	
		
			
				|  |  | +import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
 | 
	
		
			
				|  |  | +import org.springframework.transaction.annotation.Transactional;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +import javax.annotation.PostConstruct;
 | 
	
		
			
				|  |  | +import java.math.BigDecimal;
 | 
	
		
			
				|  |  | +import java.util.*;
 | 
	
		
			
				|  |  | +import java.util.function.Consumer;
 | 
	
		
			
				|  |  | +import java.util.function.Function;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +@Service
 | 
	
		
			
				|  |  | +public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> implements UserOrderService {
 | 
	
		
			
				|  |  | +    private final static Logger log = LoggerFactory.getLogger(UserOrderServiceImpl.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private VipCardRecordService vipCardRecordService;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private SysConfigService sysConfigService;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private UserOrderDetailService orderDetailService;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private UserOrderPaymentService orderPaymentService;
 | 
	
		
			
				|  |  | +    @Autowired
 | 
	
		
			
				|  |  | +    private PaymentSdk paymentSdk;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    //验证订单是否可以下单
 | 
	
		
			
				|  |  | +    private static final Map<String, Function<OrderReq, HttpResponseResult<OrderCheckRes>>> checkOrder = new HashMap<>();
 | 
	
		
			
				|  |  | +    //插入订单后执行
 | 
	
		
			
				|  |  | +    private static final Map<String, Consumer<UserOrderVo>> orderAfter = new HashMap<>();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @PostConstruct
 | 
	
		
			
				|  |  | +    private void init() {
 | 
	
		
			
				|  |  | +        //vip开通缴费
 | 
	
		
			
				|  |  | +        checkOrder.put(OrderTypeEnum.VIP.getCode(), vipCardRecordService::checkOrder);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        //vip开通缴费
 | 
	
		
			
				|  |  | +        orderAfter.put(OrderTypeEnum.VIP.getCode(), vipCardRecordService::orderAfter);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public UserOrderVo detail(Long id) {
 | 
	
		
			
				|  |  | +        return baseMapper.detailById(id);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public UserOrderVo detail(String orderNo) {
 | 
	
		
			
				|  |  | +        return baseMapper.detailByOrderNo(orderNo);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public IPage<UserOrderVo> selectPage(IPage<UserOrderVo> page, OrderSearch query) {
 | 
	
		
			
				|  |  | +        return page.setRecords(baseMapper.selectPage(page, query));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  | +    public HttpResponseResult<UserOrder> executeOrder(OrderReq orderReq) {
 | 
	
		
			
				|  |  | +        log.info("订单[创建订单] Req:{}", JSONObject.toJSONString(orderReq));
 | 
	
		
			
				|  |  | +        //todo 假定一个用户最多有三个待支付,支付中订单
 | 
	
		
			
				|  |  | +        /*Integer num = baseMapper.selectCount(Wrappers.<Order>query().lambda()
 | 
	
		
			
				|  |  | +                .eq(Order::getUserId, orderReq.getUserId())
 | 
	
		
			
				|  |  | +                .in(Order::getStatus, OrderStatusEnum.PAYING.getCode(), OrderStatusEnum.WAIT_PAY.getCode())
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        Integer payingNum = 3;
 | 
	
		
			
				|  |  | +        if (num >= payingNum) {
 | 
	
		
			
				|  |  | +            return HttpResponseResult.failed("未完成订单数过多");
 | 
	
		
			
				|  |  | +        }*/
 | 
	
		
			
				|  |  | +        //todo 订单验证参数,金额不小于0等
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        //验证参数,必须验证参数
 | 
	
		
			
				|  |  | +        Function<OrderReq, HttpResponseResult<OrderCheckRes>> checkFunction = checkOrder.get(orderReq.getOrderType());
 | 
	
		
			
				|  |  | +        if (Objects.isNull(checkFunction)) {
 | 
	
		
			
				|  |  | +            return HttpResponseResult.failed("参数校验失败");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        HttpResponseResult<OrderCheckRes> checkResult = checkFunction.apply(orderReq);
 | 
	
		
			
				|  |  | +        if (!checkResult.getStatus() || null == checkResult.getData() || !checkResult.getData().getRes()) {
 | 
	
		
			
				|  |  | +            log.info("订单[创建订单] Res:{}", JSONObject.toJSONString(checkResult));
 | 
	
		
			
				|  |  | +            return HttpResponseResult.failed("参数校验失败");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //验证成功后,订单入库
 | 
	
		
			
				|  |  | +        UserOrderVo orderVo = insertOrder(orderReq, checkResult.getData());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Consumer<UserOrderVo> afterFunction = orderAfter.get(orderReq.getOrderType());
 | 
	
		
			
				|  |  | +        if (!Objects.isNull(afterFunction)) {
 | 
	
		
			
				|  |  | +            afterFunction.accept(orderVo);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return HttpResponseResult.succeed();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  | +    public HttpResponseResult<OrderPayRes> orderPay(OrderPayReq payReq) {
 | 
	
		
			
				|  |  | +        //查询订单
 | 
	
		
			
				|  |  | +        UserOrderVo detail = detail(payReq.getOrderNo());
 | 
	
		
			
				|  |  | +        if (null == detail) {
 | 
	
		
			
				|  |  | +            return HttpResponseResult.failed("订单不存在");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (OrderStatusEnum.WAIT_PAY.equals(detail.getStatus())) {
 | 
	
		
			
				|  |  | +            //处于待支付状态,需要调用汇付发起付款请求接口
 | 
	
		
			
				|  |  | +            return orderPayWaitPay(payReq, detail);
 | 
	
		
			
				|  |  | +        } else if (OrderStatusEnum.PAYING.equals(detail.getStatus())) {
 | 
	
		
			
				|  |  | +            //处于付款中状态,需要拉起付款接口返回信息,并且去到汇付
 | 
	
		
			
				|  |  | +            return orderPayPaying(payReq, detail);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return HttpResponseResult.failed("订单状态异常");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /***
 | 
	
		
			
				|  |  | +     * 处理待支付订单
 | 
	
		
			
				|  |  | +     * @author liweifan
 | 
	
		
			
				|  |  | +     * @param: payReq
 | 
	
		
			
				|  |  | +     * @param: detail
 | 
	
		
			
				|  |  | +     * @updateTime 2022/4/1 10:32
 | 
	
		
			
				|  |  | +     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private HttpResponseResult<OrderPayRes> orderPayWaitPay(OrderPayReq payReq, UserOrderVo detail) {
 | 
	
		
			
				|  |  | +        PaymentReq paymentReq = new PaymentReq();
 | 
	
		
			
				|  |  | +        paymentReq.setOrder_no(payReq.getOrderNo());
 | 
	
		
			
				|  |  | +        paymentReq.setPay_channel(payReq.getPayChannel().getCode());
 | 
	
		
			
				|  |  | +        paymentReq.setPay_amt(detail.getActualPrice().setScale(2).toString());
 | 
	
		
			
				|  |  | +        paymentReq.setGoods_title(detail.getOrderName());
 | 
	
		
			
				|  |  | +        paymentReq.setGoods_desc(detail.getOrderDesc());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        DeviceInfo deviceInfo = new DeviceInfo();
 | 
	
		
			
				|  |  | +        deviceInfo.setDevice_ip(payReq.getIpAddress());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        paymentReq.setDevice_info(deviceInfo);
 | 
	
		
			
				|  |  | +        paymentReq.setNotify_url("异步通知地址");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (PayChannelEnum.wx_lite.equals(payReq.getPayChannel())) {
 | 
	
		
			
				|  |  | +            Map<String, Object> expend = new HashMap<>();
 | 
	
		
			
				|  |  | +            expend.put("open_id", payReq.getOpenId());
 | 
	
		
			
				|  |  | +            paymentReq.setExpend(expend);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        //付款请求
 | 
	
		
			
				|  |  | +        Map<String, Object> res = paymentSdk.executePayment(paymentReq);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        OrderPayRes orderPayRes = new OrderPayRes();
 | 
	
		
			
				|  |  | +        orderPayRes.setPay_amt(detail.getActualPrice().setScale(2).toString());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        orderPayRes.setPay_info(
 | 
	
		
			
				|  |  | +                MapUtil.populateMap(new HashMap<>(), res.get("expend"))
 | 
	
		
			
				|  |  | +                        .get("pay_info").toString()
 | 
	
		
			
				|  |  | +        );
 | 
	
		
			
				|  |  | +        //insertOrderPayment();
 | 
	
		
			
				|  |  | +        //入订单付款表,同时修改订单状态
 | 
	
		
			
				|  |  | +        UserOrderPayment orderPayment = new UserOrderPayment();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return HttpResponseResult.succeed(orderPayRes);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /***
 | 
	
		
			
				|  |  | +     * 处理待支付中订单
 | 
	
		
			
				|  |  | +     * @author liweifan
 | 
	
		
			
				|  |  | +     * @param: payReq
 | 
	
		
			
				|  |  | +     * @param: detail
 | 
	
		
			
				|  |  | +     * @updateTime 2022/4/1 10:32
 | 
	
		
			
				|  |  | +     * @return: com.yonge.cooleshow.common.entity.HttpResponseResult<java.lang.Boolean>
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private HttpResponseResult<OrderPayRes> orderPayPaying(OrderPayReq payReq, UserOrderVo detail) {
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /***
 | 
	
		
			
				|  |  | +     * 订单入库
 | 
	
		
			
				|  |  | +     * @author liweifan
 | 
	
		
			
				|  |  | +     * @param: orderReq
 | 
	
		
			
				|  |  | +     * @updateTime 2022/3/31 16:15
 | 
	
		
			
				|  |  | +     * @return: com.yonge.cooleshow.biz.dal.entity.Order
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private UserOrderVo insertOrder(OrderReq orderReq, OrderCheckRes data) {
 | 
	
		
			
				|  |  | +        UserOrder userOrder = new UserOrder();
 | 
	
		
			
				|  |  | +        //todo 订单号生产规则
 | 
	
		
			
				|  |  | +        userOrder.setOrderNo("123");
 | 
	
		
			
				|  |  | +        userOrder.setUserId(orderReq.getUserId());
 | 
	
		
			
				|  |  | +        userOrder.setMerchId(data.getMerchId());
 | 
	
		
			
				|  |  | +        userOrder.setOrderName(orderReq.getOrderName());
 | 
	
		
			
				|  |  | +        userOrder.setOrderDesc(orderReq.getOrderDesc());
 | 
	
		
			
				|  |  | +        userOrder.setStatus(OrderStatusEnum.WAIT_PAY);
 | 
	
		
			
				|  |  | +        userOrder.setOriginalPrice(orderReq.getOriginalPrice());
 | 
	
		
			
				|  |  | +        userOrder.setExpectPrice(orderReq.getExpectPrice());
 | 
	
		
			
				|  |  | +        userOrder.setActualPrice(orderReq.getActualPrice());
 | 
	
		
			
				|  |  | +        userOrder.setCouponAmount(orderReq.getCouponAmount());
 | 
	
		
			
				|  |  | +        //平台服务费
 | 
	
		
			
				|  |  | +        BigDecimal serviceFeeRate = getServiceFeeRate(orderReq.getOrderType());
 | 
	
		
			
				|  |  | +        userOrder.setPlantformFee(orderReq.getActualPrice().multiply(serviceFeeRate));
 | 
	
		
			
				|  |  | +        userOrder.setPlantformFeeRate(serviceFeeRate);
 | 
	
		
			
				|  |  | +        userOrder.setUserNote(orderReq.getUserNote());
 | 
	
		
			
				|  |  | +        userOrder.setOrderType(orderReq.getOrderType());
 | 
	
		
			
				|  |  | +        userOrder.setCreateTime(new Date());
 | 
	
		
			
				|  |  | +        int insert = baseMapper.insert(userOrder);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (insert == 0 || null == userOrder.getId()) {
 | 
	
		
			
				|  |  | +            throw new BizException("插入失败");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        UserOrderDetail orderDetail = new UserOrderDetail();
 | 
	
		
			
				|  |  | +        orderDetail.setOrderNo(userOrder.getOrderNo());
 | 
	
		
			
				|  |  | +        orderDetail.setBizId(orderReq.getBizId());
 | 
	
		
			
				|  |  | +        orderDetail.setBizContent(orderReq.getBizContent());
 | 
	
		
			
				|  |  | +        orderDetail.setCreateTime(new Date());
 | 
	
		
			
				|  |  | +        orderDetailService.save(orderDetail);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        UserOrderVo vo = new UserOrderVo();
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            BeanUtils.copyProperties(vo, userOrder);
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            e.printStackTrace();
 | 
	
		
			
				|  |  | +            throw new BizException("对象转换失败");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        vo.setOrderDetail(orderDetail);
 | 
	
		
			
				|  |  | +        return vo;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /***
 | 
	
		
			
				|  |  | +     * 获取平台服务费率
 | 
	
		
			
				|  |  | +     * @author liweifan
 | 
	
		
			
				|  |  | +     * @param: orderTypeEnum
 | 
	
		
			
				|  |  | +     * @updateTime 2022/3/31 16:49
 | 
	
		
			
				|  |  | +     * @return: java.math.BigDecimal
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private BigDecimal getServiceFeeRate(OrderTypeEnum orderTypeEnum) {
 | 
	
		
			
				|  |  | +        String configValue = "0";
 | 
	
		
			
				|  |  | +        if (OrderTypeEnum.VIDEO.equals(orderTypeEnum)) {
 | 
	
		
			
				|  |  | +            configValue = sysConfigService.findConfigValue(SysConfigConstant.VIDEO_LESSON_SERVICE_FEE);
 | 
	
		
			
				|  |  | +        } else if (OrderTypeEnum.PRACTICE.equals(orderTypeEnum)) {
 | 
	
		
			
				|  |  | +            configValue = sysConfigService.findConfigValue(SysConfigConstant.PRACTICE_SERVICE_FEE);
 | 
	
		
			
				|  |  | +        } else if (OrderTypeEnum.LIVE.equals(orderTypeEnum)) {
 | 
	
		
			
				|  |  | +            configValue = sysConfigService.findConfigValue(SysConfigConstant.LIVE_SERVICE_RATE);
 | 
	
		
			
				|  |  | +        } else if (OrderTypeEnum.MUSIC.equals(orderTypeEnum)) {
 | 
	
		
			
				|  |  | +            configValue = sysConfigService.findConfigValue(SysConfigConstant.MUSIC_SHEET_SERVICE_FEE);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return new BigDecimal(configValue).divide(new BigDecimal(100));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 |