|
@@ -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));
|
|
|
+ }
|
|
|
+}
|