package com.zbkj.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.huifu.bspay.sdk.opps.core.utils.RsaUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.beust.jcommander.internal.Lists;
import com.google.common.collect.Maps;
import com.zbkj.common.constants.*;
import com.zbkj.common.dto.HuifuWalletAccountDto;
import com.zbkj.common.dto.HuifuWalletTransferDto;
import com.zbkj.common.dto.JsPayTransferDto;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.exception.CrmebWalletException;
import com.zbkj.common.model.admin.SystemAdmin;
import com.zbkj.common.model.alipay.AliPayInfo;
import com.zbkj.common.model.bcx.*;
import com.zbkj.common.model.bill.Bill;
import com.zbkj.common.model.bill.MerchantBill;
import com.zbkj.common.model.coupon.CouponUser;
import com.zbkj.common.model.huifu.JsPayTrade;
import com.zbkj.common.model.merchant.Merchant;
import com.zbkj.common.model.order.*;
import com.zbkj.common.model.product.ProductAttrValue;
import com.zbkj.common.model.product.ProductCoupon;
import com.zbkj.common.model.system.SystemNotification;
import com.zbkj.common.model.user.*;
import com.zbkj.common.model.wechat.WechatPayInfo;
import com.zbkj.common.model.wechat.video.PayComponentProduct;
import com.zbkj.common.request.OrderPayRequest;
import com.zbkj.common.request.bcx.BcxMerchantPayOfflineRequest;
import com.zbkj.common.response.OrderPayResultResponse;
import com.zbkj.common.response.PayConfigResponse;
import com.zbkj.common.utils.*;
import com.zbkj.common.vo.*;
import com.zbkj.common.vo.wxvedioshop.ShopOrderAddResultVo;
import com.zbkj.common.vo.wxvedioshop.order.*;
import com.zbkj.service.config.PaymentChannel;
import com.zbkj.service.dao.HuifuWalletAccountDao;
import com.zbkj.service.dao.JsPayTradeDao;
import com.zbkj.service.factory.PaymentFactory;
import com.zbkj.service.huifu.constants.HFConstants;
import com.zbkj.service.huifu.constants.HFProfileCPayConstants;
import com.zbkj.service.huifu.constants.HFProfileConstants;
import com.zbkj.service.service.*;
import com.zbkj.service.service.bcx.BcxOrderRelationService;
import com.zbkj.service.service.bcx.BcxPayOfflineFileService;
import com.zbkj.service.service.bcx.BcxPayOfflineService;
import com.zbkj.service.service.bcx.BcxPlatformFeeService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zbkj.common.constants.PayConstants.PAY_TYPE_OFFLINE;

/**
 * PayServiceImpl 接口实现
 * +----------------------------------------------------------------------
 * | CRMEB [ CRMEB赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2016~2023 https://www.crmeb.com All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed CRMEB并不是自由软件，未经许可不能去掉CRMEB相关版权
 * +----------------------------------------------------------------------
 * | Author: CRMEB Team <admin@crmeb.com>
 * +----------------------------------------------------------------------
 */
@Service
public class PayServiceImpl implements PayService {

    private static final Logger logger = LoggerFactory.getLogger(PayServiceImpl.class);

    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private UserService userService;
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private UserTokenService userTokenService;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private WechatPayInfoService wechatPayInfoService;
    @Autowired
    private AliPayService aliPayService;
    @Autowired
    private MerchantOrderService merchantOrderService;
    @Autowired
    private OrderStatusService orderStatusService;
    @Autowired
    private UserIntegralRecordService userIntegralRecordService;
    @Autowired
    private SystemNotificationService systemNotificationService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private TemplateMessageService templateMessageService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private ProductCouponService productCouponService;
    @Autowired
    private CouponUserService couponUserService;
    @Autowired
    private CouponService couponService;
    @Autowired
    private UserBrokerageRecordService userBrokerageRecordService;
    @Autowired
    private UserBalanceRecordService userBalanceRecordService;
    @Autowired
    private MerchantService merchantService;
    @Autowired
    private MerchantBillService merchantBillService;
    @Autowired
    private OrderProfitSharingService orderProfitSharingService;
    @Autowired
    private BillService billService;
    @Autowired
    private WechatVideoOrderService wechatVideoOrderService;
    @Autowired
    @Lazy
    private AsyncService asyncService;
    @Autowired
    private PayComponentOrderService payComponentOrderService;
    @Autowired
    private PayComponentProductService payComponentProductService;
    @Autowired
    private AliPayInfoService aliPayInfoService;
    @Autowired
    private RechargeOrderService rechargeOrderService;

    @Resource
    private BcxPlatformFeeService bcxPlatformFeeService;
    @Resource
    private RestTemplateUtil restTemplateUtil;

    @Autowired
    HuifuReconcileService huifuReconcileService;
    @Resource
    private JsPayTradeDao jsPayTradeDao;
    @Resource
    private ProductAttrValueService productAttrValueService;
    @Autowired
    TransactionLogService transactionLogService;
    @Resource
    private HuifuWalletAccountDao huifuWalletAccountDao;
    @Resource
    private BcxPayOfflineService bcxPayOfflineService;
    @Resource
    private BcxPayOfflineFileService bcxPayOfflineFileService;
    @Resource
    BcxOrderRelationService bcxOrderRelationService;
    @Resource
    VirtualOrderService virtualOrderService;

    @Autowired
    private PaymentFactory paymentFactory;
    @Autowired
    private RedissonClient redisson;

    private final static String TRANSFERKEY = "Callback:";

    private static final DecimalFormat decimalFormat = new DecimalFormat(Constants.DECIMAL_FORMAT);

    /**
     * 发送短信验证码
     *
     * @param phone 手机号
     * @return Boolean
     */
    @Override
    public Boolean sendWalletCode(String phone) {
        return smsService.sendCommonCode(phone);
    }

    /**
     * 获取支付配置
     */
    @Override
    public PayConfigResponse getPayConfig() {
        String payWxOpen = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_WECHAT_OPEN);
        String yuePayStatus = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_YUE_PAY_STATUS);
        String aliPayStatus = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_ALI_PAY_STATUS);
        PayConfigResponse response = new PayConfigResponse();
        response.setWalletStatus(true);// 默认使用企业钱包，如果要配置，需要后台加功能
        User user = userService.getInfo();
        try {
            BigDecimal accountBalance = paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).getHuifuWallectBalanceByUniId(user.getIdentityNo());// 企业钱包可用余额
            response.setWalletBalance(accountBalance);
        } catch (Exception e) {
            logger.error("获取企业钱包余额出错：", e);
            response.setWalletStatus(false);
        }
        response.setYuePayStatus(Constants.CONFIG_FORM_SWITCH_OPEN.equals(yuePayStatus));
        response.setPayWechatOpen(Constants.CONFIG_FORM_SWITCH_OPEN.equals(payWxOpen));
        response.setAliPayStatus(Constants.CONFIG_FORM_SWITCH_OPEN.equals(aliPayStatus));
        if (Constants.CONFIG_FORM_SWITCH_OPEN.equals(yuePayStatus)) {
            response.setUserBalance(user.getNowMoney());
        }
        return response;
    }

    /**
     * <b> 根据订单号获取商户identify_no和订单金额 </b>
     * @author ZXF
     * @create 2024/02/29 0029 10:40
     * @version
     * @注意事项 </b>
     */
    public Map<String,String> getIdentifyNoByOrderNo(String orderNo){
        Order order = orderService.getByOrderNo(orderNo);
        if(order == null){
            throw new CrmebException("未找到订单信息");
        }
        Integer merId = order.getMerId();
        Merchant merchant = merchantService.getByIdException(merId);
        if (StrUtil.isBlank(merchant.getIdentityNo())) {
            throw new CrmebException("商户未开通企业钱包");
        }
        Map<String,String> map = Maps.newHashMap();
        map.put("inId",merchant.getIdentityNo());
        map.put("amount",order.getPayPrice().toPlainString());
        return map;
    }

    /**
     * <b> 虚拟订单支付业务 </b>
     * @author ZXF
     * @create 2025/08/28 0028 11:26
     * @version
     * @注意事项 </b>
     */
    private OrderPayResultResponse virtualPayment(OrderPayRequest orderPayRequest) {
        VirtualOrder virtualOrder = virtualOrderService.getByVirtualOrderNo(orderPayRequest.getOrderNo());
        OrderPayResultResponse response = new OrderPayResultResponse();
        if(virtualOrder == null){
            throw new CrmebException("订单不存在");
        }
        User user = userService.getById(virtualOrder.getUid());
        // 0元付
        if (virtualOrder.getTotalPrice().compareTo(BigDecimal.ZERO) <= 0) {
            response.setPayType(PayConstants.PAY_TYPE_ZERO);
            response.setStatus(virtualOrderService.virtualOrderPay(virtualOrder,user.getIdentityNo()));
            response.setOrderNo(orderPayRequest.getOrderNo());
            return response;
        }
        // 余额支付
        if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            if (user.getNowMoney().compareTo(virtualOrder.getTotalPrice()) < 0) {
                throw new CrmebException("用户余额不足");
            }
        }
        // 企业钱包支付
        if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_WALLET)) {
            if (StrUtil.isBlank(user.getIdentityNo())) {
                throw new CrmebException("用户未开通企业钱包");
            }
            BigDecimal accountBalance = null;
            try {
                accountBalance = paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).getHuifuWallectBalanceByUniId(user.getIdentityNo());// 企业钱包可用余额
            } catch (Exception e) {
                logger.error("获取企业钱包余额出错：", e);
                throw new CrmebException("获取企业钱包余额出错,是否有开通企业钱包？");
            }
            if (accountBalance.compareTo(virtualOrder.getTotalPrice()) < 0) {
                throw new CrmebException("企业钱包余额不足");
            }
        }
        Integer merId = virtualOrder.getMerId();
        Merchant merchant = merchantService.getByIdException(merId);
        if (StrUtil.isBlank(merchant.getIdentityNo())) {
            throw new CrmebException("商户未开通企业钱包");
        }

        response.setOrderNo(orderPayRequest.getOrderNo());
        response.setPayType(orderPayRequest.getPayType());
        response.setPayChannel(orderPayRequest.getPayChannel());

        response.setStatus(virtualOrderService.virtualOrderPay(virtualOrder,user.getIdentityNo()));
        return response;
    }

    /**
     * 订单支付
     *
     * @param orderPayRequest 订单支付参数
     * @return OrderPayResultResponse
     */
    @Override
    public OrderPayResultResponse payment(OrderPayRequest orderPayRequest) {
        logger.info("订单支付 START orderPayRequest:{}", JSON.toJSONString(orderPayRequest));
        ////单独虚拟订单支付业务
        if(orderPayRequest.getOrderNo().startsWith(OrderConstants.ORDER_ATTR_VIR_SIGN)){
            return virtualPayment(orderPayRequest);
        }
        Order order = orderService.getByOrderNo(orderPayRequest.getOrderNo());
        logger.info("订单支付 当前操作的订单信息:{}", JSON.toJSONString(order));
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException("订单已取消");
        }
        if (order.getPaid()) {
            throw new CrmebException("订单已支付");
        }
        if (order.getStatus() > OrderConstants.ORDER_STATUS_WAIT_PAY) {
            throw new CrmebException("订单状态异常");
        }
//        User user = userService.getInfo();
        User user = userService.getById(order.getUid());
        OrderPayResultResponse response = new OrderPayResultResponse();
        // 0元付
        if (order.getPayPrice().compareTo(BigDecimal.ZERO) <= 0) {
            Boolean aBoolean = zeroPay(order, user);
            response.setPayType(PayConstants.PAY_TYPE_ZERO);
            response.setStatus(aBoolean);
            response.setOrderNo(order.getOrderNo());
            return response;
        }

        // 根据支付类型进行校验,更换支付类型
        order.setPayType(orderPayRequest.getPayType());
        order.setPayChannel(orderPayRequest.getPayChannel());
        // 余额支付
        if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            if (user.getNowMoney().compareTo(order.getPayPrice()) < 0) {
                throw new CrmebException("用户余额不足");
            }
        }
        // 企业钱包支付
        if (orderPayRequest.getPayType().equals(PayConstants.PAY_TYPE_WALLET)) {
            if (StrUtil.isBlank(user.getIdentityNo())) {
                throw new CrmebException("用户未开通企业钱包");
            }
            BigDecimal accountBalance = null;
            try {
                accountBalance = paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).getHuifuWallectBalanceByUniId(user.getIdentityNo());// 企业钱包可用余额
            } catch (Exception e) {
                logger.error("获取企业钱包余额出错：", e);
                throw new CrmebException("获取企业钱包余额出错,是否有开通企业钱包？");
            }
            if (accountBalance.compareTo(order.getPayPrice()) < 0) {
                throw new CrmebException("企业钱包余额不足");
            }
        }
        Integer merId = order.getMerId();
        Merchant merchant = merchantService.getByIdException(merId);
        if (StrUtil.isBlank(merchant.getIdentityNo())) {
            throw new CrmebException("商户未开通企业钱包");
        }

        response.setOrderNo(order.getOrderNo());
        response.setPayType(order.getPayType());
        response.setPayChannel(order.getPayChannel());

        // 余额支付
        if (order.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            Boolean yueBoolean = yuePay(order, user);
            response.setStatus(yueBoolean);
            logger.info("余额支付 response : {}", JSON.toJSONString(response));
            return response;
        }
        // 企业钱包支付
        if (order.getPayType().equals(PayConstants.PAY_TYPE_WALLET)) {
            List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(orderPayRequest.getOrderNo());
            List<Integer> productIds = orderDetails.stream().map(OrderDetail::getProductId).collect(Collectors.toList());
            Integer bizType = orderService.getBizTypeByProductsType(productIds);// 0-实物 1-虚拟 2-特殊(考培)
            Boolean walletBoolean = walletFreezeAndPay(order, orderDetails.get(0), bizType, user, merchant);
            response.setStatus(walletBoolean);
            logger.info("企业钱包支付 response : {}", JSON.toJSONString(response));
            return response;
        }
        // 微信支付，调用微信预下单，返回拉起微信支付需要的信息
        if (order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
            logger.info("订单支付 微信下单");
            WxPayJsResultVo vo = wechatPayment(order);
            orderService.updateById(order);
            response.setStatus(true);
            response.setJsConfig(vo);
            logger.info("订单支付 微信下单 response :{}", JSON.toJSONString(response));
        }

        // 微信视频号下单 需要额外调用支付参数
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO)) {
            WxPayJsResultVo vo = new WxPayJsResultVo();
            UserToken tokenByUser = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
            List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
            logger.info("视频号下单，订单详情:{}", JSON.toJSONString(orderDetailList));
            //  视频号下单都是单品
            PayComponentProduct payComponentProduct = payComponentProductService.getById(orderDetailList.get(0).getProductId());
            logger.info("视频号下单，当前视频号商品:{}", JSON.toJSONString(payComponentProduct));
            //组装商品信息
            ShopOrderDetailAddVo shopOrderDetailAddVo = new ShopOrderDetailAddVo();
            List<ShopOrderProductInfoAddVo> shopOrderProductInfoAddVoList = new ArrayList<>();
            for (OrderDetail orderDetail : orderDetailList) {
                ShopOrderProductInfoAddVo shopOrderProductInfoAddVo = new ShopOrderProductInfoAddVo();
                shopOrderProductInfoAddVo.setOutProductId(orderDetail.getProductId().toString());
                shopOrderProductInfoAddVo.setOutSkuId(orderDetail.getAttrValueId().toString());
                shopOrderProductInfoAddVo.setProductCnt(orderDetail.getPayNum());
                shopOrderProductInfoAddVo.setSalePrice(orderDetail.getPrice().multiply(new BigDecimal("100")).longValue());
                shopOrderProductInfoAddVo.setSkuRealPrice(orderDetail.getPayPrice().multiply(new BigDecimal("100")).longValue());
                shopOrderProductInfoAddVo.setPath(payComponentProduct.getPath());
                shopOrderProductInfoAddVo.setTitle(payComponentProduct.getTitle());
                shopOrderProductInfoAddVo.setHeadImg(payComponentProduct.getHeadImg());
                shopOrderProductInfoAddVoList.add(shopOrderProductInfoAddVo);
            }
            shopOrderDetailAddVo.setProductInfos(shopOrderProductInfoAddVoList);

            // 组装支付方式
            ShopOrderPayInfoAddVo payInfoAddVo = new ShopOrderPayInfoAddVo();
            payInfoAddVo.setPayMethodType(0);
            payInfoAddVo.setPayMethod("微信支付"); // 视频号暂时只有微信支付
            shopOrderDetailAddVo.setPayInfo(payInfoAddVo);

            // 组装支付详细信息
            ShopOrderPriceInfoVo shopOrderPriceInfoVo = new ShopOrderPriceInfoVo();
            shopOrderPriceInfoVo.setOrderPrice(order.getPayPrice().multiply(new BigDecimal("100")).longValue());
            // 视频号商品暂时面部免运费
            shopOrderPriceInfoVo.setFreight(0L);
            shopOrderPriceInfoVo.setDiscountedPrice(0L);
            shopOrderPriceInfoVo.setAdditionalPrice(0L);
            shopOrderPriceInfoVo.setAdditional_remarks(null);
            shopOrderDetailAddVo.setPriceInfo(shopOrderPriceInfoVo);

            // 组装自定义交易组件主体数据
            ShopOrderAddVo shopOrderAddVo = new ShopOrderAddVo();
            shopOrderAddVo.setOrderDetail(shopOrderDetailAddVo);
            shopOrderAddVo.setFund_type(1);
            shopOrderAddVo.setTrace_id(null);
            shopOrderAddVo.setOutOrderId(order.getOrderNo());
            shopOrderAddVo.setOpenid(tokenByUser.getToken());
            shopOrderAddVo.setOutUserId(user.getId());
            shopOrderAddVo.setMerId(merId);

            // 订单路由地址
            shopOrderAddVo.setPath("/pages/users/order_details/index?orderNo=" + orderPayRequest.getOrderNo());

            // 组装订单信息 视频号都是单品 最多是多量
            List<MerchantOrder> merchantOrderList = merchantOrderService.getByOrderNo(orderPayRequest.getOrderNo());
            if (ObjectUtil.isNull(merchantOrderList) || merchantOrderList.size() == 0) {
                throw new CrmebException("未找到视频号商品订单");
            }
            MerchantOrder CurrentMerchantOrder = merchantOrderList.get(0);
            ShopOrderAddressInfoAddVo shopOrderAddressInfoAddVo = new ShopOrderAddressInfoAddVo();
            shopOrderAddressInfoAddVo.setReceiverName(CurrentMerchantOrder.getRealName());
            shopOrderAddressInfoAddVo.setDetailedAddress(CurrentMerchantOrder.getUserAddress());
            shopOrderAddressInfoAddVo.setTelNumber(CurrentMerchantOrder.getUserPhone());
            shopOrderAddVo.setAddressInfo(shopOrderAddressInfoAddVo);

            // 1: 正常快递, 2: 无需快递, 3: 线下配送, 4: 用户自提，视频号场景目前只支持 1，正常快递
            ShopOrderDeliveryDetailAddVo shopOrderDeliveryDetailAddVo = new ShopOrderDeliveryDetailAddVo();
            shopOrderDeliveryDetailAddVo.setDeliveryType(1);

            shopOrderAddVo.setDeliveryDetail(shopOrderDeliveryDetailAddVo);
            shopOrderAddVo.setExpire_time(WxPayUtil.getCurrentTimestamp().intValue() + 900);
            shopOrderAddVo.setCreateTime(CrmebDateUtil.nowDateTimeStr());
            ShopOrderAddResultVo shopOrderAddResultVo = payComponentOrderService.create(shopOrderAddVo);
            ShopOrderGetPaymentParamsRequestVo videoPaymentRequestVo = new ShopOrderGetPaymentParamsRequestVo(shopOrderAddResultVo.getOutOrderId(), order.getOrderNo(), tokenByUser.getToken());
            logger.info("视频号下单时 支付接口参数:{}", JSON.toJSONString(videoPaymentRequestVo));
            ShopOrderGetPaymentParamsRersponseVo shopOrderGetPaymentParamsRersponseVo = wechatVideoOrderService.shopOrderGetPaymentParams(videoPaymentRequestVo);
            logger.info("视频号下单时 获取的支付参数 {}", JSON.toJSONString(shopOrderGetPaymentParamsRersponseVo));
            response.setStatus(true);
            vo.setTimeStamp(WxPayUtil.getCurrentTimestamp() + "");
            vo.setNonceStr(shopOrderGetPaymentParamsRersponseVo.getNonceStr());
            vo.setPackages(shopOrderGetPaymentParamsRersponseVo.get_package());
            vo.setPaySign(shopOrderGetPaymentParamsRersponseVo.getPaySign());
            vo.setSignType(shopOrderGetPaymentParamsRersponseVo.getSignType());
            response.setJsConfig(vo);
            logger.info("订单支付 视频号下单 response:{}", JSON.toJSONString(response));
            return response;
        }
        // 微信支付，调用微信预下单，返回拉起微信支付需要的信息
        if (order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
            logger.info("订单支付 微信下单");
            WxPayJsResultVo vo = wechatPayment(order);
            orderService.updateById(order);
            response.setStatus(true);
            response.setJsConfig(vo);
            logger.info("订单支付 微信下单 response :{}", JSON.toJSONString(response));
            return response;
        }
        if (order.getPayType().equals(PayConstants.PAY_TYPE_ALI_PAY)) {
            logger.info("订单支付 支付宝");
            String result = aliPayment(order);
            order.setOutTradeNo(order.getOrderNo());
            orderService.updateById(order);
            response.setStatus(true);
            response.setAlipayRequest(result);
            logger.info("订单支付 支付宝 response :{}", JSON.toJSONString(response));
            return response;
        }
        response.setStatus(false);
        logger.info("订单支付 END response:{}", JSON.toJSONString(response));
        return response;
    }

    /**
     * 查询支付结果
     *
     * @param orderNo 订单编号
     */
    @Override
    public Boolean queryWechatPayResult(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(order)) {
            throw new CrmebException("订单不存在");
        }
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException("订单已取消");
        }
        if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT) && !order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT_TO_HUIFU)) {
            throw new CrmebException("不是微信支付类型订单");
        }
        if (order.getPaid()) {
            return Boolean.TRUE;
        }
        if (order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT_TO_HUIFU)){
            //TODO 雪峰查询汇付支付结果，如果成功
            //setOrderPaySuccess(orderNo);
            return false;
        }
        WechatPayInfo wechatPayInfo = wechatPayInfoService.getByNo(order.getOutTradeNo());
        if (ObjectUtil.isNull(wechatPayInfo)) {
            throw new CrmebException("未找到对应微信订单");
        }
        Map<String, String> payVo = getWechatQueryPayVo(order.getOutTradeNo(), order.getPayChannel());
        MyRecord myRecord = wechatService.payOrderQuery(payVo);
        wechatPayInfo.setIsSubscribe(myRecord.getStr("is_subscribe"));
        wechatPayInfo.setTradeState(myRecord.getStr("trade_state"));
        wechatPayInfo.setBankType(myRecord.getStr("bank_type"));
        wechatPayInfo.setCashFee(myRecord.getInt("cash_fee"));
        wechatPayInfo.setCouponFee(myRecord.getInt("coupon_fee"));
        wechatPayInfo.setTransactionId(myRecord.getStr("transaction_id"));
        wechatPayInfo.setTimeEnd(myRecord.getStr("time_end"));
        wechatPayInfo.setTradeStateDesc(myRecord.getStr("trade_state_desc"));
        Boolean updatePaid = transactionTemplate.execute(e -> {
            orderService.updatePaid(orderNo);
            wechatPayInfoService.updateById(wechatPayInfo);
            return Boolean.TRUE;
        });
        if (!updatePaid) {
            throw new CrmebException("支付成功更新订单失败");
        }
        asyncService.orderPaySuccessSplit(order.getOrderNo());
        // 添加支付成功task
//        redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, orderNo);
        return Boolean.TRUE;
    }

    /**
     * 查询订单支付宝支付结果
     *
     * @param orderNo 订单编号
     */
    @Override
    public Boolean queryAliPayResult(String orderNo) {
        AliPayInfo aliPayInfo = aliPayInfoService.getByOutTradeNo(orderNo);
        if (ObjectUtil.isNull(aliPayInfo)) {
            throw new CrmebException("支付宝订单信息不存在");
        }
        String passbackParams = aliPayInfo.getPassbackParams();
        if (StrUtil.isBlank(passbackParams)) {
            throw new CrmebException("未知的支付宝订单类型");
        }
        String decode;
        try {
            decode = URLDecoder.decode(passbackParams, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new CrmebException("ali pay query error : 订单支付类型解码失败==》" + orderNo);
        }

        String[] split = decode.split("=");
        String orderType = split[1];
        if (PayConstants.PAY_SERVICE_TYPE_RECHARGE.equals(orderType)) {// 充值订单
            RechargeOrder rechargeOrder = rechargeOrderService.getByOutTradeNo(orderNo);
            if (ObjectUtil.isNull(rechargeOrder)) {
                throw new CrmebException(StrUtil.format("ali pay query error : 充值订单后置处理，没有找到对应订单，支付服务方订单号：{}", orderNo));
            }
            if (rechargeOrder.getPaid()) {
                return Boolean.TRUE;
            }
            aliPayQuery(orderNo);
            // 支付成功处理
            Boolean rechargePayAfter = rechargeOrderService.paySuccessAfter(rechargeOrder);
            if (!rechargePayAfter) {
                throw new CrmebException(StrUtil.format("ali pay recharge pay after error : 数据保存失败==》" + orderNo));
            }
            return Boolean.TRUE;
        }

        Order order = orderService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(order)) {
            throw new CrmebException("订单不存在");
        }
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException("订单已取消");
        }
        if (!order.getPayType().equals(PayConstants.PAY_TYPE_ALI_PAY)) {
            throw new CrmebException("不是支付宝支付类型订单");
        }
        if (order.getPaid()) {
            return Boolean.TRUE;
        }
        aliPayQuery(orderNo);
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean updatePaid = orderService.updatePaid(orderNo);
            if (!updatePaid) {
                logger.warn("商品订单更新支付状态失败，orderNo = {}", orderNo);
                e.setRollbackOnly();
            }
            return Boolean.TRUE;
        });

        if (!execute) {
            throw new CrmebException("支付成功更新订单失败");
        }
        asyncService.orderPaySuccessSplit(order.getOrderNo());
//        // 添加支付成功task
//        redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, orderNo);
        return Boolean.TRUE;
    }

    private AlipayTradeQueryResponse aliPayQuery(String orderNo) {
        //支付宝交易号
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        String aliPayAppid = systemConfigService.getValueByKey(AlipayConfig.APPID);
        String aliPayPrivateKey = systemConfigService.getValueByKey(AlipayConfig.RSA_PRIVATE_KEY);
        String aliPayPublicKey = systemConfigService.getValueByKey(AlipayConfig.ALIPAY_PUBLIC_KEY_2);
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, aliPayAppid, aliPayPrivateKey, AlipayConfig.FORMAT, AlipayConfig.CHARSET, aliPayPublicKey, AlipayConfig.SIGNTYPE);
        AlipayTradeQueryRequest alipay_request = new AlipayTradeQueryRequest();

        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        model.setOutTradeNo(orderNo);
        alipay_request.setBizModel(model);
        logger.info("alipay_request = " + alipay_request);

        AlipayTradeQueryResponse alipay_response = null;
        try {
            alipay_response = client.execute(alipay_request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            logger.error("支付宝支付查询异常，" + e.getMessage());
            throw new CrmebException("支付宝支付查询异常");
        }
        logger.info("alipay_response = ");
        if (!alipay_response.getTradeStatus().equals("TRADE_SUCCESS")) {
            logger.error("支付宝支付结果异常，tradeStatus = " + alipay_response.getTradeStatus());
            throw new CrmebException("支付宝支付结果异常");
        }
        return alipay_response;
    }

    /**
     * 支付成功后置处理
     * 经验逻辑确定后，可在处理中加入经验处理
     *
     * @param orderNo 订单编号
     */
    @Override
    public Boolean payAfterProcessing(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(order)) {
            logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 订单不存在，orderNo: {}", orderNo);
            throw new CrmebException("订单不存在，orderNo: " + orderNo);
        }
        User user = userService.getById(order.getUid());

        List<MerchantOrder> merchantOrderList = merchantOrderService.getByOrderNo(orderNo);
        if (CollUtil.isEmpty(merchantOrderList)) {
            logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 商户订单信息不存在,orderNo: {}", orderNo);
            throw new CrmebException("商户订单信息不存在，orderNo: " + orderNo);
        }
        Boolean execute;
        if (merchantOrderList.size() == 1) {
            // 单商户订单
            execute = oneMerchantOrderProcessing(order, merchantOrderList.get(0), user);
        } else {
            throw new CrmebException("商城已重度二次开发，暂不支持多商户一个订单");
            //execute = manyMerchantOrderProcessing(order, merchantOrderList, user);
        }
        if (execute) {
            SystemNotification payNotification = systemNotificationService.getByMark(NotifyConstants.PAY_SUCCESS_MARK);
            // 发送短信
            if (StrUtil.isNotBlank(user.getPhone()) && payNotification.getIsSms().equals(1)) {
                try {
                    smsService.sendPaySuccess(user.getPhone(), order.getOrderNo(), order.getPayPrice());
                } catch (Exception e) {
                    logger.error("支付成功短信发送异常，{}", e.getMessage());
                }
            }
//            if (payNotification.getIsWechat().equals(1) || payNotification.getIsRoutine().equals(1)) {
//                //下发模板通知 TODO
//                pushMessageOrder(order, user, payNotification);
//            }

            // 购买成功后根据配置送优惠券
            autoSendCoupons(order);

            // TODO 根据配置 打印小票
//            try {
//                ylyPrintService.YlyPrint(storeOrder.getOrderId?(),true);
//            } catch (Exception e) {
//                logger.error("打印小票异常,{}", e.getMessage());
//            }
        }
        return execute;
    }

    /**
     * 支付成功后置处理(临时)
     *
     * @param orderNo 订单编号
     */
    @Override
    public Boolean payAfterProcessingTemp(String orderNo) {
        Order platOrder = orderService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(platOrder)) {
            logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 订单不存在，orderNo: {}", orderNo);
            throw new CrmebException("订单不存在，orderNo: " + orderNo);
        }
        User user = userService.getById(platOrder.getUid());
        // 获取拆单后订单
        List<Order> orderList = orderService.getByPlatOrderNo(platOrder.getOrderNo());
        if (CollUtil.isEmpty(orderList)) {
            logger.error("OrderTaskServiceImpl.orderPaySuccessAfter | 商户订单信息不存在,orderNo: {}", orderNo);
            throw new CrmebException("商户订单信息不存在，orderNo: " + orderNo);
        }
        List<UserIntegralRecord> integralList = CollUtil.newArrayList();
//        List<UserBrokerageRecord> brokerageRecordList = CollUtil.newArrayList();
        List<OrderProfitSharing> profitSharingList = CollUtil.newArrayList();
        List<MerchantBill> merchantBillList = CollUtil.newArrayList();
        List<Bill> billList = CollUtil.newArrayList();
        List<MerchantOrder> merchantOrderList = CollUtil.newArrayList();
        List<OrderDetail> orderDetailList = CollUtil.newArrayList();

        for (Order order : orderList) {
            // 拆单后，一个主订单只会对应一个商户订单
            MerchantOrder merchantOrder = merchantOrderService.getOneByOrderNo(order.getOrderNo());
            if (order.getGainIntegral() > 0) {
                // 生成赠送积分记录
                UserIntegralRecord integralRecord = integralRecordGainInit(user.getId(), order.getOrderNo(), order.getGainIntegral());
                integralList.add(integralRecord);
            }
//            List<OrderDetail> merOrderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
            // 佣金处理，分销那边自己处理，不再用商城计算
//            List<UserBrokerageRecord> broRecordList = assignCommission(merchantOrder, merOrderDetailList);
//            if (CollUtil.isNotEmpty(broRecordList)) {
//                brokerageRecordList.addAll(broRecordList);
//                merchantOrderList.add(merchantOrder);
//                orderDetailList.addAll(merOrderDetailList);
//            }
            // 商户帐单流水、分账
            OrderProfitSharing orderProfitSharing = initOrderProfitSharing(merchantOrder);
            MerchantBill merchantBill = initPayMerchantBill(merchantOrder, orderProfitSharing.getProfitSharingMerPrice());
            List<Bill> platBillList = initPlatformBill(order, merchantOrder, orderProfitSharing);
            profitSharingList.add(orderProfitSharing);
            merchantBillList.add(merchantBill);
            billList.addAll(platBillList);
        }
        // 分销员逻辑
        if (!user.getIsPromoter()) {
            String funcStatus = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
            if (funcStatus.equals("1")) {
                String broQuota = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_LINE);
                if (!broQuota.equals("-1") && platOrder.getPayPrice().compareTo(new BigDecimal(broQuota)) >= 0) {// -1 不成为分销员
                    user.setIsPromoter(true);
                }
            }
        } else {
            user.setIsPromoter(false);
        }
        Boolean execute = transactionTemplate.execute(e -> {
            // 订单、佣金
//            if (CollUtil.isNotEmpty(brokerageRecordList)) {
//                merchantOrderService.updateBatchById(merchantOrderList);
//                orderDetailService.updateBatchById(orderDetailList);
//                userBrokerageRecordService.saveBatch(brokerageRecordList);
//            }
            // 订单日志
            orderList.forEach(o -> orderStatusService.createLog(o.getOrderNo(), OrderStatusConstants.ORDER_STATUS_PAY_SPLIT, StrUtil.format(OrderStatusConstants.ORDER_LOG_MESSAGE_PAY_SPLIT, platOrder.getOrderNo())));
            // 用户信息变更
            userService.paySuccessChange(user.getId(), user.getIsPromoter());
            // 积分记录
            if (CollUtil.isNotEmpty(integralList)) {
                userIntegralRecordService.saveBatch(integralList);
            }
            billService.saveBatch(billList);
            merchantBillService.saveBatch(merchantBillList);
            orderProfitSharingService.saveBatch(profitSharingList);
            profitSharingList.forEach(p -> {
                merchantService.operationBalance(p.getMerId(), p.getProfitSharingMerPrice(), Constants.OPERATION_TYPE_ADD);
            });
            return Boolean.TRUE;
        });
        if (execute) {
            SystemNotification payNotification = systemNotificationService.getByMark(NotifyConstants.PAY_SUCCESS_MARK);
            // 发送短信
            if (StrUtil.isNotBlank(user.getPhone()) && payNotification.getIsSms().equals(1)) {
                try {
                    smsService.sendPaySuccess(user.getPhone(), platOrder.getOrderNo(), platOrder.getPayPrice());
                } catch (Exception e) {
                    logger.error("支付成功短信发送异常", e);
                }
            }
            if (payNotification.getIsWechat().equals(1) || payNotification.getIsRoutine().equals(1)) {
                //下发模板通知
                try {
                    pushMessageOrder(platOrder, user, payNotification);
                } catch (Exception e) {
                    logger.error("支付成功发送微信通知失败", e);
                }
            }

            // 购买成功后根据配置送优惠券
            autoSendCoupons(platOrder);
        }
        return execute;
    }

    /**
     * 单商户订单处理
     *
     * @param order         主订单
     * @param merchantOrder 商户订单
     * @param user          用户
     */
    private Boolean oneMerchantOrderProcessing(Order order, MerchantOrder merchantOrder, User user) {
        List<UserIntegralRecord> integralList = CollUtil.newArrayList();
        // 积分抵扣记录 已在生成订单时处理
//        if (order.getUseIntegral() > 0) {
//            UserIntegralRecord integralRecordSub = integralRecordSubInit(order, user.getIntegral());
//            integralList.add(integralRecordSub);
//        }
        // 赠送积分积分处理：1.下单赠送积分
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
        presentIntegral(merchantOrder, orderDetailList, integralList, user, order);
        // 佣金处理，分销那边自己处理，不再用商城计算
//        List<UserBrokerageRecord> brokerageRecordList = assignCommission(merchantOrder, orderDetailList);

        // 生成新的商户订单
        Order newOrder = new Order();
        BeanUtils.copyProperties(order, newOrder);
        MerchantOrder newMerOrder = new MerchantOrder();
        BeanUtils.copyProperties(merchantOrder, newMerOrder);
        newOrder.setOrderNo(order.getOrderNo()+"S01");
//        newOrder.setOrderNo(CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_MERCHANT));
        newOrder.setMerId(merchantOrder.getMerId());
        newOrder.setLevel(OrderConstants.ORDER_LEVEL_MERCHANT);
        newOrder.setPlatOrderNo(order.getOrderNo());
        if (merchantOrder.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP)) {
            newOrder.setStatus(OrderConstants.ORDER_STATUS_AWAIT_VERIFICATION);
        }
        newMerOrder.setOrderNo(newOrder.getOrderNo());
        List<OrderDetail> newOrderDetailList = orderDetailList.stream().map(e -> {
            OrderDetail orderDetail = new OrderDetail();
            BeanUtils.copyProperties(e, orderDetail);
            orderDetail.setId(null);
            orderDetail.setOrderNo(newOrder.getOrderNo());
            return orderDetail;
        }).collect(Collectors.toList());

        // 分销员逻辑
        if (!user.getIsPromoter()) {
            String funcStatus = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
            if (funcStatus.equals("1")) {
                String broQuota = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_LINE);
                if (!broQuota.equals("-1") && order.getPayPrice().compareTo(new BigDecimal(broQuota)) >= 0) {// -1 不成为分销员
                    user.setIsPromoter(true);
                    user.setPromoterTime(DateUtil.date());
                }
            }
        } else {
            user.setIsPromoter(false);
        }
        // 商户帐单流水、分账
        OrderProfitSharing orderProfitSharing = initOrderProfitSharing(newMerOrder);
        MerchantBill merchantBill = initPayMerchantBill(newMerOrder, orderProfitSharing.getProfitSharingMerPrice());
        List<Bill> billList = initPlatformBill(newOrder, newMerOrder, orderProfitSharing);
        BcxPlatformFee oldFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        BcxPlatformFee newFee = new BcxPlatformFee();
        BeanUtils.copyProperties(oldFee, newFee);
        newFee.setId(null);
        newFee.setOrderNo(newOrder.getOrderNo());

        order.setIsDel(true);
        return transactionTemplate.execute(e -> {
            // 订单
            orderService.updateById(order);
            merchantOrderService.updateById(merchantOrder);
            if (order.getGainIntegral() > 0) {
                orderDetailService.updateBatchById(orderDetailList);
            }
            orderService.save(newOrder);
            merchantOrderService.save(newMerOrder);
            orderDetailService.saveBatch(newOrderDetailList);
            bcxPlatformFeeService.save(newFee);
            //订单日志
            orderStatusService.createLog(order.getOrderNo(), OrderStatusConstants.ORDER_STATUS_PAY_SUCCESS, OrderStatusConstants.ORDER_LOG_MESSAGE_PAY_SUCCESS);
            // 用户信息变更
            userService.paySuccessChange(user.getId(), user.getIsPromoter());
            // 积分记录
            userIntegralRecordService.saveBatch(integralList);
//            // 佣金记录
//            if (CollUtil.isNotEmpty(brokerageRecordList)) {
//                brokerageRecordList.forEach(temp -> {
//                    temp.setLinkNo(order.getOrderNo());
//                });
//                userBrokerageRecordService.saveBatch(brokerageRecordList);
//            }
            billService.saveBatch(billList);
            merchantBillService.save(merchantBill);
            orderProfitSharingService.save(orderProfitSharing);
            merchantService.operationBalance(orderProfitSharing.getMerId(), orderProfitSharing.getProfitSharingMerPrice(), Constants.OPERATION_TYPE_ADD);
            return Boolean.TRUE;
        });
    }

    /**
     * 多商户订单处理
     *
     * @param order             主订单
     * @param merchantOrderList 商户订单列表
     * @param user              用户
     */
    private Boolean manyMerchantOrderProcessing(Order order, List<MerchantOrder> merchantOrderList, User user) {
        List<UserIntegralRecord> integralList = CollUtil.newArrayList();
        // 积分抵扣记录
        if (order.getUseIntegral() > 0) {
            UserIntegralRecord integralRecordSub = integralRecordSubInit(order, user.getIntegral());
            integralList.add(integralRecordSub);
        }
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
        // 赠送积分积分处理：1.下单赠送积分
        presentIntegral(merchantOrderList, orderDetailList, integralList, user, order);
        // 分销员逻辑
        if (!user.getIsPromoter()) {
            String funcStatus = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
            if (funcStatus.equals("1")) {
                String broQuota = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_LINE);
                if (!broQuota.equals("-1") && order.getPayPrice().compareTo(new BigDecimal(broQuota)) >= 0) {// -1 不成为分销员
                    user.setIsPromoter(true);
                    user.setPromoterTime(DateUtil.date());
                }
            }
        } else {
            user.setIsPromoter(false);
        }
        // 佣金处理，分销那边自己处理，不再用商城计算
//        List<UserBrokerageRecord> brokerageRecordList = assignCommission(order, merchantOrderList, orderDetailList);
        // 商户拆单
        List<Order> newOrderList = CollUtil.newArrayList();
        List<MerchantOrder> newMerchantOrderList = CollUtil.newArrayList();
        List<OrderDetail> newOrderDetailList = CollUtil.newArrayList();

        List<OrderProfitSharing> profitSharingList = CollUtil.newArrayList();
        List<MerchantBill> merchantBillList = CollUtil.newArrayList();
        List<Bill> billList = CollUtil.newArrayList();

        order.setIsDel(true);
        for (MerchantOrder merchantOrder : merchantOrderList) {
            Order newOrder = AsyncServiceImpl.copyNewOrder(order, merchantOrder);
            newOrder.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            newOrder.setPlatOrderNo(order.getOrderNo());
            newOrder.setIsDel(false);
            if (merchantOrder.getShippingType().equals(OrderConstants.ORDER_SHIPPING_TYPE_PICK_UP)) {
                newOrder.setStatus(OrderConstants.ORDER_STATUS_AWAIT_VERIFICATION);
            }
            MerchantOrder newMerchantOrder = new MerchantOrder();
            BeanUtils.copyProperties(merchantOrder, newMerchantOrder);
            AsyncServiceImpl.constructNewOrders(orderDetailList, newOrderList, newMerchantOrderList, newOrderDetailList, merchantOrder, newOrder, newMerchantOrder);
//            if (CollUtil.isNotEmpty(brokerageRecordList)) {
//                for (UserBrokerageRecord record : brokerageRecordList) {
//                    if (record.getLinkNo().equals(newMerchantOrder.getMerId().toString())) {
//                        record.setLinkNo(newOrder.getOrderNo());
//                    }
//                }
//            }
            // 商户帐单流水、分账
            OrderProfitSharing orderProfitSharing = initOrderProfitSharing(newMerchantOrder);
            MerchantBill merchantBill = initPayMerchantBill(newMerchantOrder, orderProfitSharing.getProfitSharingMerPrice());
            List<Bill> platBillList = initPlatformBill(newOrder, newMerchantOrder, orderProfitSharing);
            profitSharingList.add(orderProfitSharing);
            merchantBillList.add(merchantBill);
            billList.addAll(platBillList);
        }

        return transactionTemplate.execute(e -> {
            // 订单
            orderService.updateById(order);
            merchantOrderService.updateBatchById(merchantOrderList);
            orderService.saveBatch(newOrderList);
            merchantOrderService.saveBatch(newMerchantOrderList);
            orderDetailService.saveBatch(newOrderDetailList);
            // 订单日志
            orderStatusService.createLog(order.getOrderNo(), OrderStatusConstants.ORDER_STATUS_PAY_SUCCESS, OrderStatusConstants.ORDER_LOG_MESSAGE_PAY_SUCCESS);
            newOrderList.forEach(o -> orderStatusService.createLog(o.getOrderNo(), OrderStatusConstants.ORDER_STATUS_PAY_SPLIT, StrUtil.format(OrderStatusConstants.ORDER_LOG_MESSAGE_PAY_SPLIT, order.getOrderNo())));
            // 用户信息变更
            userService.paySuccessChange(user.getId(), user.getIsPromoter());
            // 积分记录
            userIntegralRecordService.saveBatch(integralList);
            // 佣金记录
//            if (CollUtil.isNotEmpty(brokerageRecordList)) {
//                userBrokerageRecordService.saveBatch(brokerageRecordList);
//            }
            billService.saveBatch(billList);
            merchantBillService.saveBatch(merchantBillList);
            orderProfitSharingService.saveBatch(profitSharingList);
            profitSharingList.forEach(p -> {
                merchantService.operationBalance(p.getMerId(), p.getProfitSharingMerPrice(), Constants.OPERATION_TYPE_ADD);
            });
            return Boolean.TRUE;
        });
    }

    /**
     * 发送消息通知
     * 根据用户类型发送
     * 公众号模板消息
     * 小程序订阅消息
     */
    private void pushMessageOrder(Order order, User user, SystemNotification payNotification) {
        logger.info("发送微信模板消息，订单编号：" + order.getOrderNo());
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {// H5
            return;
        }
        UserToken userToken;
        HashMap<String, String> temMap = new HashMap<>();
        if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT) && !order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT_TO_HUIFU)) {
            return;
        }
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
        // 公众号模板消息
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC) && payNotification.getIsWechat().equals(1) && user.getIsWechatPublic()) {
            userToken = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_WECHAT);
            if (ObjectUtil.isNull(userToken)) {
                return;
            }
            // 发送微信模板消息
            /**
             * {{first.DATA}}
             * 订单号：{{keyword1.DATA}}
             * 商品名称：{{keyword2.DATA}}
             * 支付金额：{{keyword3.DATA}}
             * 下单人：{{keyword4.DATA}}
             * 订单支付时间：{{keyword5.DATA}}
             * {{remark.DATA}}
             */
            temMap.put(Constants.WE_CHAT_TEMP_KEY_FIRST, "订单支付成功通知！");
            temMap.put("keyword1", order.getOrderNo());
            temMap.put("keyword2", orderDetailList.stream().map(OrderDetail::getProductName).collect(Collectors.joining(",")));
            temMap.put("keyword3", order.getPayPrice().toString());
            temMap.put("keyword4", user.getNickname());
            temMap.put("keyword5", order.getPayTime().toString());
            temMap.put(Constants.WE_CHAT_TEMP_KEY_END, "欢迎下次再来！");
            templateMessageService.pushTemplateMessage(payNotification.getWechatId(), temMap, userToken.getToken());
            return;
        }
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI) && payNotification.getIsRoutine().equals(1)) {
            // 小程序发送订阅消息
            userToken = userTokenService.getTokenByUserId(user.getId(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
            if (ObjectUtil.isNull(userToken)) {
                return;
            }
            // 组装数据
//            temMap.put("character_string1", storeOrder.getOrderId());
//            temMap.put("amount2", storeOrder.getPayPrice().toString() + "元");
//            temMap.put("thing7", "您的订单已支付成功");
            temMap.put("character_string3", order.getOrderNo());
            temMap.put("amount9", order.getPayPrice().toString() + "元");
            temMap.put("thing6", "您的订单已支付成功");
            templateMessageService.pushMiniTemplateMessage(payNotification.getRoutineId(), temMap, userToken.getToken());
        }
    }


    /**
     * 佣金处理
     *
     * @param merchantOrder   商户订单部分
     * @param orderDetailList 订单详情列表
     * @return 佣金记录列表
     */
//    private List<UserBrokerageRecord> assignCommission(MerchantOrder merchantOrder, List<OrderDetail> orderDetailList) {
//        // 秒杀订单不参与分佣
//        if (merchantOrder.getType().equals(OrderConstants.ORDER_TYPE_SECKILL)) {
//            return CollUtil.newArrayList();
//        }
//        // 检测商城是否开启分销功能
//        String isOpen = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
//        if (StrUtil.isBlank(isOpen) || isOpen.equals("0")) {
//            return CollUtil.newArrayList();
//        }
//        long count = orderDetailList.stream().filter(e -> e.getSubBrokerageType() > 0).count();
//        if (count <= 0L) {
//            return CollUtil.newArrayList();
//        }
//        // 查找订单所属人信息
//        User user = userService.getById(merchantOrder.getUid());
//        // 当前用户不存在 没有上级 或者 当用用户上级时自己  直接返回
//        if (ObjectUtil.isNull(user.getSpreadUid()) || user.getSpreadUid() < 1 || user.getSpreadUid().equals(merchantOrder.getUid())) {
//            return CollUtil.newArrayList();
//        }
//        // 获取参与分佣的人（两级）
//        List<MyRecord> spreadRecordList = getSpreadRecordList(user.getSpreadUid());
//        if (CollUtil.isEmpty(spreadRecordList)) {
//            return CollUtil.newArrayList();
//        }
//        // 获取佣金冻结期
//        String freezingTime = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FREEZING_TIME);
//        List<UserBrokerageRecord> brokerageRecordList = new ArrayList<>();
//        // 计算两级佣金金额
//        if (spreadRecordList.size() == 1) {
//            BigDecimal firstBrokerage = BigDecimal.ZERO;
//            for (OrderDetail orderDetail : orderDetailList) {
//                if (orderDetail.getSubBrokerageType().equals(0)) {
//                    continue;
//                }
////                BigDecimal brokerage = orderDetail.getPayPrice().multiply(new BigDecimal(orderDetail.getBrokerage().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//                BigDecimal brokerage = orderDetail.getCanBrokeragePrice()
//                        .multiply(new BigDecimal(orderDetail.getBrokerage().toString()))
//                        .divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//                orderDetail.setFirstBrokerageFee(brokerage);
//                firstBrokerage = firstBrokerage.add(brokerage);
//            }
//            merchantOrder.setFirstBrokerage(firstBrokerage);
//            UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
//            brokerageRecord.setUid(spreadRecordList.get(0).getInt("spreadUid"));
//            brokerageRecord.setSubUid(merchantOrder.getUid());
//            brokerageRecord.setLinkNo(merchantOrder.getOrderNo());
//            brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
//            brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
//            brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
//            brokerageRecord.setPrice(firstBrokerage);
//            brokerageRecord.setMark(StrUtil.format("获得推广佣金，分佣{}", firstBrokerage));
//            brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
//            brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
//            brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
//            brokerageRecord.setBrokerageLevel(spreadRecordList.get(0).getInt("index"));
//            brokerageRecordList.add(brokerageRecord);
//            return brokerageRecordList;
//        }
//        BigDecimal firstBrokerage = BigDecimal.ZERO;
//        BigDecimal secondBrokerage = BigDecimal.ZERO;
//        for (OrderDetail orderDetail : orderDetailList) {
//            if (orderDetail.getSubBrokerageType().equals(0)) {
//                continue;
//            }
////            BigDecimal brokerage = orderDetail.getPayPrice().multiply(new BigDecimal(orderDetail.getBrokerage().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
////            BigDecimal brokerageTwo = orderDetail.getPayPrice().multiply(new BigDecimal(orderDetail.getBrokerageTwo().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//
//            BigDecimal brokerage = orderDetail.getCanBrokeragePrice()
//                    .multiply(new BigDecimal(orderDetail.getBrokerage().toString()))
//                    .divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//            BigDecimal brokerageTwo = orderDetail.getCanBrokeragePrice()
//                    .multiply(new BigDecimal(orderDetail.getBrokerageTwo().toString()))
//                    .divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//
//            orderDetail.setFirstBrokerageFee(brokerage);
//            orderDetail.setSecondBrokerageFee(brokerageTwo);
//            firstBrokerage = firstBrokerage.add(brokerage);
//            secondBrokerage = secondBrokerage.add(brokerageTwo);
//        }
//        merchantOrder.setFirstBrokerage(firstBrokerage);
//        merchantOrder.setSecondBrokerage(secondBrokerage);
//        // 生成佣金记录
//        brokerageRecordList = spreadRecordList.stream().map(record -> {
//            UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
//            brokerageRecord.setUid(record.getInt("spreadUid"));
//            brokerageRecord.setSubUid(merchantOrder.getUid());
//            brokerageRecord.setLinkNo(merchantOrder.getOrderNo());
//            brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
//            brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
//            brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
//            BigDecimal price = record.getInt("index") == 1 ? merchantOrder.getFirstBrokerage() : merchantOrder.getSecondBrokerage();
//            brokerageRecord.setPrice(price);
//            brokerageRecord.setMark(StrUtil.format("获得推广佣金，分佣{}", price));
//            brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
//            brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
//            brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
//            brokerageRecord.setBrokerageLevel(record.getInt("index"));
//            return brokerageRecord;
//        }).collect(Collectors.toList());
//        return brokerageRecordList;
//    }

    /**
     * 佣金处理
     *
     * @param order             订单
     * @param merchantOrderList 商户订单部分
     * @param orderDetailList   订单详情列表
     * @return 佣金记录列表
     */
//    private List<UserBrokerageRecord> assignCommission(Order order, List<MerchantOrder> merchantOrderList, List<OrderDetail> orderDetailList) {
//        // 检测商城是否开启分销功能
//        String isOpen = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_SWITCH);
//        if (StrUtil.isBlank(isOpen) || isOpen.equals("0")) {
//            return CollUtil.newArrayList();
//        }
//        // 营销产品不参与
////        if(storeOrder.getCombinationId() > 0 || storeOrder.getSeckillId() > 0 || storeOrder.getBargainId() > 0){
////            return CollUtil.newArrayList();
////        }
//        long count = orderDetailList.stream().filter(e -> e.getSubBrokerageType() > 0).count();
//        if (count <= 0L) {
//            return CollUtil.newArrayList();
//        }
//        // 查找订单所属人信息
//        User user = userService.getById(order.getUid());
//        // 当前用户不存在 没有上级 或者 当用用户上级时自己  直接返回
//        if (ObjectUtil.isNull(user.getSpreadUid()) || user.getSpreadUid() < 1 || user.getSpreadUid().equals(order.getUid())) {
//            return CollUtil.newArrayList();
//        }
//        // 获取参与分佣的人（两级）
//        List<MyRecord> spreadRecordList = getSpreadRecordList(user.getSpreadUid());
//        if (CollUtil.isEmpty(spreadRecordList)) {
//            return CollUtil.newArrayList();
//        }
//        List<UserBrokerageRecord> brokerageRecordList = new ArrayList<>();
//        // 获取佣金冻结期
//        String freezingTime = systemConfigService.getValueByKey(SysConfigConstants.RETAIL_STORE_BROKERAGE_FREEZING_TIME);
//        for (MerchantOrder merchantOrder : merchantOrderList) {
//            // 计算两级佣金金额
//            if (spreadRecordList.size() == 1) {
//                BigDecimal firstBrokerage = BigDecimal.ZERO;
//                for (OrderDetail orderDetail : orderDetailList) {
//                    if (orderDetail.getSubBrokerageType().equals(0)) {
//                        continue;
//                    }
//                    BigDecimal brokerage = orderDetail.getCanBrokeragePrice().multiply(new BigDecimal(orderDetail.getBrokerage().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//                    orderDetail.setFirstBrokerageFee(brokerage);
//                    firstBrokerage = firstBrokerage.add(brokerage);
//                }
//                merchantOrder.setFirstBrokerage(firstBrokerage);
//                UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
//                brokerageRecord.setLinkNo(merchantOrder.getMerId().toString());
//                brokerageRecord.setUid(spreadRecordList.get(0).getInt("spreadUid"));
//                brokerageRecord.setSubUid(merchantOrder.getUid());
//                brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
//                brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
//                brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
//                brokerageRecord.setPrice(firstBrokerage);
//                brokerageRecord.setMark(StrUtil.format("获得推广佣金，分佣{}", firstBrokerage));
//                brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
//                brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
//                brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
//                brokerageRecord.setBrokerageLevel(spreadRecordList.get(0).getInt("index"));
//                brokerageRecordList.add(brokerageRecord);
//                continue;
//            }
//
//            BigDecimal firstBrokerage = BigDecimal.ZERO;
//            BigDecimal secondBrokerage = BigDecimal.ZERO;
//            for (OrderDetail orderDetail : orderDetailList) {
//                if (orderDetail.getSubBrokerageType().equals(0)) {
//                    continue;
//                }
//                BigDecimal brokerage = orderDetail.getCanBrokeragePrice().multiply(new BigDecimal(orderDetail.getBrokerage().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//                BigDecimal brokerageTwo = orderDetail.getCanBrokeragePrice().multiply(new BigDecimal(orderDetail.getBrokerageTwo().toString())).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_DOWN);
//                orderDetail.setFirstBrokerageFee(brokerage);
//                orderDetail.setSecondBrokerageFee(brokerageTwo);
//                firstBrokerage = firstBrokerage.add(brokerage);
//                secondBrokerage = secondBrokerage.add(brokerageTwo);
//            }
//            merchantOrder.setFirstBrokerage(firstBrokerage);
//            merchantOrder.setSecondBrokerage(secondBrokerage);
//            // 生成佣金记录
//            List<UserBrokerageRecord> recordList = spreadRecordList.stream().map(record -> {
//                UserBrokerageRecord brokerageRecord = new UserBrokerageRecord();
//                brokerageRecord.setLinkNo(merchantOrder.getMerId().toString());
//                brokerageRecord.setUid(record.getInt("spreadUid"));
//                brokerageRecord.setSubUid(merchantOrder.getUid());
//                brokerageRecord.setLinkType(BrokerageRecordConstants.BROKERAGE_RECORD_LINK_TYPE_ORDER);
//                brokerageRecord.setType(BrokerageRecordConstants.BROKERAGE_RECORD_TYPE_ADD);
//                brokerageRecord.setTitle(BrokerageRecordConstants.BROKERAGE_RECORD_TITLE_ORDER);
//                BigDecimal price = record.getInt("index") == 1 ? merchantOrder.getFirstBrokerage() : merchantOrder.getSecondBrokerage();
//                brokerageRecord.setPrice(price);
//                brokerageRecord.setMark(StrUtil.format("获得推广佣金，分佣{}", price));
//                brokerageRecord.setStatus(BrokerageRecordConstants.BROKERAGE_RECORD_STATUS_CREATE);
//                brokerageRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezingTime).orElse("0")));
//                brokerageRecord.setCreateTime(CrmebDateUtil.nowDateTime());
//                brokerageRecord.setBrokerageLevel(record.getInt("index"));
//                return brokerageRecord;
//            }).collect(Collectors.toList());
//            brokerageRecordList.addAll(recordList);
//        }
//        return brokerageRecordList;
//    }

    /**
     * 获取参与分佣人员（两级）
     *
     * @param spreadUid 一级分佣人Uid
     * @return List<MyRecord>
     */
    private List<MyRecord> getSpreadRecordList(Integer spreadUid) {
        List<MyRecord> recordList = CollUtil.newArrayList();

        // 第一级
        User spreadUser = userService.getById(spreadUid);
        if (ObjectUtil.isNull(spreadUser) || !spreadUser.getIsPromoter()) {
            return recordList;
        }

        MyRecord firstRecord = new MyRecord();
        firstRecord.set("index", 1);
        firstRecord.set("spreadUid", spreadUid);
        recordList.add(firstRecord);

        // 第二级
        User spreadSpreadUser = userService.getById(spreadUser.getSpreadUid());
        if (ObjectUtil.isNull(spreadSpreadUser) || !spreadSpreadUser.getIsPromoter()) {
            return recordList;
        }
        MyRecord secondRecord = new MyRecord();
        secondRecord.set("index", 2);
        secondRecord.set("spreadUid", spreadSpreadUser.getId());
        recordList.add(secondRecord);
        return recordList;
    }

    /**
     * 赠送积分处理
     */
    private void presentIntegral(MerchantOrder merchantOrder, List<OrderDetail> orderDetailList, List<UserIntegralRecord> integralList, User user, Order order) {
        //比例
        String integralRatioStr = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_INTEGRAL_RATE_ORDER_GIVE);
        // 当下单支付金额按比例赠送积分 <= 0 时，不进行计算
        if (StrUtil.isNotBlank(integralRatioStr) && order.getPayPrice().compareTo(BigDecimal.ZERO) > 0 && new BigDecimal(integralRatioStr).compareTo(BigDecimal.ZERO) > 0) {
            BigDecimal integralBig = new BigDecimal(integralRatioStr);
            int giveIntegral = merchantOrder.getPayPrice().divide(integralBig, 0, BigDecimal.ROUND_DOWN).intValue();
            merchantOrder.setGainIntegral(giveIntegral);
            order.setGainIntegral(giveIntegral);
            if (giveIntegral > 0) {
                // 生成积分记录
                UserIntegralRecord integralRecord = integralRecordGainInit(user.getId(), order.getOrderNo(), giveIntegral);
                integralList.add(integralRecord);
                // 订单详情
                for (int i = 0; i < orderDetailList.size(); i++) {
                    OrderDetail orderDetail = orderDetailList.get(i);
                    if (orderDetailList.size() == (i + 1)) {
                        orderDetail.setGainIntegral(giveIntegral);
                    }
                    BigDecimal ratio = orderDetail.getPayPrice().divide(merchantOrder.getPayPrice(), 10, BigDecimal.ROUND_HALF_UP);
                    int integral = new BigDecimal(Integer.toString(giveIntegral)).multiply(ratio).setScale(0, BigDecimal.ROUND_DOWN).intValue();
                    orderDetail.setGainIntegral(integral);
                    giveIntegral = giveIntegral - integral;
                }
            }
        }
    }

    /**
     * 赠送积分处理
     */
    private void presentIntegral(List<MerchantOrder> merchantOrderList, List<OrderDetail> orderDetailList, List<UserIntegralRecord> integralList, User user, Order order) {
        int integral = 0;
        //比例
        String integralRatioStr = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_INTEGRAL_RATE_ORDER_GIVE);
        if (StrUtil.isNotBlank(integralRatioStr) && order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
            for (MerchantOrder merOrder : merchantOrderList) {
                BigDecimal integralBig = new BigDecimal(integralRatioStr);
                int giveIntegral = merOrder.getPayPrice().divide(integralBig, 0, BigDecimal.ROUND_DOWN).intValue();
                integral += giveIntegral;
                merOrder.setGainIntegral(giveIntegral);
                if (giveIntegral > 0) {
                    List<OrderDetail> detailList = orderDetailList.stream().filter(e -> e.getMerId().equals(merOrder.getMerId())).collect(Collectors.toList());
                    // 订单详情
                    for (int i = 0; i < detailList.size(); i++) {
                        OrderDetail orderDetail = detailList.get(i);
                        if (detailList.size() == (i + 1)) {
                            orderDetail.setGainIntegral(giveIntegral);
                        }
                        BigDecimal ratio = orderDetail.getPayPrice().divide(merOrder.getPayPrice(), 10, BigDecimal.ROUND_HALF_UP);
                        int detailIntegral = new BigDecimal(Integer.toString(giveIntegral)).multiply(ratio).setScale(0, BigDecimal.ROUND_DOWN).intValue();
                        orderDetail.setGainIntegral(detailIntegral);
                        giveIntegral = giveIntegral - detailIntegral;
                    }
                }
            }
            if (integral > 0) {
                order.setGainIntegral(integral);
                // 生成积分记录
                UserIntegralRecord integralRecord = integralRecordGainInit(user.getId(), order.getOrderNo(), integral);
                integralList.add(integralRecord);
            }
        }
    }

    /**
     * 初始化订单分帐表
     *
     * @param merchantOrder 商户部分订单
     * @return 分账记录
     */
    private OrderProfitSharing initOrderProfitSharing(MerchantOrder merchantOrder) {
        // 获取商户信息
        Merchant merchant = merchantService.getByIdException(merchantOrder.getMerId());
        // 分账计算
        // 商户收入 = 订单应付 - 商户优惠 -平台手续费 - 佣金
        BigDecimal orderPrice = merchantOrder.getPayPrice().add(merchantOrder.getIntegralPrice()).add(merchantOrder.getPlatCouponPrice()).subtract(merchantOrder.getPayPostage());
        // 平台手续费
        BigDecimal platFee = orderPrice.multiply(new BigDecimal(merchant.getHandlingFee())).divide(new BigDecimal(100), 2, BigDecimal.ROUND_UP);
        // 商户收入金额
        BigDecimal merchantFee = orderPrice.subtract(platFee).subtract(merchantOrder.getFirstBrokerage()).subtract(merchantOrder.getSecondBrokerage());
        OrderProfitSharing orderProfitSharing = new OrderProfitSharing();
        orderProfitSharing.setOrderNo(merchantOrder.getOrderNo());
        orderProfitSharing.setMerId(merchantOrder.getMerId());
        orderProfitSharing.setOrderPrice(merchantOrder.getPayPrice());
        orderProfitSharing.setIntegralNum(merchantOrder.getUseIntegral());
        orderProfitSharing.setIntegralPrice(merchantOrder.getIntegralPrice());
        orderProfitSharing.setProfitSharingPlatPrice(platFee);
        orderProfitSharing.setProfitSharingMerPrice(merchantFee);
        orderProfitSharing.setFirstBrokerageFee(merchantOrder.getFirstBrokerage());
        orderProfitSharing.setSecondBrokerageFee(merchantOrder.getSecondBrokerage());
        orderProfitSharing.setPlatCouponPrice(merchantOrder.getPlatCouponPrice());
        orderProfitSharing.setFreightFee(merchantOrder.getPayPostage());
        return orderProfitSharing;
    }

    /**
     * 初始化订单支付商户账单表
     *
     * @param merchantOrder 商户订单部分
     * @param merchantFee   商户分账金额
     */
    private MerchantBill initPayMerchantBill(MerchantOrder merchantOrder, BigDecimal merchantFee) {
        MerchantBill merchantBill = new MerchantBill();
        merchantBill.setMerId(merchantOrder.getMerId());
        merchantBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
        merchantBill.setOrderNo(merchantOrder.getOrderNo());
        merchantBill.setUid(merchantOrder.getUid());
        merchantBill.setPm(BillConstants.BILL_PM_ADD);
        merchantBill.setAmount(merchantFee);
        merchantBill.setMark(StrUtil.format("订单{}支付{}元，商户收入{}元", merchantOrder.getOrderNo(), merchantOrder.getPayPrice(), merchantFee));
        return merchantBill;
    }

    /**
     * 初始化订单支付平台账单表
     *
     * @param order              订单
     * @param merchantOrder      商户订单部分
     * @param orderProfitSharing 分账数据
     * @return List
     */
    private List<Bill> initPlatformBill(Order order, MerchantOrder merchantOrder, OrderProfitSharing orderProfitSharing) {
        List<Bill> billList = CollUtil.newArrayList();

        Bill payBill = new Bill();
        payBill.setUid(order.getUid());
        payBill.setOrderNo(order.getOrderNo());
        payBill.setAmount(order.getPayPrice());
        if (order.getPayType().equals(PayConstants.PAY_TYPE_YUE)) {
            payBill.setPm(BillConstants.BILL_PM_SUB);
            payBill.setType(BillConstants.BILL_TYPE_YUE_PAY);
            payBill.setMark(StrUtil.format("余额支付成功，扣除用户余额{}元", order.getPayPrice()));
        } else {
            payBill.setPm(BillConstants.BILL_PM_ADD);
            payBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
            payBill.setMark(StrUtil.format("订单支付成功，支付金额{}元", order.getPayPrice()));
        }
        billList.add(payBill);

        Bill collectBill = new Bill();
        collectBill.setMerId(merchantOrder.getMerId());
        collectBill.setOrderNo(order.getOrderNo());
        collectBill.setAmount(orderProfitSharing.getProfitSharingMerPrice());
        collectBill.setPm(BillConstants.BILL_PM_SUB);
        collectBill.setType(BillConstants.BILL_TYPE_MERCHANT_COLLECT);
        collectBill.setMark(StrUtil.format("订单支付成功，商户分账{}元", orderProfitSharing.getProfitSharingMerPrice()));
        billList.add(collectBill);

        Bill platBill = new Bill();
        platBill.setOrderNo(order.getOrderNo());
        platBill.setAmount(orderProfitSharing.getProfitSharingPlatPrice());
        platBill.setPm(BillConstants.BILL_PM_ADD);
        platBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
        platBill.setMark(StrUtil.format("订单支付成功，平台手续费{}元", orderProfitSharing.getProfitSharingPlatPrice()));
        billList.add(platBill);

        if (ObjectUtil.isNotNull(orderProfitSharing.getFirstBrokerageFee()) && orderProfitSharing.getFirstBrokerageFee().compareTo(BigDecimal.ZERO) > 0) {
            Bill firstBill = new Bill();
            firstBill.setOrderNo(order.getOrderNo());
            firstBill.setAmount(orderProfitSharing.getFirstBrokerageFee());
            firstBill.setPm(BillConstants.BILL_PM_SUB);
            firstBill.setType(BillConstants.BILL_TYPE_BROKERAGE);
            firstBill.setMark(StrUtil.format("订单支付成功，分配一级佣金{}元", orderProfitSharing.getFirstBrokerageFee()));
            billList.add(firstBill);
            if (orderProfitSharing.getSecondBrokerageFee().compareTo(BigDecimal.ZERO) > 0) {
                Bill secondBill = new Bill();
                secondBill.setOrderNo(order.getOrderNo());
                secondBill.setAmount(orderProfitSharing.getSecondBrokerageFee());
                secondBill.setPm(BillConstants.BILL_PM_SUB);
                secondBill.setType(BillConstants.BILL_TYPE_BROKERAGE);
                secondBill.setMark(StrUtil.format("订单支付成功，分配二级佣金{}元", orderProfitSharing.getSecondBrokerageFee()));
                billList.add(secondBill);
            }
        }

        if (orderProfitSharing.getIntegralNum() > 0) {
            Bill integralBill = new Bill();
            integralBill.setOrderNo(order.getOrderNo());
            integralBill.setAmount(order.getIntegralPrice());
            integralBill.setPm(BillConstants.BILL_PM_SUB);
            integralBill.setType(BillConstants.BILL_TYPE_PAY_ORDER);
            integralBill.setMark(StrUtil.format("订单支付成功，用户使用{}积分抵扣{}元，平台扣除", orderProfitSharing.getIntegralNum(), orderProfitSharing.getIntegralPrice()));
            billList.add(integralBill);
        }
        return billList;
    }

    /**
     * 初始化积分抵扣记录
     */
    private UserIntegralRecord integralRecordSubInit(Order order, Integer balance) {
        UserIntegralRecord integralRecord = new UserIntegralRecord();
        integralRecord.setUid(order.getUid());
        integralRecord.setLinkId(order.getOrderNo());
        integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER);
        integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_SUB);
        integralRecord.setTitle(IntegralRecordConstants.INTEGRAL_RECORD_TITLE_ORDER);
        integralRecord.setIntegral(order.getUseIntegral());
        integralRecord.setBalance(balance);
        integralRecord.setMark(StrUtil.format("订单支付使用{}积分抵扣金额购买商品", order.getUseIntegral()));
        integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_COMPLETE);
        return integralRecord;
    }

    /**
     * 初始化积分赠送记录
     */
    private UserIntegralRecord integralRecordGainInit(Integer uid, String orderNo, Integer gainIntegral) {
        UserIntegralRecord integralRecord = new UserIntegralRecord();
        integralRecord.setUid(uid);
        integralRecord.setLinkId(orderNo);
        integralRecord.setLinkType(IntegralRecordConstants.INTEGRAL_RECORD_LINK_TYPE_ORDER);
        integralRecord.setType(IntegralRecordConstants.INTEGRAL_RECORD_TYPE_ADD);
        integralRecord.setTitle(IntegralRecordConstants.INTEGRAL_RECORD_TITLE_ORDER);
        integralRecord.setIntegral(gainIntegral);
//        integralRecord.setBalance(balance);
        integralRecord.setMark(StrUtil.format("订单支付成功奖励{}积分", gainIntegral));
        integralRecord.setStatus(IntegralRecordConstants.INTEGRAL_RECORD_STATUS_CREATE);
        // 获取积分冻结期
        String freezeTime = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_STORE_INTEGRAL_EXTRACT_TIME);
        integralRecord.setFrozenTime(Integer.valueOf(Optional.ofNullable(freezeTime).orElse("0")));
        integralRecord.setCreateTime(CrmebDateUtil.nowDateTime());
        return integralRecord;
    }

    private Map<String, String> getWechatQueryPayVo(String outTradeNo, String payChannel) {
        // 获取appid、mch_id
        // 微信签名key
        String appId = "";
        String mchId = "";
        String signKey = "";
        switch (payChannel) {
            case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
            case PayConstants.PAY_CHANNEL_H5:// H5使用公众号的信息
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PUBLIC_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
                break;
            case PayConstants.PAY_CHANNEL_WECHAT_MINI:
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_MINI_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
                break;
            case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
            case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_APP_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
                break;
        }

        // 生成查询订单对象
        Map<String, String> map = CollUtil.newHashMap();
        map.put("appid", appId);
        map.put("mch_id", mchId);
        map.put("out_trade_no", outTradeNo);
        map.put("nonce_str", WxPayUtil.getNonceStr());
        map.put("sign_type", PayConstants.WX_PAY_SIGN_TYPE_MD5);
        map.put("sign", WxPayUtil.getSign(map, signKey));
        return map;
    }

    /**
     * 支付宝支付
     *
     * @param order 订单
     * @return result
     */
    private String aliPayment(Order order) {
        return aliPayService.pay(order.getOrderNo(), order.getPayPrice(), "order", order.getPayChannel());
    }

    /**
     * 微信支付
     *
     * @param order 订单
     * @return WxPayJsResultVo
     */
    private WxPayJsResultVo wechatPayment(Order order) {
        // 预下单
        Map<String, String> unifiedorder = unifiedorder(order);
        WxPayJsResultVo vo = new WxPayJsResultVo();
        vo.setAppId(unifiedorder.get("appId"));
        vo.setNonceStr(unifiedorder.get("nonceStr"));
        vo.setPackages(unifiedorder.get("package"));
        vo.setSignType(unifiedorder.get("signType"));
        vo.setTimeStamp(unifiedorder.get("timeStamp"));
        vo.setPaySign(unifiedorder.get("paySign"));
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
            vo.setMwebUrl(unifiedorder.get("mweb_url"));
        }
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
                order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
            vo.setPartnerid(unifiedorder.get("partnerid"));
        }
        // 更新商户订单号
        order.setOutTradeNo(unifiedorder.get("outTradeNo"));
        return vo;
    }

    private Boolean zeroPay(Order order, User user) {
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean update = Boolean.TRUE;
            // 订单修改
            order.setPaid(true);
            order.setPayType(PayConstants.PAY_TYPE_ZERO);
            order.setPayTime(DateUtil.date());
            order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            orderService.updateById(order);

            UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
            userBalanceRecord.setUid(user.getId());
            userBalanceRecord.setLinkId(order.getOrderNo());
            userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
            userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
            userBalanceRecord.setAmount(BigDecimal.ZERO);
            userBalanceRecord.setBalance(user.getNowMoney());
            userBalanceRecord.setRemark(StrUtil.format(BalanceRecordConstants.BALANCE_RECORD_REMARK_ORDER, BigDecimal.ZERO));
            userBalanceRecordService.save(userBalanceRecord);
            return update;
        });
        if (!execute) {
            throw new CrmebException("0元支付失败");
        }
        asyncService.orderPaySuccessSplit(order.getOrderNo());
        return true;
    }

    /**
     * 余额支付
     *
     * @param order 订单
     * @return Boolean Boolean
     */
    private Boolean yuePay(Order order, User user) {
        // 用户余额扣除
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean update = Boolean.TRUE;
            // 订单修改
            order.setPaid(true);
            order.setPayTime(DateUtil.date());
            order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            orderService.updateById(order);
            // 这里只扣除金额，账单记录在task中处理
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                update = userService.updateNowMoney(order.getUid(), order.getPayPrice(), Constants.OPERATION_TYPE_SUBTRACT);
                if (!update) {
                    logger.error("余额支付，扣除用户余额失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    return update;
                }
                // 用户余额记录
                UserBalanceRecord userBalanceRecord = new UserBalanceRecord();
                userBalanceRecord.setUid(user.getId());
                userBalanceRecord.setLinkId(order.getOrderNo());
                userBalanceRecord.setLinkType(BalanceRecordConstants.BALANCE_RECORD_LINK_TYPE_ORDER);
                userBalanceRecord.setType(BalanceRecordConstants.BALANCE_RECORD_TYPE_SUB);
                userBalanceRecord.setAmount(order.getPayPrice());
                userBalanceRecord.setBalance(user.getNowMoney().subtract(order.getPayPrice()));
                userBalanceRecord.setRemark(StrUtil.format(BalanceRecordConstants.BALANCE_RECORD_REMARK_ORDER, order.getPayPrice()));
                userBalanceRecordService.save(userBalanceRecord);
            }
            return update;
        });
        if (!execute) throw new CrmebException("余额支付订单失败");
        asyncService.orderPaySuccessSplit(order.getOrderNo());
//        // 添加支付成功redis队列
//        redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, order.getOrderNo());
        return true;
    }

    /**
     * 提供给汇付微信支付控件，当确定微信支付成功后，调用该方法设置订单状态为已支付
     *
     * @param orderNo
     */
    @Override
    public void setOrderPaySuccess(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(order) || ObjectUtil.isNull(orderDetails) || orderDetails.size() < 1) {
            throw new CrmebException("订单不存在");
        }
        if (order.getCancelStatus() > OrderConstants.ORDER_CANCEL_STATUS_NORMAL) {
            throw new CrmebException("订单已取消");
        }
//        if (!order.getPayType().equals(PayConstants.PAY_TYPE_WE_CHAT)) {
//            throw new CrmebException("不是微信支付类型订单");
//        }
        if (order.getPaid()) {
            return;
        }
        logger.info("C端支付，异步回调开始，setOrderPaySuccess=1");
        OrderDetail orderDetail = orderDetails.get(0);

        Boolean updatePaid = transactionTemplate.execute(e -> {
            order.setPayType(PayConstants.PAY_TYPE_WE_CHAT_TO_HUIFU);
            order.setPayChannel(PayConstants.PAY_CHANNEL_WECHAT_MINI);
            orderService.updateById(order);
            orderService.updatePaid(orderNo);
            return Boolean.TRUE;
        });
        if (!updatePaid) {
            throw new CrmebException("支付成功更新订单失败");
        }
        //PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())  &&
        if(order.getBizType().equals(ProductConstants.BIZ_TYPE_RISK)) {//线下支付 && 风评订单
            logger.info("C端支付，异步回调开始，setOrderPaySuccess=2");
            syncReportOrder2RiskSystem(order, orderDetail);
        }
        logger.info("C端支付，异步回调开始，setOrderPaySuccess=3");
        asyncService.orderPaySuccessSplit(order.getOrderNo());
    }

    private void syncReportOrder2RiskSystem(Order order, OrderDetail orderDetail) {

        ProductAttrValue sku = productAttrValueService.getById(orderDetail.getAttrValueId());
        try {
            boolean isPlatOrderNo = StrUtil.isBlank(order.getPlatOrderNo());
            String relateOrderNo = isPlatOrderNo ? order.getOrderNo() : order.getPlatOrderNo();
            BcxOrderRelation relation = bcxOrderRelationService.query().eq("order_no", relateOrderNo).one();
            if(relation == null){
                logger.error("=============风评订单推送到风评系统失败：订单主副业务关系表无记录（一般情况订单的创建主副表必定相应创建一条记录）");
                return;
            }
            String productCode = StringUtils.isNotEmpty(sku.getBarCode())?sku.getBarCode():"";
            if(StringUtils.isEmpty(productCode)){
                logger.error("=============风评订单推送到风评系统失败：未配置商品条码");
                return;
            }
            // 获取商户信息
            Merchant merchant = merchantService.getByIdException(order.getMerId());
            String orderNo = relation.getMasterOrderNo();
            Map<String, Object> body = new HashMap<>();
            body.put("activityNo", orderNo);
            body.put("costId", orderDetail.getSourceId());
            body.put("amount", orderDetail.getPayPrice());
            body.put("orderNo", order.getOrderNo());
            body.put("productName", orderDetail.getProductName());
            //ESTAND-TK-10313 切割后 313
            body.put("productCode", productCode.substring(productCode.length()-3, productCode.length()));
            body.put("serverOrg", merchant.getName());
            body.put("skuId", orderDetail.getAttrValueId());
            String url = "";
            if (sku.getBarCode().toUpperCase().startsWith(ProductConstants.PRODUCT_E_RISK_REPORT)) {
                url = systemConfigService.getRiskSystemUrl() + "/wechat/wechat-enter-activity-info";
            }else if (sku.getBarCode().toUpperCase().startsWith(ProductConstants.PRODUCT_E_RISK_EXPLORATION)) {
                url = systemConfigService.getRiskSystemUrl() + "/wechat/buySurveyLevel";
            }else if (sku.getBarCode().toUpperCase().startsWith(ProductConstants.PRODUCT_E_RISK_EXPERT)) {
                url = systemConfigService.getRiskSystemUrl() + "/wechat/buyExpertType";
            }else {
                logger.error("=============风评订单推送到风评系统失败：未匹配到业务地址");
                return;
            }
            logger.info("=============风评订单推送到风评系统,url："+url);
            logger.info("=============风评订单推送到风评系统,body："+JSON.toJSONString(body));
            //TODO 推送创建活动新或其它风评商品
            JSONObject result = restTemplateUtil.postJson(url, new JSONObject(body), ERiskUtil.getHeader());
            logger.info(result.toJSONString());
            if (!result.getBoolean("success")) {
                logger.error("=============风评订单推送到风评系统活动创建失败："+result.getString("message")+",orderNo:" + order.getOrderNo());
                //支付成功，通知风评系统不成功，风评系统应有反查机制
                return;
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        try {
            if (sku.getBarCode().toUpperCase().startsWith(ProductConstants.PRODUCT_E_RISK_REPORT)) {
                User user = userService.getById(order.getUid());
                if (StrUtil.isNotBlank(user.getPhone())) {
                    smsService.sendMessage(user.getPhone(), "尊敬的用户，您已成功购买【风评报告】商品，请尽快登录【" + systemConfigService.getRiskSystemUrl() + "】完成申报材料的提交。");
                } else {
                    logger.error("找不到用户手机号，取消发送短信");
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    /**
     * 企业钱包支付
     *
     * @param order 订单  bizType 0-实体, 1-虚拟, 2-特殊(考培), 3-保险, 4-风评
     * @return Boolean Boolean
     */
    private Boolean walletFreezeAndPay(Order order, OrderDetail orderDetail, Integer bizType, User user, Merchant merchant) {
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        String productDesc = orderDetail.getProductName() + "(" + orderDetail.getSku() + ") * " + orderDetail.getPayNum();
        Boolean execute = transactionTemplate.execute(e -> {
            Boolean update = Boolean.TRUE;
            // 订单修改
            order.setPaid(true);
            order.setBizType(bizType);
            order.setPayTime(DateUtil.date());
            if (order.getStatus().intValue() == OrderConstants.ORDER_STATUS_WAIT_PAY) {
                order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            }
            orderService.updateById(order);

            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
                transferDto.setAmount(order.getPayPrice().toPlainString())//订单金额
                        .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),3-保险, 4-风评
                        .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
                        .setComment(productDesc)
                        .setGoodsName(orderDetail.getProductName()).setGoodsUnit(orderDetail.getSku()).setGoodsNumber(String.valueOf(orderDetail.getPayNum()))
                        .setInId(merchant.getIdentityNo())
                        .setSellFeePriority(platFee.getTransPriority())
                        .setNeedActiveCode("0")//是否需要验证码
                        .setOutId(user.getIdentityNo())
                        .setPlatAmount(platFee.getPlatFee() != null ? platFee.getPlatFee().toPlainString() : "0")
                ;
                try {
                    //TODO 根据不同分账对象实现转账业务保留参考
//                    if (bizType.equals(ProductConstants.BIZ_TYPE_VIRTUAL)) {// 虚拟商品直接转账
//                        huifuWalletService.pay(transferDto);//直接转账
//                    } else {// 实体 或 特殊(考培) 先冻结
//                        huifuWalletService.freeze(transferDto);//冻结
                    ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(orderDetail.getAttrValueId()
                            , orderDetail.getProductId(), ProductConstants.PRODUCT_TYPE_NORMAL);
                    //虚拟或规则标记为虚拟的走直接转账
                    if (bizType==1) {// 虚拟商品直接转账
                        transferDto.setTradeType("03");//03-无解冻，直接支付。 05-解冻再支付
                        if(PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())){//线下支付
                            paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).offlinePayPlatTransfer(transferDto);
                        }else {
                            paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountTransfer(transferDto);
                        }
                    } else {// 实体 或 特殊(考培) 先冻结  报名缴费 直接转账并冻结
                        transferDto.setTradeType("04");//04-转账并冻结。 05-解冻并转账（退款）
                        if(PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())){//线下支付
                            paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).offlinePayPlatTransfer(transferDto);
                        }else {
                            paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountTransfer(transferDto);
                        }
                    }
                } catch (Exception exception) {
                    logger.error(exception.getMessage());
                    logger.error("企业钱包支付，冻结失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    update = false;
                }
            } else {
                logger.info("订单金额小等于0，众邦商城不走支付流程，直接成功");
            }
            return update;
        });
        if (!execute) throw new CrmebException("企业钱包冻结失败");
        /*if(PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())  && order.getBizType().equals(ProductConstants.BIZ_TYPE_RISK)) {//线下支付 && 风评订单
            syncReportOrder2RiskSystem(order, orderDetail);
        }*/
        if(!PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())) {//不是线下支付
            asyncService.orderPaySuccessSplit(order.getOrderNo());
        }

//        // 添加支付成功redis队列
//        redisUtil.lPush(TaskConstants.ORDER_TASK_PAY_SUCCESS_AFTER, order.getOrderNo());
        return true;
    }

    @Override
    public Boolean specialOrderUnfreezeAndPay(String orderNo) {
        LambdaQueryWrapper<Order> lqw = new LambdaQueryWrapper<>();
        lqw.eq(Order::getOrderNo, orderNo);
        Order order = orderService.getOne(lqw);
        if (order == null || order.getMerId() < 1) {
            throw new CrmebException("没有该订单或订单商户数据异常");
        }
        List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(order.getOrderNo());
        OrderDetail orderDetail = orderDetails.get(0);
        String productDesc = orderDetail.getProductName() + "(" + orderDetail.getSku() + ") * " + orderDetail.getPayNum()+"确认";
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        if (StrUtil.isBlank(merchant.getIdentityNo())) {
            throw new CrmebException("商户未开通汇付钱包:" + merchant.getId() + ":" + merchant.getName());
        }
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        User user = userService.getById(order.getUid());
        if (StrUtil.isBlank(user.getIdentityNo())) {
            throw new CrmebException("用户未开通汇付钱包:" + user.getId() + ":" + user.getRealName());
        }
        BigDecimal total = order.getPayPrice();
        if (total.compareTo(BigDecimal.ZERO) > 0) {
            HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
            transferDto.setAmount(total.toPlainString())//订单金额
                    .setBusinessCode(String.valueOf(order.getBizType()))//特殊(考培)
                    .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
//                    .setBusinessPartnerSeq(orderNo)//业务交易流水号
                    .setComment(productDesc)
                    .setGoodsName(orderDetail.getProductName()).setGoodsUnit(orderDetail.getSku()).setGoodsNumber(String.valueOf(orderDetail.getPayNum()))
                    // 根据不同分账对象实现转账业务
                    .setSellFeePriority(platFee.getTransPriority())
                    .setInId(merchant.getIdentityNo())
                    .setNeedActiveCode("0")//是否需要验证码
                    .setOutId(user.getIdentityNo())
                    .setPlatAmount(platFee.getPlatFee().toPlainString())
            ;
            try {
                //TODO 根据不同分账对象实现转账业务保留参考
//                huifuWalletService.payAndThaw(transferDto);//解冻再支付
                transferDto.setTradeType("05");//03-无解冻，直接支付。 05-解冻再支付 TODO 确认成绩 只做解冻
                paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountLock(transferDto);
            } catch (Exception exception) {
                logger.error("考培订单解冻支付失败seqNo = " + orderNo + exception.getMessage());
                throw new CrmebException("考培订单解冻支付失败seqNo = " + orderNo + exception.getMessage());
            }
        } else {
            logger.info("订单金额小等于0，不走支付流程，直接成功");
        }
        return true;
    }

    @Override
    public Boolean walletUnfreezeAndPay(Order order, List<OrderDetail> orderDetails, Integer bizType, User user, Merchant merchant) {
        if (orderDetails.isEmpty()) {
            throw new CrmebException("订单明细为空,无法支付,请联系管理页");
        }
        String productDesc = orderDetails.stream().map(d -> d.getProductName() + "(" + d.getSku() + ") * " + d.getPayNum()).collect(Collectors.joining(";"));
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        Boolean execute = transactionTemplate.execute(e -> {
            boolean update = true;
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
                transferDto.setAmount(order.getPayPrice().toPlainString())//订单金额
                        .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),保险
                        .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
                        .setComment(productDesc)
                        .setGoodsName(orderDetails.get(0).getProductName()).setGoodsUnit(orderDetails.get(0).getSku()).setGoodsNumber(String.valueOf(orderDetails.get(0).getPayNum()))
                        .setInId(merchant.getIdentityNo())
                        .setSellFeePriority(platFee.getTransPriority())
                        .setNeedActiveCode("0")//是否需要验证码
                        .setOutId(user.getIdentityNo())
                        .setPlatAmount(platFee.getPlatFee().toPlainString())
                ;
                try {
                    if (bizType.equals(ProductConstants.BIZ_TYPE_SPACIAL) || bizType.equals(ProductConstants.BIZ_TYPE_RISK)) {// 特殊商品(考培)+风评商品 解冻再支付
                        //TODO 根据不同分账对象实现转账业务保留参考
//                        huifuWalletService.payAndThaw(transferDto);//解冻再支付
                        transferDto.setTradeType("05");//03-无解冻，直接支付。 05-解冻再支付 考培确认成绩 只做解冻
                        paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountLock(transferDto);
                    }
                } catch (Exception exception) {
                    logger.error(exception.getMessage());
                    logger.error("企业钱包支付，解冻支付失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    update = false;
                }
            } else {
                logger.info("订单金额小等于0，众邦商城不走支付流程，直接成功");
            }
            return update;
        });
        if (Boolean.FALSE.equals(execute)) throw new CrmebException("企业钱包解冻支付失败");
        return true;
    }

    @Override
    public Boolean platWalletUnfreezeAndPay(Order order, List<OrderDetail> orderDetails, Integer bizType, User user, Merchant merchant) {
        if (orderDetails.isEmpty()) {
            throw new CrmebException("订单明细为空,无法支付,请联系管理页");
        }
        String productDesc = orderDetails.stream().map(d -> d.getProductName() + "(" + d.getSku() + ") * " + d.getPayNum()).collect(Collectors.joining(";"));
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        Boolean execute = transactionTemplate.execute(e -> {
            boolean update = true;
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
                transferDto.setAmount(order.getPayPrice().toPlainString())//订单金额
                        .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),保险
                        .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
                        .setComment(productDesc)
                        .setGoodsName(orderDetails.get(0).getProductName()).setGoodsUnit(orderDetails.get(0).getSku()).setGoodsNumber(String.valueOf(orderDetails.get(0).getPayNum()))
                        .setInId(merchant.getIdentityNo())
                        .setSellFeePriority(platFee.getTransPriority())
                        .setNeedActiveCode("0")//是否需要验证码
                        .setOutId(user.getIdentityNo())
                        .setPlatAmount(platFee.getPlatFee().toPlainString())
                ;
                try {
                    if (bizType.equals(ProductConstants.BIZ_TYPE_SPACIAL) || bizType.equals(ProductConstants.BIZ_TYPE_RISK)) {// 特殊商品(考培)+风评商品 解冻再支付
                        //TODO 根据不同分账对象实现转账业务保留参考
//                        huifuWalletService.payAndThaw(transferDto);//解冻再支付
                        transferDto.setTradeType("05");//03-无解冻，直接支付。 05-解冻再支付 考培确认成绩 只做解冻
                        paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).platHuifuWalletAccountLock(transferDto);
                    }
                } catch (Exception exception) {
                    logger.error(exception.getMessage());
                    logger.error("企业钱包支付，解冻支付失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    update = false;
                }
            } else {
                logger.info("订单金额小等于0，众邦商城不走支付流程，直接成功");
            }
            return update;
        });
        if (Boolean.FALSE.equals(execute)) throw new CrmebException("企业钱包解冻支付失败");
        return true;
    }

    @Override
    public Boolean walletUnfreeze(Order order, List<OrderDetail> orderDetails, Integer bizType, User user, Merchant merchant) {
        if (orderDetails.isEmpty()) {
            throw new CrmebException("订单明细为空,无法支付,请联系管理页");
        }
        String productDesc = orderDetails.stream().map(d -> d.getProductName() + "(" + d.getSku() + ") * " + d.getPayNum()).collect(Collectors.joining(";"));
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        Boolean execute = transactionTemplate.execute(e -> {
            boolean update = true;
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
                transferDto.setAmount(order.getPayPrice().toPlainString())//订单金额
                        .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),保险
                        .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
                        .setComment(productDesc)
                        .setGoodsName(orderDetails.get(0).getProductName()).setGoodsUnit(orderDetails.get(0).getSku()).setGoodsNumber(String.valueOf(orderDetails.get(0).getPayNum()))
                        .setInId(merchant.getIdentityNo())
                        .setSellFeePriority(platFee.getTransPriority())
                        .setNeedActiveCode("0")//是否需要验证码
                        .setOutId(user.getIdentityNo())
                        .setPlatAmount(platFee.getPlatFee().toPlainString())
                ;
                try {
                    //TODO 根据不同分账对象实现转账业务保留参考
//                    if (bizType.equals(2)) {// 特殊商品(考培)解冻再支付
//                        huifuWalletService.thaw(transferDto);//解冻
                    if (bizType.equals(2)) {// 特殊商品(考培)解冻再支付 TODO 考培退款 并解冻
                        transferDto.setTradeType("05");//04-冻结。 05-解冻
                        if(PAY_TYPE_OFFLINE.equalsIgnoreCase(order.getPayType())) {//线下付款，产品经历定 暂不支持退款
                            //huifuWalletService.offlinePayPlatRefund(transferDto);
                        }else{
                            paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountRefund(transferDto);
                        }
                    } else {
                        logger.error("只有特殊商品才走解冻流程-orderNo:" + order.getOrderNo() + ":orderDetailId:" + orderDetails.get(0).getId());
                        update = false;
                    }
                } catch (Exception exception) {
                    logger.error(exception.getMessage());
                    logger.error("企业钱包支付，解冻失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    update = false;
                }
            } else {
                logger.info("订单金额小等于0，众邦商城不走支付流程，直接成功");
            }
            return update;
        });
        if (Boolean.FALSE.equals(execute)) throw new CrmebException("企业钱包解冻失败");
        return true;
    }

    @Override
    public Boolean wechat2HuifuRefund(Order order) {
        BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(order.getOrderNo(), 0);
        Boolean execute = transactionTemplate.execute(e -> {
            boolean update = true;
            if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
                JsPayTransferDto refundDto = new JsPayTransferDto();
                refundDto.setOldBusinessPartnerSeq(order.getPlatOrderNo());
                refundDto.setBusinessPartnerSeq(order.getPlatOrderNo());
                refundDto.setBusinessCode(String.valueOf(order.getBizType()));
                refundDto.setAmount(String.valueOf(order.getPayPrice()));
                refundDto.setComment("风评商品微信退款");
                refundDto.setSellFeePriority(platFee.getTransPriority());
                refundDto.setPlatAmount(platFee.getPlatFee().toPlainString());

                try {
                    if (order.getBizType().equals(4)) {// 风评商品退款
                        refundDto.setTradeType("05");
                        paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuJspayRefund(refundDto);
                    } else {
                        logger.error("只有风评商品才走该微信退款流程-orderNo:" + order.getOrderNo());
                        update = false;
                    }
                } catch (Exception exception) {
                    logger.error(exception.getMessage());
                    logger.error("风评商品 微信退款 失败，orderNo = {}", order.getOrderNo());
                    e.setRollbackOnly();
                    update = false;
                }
            } else {
                logger.info("订单金额小等于0，商城不走退款流程，直接成功");
            }
            return update;
        });
        if (Boolean.FALSE.equals(execute)) throw new CrmebException("退款失败，请联系管理员");
        return true;
    }

    /**
     * 预下单
     *
     * @param order 订单
     * @return 预下单返回对象
     */
    private Map<String, String> unifiedorder(Order order) {
        // 获取用户openId
        // 根据订单支付类型来判断获取公众号openId还是小程序openId
        UserToken userToken = new UserToken();
        userToken.setToken("");
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_PUBLIC)) {// 公众号
            userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_WECHAT);
        }
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI)
                || order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO)) {// 小程序
            userToken = userTokenService.getTokenByUserId(order.getUid(), UserConstants.USER_TOKEN_TYPE_ROUTINE);
        }

        // 获取appid、mch_id、微信签名key
        String appId = "";
        String mchId = "";
        String signKey = "";
        switch (order.getPayChannel()) {
            case PayConstants.PAY_CHANNEL_WECHAT_PUBLIC:
            case PayConstants.PAY_CHANNEL_H5:// H5使用公众号的信息
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PUBLIC_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_PUBLIC_KEY);
                break;
            case PayConstants.PAY_CHANNEL_WECHAT_MINI:
            case PayConstants.PAY_CHANNEL_WECHAT_MINI_VIDEO:
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_MINI_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_MINI_KEY);
                break;
            case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
            case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
                appId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_APP_APPID);
                mchId = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_MCHID);
                signKey = systemConfigService.getValueByKeyException(WeChatConstants.WECHAT_PAY_APP_KEY);
                break;
        }
        // 获取微信预下单对象
        CreateOrderRequestVo unifiedorderVo = getUnifiedorderVo(order, userToken.getToken(), appId, mchId, signKey);
        // 预下单（统一下单）
        CreateOrderResponseVo responseVo = wechatService.payUnifiedorder(unifiedorderVo);
        // 组装前端预下单参数
        Map<String, String> map = new HashMap<>();
        map.put("appId", unifiedorderVo.getAppid());
        map.put("nonceStr", unifiedorderVo.getAppid());
        map.put("package", "prepay_id=".concat(responseVo.getPrepayId()));
        map.put("signType", unifiedorderVo.getSign_type());
        Long currentTimestamp = WxPayUtil.getCurrentTimestamp();
        map.put("timeStamp", Long.toString(currentTimestamp));
        String paySign = WxPayUtil.getSign(map, signKey);
        map.put("paySign", paySign);
        map.put("prepayId", responseVo.getPrepayId());
        map.put("prepayTime", CrmebDateUtil.nowDateTimeStr());
        map.put("outTradeNo", unifiedorderVo.getOut_trade_no());
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_H5)) {
            map.put("mweb_url", responseVo.getMWebUrl());
        }
        if (order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_IOS) ||
                order.getPayChannel().equals(PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID)) {// App
            map.put("partnerid", mchId);
            map.put("package", responseVo.getPrepayId());
            Map<String, Object> appMap = new HashMap<>();
            appMap.put("appid", unifiedorderVo.getAppid());
            appMap.put("partnerid", mchId);
            appMap.put("prepayid", responseVo.getPrepayId());
            appMap.put("package", "Sign=WXPay");
            appMap.put("noncestr", unifiedorderVo.getAppid());
            appMap.put("timestamp", currentTimestamp);
            logger.info("================================================app支付签名，map = " + appMap);
            String sign = WxPayUtil.getSignObject(appMap, signKey);
            logger.info("================================================app支付签名，sign = " + sign);
            map.put("paySign", sign);
        }
        return map;
    }

    /**
     * 获取微信预下单对象
     *
     * @return 微信预下单对象
     */
    private CreateOrderRequestVo getUnifiedorderVo(Order order, String openid, String appId, String mchId, String signKey) {
        // 获取域名
        String domain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_URL);
        String apiDomain = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_API_URL);

        AttachVo attachVo = new AttachVo(PayConstants.PAY_SERVICE_TYPE_ORDER, order.getUid());

        CreateOrderRequestVo vo = new CreateOrderRequestVo();
        vo.setAppid(appId);
        vo.setMch_id(mchId);
        vo.setNonce_str(WxPayUtil.getNonceStr());
        vo.setSign_type(PayConstants.WX_PAY_SIGN_TYPE_MD5);
        String siteName = systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME);
        // 因商品名称在微信侧超长更换为网站名称
        vo.setBody(siteName);
        vo.setAttach(JSONObject.toJSONString(attachVo));
        vo.setOut_trade_no(CrmebUtil.getOrderNo(OrderConstants.ORDER_PREFIX_WECHAT));
        // 订单中使用的是BigDecimal,这里要转为Integer类型
        vo.setTotal_fee(order.getPayPrice().multiply(BigDecimal.TEN).multiply(BigDecimal.TEN).intValue());
        vo.setSpbill_create_ip(RequestUtil.getClientIp());
        vo.setNotify_url(apiDomain + PayConstants.WX_PAY_NOTIFY_API_URI);
        switch (order.getPayChannel()) {
            case PayConstants.PAY_CHANNEL_H5:
                vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_H5);
                vo.setOpenid(null);
                break;
            case PayConstants.PAY_CHANNEL_WECHAT_APP_IOS:
            case PayConstants.PAY_CHANNEL_WECHAT_APP_ANDROID:
                vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_APP);
                vo.setOpenid(null);
                break;
            default:
                vo.setTrade_type(PayConstants.WX_PAY_TRADE_TYPE_JS);
                vo.setOpenid(openid);
        }
        CreateOrderH5SceneInfoVo createOrderH5SceneInfoVo = new CreateOrderH5SceneInfoVo(
                new CreateOrderH5SceneInfoDetailVo(
                        domain,
                        systemConfigService.getValueByKeyException(SysConfigConstants.CONFIG_KEY_SITE_NAME)
                )
        );
        vo.setScene_info(JSONObject.toJSONString(createOrderH5SceneInfoVo));
        String sign = WxPayUtil.getSign(vo, signKey);
        vo.setSign(sign);
        return vo;
    }

    /**
     * 商品购买后根据配置送券
     */
    private void autoSendCoupons(Order order) {
        List<OrderDetail> orderDetailList = orderDetailService.getByOrderNo(order.getOrderNo());
        if (CollUtil.isEmpty(orderDetailList)) {
            return;
        }
        List<CouponUser> couponUserList = CollUtil.newArrayList();
        Map<Integer, Boolean> couponMap = CollUtil.newHashMap();
        List<Integer> proIdList = orderDetailList.stream().map(OrderDetail::getProductId).distinct().collect(Collectors.toList());
        for (Integer proId : proIdList) {
            List<ProductCoupon> couponsForGiveUser = productCouponService.getListByProductId(proId);
            for (int i = 0; i < couponsForGiveUser.size(); ) {
                ProductCoupon productCoupon = couponsForGiveUser.get(i);
                MyRecord record = couponUserService.paySuccessGiveAway(productCoupon.getCouponId(), order.getUid());
                if (record.getStr("status").equals("fail")) {
                    logger.error(StrUtil.format("支付成功领取优惠券失败，失败原因：{}", record.getStr("errMsg")));
                    couponsForGiveUser.remove(i);
                    continue;
                }
                CouponUser couponUser = record.get("couponUser");
                couponUserList.add(couponUser);
                couponMap.put(couponUser.getCouponId(), record.getBoolean("isLimited"));
                i++;
            }
        }

        Boolean execute = transactionTemplate.execute(e -> {
            if (CollUtil.isNotEmpty(couponUserList)) {
                couponUserService.saveBatch(couponUserList);
                couponUserList.forEach(i -> couponService.deduction(i.getCouponId(), 1, couponMap.get(i.getCouponId())));
            }
            return Boolean.TRUE;
        });
        if (!execute) {
            logger.error(StrUtil.format("支付成功领取优惠券，更新数据库失败，订单编号：{}", order.getOrderNo()));
        }
    }

    @Override
    public boolean checkPayResult(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(orderNo);
        if (ObjectUtil.isNull(order)) {
            throw new CrmebException("订单不存在");
        }
        return order.getPaid();
    }


    /**
     * <b> C端聚合正扫回调 </b>
     *
     * @author ZXF
     * @create 2023/08/25 0025 16:13
     * @version
     * @注意事项 </b>
     */
    @Override
    public String huifuJspayCallback(String messageBody) {

        Map<String, Object> response = pathToJson(messageBody);
        logger.info("C端支付，异步回调开始，参数，response={}", response.toString());
        transactionLogService.save("huifuJspayCallback", Constants.Y, response.toString(), "ok",PaymentChannel.HUIFU.toString());
        if (!HFConstants.REQUEST_SUCC_CODE.equals(response.get("resp_code").toString())) {
            return "ok";
        }
        // 验签请参sign
        String sign = response.get("sign").toString();
        // 使用汇付公钥验签
        if (!RsaUtils.verify(response.get("resp_data").toString(), HFProfileCPayConstants.RSA_PUBLIC_KEY, sign)) {
            logger.info("C端支付，异步回调开始，fail=验签失败");
            // 验签失败处理
            return "";
        }
        JSONObject dataObj = JSON.parseObject(response.get("resp_data").toString());
        String subRespCode = dataObj.getString("sub_resp_code");
        String reqSeqId = dataObj.getString("req_seq_id");
        String bankMessage = dataObj.getString("bank_message");
        String tradeStatus = Constants.tradeStatus(dataObj.get("trans_stat").toString());
        String lockId = TRANSFERKEY+reqSeqId;
        RLock lock = redisson.getLock(lockId);
        try {
            if(lock.tryLock(3,10, TimeUnit.SECONDS)){
                logger.debug(lockId+":getLock: " + Thread.currentThread().getId());
                JsPayTrade jsPayTrade = jsPayTradeDao.getJsPayTradeByHfSeqId(dataObj.get("hf_seq_id").toString());
                if (jsPayTrade == null) {
                    logger.info("C端支付，异步回调开始，fail=交易不存在");
                    // 交易失败处理
                    return "RECV_ORD_ID_" + reqSeqId;
                }
                // 支付成功记录已存在
                if (Constants.TRADESTATUS_JYCG.equals(jsPayTrade.getTradeStatus())) {
                    logger.info("C端支付，异步回调开始，succ1={}", reqSeqId);
                    return "RECV_ORD_ID_" + reqSeqId;
                }
                //支付成功，通知订单
                if ("00000000".equals(subRespCode) && Constants.TRADESTATUS_JYCG.equals(tradeStatus)) {
                    BcxPlatformFee platFee = bcxPlatformFeeService.queryByOrderNo(jsPayTrade.getBusinessPartnerSeq(), 0);
                    setOrderPaySuccess(jsPayTrade.getBusinessPartnerSeq());
                    //C端二级分账业务处理
                    transferToPlatBody(jsPayTrade,platFee);

                    //冻结/解冻业务逻辑判断，计算记录冻结金额并入库 当前 TODO 冻结   业务待完善
                    String platAmount = platFee.getPlatFee() != null ? platFee.getPlatFee().toPlainString() : "0";
                    String lockAmount = decimalFormat.format(jsPayTrade.getAmount().subtract(new BigDecimal(platAmount)));
                    if(platFee.getTransPriority()==0){
                        // 先到平台的话直接拿记录的分账金额当冻结金额
                        lockAmount = decimalFormat.format(new BigDecimal(platAmount));
                    }
                    /*String objId = jsPayTrade.getInUniId();
                    if("03".equals(jsPayTrade.getTradeType())){
                        objId = jsPayTrade.getUniId();
                    }*/
                    //扣除手续费后才是实际要冻结的金额
                    lockAmount = decimalFormat.format(new BigDecimal(lockAmount).subtract(jsPayTrade.getCommissionAmount()));
//                  BigDecimal frozenAmount = huifuWalletService.extractedLock(objId, jsPayTrade.getTradeType(), lockAmount);
                    //更新冻结金额
//                  huifuWalletAccountDao.updateFrozenAmount(jsPayTrade.getInUniId(),frozenAmount.toString());
//                    String lockAmountStr = lockAmount;
                    try {
                        HuifuWalletService service = paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService());
                        service.syncUpdateSumFrozenAmount(jsPayTrade.getInUniId(),"04".equals(jsPayTrade.getTradeType())?(new BigDecimal(lockAmount)):"05".equals(jsPayTrade.getTradeType())?(new BigDecimal("-"+lockAmount)):BigDecimal.ZERO);
                    } catch (CrmebWalletException e) {
                        //支付通道业务获取异常
                        return "RECV_ORD_ID_" + reqSeqId;
                    }
//                    huifuReconcileService.syncUpdateSumFrozenAmount(jsPayTrade.getInUniId(),"04".equals(jsPayTrade.getTradeType())?(new BigDecimal(lockAmount)):"05".equals(jsPayTrade.getTradeType())?(new BigDecimal("-"+lockAmount)):BigDecimal.ZERO);
                }
                Boolean execute = transactionTemplate.execute(e -> {
                    String lTime = dataObj.getString("trans_date") + dataObj.getString("trans_time");
                    Date date;
                    try {
                        date = new SimpleDateFormat("yyyyMMddHHmmss").parse(lTime);
                    } catch (ParseException ex) {
                        throw new RuntimeException(ex);
                    }
                    jsPayTrade.setTransFinishTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
                    jsPayTrade.setErrorMsg(dataObj.getString("bank_message")+";"+dataObj.getString("resp_desc"));
                    jsPayTrade.setTradeStatus(tradeStatus);
                    jsPayTrade.setUpdateTime(new Date());
                    /*** 更新企业钱包账户交易记录 ***/
                    jsPayTradeDao.updateJsPayTrade(jsPayTrade);
                    logger.info("C端支付，异步回调开始，succ2={},errorMsg={}", reqSeqId, jsPayTrade.getErrorMsg());
                    return Boolean.TRUE;
                });
                if (!execute) {
                    logger.error("C端支付，异步回调入库失败，request={}", response.get("resp_data").toString());
                    return "";
                }
                return "RECV_ORD_ID_" + reqSeqId;
            }else{
                return "";
            }
        } catch (InterruptedException e) {
            logger.error("huifuJspayCallback error", e);
            return "";
        }finally {
            if (lock.isHeldByCurrentThread()) {
                logger.debug(lockId+":unLock: " + Thread.currentThread().getId());
                lock.unlock();
            }
        }
    }

    /**
     * <b> C端二级分账业务处理 </b>
     * @author ZXF
     * @create 2024/03/21 0021 15:59
     * @version
     * @注意事项 </b>
     */
    private void transferToPlatBody(JsPayTrade jsPayTrade,BcxPlatformFee platFee){
        logger.info(">>>>>>>>> C端二级分账业务处理transferToPlatBody：业务开始");
        Order order = orderService.getByOrderNo(jsPayTrade.getBusinessPartnerSeq());
        Integer merId = order.getMerId();
        Merchant merchant = merchantService.getByIdException(merId);
        List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(order.getOrderNo());
        List<Integer> productIds = orderDetails.stream().map(OrderDetail::getProductId).collect(Collectors.toList());
        Integer bizType = orderService.getBizTypeByProductsType(productIds);// 0-实物 1-虚拟 2-特殊(考培)
        OrderDetail orderDetail = orderDetails.get(0);
        String productDesc = orderDetail.getProductName() + "(" + orderDetail.getSku() + ") * " + orderDetail.getPayNum();
        HuifuWalletTransferDto dto = new HuifuWalletTransferDto();
        dto.setAmount(order.getPayPrice().toPlainString())//订单金额
                .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),3-保险, 4-风评
                .setBusinessPartnerSeq(order.getOrderNo())//业务交易流水号
                .setComment(productDesc)
                .setGoodsName(orderDetail.getProductName()).setGoodsUnit(orderDetail.getSku()).setGoodsNumber(String.valueOf(orderDetail.getPayNum()))
                .setInId(merchant.getIdentityNo())
                .setSellFeePriority(platFee.getTransPriority())
                .setNeedActiveCode("0")//是否需要验证码
                .setOutId(jsPayTrade.getUniId())
                .setPlatAmount(platFee.getPlatFee() != null ? platFee.getPlatFee().toPlainString() : "0")
        ;
        HuifuWalletAccountDto platAccount;//入账方 平台
        if(platFee.getTransPriority()==0){
            // 买方 -> 平台 -> 商家
            // 订单100-平台10=分商家90
            dto.setPlatAmount((new BigDecimal(dto.getAmount())).subtract(new BigDecimal(dto.getPlatAmount())).toString());
            platAccount = huifuWalletAccountDao.getHuifuWalletAccountByUniId(dto.getInId(),PaymentChannel.HUIFU.toString());
        }else{
            // 买方 -> 商家 -> 平台
            platAccount = huifuWalletAccountDao.getHuifuWalletAccountByWalletNo(HFProfileConstants.HUIFU_ID);
        }
        //平台分账业务
        if(Double.parseDouble(dto.getPlatAmount())>0){
            HuifuWalletTransferDto dtoP = new HuifuWalletTransferDto();
            BeanUtils.copyProperties(dto,dtoP);
            dtoP.setAmount(dto.getPlatAmount());
            dtoP.setOutId(jsPayTrade.getInUniId());
            dtoP.setInId(platAccount.getUniId());
            String comment = platFee.getTransPriority()==0?"订单【"+dtoP.getBusinessPartnerSeq()+"】支付商品费："+dto.getPlatAmount()+"元":"订单【"+dtoP.getBusinessPartnerSeq()+"】支付平台服务费："+dto.getPlatAmount()+"元";
            dtoP.setComment(comment);
            dtoP.setBusinessPartnerSeq(dtoP.getBusinessPartnerSeq()+"-P"+platFee.getTransPriority());
            dtoP.setTradeType(jsPayTrade.getTradeType());
            logger.info(">>>>>>>>> C端二级分账业务处理transferToPlatBody：请求报文："+JSON.toJSONString(dtoP));
            //异步 二级分账业务
            try {
                HuifuWalletService service = paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService());
                service.syncTransferToPlat(dtoP);
            } catch (CrmebWalletException e) {
                throw new RuntimeException(e);
            }
            logger.info(">>>>>>>>> C端二级分账业务处理transferToPlatBody：任务创建成功");
        }
        logger.info(">>>>>>>>> C端二级分账业务处理transferToPlatBody：无分账业务需求，业务结束");
    }

    /**
     * <b> C端聚合正扫回调 </b>
     *
     * @author ZXF
     * @create 2023/08/25 0025 16:13
     * @version
     * @注意事项 </b>
     */
    @Override
    public String huifuJspayRefundCallback(String messageBody) {

        Map<String, Object> response = pathToJson(messageBody);
        logger.info("C端退款，异步回调开始，参数，response={}", response.toString());
        transactionLogService.save("huifuJspayRefundCallback", Constants.Y, response.toString(), "ok",PaymentChannel.HUIFU.toString());
        if (!HFConstants.REQUEST_SUCC_CODE.equals(response.get("resp_code").toString())) {
            return "ok";
        }
        // 验签请参sign
        String sign = response.get("sign").toString();
        // 使用汇付公钥验签
        if (!RsaUtils.verify(response.get("resp_data").toString(), HFProfileCPayConstants.RSA_PUBLIC_KEY, sign)) {
            logger.info("C端退款，异步回调开始，fail=验签失败");
            // 验签失败处理
            return "";
        }
        JSONObject dataObj = JSON.parseObject(response.get("resp_data").toString());
        String subRespCode = dataObj.getString("sub_resp_code");
        String reqSeqId = dataObj.getString("req_seq_id");
        String bankMessage = dataObj.getString("bank_message");
        String tradeStatus = Constants.tradeStatus(dataObj.get("trans_stat").toString());
        String lockId = TRANSFERKEY+reqSeqId;
        RLock lock = redisson.getLock(lockId);
        try {
            if(lock.tryLock(3,10, TimeUnit.SECONDS)){
                logger.debug(lockId+":getLock: " + Thread.currentThread().getId());
                JsPayTrade jsPayTrade = jsPayTradeDao.getJsPayTradeByHfSeqId(dataObj.get("hf_seq_id").toString());
                if ((!"00000000".equals(subRespCode) || Constants.TRADESTATUS_JYSB.equals(tradeStatus)) && jsPayTrade == null) {
                    logger.info("C端支付，异步回调开始，fail="+bankMessage);
                    // 交易失败处理
                    return "ok";
                }
                // 支付成功记录已存在
                if (Constants.TRADESTATUS_JYCG.equals(jsPayTrade.getTradeStatus())) {
                    logger.info("C端退款，异步回调开始，succ1={}", reqSeqId);
                    return "RECV_ORD_ID_" + reqSeqId;
                }
                Boolean execute = transactionTemplate.execute(e -> {
                    String lTime = dataObj.getString("trans_finish_time");
                    Date date;
                    try {
                        date = new SimpleDateFormat("yyyyMMddHHmmss").parse(lTime);
                    } catch (ParseException ex) {
                        throw new RuntimeException(ex);
                    }
                    jsPayTrade.setTransFinishTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date));
                    jsPayTrade.setErrorMsg(dataObj.getString("resp_desc"));
                    jsPayTrade.setTradeStatus(tradeStatus);
                    jsPayTrade.setUpdateTime(new Date());
                    /*** 更新企业钱包账户交易记录 ***/
                    jsPayTradeDao.updateJsPayTrade(jsPayTrade);
                    logger.info("C端退款，异步回调开始，succ2={},errorMsg={}", reqSeqId, jsPayTrade.getErrorMsg());
                    return Boolean.TRUE;
                });
                if (!execute) {
                    logger.error("C端退款，异步回调入库失败，request={}", response.get("resp_data").toString());
                    return "";
                }
                return "RECV_ORD_ID_" + reqSeqId;
            }else{
                return "";
            }
        } catch (InterruptedException e) {
            logger.error("huifuJspayRefundCallback error", e);
            return "";
        }finally {
            if (lock.isHeldByCurrentThread()) {
                logger.debug(lockId+":unLock: " + Thread.currentThread().getId());
                lock.unlock();
            }
        }
    }

    private Map<String, Object> pathToJson(String urlData) {
        String data = null;
        try {
            data = URLDecoder.decode(urlData, "UTF-8");
        } catch (Exception e) {
            logger.error("解码失败：{}", e);
        }
        Map<String, Object> collect = Arrays.stream(data.split("&"))
                .map(str -> str.split("="))
                .collect(Collectors.toMap(x -> x[0], x -> x.length == 2 ? x[1] : "",
                        (u, v) -> {
                            throw new IllegalStateException(String.format("Duplicate key %s", u));
                        }, LinkedHashMap::new));
        return collect;
    }

    @Override
    public String getMerchantIdentifyNoByOrderNo(String orderNo) {
        Order order = orderService.getByOrderNo(orderNo);
        if (order == null || order.getMerId() == null) {
            throw new CrmebException("没有该订单：" + orderNo);
        }
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        if (merchant == null || merchant.getIdentityNo() == null) {
            throw new CrmebException("没有该商户或商户未开通汇付支付：" + order.getMerId());
        }
        return merchant.getIdentityNo();
    }

    @Override
    public void allOrder(String orderNo){
        List<Order> list = Lists.newArrayList();
        if(StrUtil.isNotBlank(orderNo)){
            Order order = orderService.getByOrderNo(orderNo);
            list.add(order);
            System.out.println(">>>>>>>>> 100000 单个订单:"+order.getOrderNo()+",amount:"+order.getPayPrice()
                    //+",pAmount:"+order.getPlatFee()
                    +",orders:"+order.getPayChannel());
        }else{
            list = orderService.testAllOrderNo();
            System.out.println(">>>>>>>>> 100000 合并订单:"+list.size()+"个");
        }
        Map<String,Order> map = Maps.newHashMap();
        for (Order order:list) {
            String key = order.getUid()+"ORDER"+order.getMerId()+"DATE"+DateUtil.format(order.getPayTime(),"yyyyMMdd");
            Order o = map.get(key);
            if(o != null){
                o.setPayPrice(o.getPayPrice().add(order.getPayPrice()));
                //o.setPlatFee(o.getPlatFee().add(order.getPlatFee()));
                o.setPayChannel(o.getPayChannel()+","+order.getOrderNo());
            }else{
                o = order;
                o.setPayChannel(o.getOrderNo());
            }
            map.put(key,o);
        }
        for(Map.Entry<String, Order> entry:map.entrySet()){
            Order order = entry.getValue();
            System.out.println(">>>>>>>>> 000000 合并订单:"+order.getOrderNo()+",amount:"+order.getPayPrice()
                    //+",pAmount:"+order.getPlatFee()
                    +",orders:"+order.getPayChannel());
            if(order.getPayPrice().compareTo(BigDecimal.ZERO)<=0
                    //||order.getPlatFee()==null
            ){
                continue;
            }
            paymentUtil(order);
        }

    }

    private Boolean paymentUtil(Order order) {
        User user = userService.getById(order.getUid());
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        String[] orders = order.getPayChannel().split(",");
        List<OrderDetail> orderDetails = Lists.newArrayList();
        for (String orderNo:orders) {
            orderDetails.addAll(orderDetailService.getByOrderNo(orderNo));
        }
        return walletFreezeAndPayTest(order, orderDetails, order.getBizType(), user, merchant);
    }

    private static Map<String,String> smap = Maps.newHashMap();

    /**
     * 企业钱包支付
     *
     * @param order 订单  bizType 0-实体, 1-虚拟, 2-特殊(考培), 3-保险
     * @return Boolean Boolean
     */
    private Boolean walletFreezeAndPayTest(Order order, List<OrderDetail> orderDetails, Integer bizType, User user, Merchant merchant) {
        if (orderDetails.isEmpty()) {
            throw new CrmebException("订单明细为空,无法支付,请联系管理页");
        }
        String productDesc = orderDetails.stream().map(d -> d.getProductName() + "(" + d.getSku() + ") * " + d.getPayNum()).collect(Collectors.joining(";"));

        if (order.getPayPrice().compareTo(BigDecimal.ZERO) > 0) {
            HuifuWalletTransferDto transferDto = new HuifuWalletTransferDto();
            String isPlatAcct = "0";
            if (order.getPlatFee() != null && order.getPlatFee().compareTo(BigDecimal.ZERO) > 0) {
                isPlatAcct = "1";
            }
            transferDto.setAmount(order.getPayPrice().toPlainString())//订单金额
                    .setBusinessCode(bizType.toString())//虚拟,实物,特殊(考培),3-保险
                    .setBusinessPartnerSeq(order.getOrderNo()+"B")//业务交易流水号
                    .setComment(productDesc)
                    .setGoodsName(orderDetails.get(0).getProductName()).setGoodsUnit(orderDetails.get(0).getSku()).setGoodsNumber(String.valueOf(orderDetails.get(0).getPayNum()))
                    .setInId(merchant.getIdentityNo())
                    //TODO 根据不同分账对象实现转账业务保留参考
                    .setSellFeePriority(1)
//                    .setIsPlatAcct(isPlatAcct)
                    .setNeedActiveCode("0")//是否需要验证码
                    .setOutId(user.getIdentityNo())
                    .setPlatAmount(order.getPlatFee().toPlainString())
            ;
            try {
                System.out.println(">>>>>>>>> order:"+transferDto.getBusinessPartnerSeq()+",amount:"+transferDto.getAmount()+",pAmount:"+transferDto.getPlatAmount());
                if (bizType.equals(1)) {// 虚拟商品直接转账

                } else {// 实体 或 特殊(考培) 先冻结  报名缴费 直接转账并冻结
                    transferDto.setTradeType("04");//04-转账并冻结。 05-解冻并转账（退款）
                    paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).huifuWalletAccountTransfer(transferDto);
                    String sign = smap.get(transferDto.getBusinessPartnerSeq());
                    if(StringUtils.isEmpty(sign)){
                        System.out.println(">>>>>>>>> 000000 order:"+transferDto.getBusinessPartnerSeq()+",amount:"+transferDto.getAmount()+",pAmount:"+transferDto.getPlatAmount());
                        paymentFactory.getPaymentChannel(PaymentChannel.getByName(systemConfigService.getValueByKey(SysConfigConstants.CONFIG_PAY_CHANNEL)).getService()).testLock(transferDto.getOutId(),"05",transferDto.getAmount());
                        smap.put(transferDto.getBusinessPartnerSeq(),"1");
                    }
                }
            } catch (Exception exception) {
                logger.error(exception.getMessage());
                logger.error("企业钱包支付，冻结失败，orderNo = {}", order.getOrderNo());
                return false;
            }
        } else {
            logger.info("订单金额小等于0，众邦商城不走支付流程，直接成功");
        }
        return true;
    }

    @Override
    public boolean payOffline(BcxMerchantPayOfflineRequest request) {
        SystemAdmin admin = SecurityUtil.getLoginUserVo().getUser();
        Order order = orderService.getByOrderNo(request.getOrderNo());
        Integer uid = order.getUid();
        User user = userService.getById(uid);
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        if (order == null || !order.getMerId().equals(admin.getMerId())){
            throw new CrmebException("无权限");
        }
        BcxPayOffline offline = bcxPayOfflineService.queryByOrderNo(request.getOrderNo());
        if (offline == null){
            throw new CrmebException("用户未确认线下支付");
        }

        Boolean execute = transactionTemplate.execute(e -> {
            // 订单修改
            order.setPayType(PAY_TYPE_OFFLINE);
            order.setPaid(true);
            order.setStatus(OrderConstants.ORDER_STATUS_WAIT_SHIPPING);
            orderService.updateById(order);
            offline.setMerMsg(request.getMerMsg());
            offline.setStatus(2);
            bcxPayOfflineService.updateById(offline);
            if (CollUtil.isNotEmpty(request.getFileList())){
                List<BcxPayOfflineFile> files = request.getFileList().stream().map(file ->
                        new BcxPayOfflineFile().setOrderNo(request.getOrderNo()).setFileUrl(file.getFileUrl())
                                .setFileName(file.getFileName()).setPayOfflineId(offline.getId())).collect(Collectors.toList());
                bcxPayOfflineFileService.saveBatch(files);
            }
            List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(order.getOrderNo());
            List<Integer> productIds = orderDetails.stream().map(OrderDetail::getProductId).collect(Collectors.toList());
            Integer bizType = orderService.getBizTypeByProductsType(productIds);// 0-实物 1-虚拟 2-特殊(考培)
            if(order.getBizType().equals(ProductConstants.BIZ_TYPE_RISK)) {//风评订单
                syncReportOrder2RiskSystem(order, orderDetails.get(0));
                return true;
            }else{
                return walletFreezeAndPay(order, orderDetails.get(0), bizType, user, merchant);
            }
        });
        if (!execute) {
            throw new CrmebException("线下支付提交失败");
        }
        //拆单
        asyncService.orderPaySuccessSplit(order.getOrderNo());
        return true;
    }


    /**
     * description：确认到款
     * author：linchunpeng
     * date：2025/8/12
     */
    @Override
    public boolean payOfflineReceived(BcxMerchantPayOfflineRequest request) {
        SystemAdmin admin = SecurityUtil.getLoginUserVo().getUser();
        Order order = orderService.getByOrderNo(request.getOrderNo());
        Integer uid = order.getUid();
        User user = userService.getById(uid);
        Merchant merchant = merchantService.getByIdException(order.getMerId());
        if (!order.getMerId().equals(admin.getMerId())){
            throw new CrmebException("无权限");
        }
        BcxPayOffline offline = bcxPayOfflineService.queryByOrderNo(request.getOrderNo());
        if (offline == null){
            throw new CrmebException("用户未确认线下支付");
        }
        if (offline.getStatus() != 2){
            throw new CrmebException("商户未确认线下支付");
        }

        Boolean execute = transactionTemplate.execute(e -> {
            //修改为确认到款
            offline.setMerMsg(request.getMerMsg());
            offline.setStatus(3);
            bcxPayOfflineService.updateById(offline);

            if (CollUtil.isNotEmpty(request.getFileList())){
                List<BcxPayOfflineFile> files = request.getFileList().stream().map(file ->
                        new BcxPayOfflineFile().setOrderNo(request.getOrderNo()).setFileUrl(file.getFileUrl())
                                .setFileName(file.getFileName()).setPayOfflineId(offline.getId())).collect(Collectors.toList());
                bcxPayOfflineFileService.saveBatch(files);
            }

            List<OrderDetail> orderDetails = orderDetailService.getByOrderNo(order.getOrderNo());
            List<Integer> productIds = orderDetails.stream().map(OrderDetail::getProductId).collect(Collectors.toList());
            Integer bizType = orderService.getBizTypeByProductsType(productIds);// 0-实物 1-虚拟 2-特殊(考培)
            return walletFreezeAndPay(order, orderDetails.get(0), bizType, user, merchant);
        });
        if (!execute) {
            throw new CrmebException("确认到款提交失败");
        }
        return true;
    }
}

