package com.fs.store.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.api.param.OrderListParam;
import com.fs.api.vo.OrderListVO;
import com.fs.api.vo.ProductListVO;
import com.fs.common.config.FSSysConfig;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.event.TemplateBean;
import com.fs.common.event.TemplateEvent;
import com.fs.common.event.TemplateListenEnum;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.*;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyDept;
import com.fs.company.domain.CompanyMoneyLogs;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyMoneyLogsMapper;
import com.fs.company.service.ICompanyDeptService;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.erp.domain.*;
import com.fs.erp.dto.*;
import com.fs.erp.service.IErpOrderService;
import com.fs.erp.utils.ErpContextHolder;
import com.fs.express.FsStoreDeliversService;
import com.fs.express.cache.FsStoreDeliversCacheService;
import com.fs.huifuPay.domain.HuiFuCreateOrder;
import com.fs.huifuPay.domain.HuiFuRefundResult;
import com.fs.huifuPay.domain.HuifuCreateOrderResult;
import com.fs.huifuPay.dto.*;
import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
import com.fs.huifuPay.service.HuiFuService;
import com.fs.pay.pay.domain.CreateWxOrderResult;
import com.fs.pay.pay.domain.RefundResult;
import com.fs.pay.pay.dto.OrderQueryDTO;
import com.fs.pay.pay.dto.RefundDTO;
import com.fs.pay.pay.dto.WxJspayDTO;
import com.fs.pay.pay.service.PayService;
import com.fs.pay.pay.util.PayUtil;
import com.fs.store.cache.IFsUserCacheService;
import com.fs.store.cache.impl.IFsStoreProductCacheServiceImpl;
import com.fs.store.config.StoreConfig;
import com.fs.store.config.StoreIntegralConfig;
import com.fs.store.constants.StoreConstants;
import com.fs.store.domain.*;
import com.fs.store.dto.*;
import com.fs.store.enums.*;
import com.fs.store.mapper.*;
import com.fs.store.param.*;
import com.fs.store.service.*;
import com.fs.store.service.channel.PaymentHandler;
import com.fs.store.service.channel.PaymentHandlerHolder;
import com.fs.store.service.channel.param.PayProcessContext;
import com.fs.store.strategy.ShippingOrder;
import com.fs.store.strategy.ShippingTemplateManager;
import com.fs.store.vo.*;
import com.fs.system.service.ISysConfigService;
import com.fs.tzBank.TzBankService;
import com.fs.tzBank.utils.TzConfigUtils;
import com.fs.wx.domain.FsWxExpressTask;
import com.fs.wx.dto.*;
import com.fs.wx.mapper.FsWxExpressTaskMapper;
import com.fs.wx.miniapp.config.WxMaConfiguration;
import com.fs.wx.miniapp.config.WxMaProperties;
import com.fs.wx.service.OrderQueryService;
import com.fs.wx.service.ShippingService;
import lombok.Synchronized;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.http.util.Asserts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import static com.fs.store.constants.StoreConstants.DELIVERY;

/**
 * 订单Service业务层处理
 *
 * @author fs
 * @date 2022-03-15
 */
@Service
@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)
public class FsStoreOrderServiceImpl implements IFsStoreOrderService
{

    Logger logger= LoggerFactory.getLogger(getClass());
    @Autowired
    private CompanyMoneyLogsMapper moneyLogsMapper;
    @Autowired
    private IFsStoreOrderStatusService orderStatusService;
    @Autowired
    private FsStoreCartMapper cartMapper;

    @Autowired
    private FsUserAddressMapper userAddressMapper;

    @Autowired
    private FsStoreOrderMapper fsStoreOrderMapper;

    @Autowired
    private IFsStoreProductService productService;

    @Autowired
    private IFsUserService userService;

    @Autowired
    private IFsUserCacheService fsUserCacheService;

    @Autowired
    private IFsUserBillService billService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IFsStoreCartService cartService;

    @Autowired
    private ApplicationEventPublisher publisher;

    @Autowired
    private IFsShippingTemplatesService shippingTemplatesService;

    @Autowired
    private IFsShippingTemplatesRegionService shippingTemplatesRegionService;

    @Autowired
    private IFsExpressService expressService;

    @Autowired
    private FSSysConfig sysConfig;
    @Autowired
    private IErpOrderService erpOrderService;
    @Autowired
    private IFsStorePaymentService paymentService;

    @Autowired
    private IFsStoreProductPackageService productPackageService;

    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private IFsStoreProductAttrValueService attrValueService;
    @Autowired
    private IFsStoreProductService storeProductService;

    @Autowired
    private IFsStoreCouponUserService couponUserService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private IFsStoreOrderItemService storeOrderItemService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IFsStoreProductGroupService storeProductGroupService;

    @Autowired
    private FsStoreOrderItemMapper fsStoreOrderItemMapper;
    @Autowired
    private ICompanyDeptService companyDeptService;
    @Autowired
    private IFsPrescribeService prescribeService;

    @Autowired
    private PayService ybPayService;
    @Autowired
    private HuiFuService huiFuService;

    @Autowired
    private TzBankService tzBankService;

    @Autowired
    private IFsCouponScheduleService fsCouponScheduleService;

    @Autowired
    private FsStoreDeliversMapper fsStoreDeliversMapper;

    @Autowired
    private IFsStoreOrderService orderService;

    @Autowired
    private FsStoreDeliversService fsStoreDeliversService;

    @Autowired
    private IFsStoreProductPackageService fsStoreProductPackageService;
    @Autowired
    private IFsStoreProductCacheServiceImpl fsStoreProductCacheService;
    @Autowired
    private FsStorePaymentMapper fsStorePaymentMapper;

    @Autowired
    private WxMaProperties properties;

    @Autowired
    private IFsStoreOrderItemService itemService;

    @Value("${fsConfig.omsCode}")
    private String deliverOmsCode;

    @Autowired
    private IFsShippingTemplatesService fsShippingTemplatesService;

    @Autowired
    private ShippingTemplateManager shippingTemplateManager;

    @Autowired
    private IFsStoreProductAttrValueService fsStoreProductAttrValueService;

    @Autowired
    private IFsStorePaymentService fsStorePaymentService;

    @Autowired
    private FsStoreDeliversCacheService fsStoreDeliversCacheService;

    @Autowired
    private FsWxExpressTaskMapper fsWxExpressTaskMapper;

    @Autowired
    private ShippingService shippingService;

    @Autowired
    private OrderQueryService orderQueryService;

    @Autowired
    private FsWarehousesMapper fsWarehousesMapper;


    @Override
    public void syncExpressToWx() {
        List<FsWxExpressTask> fsWxExpressTasks = fsWxExpressTaskMapper.selectPendingData();
        if (CollectionUtils.isEmpty(fsWxExpressTasks)) {
            logger.info("当前没有待同步的数据！已取消");
            return;
        }

        for (FsWxExpressTask fsWxExpressTask : fsWxExpressTasks) {

            UploadShippingInfoRequest request = new UploadShippingInfoRequest();

            OrderKey orderKey = new OrderKey();
            orderKey.setOrderNumberType(2);



            FsUser fsUser = fsUserCacheService.selectFsUserById(fsWxExpressTask.getUserId());
            FsStoreOrder fsStoreOrder = fsStoreOrderMapper.selectFsStoreOrderByOrderCode(fsWxExpressTask.getOrderCode());


            if(ObjectUtil.isNotNull(fsStoreOrder)){
                List<FsStorePayment> fsStorePayments = paymentService.selectFsStorePaymentByOrder(fsStoreOrder.getId());


                if(CollectionUtils.isNotEmpty(fsStorePayments)){
                    FsStorePayment fsStorePayment = fsStorePayments.get(0);
                    orderKey.setTransactionId(fsStorePayment.getBankTransactionId());
                }
            }

            String userPhone = "";
            String orderGoodsInfo = "商品";
            if(fsStoreOrder != null){
                userPhone = fsStoreOrder.getUserPhone();
                orderGoodsInfo = getOrderGoodsInfo(fsStoreOrder);
            }

            Payer payer = new Payer();
            if(StringUtils.isNotBlank(fsUser.getMaOpenId())){
                payer.setOpenid(fsUser.getMaOpenId());
            }
            request.setPayer(payer);
            request.setOrderKey(orderKey);

            request.setLogisticsType(1);
            request.setDeliveryMode(1);

            request.setShippingList(Collections.singletonList(ShippingItem.builder()
                    .itemDesc(orderGoodsInfo)
                            .expressCompany(fsWxExpressTask.getExpressCompany())
                            .trackingNo(fsWxExpressTask.getExpressNo())
                            .contact(Contact.builder().consignorContact(userPhone).build())
                    .build()));

            OffsetDateTime now = OffsetDateTime.now();
            DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
            String formattedTimestamp = now.format(formatter);
            request.setUploadTime(formattedTimestamp);


            WeChatApiResponse response = shippingService.uploadShippingInfo(request);
            if(ObjectUtil.equal(response.getErrcode(),0)){
                fsWxExpressTask.setStatus(2);
            } else {
                fsWxExpressTask.setRetryCount(fsWxExpressTask.getRetryCount() +1);
                fsWxExpressTask.setStatus(3);
                fsWxExpressTask.setData(JSON.toJSONString(request));
                fsWxExpressTask.setRequestBody(JSON.toJSONString(request));
                fsWxExpressTask.setResponseBody(JSON.toJSONString(response));
            }
        }
        fsWxExpressTaskMapper.batchUpdate(fsWxExpressTasks);

    }

    /**
     * 获取订单商品信息
     * @return
     */
    private String getOrderGoodsInfo(FsStoreOrder order){
        StringBuilder title = new StringBuilder();
        // 如果是套餐
        if(ObjectUtil.equal(order.getIsPackage(),1)){
            String packageJson = order.getPackageJson();
            JSONObject jsonObject = JSON.parseObject(packageJson);
            title = new StringBuilder(jsonObject.getString("title"));
        } else {
            String itemJson = order.getItemJson();
            com.alibaba.fastjson.JSONArray arrays = JSON.parseArray(itemJson);
            for(int i=0;i<arrays.size();i++){
                JSONObject jsonObject = arrays.getJSONObject(i);
                String jsonInfo = jsonObject.getString("jsonInfo");
                JSONObject jsonObject1 = JSON.parseObject(jsonInfo);
                String productName = jsonObject1.getString("productName");
                title.append(productName).append("\n");
            }
        }
        return title.toString();
    }

    /**
     * 查询订单
     *
     * @param id 订单ID
     * @return 订单
     */
    @Override
    public FsStoreOrder selectFsStoreOrderById(Long id)
    {
        return fsStoreOrderMapper.selectFsStoreOrderById(id);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
    public R pay(FsStoreOrderPayParam param) {
        FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
        if(order==null){
            return R.error("订单不存在");
        }
        if(!Objects.equals(order.getStatus(), OrderInfoEnum.STATUS_0.getValue())){
            return R.error("订单状态不正确");
        }
        R payTypeError = validatePayTypeNotModified(order, param.getPayType());
        if (payTypeError != null) {
            return payTypeError;
        }
        String orderId=redisCache.getCacheObject("isPaying:"+order.getId());
        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
            return R.error("正在支付中...");
        }

        FsUser user=userService.selectFsUserById(order.getUserId());
        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
            //已改价处理
            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
                //改过价不做处理
            }
            else{
                String config=configService.selectConfigByKey("store.config");
                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
                if(order.getPayType().equals("1")){
                    order.setPayMoney(order.getPayPrice());
                    order.setPayDelivery(BigDecimal.ZERO);
                }
                else if(order.getPayType().equals("2")){
                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
                    order.setPayMoney(payMoney);
                }
                else if(order.getPayType().equals("3")){
                    order.setPayDelivery(order.getPayPrice());
                    order.setPayMoney(BigDecimal.ZERO);
                }
                orderService.updateFsStoreOrder(order);
            }
            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();

            if(order.getPayType().equals("1")||order.getPayType().equals("2")){
                String json = configService.selectConfigByKey("store.pay");
                FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
                List<FsStorePayment> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderIdNew(order.getId());
                FsStorePayment storePayment;
                if(CollectionUtils.isEmpty(fsStorePayments)){
                    storePayment=new FsStorePayment();
                    storePayment.setCompanyId(order.getCompanyId());
                    storePayment.setCompanyUserId(order.getCompanyUserId());
                    storePayment.setPayMode(fsPayConfig.getType());
                    storePayment.setStatus(0);
                    storePayment.setPayCode(payCode);
                    storePayment.setPayMoney(order.getPayMoney());
                    storePayment.setCreateTime(new Date());
                    storePayment.setPayTypeCode("weixin");
                    storePayment.setBusinessType(2);
                    storePayment.setRemark("商城订单支付");
                    storePayment.setOpenId(user.getRealName());
                    storePayment.setUserId(user.getUserId());
                    storePayment.setBusinessOrderId(order.getId().toString());
                    storePayment.setOrderId(order.getId());
                    fsStorePaymentMapper.insertFsStorePayment(storePayment);
                } else {
                    storePayment = fsStorePayments.get(0);
                    storePayment.setPayMode(fsPayConfig.getType());
                    storePayment.setStatus(0);
                    storePayment.setPayMoney(order.getPayMoney());
                    storePayment.setCreateTime(new Date());
                    storePayment.setPayTypeCode("weixin");
                    storePayment.setBusinessType(2);
                    storePayment.setRemark("商城订单支付");
                    storePayment.setOpenId(user.getRealName());
                    storePayment.setUserId(user.getUserId());
                    storePayment.setBusinessOrderId(order.getId().toString());
                    storePayment.setOrderId(order.getId());
                }

                PayProcessContext processContext = new PayProcessContext();
                processContext.setOrderId(param.getOrderId());
                processContext.setPayType(Integer.valueOf(order.getPayType()));
                processContext.setPaymentId(storePayment.getPaymentId());
                processContext.setPayCode(storePayment.getPayCode());
                processContext.setFsPayConfig(fsPayConfig);
                processContext.setUserId(order.getUserId());
                processContext.setGoodsInfo("商城订单支付");
                processContext.setOrderPrefix("store-");
                PaymentHandler payment = PaymentHandlerHolder.findBest(fsPayConfig.getType());
                if(ObjectUtil.isNull(payment)){
                    throw new CustomException("支付方式不存在");
                }
                R process = payment.createOrder(processContext);
                if("200".equals(String.valueOf(process.get("code")))){
                    redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                    return process;
                }
            }
            else if(order.getPayType().equals("3")){
                orderService.payConfirm(2,order.getId(),null,null,null,null);
                return R.ok().put("payType",Integer.valueOf(order.getPayType()));
            }
            return R.error();
        }
        else{
            return R.error("用户OPENID不存在");
        }
    }

    /**
     * 查询订单列表
     *
     * @param fsStoreOrder 订单
     * @return 订单
     */
    @Override
    public List<FsStoreOrder> selectFsStoreOrderList(FsStoreOrder fsStoreOrder)
    {
        return fsStoreOrderMapper.selectFsStoreOrderList(fsStoreOrder);
    }

    /**
     * 新增订单
     *
     * @param fsStoreOrder 订单
     * @return 结果
     */
    @Override
    public int insertFsStoreOrder(FsStoreOrder fsStoreOrder)
    {
        fsStoreOrder.setCreateTime(DateUtils.getNowDate());
        return fsStoreOrderMapper.insertFsStoreOrder(fsStoreOrder);
    }

    /**
     * 修改订单
     *
     * @param fsStoreOrder 订单
     * @return 结果
     */
    @Override
    public int updateFsStoreOrder(FsStoreOrder fsStoreOrder)
    {
        fsStoreOrder.setUpdateTime(DateUtils.getNowDate());
        return fsStoreOrderMapper.updateFsStoreOrder(fsStoreOrder);
    }

    /**
     * 批量删除订单
     *
     * @param ids 需要删除的订单ID
     * @return 结果
     */
    @Override
    public int deleteFsStoreOrderByIds(Long[] ids)
    {
        return fsStoreOrderMapper.deleteFsStoreOrderByIds(ids);
    }

    /**
     * 删除订单信息
     *
     * @param id 订单ID
     * @return 结果
     */
    @Override
    public int deleteFsStoreOrderById(Long id)
    {
        return fsStoreOrderMapper.deleteFsStoreOrderById(id);
    }

    @Override
    public List<FsStoreOrderVO> selectFsStoreOrderListVO(FsStoreOrderParam param) {
        List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderListVO(param);
        for(FsStoreOrderVO vo:list){
            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
            vo.setNickname(nickName);
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(items.size()>0){
                    vo.setItems(items);
                }
            }
        }
        return list;
    }

    @Override
    public List<FsStoreOrderVO> selectFsStoreOrderAllListVO(FsStoreOrderParam param) {
        List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsStoreOrderAllListVO(param);
        for(FsStoreOrderVO vo:list){
            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
            vo.setNickname(nickName);
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(items.size()>0){
                    vo.setItems(items);
                }
            }
        }
        return list;
    }

    @Override
    public List<FsStoreOrderVO> selectPayRemainListVO(FsStoreOrderParam param) {
        List<FsStoreOrderVO> list= fsStoreOrderMapper.selectFsPayRemainListVO(param);
        for(FsStoreOrderVO vo:list){
            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
            vo.setNickname(nickName);
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(items.size()>0){
                    vo.setItems(items);
                }
            }

        }
        return list;
    }


    @Override
    public List<FsPromotionOrderVO> selectFsPromotionOrderListVO(FsStoreOrderParam param) {
        List<FsPromotionOrderVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVO(param);
        for(FsPromotionOrderVO vo:list){
            String nickName = vo.getUserPhone().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
            String tuiNickName = vo.getTuiNickName().replaceAll("(\\d{3})\\d*(\\d{4})", "$1****$2");
            vo.setNickname(nickName);
            vo.setTuiNickName(tuiNickName);
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(items.size()>0){
                    vo.setItems(items);
                }
            }

        }
        return list;
    }

    @Override
    public R confirmOrder(long uid, FsStoreConfirmOrderParam cartParam) {
        //获取地址信息和购物车信息
        FsUserAddress address= userAddressMapper.selectFsUserAddressByDefaultAddress(uid);
        List<FsStoreCartQueryVO>  carts=cartMapper.selectFsStoreCartListByIds(cartParam.getCartIds());
        String uuid = IdUtil.randomUUID();
        redisCache.setCacheObject("orderKey:"+uuid, cartParam.getCartIds(), 300, TimeUnit.SECONDS);
        redisCache.setCacheObject("orderCarts:"+uuid, carts, 300, TimeUnit.SECONDS);
        return R.ok().put("orderKey",uuid).put("address",address).put("carts",carts);

    }

    @Override
    public FsStoreOrderComputeDTO computedOrder(long uid, FsStoreOrderComputedParam param) {
        String cartIds = redisCache.getCacheObject("orderKey:" + param.getOrderKey());
        if (ObjectUtil.isNull(cartIds)) {
            throw new CustomException("订单已过期",501);
        }
        List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + param.getOrderKey());
        BigDecimal payPrice=getOrderSumPrice(carts,"truePrice");
        if(StringUtils.isNotEmpty(param.getCreateOrderKey()))
        {
            BigDecimal money=redisCache.getCacheObject("createOrderMoney:"+param.getCreateOrderKey());
            if(money!=null){
                payPrice=money;
            }
        }
        BigDecimal serviceFee=new BigDecimal(0);
        String configJson=configService.selectConfigByKey("store.config");
        StoreConfig config=JSONUtil.toBean(configJson,StoreConfig.class);
        if(config.getServiceFee()!=null){
            if(param.getCompanyUserId()==null||param.getCompanyUserId()==0){
                serviceFee=config.getServiceFee();
            }
        }
        payPrice = payPrice.add(serviceFee);
        FsUserAddress userAddress = null;
        if (param.getAddressId()!=null) {
            userAddress = userAddressMapper.selectFsUserAddressById(param.getAddressId());
        }
        FsStoreOrderPriceDTO priceGroup = this.getOrderPriceGroup(carts, userAddress);
        BigDecimal payPostage = priceGroup.getStorePostage();
        payPrice = NumberUtil.add(payPrice, payPostage);

        FsUser user=userService.selectFsUserById(uid);
        // 积分抵扣
        BigDecimal deductionPrice = BigDecimal.ZERO; //积分抵扣金额
        double usedIntegral = 0; //使用了多少积分
        if (param.getUseIntegral()!=null&&param.getUseIntegral()==1 && user.getIntegral().intValue() > 0) {
            //如果积分总和小于用户积分 抵扣比例 计算抵扣价格
            //默认配置
            Double integralMax = Double.valueOf(100);
            BigDecimal integralFull = new BigDecimal(100);
            Double integralRatio = Double.valueOf(1);
            String json=configService.selectConfigByKey("store.integral");
            if(StringUtils.isEmpty(json)) {

            }
            else{
                StoreIntegralConfig integralConfig=JSONUtil.toBean(json,StoreIntegralConfig.class);
                integralMax = integralConfig.getIntegralMax();
                integralFull = integralConfig.getIntegralFull();
                integralRatio =integralConfig.getIntegralRatio();

            }
            if (priceGroup.getTotalPrice().compareTo(integralFull) >= 0) {
                Double userIntegral = user.getIntegral().doubleValue();
                if (integralMax.intValue() > 0 && Double.compare(userIntegral, integralMax) >= 0) {
                    userIntegral = integralMax;
                }
                deductionPrice = BigDecimal.valueOf(NumberUtil.mul(userIntegral, integralRatio));
                if (deductionPrice.compareTo(payPrice) < 0) {
                    payPrice = NumberUtil.sub(payPrice, deductionPrice);
                    usedIntegral = userIntegral;
                } else {
                    deductionPrice = payPrice;
                    payPrice = BigDecimal.ZERO;
                    usedIntegral = NumberUtil.round(NumberUtil.div(deductionPrice,
                            BigDecimal.valueOf(integralRatio)), 2).doubleValue();
                }
            }
        }

        if (payPrice.compareTo(BigDecimal.ZERO) <= 0) {
            payPrice = BigDecimal.ZERO;
        }
        //优惠券
        if(param.getCouponUserId()!=null){
            FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
            if(couponUser!=null&&couponUser.getStatus()==0){
                if(couponUser.getUseMinPrice().compareTo(priceGroup.getTotalPrice())==-1){
                    payPrice=payPrice.subtract(couponUser.getCouponPrice());
                }
            }
        }
        if(param.getCompanyUserId()!=null){
            payPrice=payPrice.subtract(payPostage);
            payPostage=BigDecimal.ZERO;

        }
        return FsStoreOrderComputeDTO.builder()
                .totalPrice(priceGroup.getTotalPrice())
                .payPrice(payPrice)
                .payPostage(payPostage)
                .deductionPrice(deductionPrice)
                .usedIntegral(usedIntegral)
                .payIntegral(priceGroup.getPayIntegral())
                .serviceFee(serviceFee)
                .build();
    }


    @Override
    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
    public R createOrder(long userId, FsStoreOrderCreateParam param) {
        FsStoreOrderComputedParam computedParam=new FsStoreOrderComputedParam();
        BeanUtils.copyProperties(param, computedParam);
        //计算金额
        FsStoreOrderComputeDTO dto=this.computedOrder(userId, computedParam);
        String cartIds = redisCache.getCacheObject("orderKey:" + param.getOrderKey());
        Integer totalNum = 0;
        BigDecimal integral = BigDecimal.ZERO;
        if(cartIds!=null){
            //获取购物车列表
            List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + param.getOrderKey());
            //获取地址
            FsUserAddress address=userAddressMapper.selectFsUserAddressById(param.getAddressId());
            if (address == null) {
                return R.error("地址不存在");
            }
            if (!Objects.equals(address.getUserId(), userId)) {
                return R.error("非法操作");
            }
            //检测库存
            //三种特定产品发YDSP001
            int ydspHouse = 0;
            for (FsStoreCartQueryVO cart : carts) {
                totalNum += cart.getCartNum();
                integral = NumberUtil.add(integral,
                        NumberUtil.mul(cart.getCartNum(), cart.getIntegral()));

                if(param.getCompanyId()==null){
                    if(StringUtils.isEmpty(cart.getGroupBarCode())){
                        if (cart.getCartNum()>10){
                            return R.error("限购10个");
                        }
                    }else {
                        FsStoreProductGroup group=storeProductGroupService.selectFsStoreProductGroupByBarCode(cart.getGroupBarCode());
                        if(group!=null) {
                            JSONArray jsonArray = JSONUtil.parseArray(group.getProducts());
                            List<StoreProductGroupDTO> productGroupDTOS = JSONUtil.toList(jsonArray, StoreProductGroupDTO.class);
                            int num=0;
                            for (StoreProductGroupDTO productGroupDTO : productGroupDTOS) {
                               num+= productGroupDTO.getCount()*cart.getCartNum();
                            }
                            if (num>10){
                                return R.error("限购10个");
                            }
                        }else {
                            return R.error("组合码错误");
                        }
                     }

                }

                //判断是否是三种特定产品
                if(cart.getProductId()!=null&&(cart.getProductId().equals(3168L)||cart.getProductId().equals(3184L)||cart.getProductId().equals(3185L))){
                    ydspHouse++;
                }
            }
            //生成分布式唯一值
            String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
            //是否使用积分
            Boolean isIntegral=false;
            //组合数据
            FsStoreOrder storeOrder = new FsStoreOrder();

            //修改默认仓库
            if(ydspHouse>0){
                storeOrder.setStoreHouseCode("YDSP001");
            }
            else{
                storeOrder.setStoreHouseCode("CQDS001");
            }
            storeOrder.setCompanyId(param.getCompanyId());
            storeOrder.setCompanyUserId(param.getCompanyUserId());
            if(param.getCompanyUserId()!=null){
                CompanyUser companyUser=companyUserService.selectCompanyUserById(param.getCompanyUserId());
                if(companyUser!=null){
                    storeOrder.setDeptId(companyUser.getDeptId());
                }
            }
            storeOrder.setUserId(userId);
            storeOrder.setOrderCode(orderSn);
            storeOrder.setRealName(address.getRealName());
            storeOrder.setUserPhone(address.getPhone());
            storeOrder.setUserAddress(address.getProvince() + " " + address.getCity() +
                    " " + address.getDistrict() + " " + address.getDetail().trim());
            storeOrder.setCartId(cartIds);
            storeOrder.setTotalNum(Long.parseLong(String.valueOf(carts.size())));
            storeOrder.setTotalPrice(dto.getTotalPrice());
            storeOrder.setTotalPostage(dto.getPayPostage());

            //优惠券处理
            if(param.getCouponUserId()!=null){
                FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
                if(couponUser!=null&&couponUser.getStatus()==0){
                    if (couponUser.getUserId()!=userId){
                        return R.error("非法操作");
                    }
                    storeOrder.setCouponId(couponUser.getId());
                    storeOrder.setCouponPrice(couponUser.getCouponPrice());
                    //更新优惠券状态
                    couponUser.setStatus(1);
                    couponUser.setUseTime(new Date());
                    couponUserService.updateFsStoreCouponUser(couponUser);
                }
            }
            //处理推荐人
            FsUser user= userService.selectFsUserById(storeOrder.getUserId());
            if(user!=null&&user.getSpreadUserId()!=null&&user.getSpreadUserId()>0){
                storeOrder.setTuiUserId(user.getSpreadUserId());
            }
            else{
                if(param.getTuiUserId()!=null){
                    FsUser tuiUser= userService.selectFsUserById(param.getTuiUserId());
                    if(tuiUser!=null&&tuiUser.getIsPromoter()==1){
                        storeOrder.setTuiUserId(param.getTuiUserId());
                    }
                }
            }
            storeOrder.setPayPostage(dto.getPayPostage());

            storeOrder.setDeductionPrice(dto.getDeductionPrice());
            storeOrder.setPaid(0);
            storeOrder.setPayType(param.getPayType());
            if (isIntegral) {
                storeOrder.setPayIntegral(integral);
            }
            storeOrder.setUseIntegral(BigDecimal.valueOf(dto.getUsedIntegral()));
            storeOrder.setBackIntegral(BigDecimal.ZERO);
            storeOrder.setGainIntegral(BigDecimal.ZERO);
            storeOrder.setMark(param.getMark());
            //todo 获取成本价
            BigDecimal costPrice = this.getOrderSumPrice(carts, "costPrice");
            storeOrder.setCost(costPrice);
            storeOrder.setIsChannel(1);
            storeOrder.setShippingType(1);
            storeOrder.setCreateTime(new Date());

            String json=configService.selectConfigByKey("store.config");
            StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
            if (param.getCompanyUserId()==null){
                if(config.getServiceFee()!=null){

                    storeOrder.setServiceFee(config.getServiceFee());
                }
            }



            if(param.getPayType().equals("1")){
                //全款支付
                storeOrder.setStatus(0);
            }
            else if(param.getPayType().equals("2")){
                //货到付款
                storeOrder.setStatus(1);
            }
            //后台制单处理
            if(param.getPayPrice()!=null&&param.getPayPrice().compareTo(BigDecimal.ZERO)>0){
                storeOrder.setPayPrice(param.getPayPrice());
            }
            else{
                storeOrder.setPayPrice(dto.getPayPrice());
                if (param.getCompanyId()!=null){
                    storeOrder.setPayPrice(dto.getPayPrice().subtract(dto.getPayPostage()));
                    storeOrder.setPayPostage(new BigDecimal(0));
                }

            }
            storeOrder.setOrderCreateType(param.getOrderCreateType());
            Long prescribe = carts.stream().filter(item -> item.getProductType()!=null&&item.getProductType()==2).count();
            if(prescribe>0){
                storeOrder.setIsPrescribe(1);
            }
            Integer flag=fsStoreOrderMapper.insertFsStoreOrder(storeOrder);
            if (flag==0) {
                return R.error("订单创建失败");
            }

            //使用了积分扣积分
            if (dto.getUsedIntegral() > 0) {
                this.decIntegral(userId, dto.getUsedIntegral(), dto.getDeductionPrice().doubleValue(),storeOrder.getId().toString());
            }
            //减库存加销量
            this.deStockIncSale(carts);
            //保存OrderItem
            List<FsStoreOrderItem> listOrderItem=new ArrayList<>();
            //保存购物车商品信息
            for(FsStoreCartQueryVO vo:carts){
                FsStoreCartDTO fsStoreCartDTO=new FsStoreCartDTO();
                fsStoreCartDTO.setProductId(vo.getProductId());
                fsStoreCartDTO.setPrice(vo.getPrice());
                fsStoreCartDTO.setSku(vo.getProductAttrName());
                fsStoreCartDTO.setProductName(vo.getProductName());
                fsStoreCartDTO.setNum(vo.getCartNum());
                fsStoreCartDTO.setBarCode(vo.getBarCode());
                fsStoreCartDTO.setGroupBarCode(vo.getGroupBarCode());
                fsStoreCartDTO.setBrokerage(vo.getBrokerage());
                fsStoreCartDTO.setBrokerageTwo(vo.getBrokerageTwo());
                fsStoreCartDTO.setBrokerageThree(vo.getBrokerageThree());
                fsStoreCartDTO.setWarehouseCode(vo.getWarehouseCode());
                fsStoreCartDTO.setWarehouseId(vo.getWarehouseId());

                if(StringUtils.isEmpty(vo.getProductAttrImage())){
                    fsStoreCartDTO.setImage(vo.getProductImage());
                }
                else{
                    fsStoreCartDTO.setImage(vo.getProductAttrImage());
                }

                FsStoreOrderItem item=new FsStoreOrderItem();
                item.setOrderId(storeOrder.getId());
                item.setOrderCode(orderSn);
                item.setCartId(vo.getId());
                item.setProductId(vo.getProductId());
                item.setJsonInfo(JSONUtil.toJsonStr(fsStoreCartDTO));
                item.setNum(vo.getCartNum());
                item.setIsAfterSales(0);
                //处方药
                if(vo.getProductType().equals(2)){
                    item.setIsPrescribe(1);
                }
                fsStoreOrderItemMapper.insertFsStoreOrderItem(item);
                listOrderItem.add(item);
            }
            if(CollectionUtils.isNotEmpty(listOrderItem)){
                String itemJson=JSONUtil.toJsonStr(listOrderItem);
                storeOrder.setItemJson(itemJson);
                fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
            }
            //购物车状态修改
            cartMapper.updateIsPay(cartIds);

            //删除缓存
            redisCache.deleteObject("orderKey:" + param.getOrderKey());
            redisCache.deleteObject("orderCarts:" + param.getOrderKey());

            //添加记录
            orderStatusService.create(storeOrder.getId(), OrderLogEnum.CREATE_ORDER.getValue(),
                    OrderLogEnum.CREATE_ORDER.getDesc());

            //加入redis，24小时自动取消
            String redisKey = String.valueOf(StrUtil.format("{}{}",
                    StoreConstants.REDIS_ORDER_OUTTIME_UNPAY, storeOrder.getId()));

            if(config.getUnPayTime()!=null&&config.getUnPayTime()>0){
                redisCache.setCacheObject(redisKey,storeOrder.getId(),config.getUnPayTime(), TimeUnit.MINUTES);
            }
            else{
                redisCache.setCacheObject(redisKey,storeOrder.getId(),30, TimeUnit.MINUTES);
            }
            //添加支付到期时间
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(storeOrder.getCreateTime());
            calendar.add(Calendar.MINUTE,config.getUnPayTime());
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String payLimitTime = format.format(calendar.getTime() );
            //删除推荐订单KEY
            if(StringUtils.isNotEmpty(param.getCreateOrderKey())){
                redisCache.deleteObject("createOrderKey:"+param.getCreateOrderKey());
                redisCache.deleteObject("orderCarts:" +param.getCreateOrderKey());
                redisCache.deleteObject("createOrderMoney:" +param.getCreateOrderKey());
            }
            return R.ok().put("order", storeOrder).put("payLimitTime",payLimitTime);
        }
        else{
            return R.error("订单已过期");
        }
    }

    /**
     * 积分抵扣
     */
    private void decIntegral(Long uid, double usedIntegral, double deductionPrice,String busId) {
        userService.decIntegral(uid, usedIntegral);
        FsUser user=userService.selectFsUserById(uid);
        //积分记录
        billService.addBill(uid, BillDetailEnum.CATEGORY_2.getValue(),0, BillDetailEnum.TYPE_1.getDesc(),  usedIntegral, user.getIntegral().doubleValue(),
                "购买商品使用" + usedIntegral + "积分抵扣" + deductionPrice + "元",busId,0l);

    }

    public void deStockIncSale(List<FsStoreCartQueryVO> cartInfo) {
        for (FsStoreCartQueryVO storeCartVO : cartInfo) {
            productService.decProductStock(storeCartVO.getProductId(),
                    storeCartVO.getProductAttrValueId(),storeCartVO.getCartNum());
        }
    }

    /**
     * 未支付取消订单
     * @param orderId 订单id
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void cancelOrder(Long orderId) {
        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(orderId);
        if(order.getStatus()==OrderInfoEnum.STATUS_0.getValue()){
            if(!StringUtils.isEmpty(order.getExtendOrderId())){
                redisCache.deleteObject(DELIVERY+":"+order.getExtendOrderId());
            }
            //退回积分
            this.refundIntegral(order);
            //退回优惠券
            this.refundCoupon(order);
            //退回库存
            this.refundStock(order);
            fsStoreOrderMapper.cancelOrder(orderId);
            //添加记录
            orderStatusService.create(order.getId(), OrderLogEnum.CANCEL_ORDER.getValue(),
                    OrderLogEnum.CANCEL_ORDER.getDesc());
            TemplateBean templateBean = TemplateBean.builder()
                    .orderId(order.getId().toString())
                    .orderCode(order.getOrderCode().toString())
                    .remark("您的订单已取消")
                    .userId(order.getUserId())
                    .templateType(TemplateListenEnum.TYPE_1.getValue())
                    .build();
            publisher.publishEvent(new TemplateEvent(this, templateBean));
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void refundPrescribeOrder(Long orderId) {
        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(orderId);
        if(order!=null&&order.getStatus()==OrderInfoEnum.STATUS_1.getValue()&&order.getRefundStatus()==0){
            //退回积分
            this.refundIntegral(order);
            //退回库存
            this.refundStock(order);
            fsStoreOrderMapper.cancelOrder(orderId);
            //退佣金
            if(order.getTuiUserId()!=null&&order.getTuiUserId()>0){
                userService.subTuiMoney(order);
            }
            if(order.getPayType().equals(3)){
                //货到付款
            }
            else{
                FsStoreOrder orderMap=new FsStoreOrder();
                orderMap.setId(order.getId());
                orderMap.setRefundPrice(order.getPayMoney());
                orderMap.setRefundReason("拒绝开方自动退款");
                orderMap.setRefundReasonTime(new Date());
                fsStoreOrderMapper.updateFsStoreOrder(orderMap);
                //将钱退还给用户
                List<FsStorePayment> payments=paymentService.selectFsStorePaymentByOrderId(order.getId());
                if(payments!=null){
                    for(FsStorePayment payment:payments){
                        //易宝退款
                        RefundDTO refundDTO = new RefundDTO();
                        refundDTO.setRefundMoney(payment.getPayMoney().toString());
                        refundDTO.setLowRefundNo("refund-"+payment.getPayCode());
                        refundDTO.setUpOrderId(payment.getTradeNo());
                        RefundResult result=ybPayService.refund(refundDTO);
                        if(result.getState().equals("5")||result.getState().equals("6")){
                            payment.setRefundMoney(payment.getPayMoney());
                            payment.setStatus(-1);
                            payment.setRefundTime(new Date());
                            paymentService.updateFsStorePayment(payment);
                        }
                        else{
                            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                            return;
                        }
                    }
                }
            }
        }
    }


    private void refundCoupon(FsStoreOrder order) {
        if(order.getCouponId()!=null){
            FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(order.getCouponId());
            if(couponUser!=null){
                couponUser.setStatus(0);
                couponUser.setUseTime(null);
                couponUserService.updateFsStoreCouponUser(couponUser);
            }
        }
    }

    //已支付退款
    @Override
    public void refundOrder(Long orderId) {

        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(orderId);
        if(order!=null&&order.getStatus()==OrderInfoEnum.STATUS_1.getValue()&&order.getRefundStatus()==0){
            //退回积分
            this.refundIntegral(order);
            //退回库存
            this.refundStock(order);
            fsStoreOrderMapper.cancelOrder(orderId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public void deliveryOrder(String orderCode,String deliveryId,String deliverCode,String deliverName) {
        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
        if(order!=null&& Objects.equals(order.getStatus(), OrderInfoEnum.STATUS_1.getValue())){
            // 更新订单状态
            order.setStatus(OrderInfoEnum.STATUS_2.getValue());
            order.setDeliverySendTime(new Date());
            fsStoreOrderMapper.updateFsStoreOrder(order);


            // 多运单号适配
            FsExpress express=expressService.selectFsExpressByOmsCode(deliverCode);
            if(ObjectUtil.isNotNull(express)) {
                FsStoreDelivers fsStoreDeliver = new FsStoreDelivers();
                fsStoreDeliver.setOrderId(order.getId());
                fsStoreDeliver.setOrderCode(orderCode);
                fsStoreDeliver.setDeliverId(deliveryId);
                fsStoreDeliver.setDeliverSn(express.getCode());
                fsStoreDeliver.setDeliverName(express.getName());
                fsStoreDeliver.setCreateTime(LocalDateTime.now());
                fsStoreDeliver.setUpdateTime(LocalDateTime.now());
                fsStoreDeliver.setCreateBy("admin");
                fsStoreDeliver.setUpdateBy("admin");
                fsStoreDeliversMapper.insert(fsStoreDeliver);
            }

            FsWxExpressTask fsWxExpressTask = new FsWxExpressTask();
            fsWxExpressTask.setUserId(order.getUserId());
            fsWxExpressTask.setStatus(0);
            fsWxExpressTask.setRetryCount(0);
            fsWxExpressTask.setCreateTime(LocalDateTime.now());
            fsWxExpressTask.setUpdateTime(LocalDateTime.now());
            fsWxExpressTask.setOrderCode(order.getOrderCode());
            fsWxExpressTask.setExpressCompany(express.getCode());
            fsWxExpressTask.setExpressNo(deliveryId);

            List<FsStorePayment> fsStorePayments = fsStorePaymentService.selectFsStorePaymentByOrderIdNew(order.getId());
            if(CollectionUtils.isNotEmpty(fsStorePayments)){
                FsStorePayment fsStorePayment = fsStorePayments.get(0);
                fsWxExpressTask.setPayCode(fsStorePayment.getPayCode());
            }
            fsWxExpressTaskMapper.insert(fsWxExpressTask);

            // 微信消息通知
            TemplateBean templateBean = TemplateBean.builder()
                    .orderId(order.getId().toString())
                    .orderCode(order.getOrderCode())
                    .deliveryId(deliveryId)
                    .deliveryName(express.getName())
                    .userId(order.getUserId())
                    .templateType(TemplateListenEnum.TYPE_2.getValue())
                    .build();
            publisher.publishEvent(new TemplateEvent(this, templateBean));

            //订阅物流回调
            String lastFourNumber = "";
            if (StringUtils.equals(express.getCode(),ShipperCodeEnum.SF.getValue())) {
                lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
            }
            expressService.subscribeEspress(order.getOrderCode(),express.getCode(),deliveryId,lastFourNumber);
        }
    }

    @Override
    public void updateDeliveryOrder(Long id, String deliveryId, String deliverCode, String deliverName) {
        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(id);
        if (order != null) {
            FsExpress express = expressService.selectFsExpressByOmsCode(deliverCode);
            if (express != null) {
                order.setDeliveryName(deliverName);
                order.setDeliverySn(express.getCode());
                order.setDeliveryId(deliveryId);
                order.setDeliverySendTime(new Date());
                fsStoreOrderMapper.updateFsStoreOrder(order);
                orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
                        OrderLogEnum.DELIVERY_GOODS.getDesc());
                //订阅物流回调
                String lastFourNumber = "";
                if (express.getCode().equals(ShipperCodeEnum.SF.getValue())) {
                    if (StringUtils.equals(express.getCode(), ShipperCodeEnum.SF.getValue())) {
                        lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
                    }
                }
                expressService.subscribeEspress(order.getOrderCode(), express.getCode(), deliveryId, lastFourNumber);
            }
        }
    }


    @Override
    public List<FsMyStoreOrderListQueryVO> selectFsMyStoreOrderListVO(FsMyStoreOrderQueryParam param) {
        List<FsMyStoreOrderListQueryVO> list= fsStoreOrderMapper.selectFsMyStoreOrderListVO(param);
        for(FsMyStoreOrderListQueryVO vo:list){
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(items.size()>0){
                    vo.setItems(items);
                }
            }
            //处理是否可以申请售后
            vo.setIsAfterSales(0);
            if(vo.getStatus().equals(OrderInfoEnum.STATUS_3.getValue())){
                //已完成订单
                vo.setIsAfterSales(1);
                if(vo.getFinishTime()!=null){
                    String json=configService.selectConfigByKey("store.config");
                    StoreConfig storeConfig=JSONUtil.toBean(json,StoreConfig.class);
                    if(storeConfig.getStoreAfterSalesDay()!=null&&storeConfig.getStoreAfterSalesDay()>0){
                        //判断完成时间是否超过指定时间
                        Calendar calendar = new GregorianCalendar();
                        calendar.setTime(vo.getFinishTime());
                        calendar.add(calendar.DATE,storeConfig.getStoreAfterSalesDay()); //把日期往后增加一天,整数  往后推,负数往前移动
                        if(calendar.getTime().getTime()<new Date().getTime()){
                            vo.setIsAfterSales(0);
                        }
                    }
                }
            }
            else if(vo.getStatus()==1||vo.getStatus()==2){
                vo.setIsAfterSales(1);
            }
        }
        return list;
    }

    @Override
    public FsStoreOrder selectFsStoreOrderByOrderCode(String orderCode) {
        return fsStoreOrderMapper.selectFsStoreOrderByOrderCode(orderCode);
    }

    @Override
    public R getExpress(FsStoreOrder order) {
        //顺丰轨迹查询处理
        String lastFourNumber = "";
        if (order.getDeliverySn().equals(ShipperCodeEnum.SF.getValue())) {
            lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
        }
        ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),order.getDeliverySn(),order.getDeliveryId(),lastFourNumber);
        dto.setShipperName(order.getDeliveryName());
        FsExpress express=expressService.selectFsExpressByName(order.getDeliveryName());
        return R.ok().put("data", dto).put("express",express).put("deliveryId",order.getDeliveryId());
    }

    @Override
    public R getExpressMulti(FsStoreOrder order) {
        //顺丰轨迹查询处理
        String lastFourNumber = PhoneUtils.getLastFourNum(order.getUserPhone());
        // 获取该订单关联的物流信息
        List<FsStoreDelivers> fsStoreDelivers = fsStoreDeliversMapper.findByOrderId(order.getId());
        if(CollectionUtils.isEmpty(fsStoreDelivers)){
            return R.ok("当前订单号暂无物流信息");
        }

        List<ExpressInfoDTO> result = new ArrayList<>();
        for (FsStoreDelivers fsStoreDeliver : fsStoreDelivers) {
            ExpressInfoDTO dto=expressService.getExpressInfo(order.getOrderCode(),
                    fsStoreDeliver.getDeliverSn(),
                    fsStoreDeliver.getDeliverId(),
                    lastFourNumber);
            result.add(dto);
        }

        return R.ok().put("data",result);
    }

    @Override
    @Transactional
    public R createUserOrder(FsStoreOrderCreateUserParam param) {

        List<String> cartIds=new ArrayList<>();
        for(FsStoreProductAttrValueVO productAttrValue:param.getProducts()){
            FsStoreCart storeCart = FsStoreCart.builder()
                    .cartNum(productAttrValue.getCount())
                    .productAttrValueId(productAttrValue.getId())
                    .productId(productAttrValue.getProductId())
                    .userId(param.getUserId())
                    .isPay(0)
                    .isDel(0)
                    .isBuy(0)
                    .build();
            storeCart.setCreateTime(new Date());
            cartService.checkProductStock(productAttrValue.getProductId(),storeCart.getProductAttrValueId());
            cartService.insertFsStoreCart(storeCart);
            cartIds.add(storeCart.getId().toString());
        }
        FsStoreConfirmOrderParam confirmOrderParam=new FsStoreConfirmOrderParam();
        confirmOrderParam.setCartIds(StringUtils.join(cartIds.toArray(), ","));
        confirmOrderParam.setType("buy");
        R confirmResult=this.confirmOrder(param.getUserId(),confirmOrderParam);
        if(confirmResult.get("code").equals(200)){
            FsStoreOrderCreateParam createParam=new FsStoreOrderCreateParam();
            createParam.setUserId(param.getUserId());
            createParam.setAddressId(param.getAddressId());
            createParam.setOrderKey(confirmResult.get("orderKey").toString());
            createParam.setMark(param.getMark());
            createParam.setUseIntegral(0);
            createParam.setPayType(param.getPayType().toString());
            createParam.setCompanyId(param.getCompanyId());
            createParam.setCompanyUserId(param.getCompanyUserId());
            createParam.setPaymentId(param.getPaymentId());
            createParam.setPayPrice(param.getPayPrice());
            return this.createOrder(param.getUserId(),createParam);
        }
        else{
            throw new CustomException("创建失败");
        }
    }

    @Override
    public List<FsMyStoreOrderListQueryVO> selectFsCompanyStoreOrderListVO(FsMyStoreOrderQueryParam param) {
        List<FsMyStoreOrderListQueryVO> list=fsStoreOrderMapper.selectFsCompanyStoreOrderListVO(param);
        for(FsMyStoreOrderListQueryVO vo:list){
            if(StringUtils.isNotEmpty(vo.getItemJson())){
                JSONArray jsonArray=JSONUtil.parseArray(vo.getItemJson());
                List<FsStoreOrderItemVO> items=JSONUtil.toList(jsonArray, FsStoreOrderItemVO.class);
                if(CollectionUtils.isNotEmpty(items)){
                    vo.setItems(items);
                }
            }
        }
        return list;
    }

    @Override
    public FsStoreOrder selectFsStoreOrderByExtendOrderId(String extendOrderId) {
        return fsStoreOrderMapper.selectFsStoreOrderByExtendOrderId(extendOrderId);
    }

    @Override
    public List<FsStoreOrderTuiVO> selectFsStoreOrderTuiListVO(String userId) {
        return fsStoreOrderMapper.selectFsStoreOrderTuiListVO(userId);
    }

    @Override
    public R confirmPackageOrder(long uid, FsStoreConfirmPackageIdOrderParam param) {
        FsUserAddress address;
        if(ObjectUtil.isNull(param.getUserAddressId())){
            address= userAddressMapper.selectFsUserAddressByDefaultAddress(uid);
        } else {
            address = userAddressMapper.selectFsUserAddressById(param.getUserAddressId());
        }
        FsStoreProductPackage storeProductPackage=productPackageService.selectFsStoreProductPackageById(param.getPackageId());
        String uuid = IdUtil.randomUUID();
        BigDecimal totalMoney=storeProductPackage.getPayMoney();
        if(param.getCouponUserId()!=null){
            FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
            if(couponUser!=null&&couponUser.getStatus()==0){
                if(couponUser.getUseMinPrice().compareTo(storeProductPackage.getPayMoney()) < 0){
                    //
                    totalMoney=totalMoney.subtract(couponUser.getCouponPrice());
                }
            }
        }
        // 计算运费
        BigDecimal postMoney = BigDecimal.ZERO;
        if(address != null){
            postMoney = calPostMoney(storeProductPackage, address);
        }


        redisCache.setCacheObject("orderKey:"+uuid, storeProductPackage.getPackageId().toString(), 300, TimeUnit.SECONDS);

        logger.info("orderKey: {},address: {},package: {},totalMoney: {},postMoney: {}",uuid,address,storeProductPackage,totalMoney,postMoney);

        return R.ok().put("orderKey",uuid)
                .put("address",address)
                .put("package",storeProductPackage)
                .put("totalMoney",totalMoney.add(postMoney).setScale(2, RoundingMode.HALF_UP))
                .put("postMoney",postMoney.setScale(2, RoundingMode.HALF_UP));
    }

    public BigDecimal calPostMoney(FsStoreProductPackage storeProductPackage, FsUserAddress address) {
        BigDecimal postMoney = BigDecimal.ZERO;
        // 计算套餐邮费
        if(ObjectUtil.isNotNull(storeProductPackage.getTemplateId())){
            FsShippingTemplates fsShippingTemplates = fsShippingTemplatesService.selectFsShippingTemplatesById(storeProductPackage.getTemplateId());
            Asserts.notNull(fsShippingTemplates,"该套餐没有绑定邮费模板!");

            // 如果不包邮
            if(ObjectUtil.equal(0,fsShippingTemplates.getAppoint())){
                // 商品总量 重量、件、体积
                Integer type = fsShippingTemplates.getType();
                ShippingOrder.ShippingOrderBuilder shippingOrderBuilder = ShippingOrder.builder()
                        .cityId(address.getCityId());
                BigDecimal productSum = getProductSum(storeProductPackage, type);

                // 按件数
                if(ObjectUtil.equal(ShippingTempEnum.TYPE_1.getValue(),type)){
                    shippingOrderBuilder.itemCount(productSum.intValue());
                // 按重量
                } else if(ObjectUtil.equal(ShippingTempEnum.TYPE_2.getValue(),type)){
                    shippingOrderBuilder.weight(productSum);
                // 按体积
                } else if(ObjectUtil.equal(ShippingTempEnum.TYPE_3.getValue(),type)){
                    shippingOrderBuilder.volume(productSum);
                }

                BigDecimal bigDecimal = shippingTemplateManager
                        .calculateShippingFee(fsShippingTemplates.getId(), shippingOrderBuilder.build());
                if(ObjectUtil.isNotNull(bigDecimal)){
                    postMoney = bigDecimal;
                }
            }
        }else {
            throw new IllegalArgumentException("当前套餐没有设置运费模板!");
        }
        return postMoney.setScale(2,RoundingMode.HALF_UP);
    }

    private BigDecimal getProductSum(FsStoreProductPackage storeProductPackage,Integer type){
        String products = storeProductPackage.getProducts();
        com.alibaba.fastjson.JSONArray objects = JSON.parseArray(products);
        BigDecimal sum = BigDecimal.ZERO;
        for(int i=0;i<objects.size();i++){
            JSONObject jsonObject = objects.getJSONObject(i);
            Long id = jsonObject.getLong("id");
            Long count = jsonObject.getLong("count");

            // 按件数
            if(ObjectUtil.equal(ShippingTempEnum.TYPE_1.getValue(),type)){
                sum = sum.add(BigDecimal.valueOf(count));
                // 按重量
            } else if(ObjectUtil.equal(ShippingTempEnum.TYPE_2.getValue(),type)){
                FsStoreProductAttrValue fsStoreProductAttrValues
                        = fsStoreProductAttrValueService.selectFsStoreProductAttrValueById(id);
                sum = sum.add(fsStoreProductAttrValues.getWeight().multiply(BigDecimal.valueOf(count)));
                // 按体积
            } else if(ObjectUtil.equal(ShippingTempEnum.TYPE_3.getValue(),type)){
                FsStoreProductAttrValue fsStoreProductAttrValues
                        = fsStoreProductAttrValueService.selectFsStoreProductAttrValueById(id);
                sum = sum.add(fsStoreProductAttrValues.getWeight().multiply(BigDecimal.valueOf(count)));
            }
        }
        // 不满1kg按1kg计算
        if(sum.compareTo(BigDecimal.ONE) < 0){
            sum = BigDecimal.ONE;
        }
        return sum.setScale(0,RoundingMode.UP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public R createPackageOrder(long uid, FsStorePackageOrderCreateParam param) {
        //计算金额
        String packageId = redisCache.getCacheObject("orderKey:" + param.getOrderKey());
        if(packageId!=null){
            FsStoreProductPackage storeProductPackage=productPackageService.selectFsStoreProductPackageById(param.getPackageId());
            if(storeProductPackage.getStatus().equals(0)){
                return R.error("此套餐已下架" );
            }
            //限购处理
            if(storeProductPackage.getLimitCount()!=null&&storeProductPackage.getLimitCount()>0){
                //查看是否已购买
                FsUser user=userService.selectFsUserById(uid);
                if(!user.getLevel().equals(1)){
                    if(fsStoreOrderMapper.checkPackageOrderCount(uid,packageId)>=storeProductPackage.getLimitCount()){
                        return R.error("此套餐限购:"+storeProductPackage.getLimitCount()+"次");
                    }
                }
            }
            //获取地址
            FsUserAddress address=userAddressMapper.selectFsUserAddressById(param.getAddressId());
            Asserts.notNull(address,"当前地址不存在，请检查是否有维护!");
            if (!Objects.equals(address.getUserId(), uid)) {
                return R.error("非法操作");
            }
            //获取套餐数据
            JSONArray jsonArray=JSONUtil.parseArray(storeProductPackage.getProducts());
            List<StorePackageProductDTO> goodsList=JSONUtil.toList(jsonArray,StorePackageProductDTO.class);
            //检测库存
            Integer totalNum=0;
            //指定三个产品发ydsp
            int ydspHouse = 0;
            List<FsStoreCartQueryVO> carts=new ArrayList<>();
            for (StorePackageProductDTO goods : goodsList) {
                FsStoreProductAttrValue attrValue=attrValueService.selectFsStoreProductAttrValueById(goods.getId());
                if(attrValue!=null&&attrValue.getProductId()!=null){
                    FsStoreProduct product=storeProductService.selectFsStoreProductById(attrValue.getProductId());
                    if(product!=null){
                        totalNum += goods.getCount();
                        FsStoreCartQueryVO vo=new FsStoreCartQueryVO();
                        vo.setProductId(attrValue.getProductId());
                        vo.setProductAttrValueId(goods.getId());
                        vo.setCartNum(goods.getCount());
                        vo.setProductName(product.getProductName());
                        vo.setProductAttrName(attrValue.getSku());
                        vo.setProductImage(product.getImage());
                        vo.setBarCode(attrValue.getBarCode());
                        vo.setGroupBarCode(attrValue.getGroupBarCode());
                        vo.setPrice(product.getPrice());
                        vo.setProductType(product.getProductType());
                        carts.add(vo);
                        //判断是否是三种特定产品
                        if(product.getProductId()!=null&&(product.getProductId().equals(3168L)||product.getProductId().equals(3184L)||product.getProductId().equals(3185L))){
                            ydspHouse++;
                        }

                    }
                }
            }
            //生成分布式唯一值
            String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
            //组合数据
            CompanyUser user= companyUserService.selectCompanyUserById(param.getCompanyUserId());
            FsStoreOrder storeOrder = new FsStoreOrder();
            //修改默认仓库
            if(ydspHouse>0){
                storeOrder.setStoreHouseCode("YDSP001");
            }
            else{
                storeOrder.setStoreHouseCode("CQDS001");
            }
            if(user!=null){
                storeOrder.setCompanyId(user.getCompanyId());
                storeOrder.setDeptId(user.getDeptId());
            }
            BigDecimal totalMoney=storeProductPackage.getPayMoney();
            //优惠券处理
            if(param.getCouponUserId()!=null){
                FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
                if(couponUser!=null&&couponUser.getStatus()==0){
                    if(couponUser.getUseMinPrice().compareTo(storeProductPackage.getPayMoney())==-1){
                        //
                        totalMoney=totalMoney.subtract(couponUser.getCouponPrice());
                        storeOrder.setCouponId(couponUser.getId());
                        storeOrder.setCouponPrice(couponUser.getCouponPrice());
                        //更新优惠券状态
                        couponUser.setStatus(1);
                        couponUser.setUseTime(new Date());
                        couponUserService.updateFsStoreCouponUser(couponUser);
                    }
                }
            }
            storeOrder.setCompanyUserId(param.getCompanyUserId());
            storeOrder.setUserId(uid);
            storeOrder.setOrderCode(orderSn);
            storeOrder.setRealName(address.getRealName());
            storeOrder.setUserPhone(address.getPhone());
            storeOrder.setUserAddress(address.getProvince() + " " + address.getCity() +
                    " " + address.getDistrict() + " " + address.getDetail());

            storeOrder.setTotalNum(Long.parseLong(String.valueOf(goodsList.size())));
            storeOrder.setTotalPrice(storeProductPackage.getPayMoney());
            storeOrder.setTotalPostage(BigDecimal.ZERO);
            // 计算运费
            BigDecimal postMoney = calPostMoney(storeProductPackage, address);
            if(postMoney == null) {
                postMoney = BigDecimal.ZERO;
            }
            storeOrder.setPayPostage(postMoney);

            storeOrder.setDeductionPrice(BigDecimal.ZERO);
            storeOrder.setPaid(0);
            storeOrder.setUseIntegral(BigDecimal.ZERO);
            storeOrder.setBackIntegral(BigDecimal.ZERO);
            storeOrder.setGainIntegral(BigDecimal.ZERO);
            storeOrder.setMark(param.getMark());
            storeOrder.setIsChannel(1);
            storeOrder.setShippingType(1);
            storeOrder.setCreateTime(new Date());
            storeOrder.setStatus(0);
            storeOrder.setOrderCreateType(2);
            storeOrder.setPayType(storeProductPackage.getPayType().toString());
            storeOrder.setPayPrice(totalMoney.add(postMoney));
            storeOrder.setIsPackage(1);
            FsStoreProductPackage productPackage=new FsStoreProductPackage();
            productPackage.setTitle(storeProductPackage.getTitle());
            productPackage.setImgUrl(storeProductPackage.getImgUrl());
            productPackage.setDescs(storeProductPackage.getDescs());
            BigDecimal payMoney = storeOrder.getPayMoney();
            if(payMoney == null) {
                payMoney = BigDecimal.ZERO;
            }
            productPackage.setPayMoney(payMoney.add(postMoney));
            productPackage.setPackageId(storeProductPackage.getPackageId());
            storeOrder.setPackageJson(JSONUtil.toJsonStr(productPackage));
            storeOrder.setPackageId(storeProductPackage.getPackageId());
            Long prescribe = carts.stream().filter(item -> item.getProductType()!=null&&item.getProductType()==2).count();
            if(prescribe>0){
                storeOrder.setIsPrescribe(1);
            }
            Integer flag=fsStoreOrderMapper.insertFsStoreOrder(storeOrder);
            if (flag==0) {
                return R.error("订单创建失败");
            }
            //减库存加销量
            this.deStockIncSale(carts);
            //保存购物车商品信息
            for(FsStoreCartQueryVO vo:carts){
                FsStoreCartDTO fsStoreCartDTO=new FsStoreCartDTO();
                fsStoreCartDTO.setProductId(vo.getProductId());
                fsStoreCartDTO.setPrice(vo.getPrice());
                fsStoreCartDTO.setSku(vo.getProductAttrName());
                fsStoreCartDTO.setProductName(vo.getProductName());
                fsStoreCartDTO.setNum(vo.getCartNum());
                fsStoreCartDTO.setBarCode(vo.getBarCode());
                fsStoreCartDTO.setGroupBarCode(vo.getGroupBarCode());
                if(StringUtils.isEmpty(vo.getProductAttrImage())){
                    fsStoreCartDTO.setImage(vo.getProductImage());
                }
                else{
                    fsStoreCartDTO.setImage(vo.getProductAttrImage());
                }
                FsStoreOrderItem item=new FsStoreOrderItem();
                item.setOrderId(storeOrder.getId());
                item.setOrderCode(orderSn);
                item.setCartId(vo.getId());
                item.setProductId(vo.getProductId());
                item.setJsonInfo(JSONUtil.toJsonStr(fsStoreCartDTO));
                item.setNum(vo.getCartNum());
                item.setIsAfterSales(0);
                //处方药
                if(vo.getProductType().equals(2)){
                    item.setIsPrescribe(1);
                }
                fsStoreOrderItemMapper.insertFsStoreOrderItem(item);
            }
            //删除缓存
            redisCache.deleteObject("orderKey:" + param.getOrderKey());
            //添加记录
            orderStatusService.create(storeOrder.getId(), OrderLogEnum.CREATE_ORDER.getValue(),
                    OrderLogEnum.CREATE_ORDER.getDesc());

            //加入redis，30分钟自动取消
            String redisKey = String.valueOf(StrUtil.format("{}{}",
                    StoreConstants.REDIS_ORDER_OUTTIME_UNPAY, storeOrder.getId()));

            //添加支付到期时间
            String json=configService.selectConfigByKey("store.config");
            StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
            if(config.getUnPayTime()!=null&&config.getUnPayTime()>0){
                redisCache.setCacheObject(redisKey,storeOrder.getId(),config.getUnPayTime(), TimeUnit.MINUTES);
            }
            else{
                redisCache.setCacheObject(redisKey,storeOrder.getId(),30, TimeUnit.MINUTES);
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(storeOrder.getCreateTime());
            calendar.add(Calendar.MINUTE,config.getUnPayTime());
            SimpleDateFormat format = new   SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String payLimitTime = format.format(calendar.getTime() );
            return R.ok().put("order", storeOrder).put("payLimitTime",payLimitTime);
        }
        else{
            return R.error("订单已过期");
        }
    }

    @Override
    public synchronized R finishOrder(Long orderId) {
        IFsStoreOrderService fsStoreOrderService = (IFsStoreOrderService) AopContext.currentProxy();
        return fsStoreOrderService.finishStoreOrder(orderId);
    }

   @Override
   @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
   public R finishStoreOrder(Long orderId){
        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(orderId);

        // 如果是套餐类型的
        if(ObjectUtil.equal(order.getIsPackage(),1)) {
           logger.info("订单是套餐类型, 订单ID: {}", order.getId());
           // 如果该套餐有定时发放优惠券，就放置到定时发放优惠券队列
           FsStoreProductPackage fsStoreProductPackage = productPackageService.selectFsStoreProductPackageById(order.getPackageId());
           logger.info("查询到的套餐信息: {}", fsStoreProductPackage);

           if(ObjectUtil.equal(1,fsStoreProductPackage.getIcgEnable())){
               logger.info("套餐开启了定时发放优惠券功能, 套餐ID: {}", fsStoreProductPackage.getPackageId());

               FsCouponSchedule fsCouponSchedule = new FsCouponSchedule();
               fsCouponSchedule.setOrderId(order.getId());
               fsCouponSchedule.setSetmealId(fsStoreProductPackage.getPackageId());
               fsCouponSchedule.setSetmealTitle(fsStoreProductPackage.getTitle());
               fsCouponSchedule.setMonth(fsStoreProductPackage.getIcgMonth().longValue());
               fsCouponSchedule.setCount(0L);
               fsCouponSchedule.setPage(fsStoreProductPackage.getIcgUrl());
               fsCouponSchedule.setCouponIds(StringUtils.join(fsStoreProductPackage.getIcgCouponsId(),","));
               fsCouponSchedule.setRemark(fsStoreProductPackage.getIcgMark());
               fsCouponSchedule.setStatus(IcgProcessStatusEnum.PENDING.getCode());
               fsCouponSchedule.setOrderTime(LocalDateTime.now());
               fsCouponSchedule.setUserId(order.getUserId());
               // 如果上次发送时间为空，那么预计发送时间等于=下单时间+1月
               // 获取下个月10号
               fsCouponSchedule.setSendTime(fsCouponSchedule.getOrderTime().plusMonths(1L).withDayOfMonth(10));
               fsCouponSchedule.setRetryCount(0);

               fsCouponSchedule.setCompanyId(order.getCompanyId());
               fsCouponSchedule.setCompanyUserId(order.getCompanyUserId());

               fsCouponScheduleService.insertFsCouponSchedule(fsCouponSchedule);

               logger.info("插入优惠券定时发放任务成功，任务ID:{}",fsCouponSchedule.getId());
           }
        }
        if(ObjectUtil.equal(order.getStatus(),OrderInfoEnum.STATUS_2.getValue())){
            order.setFinishTime(new Date());
            order.setStatus(3);
            fsStoreOrderMapper.updateFsStoreOrder(order);
            orderStatusService.create(order.getId(), OrderLogEnum.FINISH_ORDER.getValue(),
                    OrderLogEnum.FINISH_ORDER.getDesc());
            //写入公司余额 条件是只有全款订单才分，非全款后台导入
            if(order.getCompanyId()!=null&&order.getCompanyId()>0&&order.getPayDelivery().compareTo(new BigDecimal(0))==0){
                if(order.getTuiMoneyStatus()==null||order.getTuiMoneyStatus()!=1){
                    companyService.addCompanyMoney(order);
                }
            }
            //模板消息支付成功发布事件
            TemplateBean templateBean = TemplateBean.builder()
                    .orderId(order.getId().toString())
                    .orderCode(order.getOrderCode())
                    .remark("您的订单已签收成功")
                    .finishTime(order.getFinishTime())
                    .userId(order.getUserId())
                    .templateType(TemplateListenEnum.TYPE_3.getValue())
                    .build();
            publisher.publishEvent(new TemplateEvent(this, templateBean));
            return R.ok("操作成功");
        }
        else {
            throw new RuntimeException("待收货状态才允许完成交易!");
        }
    }

    @Override
    public void orderCancel() {

        List<FsStoreOrder> fsStoreOrders = orderService.selectFsOutDateOrder();

        if (fsStoreOrders.size() > 0) {
            for (FsStoreOrder order : fsStoreOrders) {
                orderService.cancelOrder(order.getId());
            }
        }
    }

    @Override
    public List<FsStoreOrder> selectFsOutDateOrder() {
        return fsStoreOrderMapper.selectFsOutDateOrder();
    }

    @Override
    public List<FsStoreOrder> selectDeliverPenddingData() {
        return fsStoreOrderMapper.selectDeliverPendingData();
    }

    @Override
    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
    //类型1支付回调 类型2货到付款
    public synchronized String  payConfirm(Integer type,Long orderId,String payCode,String tradeNo,String bankTransactionId,String bankSerialNo) {
        //支付订单
        try {
            FsStoreOrder order=null;
            if(type.equals(1)){
                FsStorePayment storePayment=paymentService.selectFsStorePaymentByCode(payCode);
                if(storePayment==null){
                    throw new CustomException("当前支付记录未找到!");
                }
                if(!storePayment.getStatus().equals(0)){
                    logger.warn("当前支付记录不为已支付，已经跳过: paycode: {}",storePayment.getPayCode());
                    return "";
                }
                storePayment.setPaymentId(storePayment.getPaymentId());
                storePayment.setStatus(1);
                storePayment.setPayTime(new Date());
                storePayment.setTradeNo(tradeNo);
                storePayment.setBankSerialNo(bankSerialNo);
                storePayment.setBankTransactionId(bankTransactionId);
                paymentService.updateFsStorePayment(storePayment);

                // 如果是收款
                if(ObjectUtil.equal(1,storePayment.getBusinessType())){
                    logger.info("支付确认 payCode: {} ，当前类型为收款类型!",payCode);
                    companyService.addCompanyPaymentMoney(storePayment);
                    return "";
                }


                order=fsStoreOrderMapper.selectFsStoreOrderById(storePayment.getOrderId());


                if(order==null || !order.getPaid().equals(0)){
                    throw new CustomException("当前订单未找到或者订单状态不为待支付! paycode:"+payCode);
                }
            }
            else if(type.equals(2)){
                //货到付款
                order=fsStoreOrderMapper.selectFsStoreOrderById(orderId);
                if(!order.getStatus().equals(OrderInfoEnum.STATUS_0.getValue())){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return "";
                }
            }
            //写入公司佣金 当有归属公司时只进行公司分佣
            if(order.getCompanyId()!=null&&order.getCompanyId()>0){
                companyService.addCompanyTuiMoney(order);
                //没有归属公司对个人分佣
            }
            else if (order.getIsPackage()!=1&&order.getTuiUserId()!=null&&order.getTuiUserId()>0){
                //处理佣金 套餐不分佣金
                FsStoreOrderItem orderItemMap=new FsStoreOrderItem();
                orderItemMap.setOrderId(order.getId());
                List<FsStoreOrderItem> items= storeOrderItemService.selectFsStoreOrderItemList(orderItemMap);
                userService.addTuiMoney(order,items);
            }
            //增加用户购买次数
            userService.incPayCount(order.getUserId());
            //增加状态
            orderStatusService.create(order.getId(), OrderLogEnum.PAY_ORDER_SUCCESS.getValue(),
                    OrderLogEnum.PAY_ORDER_SUCCESS.getDesc());

            FsStoreOrder storeOrder = new FsStoreOrder();
            storeOrder.setId(order.getId());
            storeOrder.setPaid(OrderInfoEnum.PAY_STATUS_1.getValue());
            storeOrder.setStatus(OrderInfoEnum.STATUS_1.getValue());
            storeOrder.setPayTime(new Date());
            fsStoreOrderMapper.updateFsStoreOrder(storeOrder);

            //非处方直接提交OMS
            if(order.getIsPrescribe().equals(0)){
                createOmsOrder(order.getId());
            }
            else if(order.getIsPrescribe().equals(1)){
                //是否已开方
                FsPrescribe prescribe=prescribeService.selectFsPrescribeByOrderId(order.getId());
                if(prescribe!=null&&prescribe.getStatus()==1){
                    createOmsOrder(order.getId());
                }
            }
        }
        catch (Exception e){
            logger.error("payConfirm: {} ",e.getMessage(),e);
            throw new RuntimeException(e);
        }
        return "SUCCESS";
    }


    public  boolean containsAddress(String companyName) {
        String[] items= {"新疆","西藏","内蒙古","海南"};
        boolean found = false;
        for (String item : items) {
            if (companyName.contains(item)) {
                found = true;
                break;
            }
        }
        return found;
    }


    @Override
    public void createOmsOrder(Long orderId) throws ParseException {
        FsStoreOrder order=fsStoreOrderMapper.selectFsStoreOrderById(orderId);

        if(StringUtils.isEmpty(order.getExtendOrderId())&&order.getStatus()!=1){
            return;
        }
        ErpOrder erpOrder=new ErpOrder();
        erpOrder.setBuyer_account(String.valueOf(order.getUserId()));
        if (order.getCompanyId()!=null){
            erpOrder.setVip_code(order.getUserId().toString()+order.getCompanyId().toString());
        }else {
            erpOrder.setVip_code(order.getUserId().toString());
        }
        erpOrder.setPlatform_code(order.getOrderCode());
        erpOrder.setShop_code("18461733");
//        if(order.getStoreHouseCode().equals("YDSP001")){
//            erpOrder.setShop_code("RunDayWuHan");
//        }
//        else{
//            erpOrder.setShop_code(sysConfig.getErpShopCode());
//        }
        erpOrder.setSeller_memo(order.getMark());
        List<ErpOrderPayment> payments=new ArrayList<>();
        ErpOrderPayment payment=new ErpOrderPayment();
        payment.setPay_type_code("weixin");
        payment.setPayment(order.getPayMoney().doubleValue());
        if(order.getPayTime()!=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String timeString = sdf.format(order.getPayTime());
            Date date = sdf.parse(timeString); // 时间格式转为时间戳
            long timeLong = date.getTime();
            payment.setPaytime(new Timestamp(timeLong));
        }
        payments.add(payment);

        //1.新疆、西藏、内蒙古、海南的订单(代收+非代收）全部发EMS
        //2.全款订单选择中通，快递ID 452  ZTO 中通商城标快 ZTBK.17782167502
        //3.新疆  西藏 内蒙古 海南  全款订单走顺丰丰云配  【非全款】的就根据公司配置那来 配的哪个走哪个快递
        //4.把现在发中通的规则改成发顺丰风云配 CQRXSF.0235487868_241231
        //5.全款支付且应付金额小于等于100元，快递方式默认中通小件455 ZTO 中通小件 CQRXSF.0235487868_241231
        if(order.getCompanyId()!=null&&order.getStoreHouseCode()!=null&&order.getStoreHouseCode().equals("WHSP001")){
            //杭州家有仙妻实业有限公司 全部订单快递方式设置为商城德邦快递
            FsExpress express=expressService.selectFsExpressByOmsCode("SF-WHC");
            erpOrder.setExpress_code(express.getOmsCode());
            order.setDeliveryName(express.getName());
            order.setDeliverySn(express.getCode());
            if(order.getPayDelivery().compareTo(new BigDecimal(0))==0){

            }
            else{
                //物流代收金额
                ErpOrderPayment codPayment=new ErpOrderPayment();
                codPayment.setPay_type_code("cod");
                codPayment.setPayment(order.getPayDelivery().doubleValue());
                payments.add(codPayment);
                erpOrder.setCod(true);
            }
        }
        else if(order.getCompanyId()!=null){
            Company company = companyService.selectCompanyById(order.getCompanyId());
            if (order.getPayDelivery().compareTo(new BigDecimal(0)) == 0) {  //没有物流代收(全款订单)
                FsExpress express = new FsExpress();
                //express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                if(order.getPayPrice().compareTo(new BigDecimal(100))<=0){
                    express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                }
                else{
                    boolean found = containsAddress(order.getUserAddress());
                    if(found){
                        express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                    }
                    else{
                        express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                    }
                }
                Asserts.notNull(express,"快递没有找到!");
                erpOrder.setExpress_code(express.getOmsCode());
                order.setDeliveryName(express.getName());
                order.setDeliverySn(express.getCode());
            }
            else {
                FsExpress express = new FsExpress();
                boolean found = containsAddress(order.getUserAddress());
                if(found){
                    if(StringUtils.isNotEmpty(company.getOmsCode())){
                        express = expressService.selectFsExpressByOmsCode(company.getOmsCode());
                    }else{
                        express=expressService.selectFsExpressByOmsCode("EMS.1");
                    }
                }
                else{
                    if(StringUtils.isNotEmpty(company.getOmsCode())){
                        express = expressService.selectFsExpressByOmsCode(company.getOmsCode());
                    }else{
                        express = expressService.selectFsExpressByOmsCode(deliverOmsCode);
                    }
                }
                erpOrder.setExpress_code(express.getOmsCode());
                order.setDeliveryName(express.getName());
                order.setDeliverySn(express.getCode());
                //物流代收金额
                ErpOrderPayment codPayment = new ErpOrderPayment();
                codPayment.setPay_type_code("cod");
                codPayment.setPayment(order.getPayDelivery().doubleValue());
                payments.add(codPayment);
                erpOrder.setCod(true);
            }
        }
        else{
            if(order.getPayDelivery().compareTo(new BigDecimal(0))==0){  //没有物流代收(全款订单)
                FsExpress express=new FsExpress();
                if(order.getPayPrice().compareTo(new BigDecimal(100))<=0){
                    express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                }else{
                    boolean found = containsAddress(order.getUserAddress());
                    if(found){
                        express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                    }
                    else{
                        express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                    }
                }
                erpOrder.setExpress_code(express.getOmsCode());
                order.setDeliveryName(express.getName());
                order.setDeliverySn(express.getCode());
            }
            else{
                ErpOrderPayment codPayment=new ErpOrderPayment();
                codPayment.setPay_type_code("cod");
                codPayment.setPayment(order.getPayDelivery().doubleValue());
                payments.add(codPayment);
                erpOrder.setCod(true);
                FsExpress express=new FsExpress();
                boolean found = containsAddress(order.getUserAddress());
                if(found){
                    express=expressService.selectFsExpressByOmsCode("EMS.1");
                }
                else {
                    express=expressService.selectFsExpressByOmsCode(deliverOmsCode);
                }
                erpOrder.setExpress_code(express.getOmsCode());
                order.setDeliveryName(express.getName());
                order.setDeliverySn(express.getCode());
            }
        }
        erpOrder.setPayments(payments);
        if(order.getCompanyId()!=null){
            Company company=companyService.selectCompanyById(order.getCompanyId());
            if(company!=null){
                erpOrder.setSeller_memo(company.getCompanyName());
            }
        }
        if(order.getCompanyUserId()!=null){
            CompanyUser companyUser=companyUserService.selectCompanyUserById(order.getCompanyUserId());
            if(companyUser!=null){
                CompanyDept dept=companyDeptService.selectCompanyDeptById(companyUser.getDeptId());
                if(dept!=null){
                    List<String> names=companyDeptService.selectCompanyDeptNamesByIds(dept.getAncestors());
                    if(names!=null&&names.size()>0){
                        //写备注
                        erpOrder.setSeller_memo(erpOrder.getSeller_memo()+"-"+StringUtils.join(names, ",")+","+dept.getDeptName() );
                    }
                }
                erpOrder.setSeller_memo(erpOrder.getSeller_memo()+"-"+companyUser.getNickName());
            }
        }

        if(!"WHSP001".equals(order.getStoreHouseCode())){
            erpOrder.setSeller_memo(erpOrder.getSeller_memo()+"-"+order.getDeliveryName());
        }
        ErpRemarkDTO remarkDTO=new ErpRemarkDTO();
        remarkDTO.setTotalPrice(order.getTotalPrice());
        remarkDTO.setPayPrice(order.getPayPrice());
        remarkDTO.setDeliveryMoney(order.getPayDelivery());
        remarkDTO.setPayMoney(order.getPayMoney());
        remarkDTO.setCouponMoney(order.getCouponPrice());
        remarkDTO.setOrderId(order.getOrderCode());
        remarkDTO.setYdMoney(order.getPayPrice().subtract(order.getPayMoney().subtract(order.getPayDelivery())));

        if(order.getPayTime()!=null){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String format = sdf.format(order.getPayTime());
            remarkDTO.setPayTime(format);
        }
        erpOrder.setSeller_memo(erpOrder.getSeller_memo()+JSONUtil.toJsonStr(remarkDTO));

        erpOrder.setOrder_type_code("order");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        erpOrder.setDeal_datetime(sdf.format(new Date()));
        FsStoreOrderItem itemMap=new FsStoreOrderItem();
        itemMap.setOrderId(order.getId());
        List<FsStoreOrderItem> orderItems=storeOrderItemService.selectFsStoreOrderItemList(itemMap);
        List<ErpOrderItem> details=new ArrayList<>();
        for(FsStoreOrderItem orderItem: orderItems){
            FsStoreCartDTO cartDTO= JSONUtil.toBean(orderItem.getJsonInfo(),FsStoreCartDTO.class);
            //如果是组合码，查询出真实的商品数据 然后写入
            if(StringUtils.isNotEmpty(cartDTO.getGroupBarCode())){
                FsStoreProductGroup group=storeProductGroupService.selectFsStoreProductGroupByBarCode(cartDTO.getGroupBarCode().trim());
                if(group!=null){
                    JSONArray jsonArray=JSONUtil.parseArray(group.getProducts());
                    List<StoreProductGroupDTO> productGroupDTOS=JSONUtil.toList(jsonArray, StoreProductGroupDTO.class);
                    if(productGroupDTOS!=null){
                        for(StoreProductGroupDTO dto:productGroupDTOS){
                            FsStoreProductAttrValue attrValue=attrValueService.selectFsStoreProductAttrValueById(dto.getId());

                            ErpOrderItem item=new ErpOrderItem();
                            item.setItem_code(attrValue.getBarCode());
                            item.setPrice(attrValue.getPrice().toString());
                            item.setQty(dto.getCount()*cartDTO.getNum());
                            item.setRefund(0);
                            // 查询仓库代码
                            String warehouseCode = fsStoreProductCacheService.getWarehouseCodeByProductId(dto.getProductId());
                            if(StringUtils.isNotBlank(warehouseCode)){
                                item.setWarehouseCode(warehouseCode);
                            }
                            details.add(item);
                        }
                    }
                }
            }
            else{
                ErpOrderItem item=new ErpOrderItem();
                item.setItem_code(cartDTO.getBarCode().trim());
                item.setPrice(cartDTO.getPrice().toString());
                item.setQty(cartDTO.getNum());
                // 仓库代码
                FsStoreProduct fsStoreProduct = productService.selectFsStoreProductById(cartDTO.getProductId());
                if(ObjectUtil.isNotNull(fsStoreProduct)){
                    item.setWarehouseCode(cartDTO.getWarehouseCode());
                }
                item.setRefund(0);
                details.add(item);
            }
        }
        erpOrder.setDetails(details);
        erpOrder.setReceiver_name(order.getRealName());
        if(order.getUserPhone().length()>11){
            erpOrder.setReceiver_phone(order.getUserPhone());
        }
        else{
            erpOrder.setReceiver_mobile(order.getUserPhone());
        }
        String[] address=order.getUserAddress().split(" ");
        erpOrder.setReceiver_province(address[0]);
        erpOrder.setReceiver_city(address[1]);
        erpOrder.setReceiver_district(address[2]);
        //处理地址多空隔问题
        if(address.length>3){
            StringBuffer addrs=new StringBuffer();
            for(int i=3;i<address.length;i++){
                addrs.append(address[i]);
            }
            erpOrder.setReceiver_address(addrs.toString());
        }
        else if(address.length==3){
            erpOrder.setReceiver_address(address[2]);
        }
        //处理地址字符问题
        erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("+","加"));
        erpOrder.setReceiver_address(erpOrder.getReceiver_address().replace("\n",""));

        // 如果订单是套餐
        if(ObjectUtil.equal(order.getIsPackage(),1)){
            JSONObject jsonObject = JSON.parseObject(order.getPackageJson());
            if(StringUtils.isBlank(order.getPackageJson())){
                logger.error("套餐订单缺少套餐信息：{}", orderId);
                return;
            }
            Long packageId = jsonObject.getLong("packageId");
            // 根据套餐id找商品
            FsStoreProductPackage fsStoreProductPackage = fsStoreProductPackageService.selectFsStoreProductPackageById(packageId);
            if(ObjectUtil.isNull(fsStoreProductPackage)){
                logger.error("套餐id找不到! 套餐id:{} 订单id:{}",packageId, orderId);
                return;
            }
            String products = fsStoreProductPackage.getProducts();
            if(StringUtils.isBlank(products)){
                logger.error("套餐商品列表为空! 套餐id:{} 订单id:{}", packageId, orderId);
            }
            com.alibaba.fastjson.JSONArray objects = com.alibaba.fastjson.JSONArray.parseArray(products);
            if(CollectionUtil.isEmpty(objects)){
                logger.error("套餐商品列表为空! 套餐id:{} 订单id:{}", packageId, orderId);
                return;
            }

            JSONObject jsonObject1 = objects.getJSONObject(0);
            Long id = jsonObject1.getLong("id");
            FsStoreProductAttrValue attrValue=attrValueService.selectFsStoreProductAttrValueById(id);
            if(attrValue!=null) {
                // 根据产品id找仓库id
                String warehouseCode = fsStoreProductCacheService.getWarehouseCodeByProductId(attrValue.getProductId());
                if(StringUtils.isBlank(warehouseCode)){
                    logger.error("套餐商品id找不到! 商品id:{} 订单id:{}", attrValue.getProductId(), orderId);
                    return;
                }
                erpOrder.setWarehouse_code(warehouseCode);
                order.setStoreHouseCode(warehouseCode);

                // 根据仓库code找erp
                String erp = fsWarehousesMapper.selectErpByCode(warehouseCode);
                ErpContextHolder.setErpType(erp);

            }

        }
        // 如果不是套餐
        else {
            Asserts.notNull(order.getItemJson(),"当前订单没有商品!");
            com.alibaba.fastjson.JSONArray objects = JSON.parseArray(order.getItemJson());
            if(CollectionUtil.isEmpty(objects)){
                logger.error("订单商品列表为空! 订单id:{}", orderId);
                return;
            }
            JSONObject jsonObject = objects.getJSONObject(0);
            Long productId = jsonObject.getLong("productId");
            Asserts.notNull(productId,"产品id不存在!");
            FsStoreProduct fsStoreProduct = productService.selectFsStoreProductById(productId);
            String warehouseCode = fsStoreProduct.getWarehouseCode();
            if(StringUtils.isBlank(warehouseCode)){
                logger.error("当前订单 {} 的仓库id不存在!",order.getId());
                return;
            }
            order.setStoreHouseCode(warehouseCode);
            erpOrder.setWarehouse_code(warehouseCode);

            // 根据仓库code找erp
            String erp = fsWarehousesMapper.selectErpByCode(warehouseCode);
            ErpContextHolder.setErpType(erp);
        }

        ErpOrderResponse response= erpOrderService.addOrder(erpOrder);
        //写入日志
        logger.info("ErpCreate:{} {}",order.getOrderCode(),JSONUtil.toJsonStr(response));
        //支付成功后 将订单号写入待发货的REDIS中
        redisCache.setCacheObject(DELIVERY+":"+response.getCode(),order.getOrderCode());
        //写入外部订单号
        order.setExtendOrderId(response.getCode());
        fsStoreOrderMapper.updateFsStoreOrder(order);

        ErpContextHolder.clear();
    }

    @Override
    public FsStoreOrderVO selectFsStoreOrderVOByOrderCode(String orderCode) {
        return fsStoreOrderMapper.selectFsStoreOrderVOByOrderCode(orderCode);
    }

    @Override
    public Long selectFsStoreOrderTotalCount(int type,Long companyId) {
        return fsStoreOrderMapper.selectFsStoreOrderTotalCount(type,companyId);
    }

    @Override
    @Transactional
    public R editTuiMoney(FsStoreOrderEditTuiMoneyParam param) {
        FsStoreOrder order= fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
        if(order.getTuiMoney()!=null&&order.getTuiMoney().compareTo(new BigDecimal(0))==1){
            if(order.getTuiMoneyStatus().equals(0)){
                order.setTuiMoneyStatus(1);
                orderStatusService.create(order.getId(), OrderLogEnum.UNLOCK_TUI_MONEY.getValue(),
                        OrderLogEnum.UNLOCK_TUI_MONEY.getDesc());
                //写入公司余额
                Company company=companyService.selectCompanyById(order.getCompanyId());
                company.setMoney(company.getMoney().add(order.getTuiMoney()));
                companyService.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金解冻");
                log.setMoney(order.getTuiMoney());
                log.setLogsType(4);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
                fsStoreOrderMapper.updateFsStoreOrder(order);
                return R.ok("解冻成功");
            }
            else{
                order.setTuiMoneyStatus(0);
                //写入公司余额
                Company company=companyService.selectCompanyById(order.getCompanyId());
                company.setMoney(company.getMoney().subtract(order.getTuiMoney()));
                companyService.updateCompany(company);
                //写入日志
                CompanyMoneyLogs log=new CompanyMoneyLogs();
                log.setCompanyId(order.getCompanyId());
                log.setRemark("订单佣金冻结");
                log.setMoney(order.getTuiMoney().multiply(new BigDecimal(-1)));
                log.setLogsType(5);
                log.setBalance(company.getMoney());
                log.setCreateTime(new Date());
                log.setBusinessId(order.getId().toString());
                moneyLogsMapper.insertCompanyMoneyLogs(log);
                fsStoreOrderMapper.updateFsStoreOrder(order);
                return R.ok("冻结成功");
            }

        }
        else {
            return R.error("推广佣金不存在");
        }
    }

    @Override
    public List<OrderListVO> selectCompanyStoreOrderListAPI(OrderListParam param) {
        List<OrderListVO> list=fsStoreOrderMapper.selectCompanyStoreOrderListAPI(param);
        if(list!=null){
            for(OrderListVO vo:list){
                List<ProductListVO> productList=new ArrayList<>();
                FsStoreOrderItem map=new FsStoreOrderItem();
                map.setOrderId(vo.getOrderid());
                List<FsStoreOrderItem> items=fsStoreOrderItemMapper.selectFsStoreOrderItemList(map);
                if(items!=null){
                    for(FsStoreOrderItem item:items){
                        FsStoreCartDTO cartDTO= JSONUtil.toBean(item.getJsonInfo(),FsStoreCartDTO.class);
                        ProductListVO productListVO=new ProductListVO();
                        productListVO.setProductid(cartDTO.getProductId());
                        productListVO.setProductname(cartDTO.getProductName());
                        productListVO.setProductprice(cartDTO.getPrice());
                        productListVO.setProductqty(cartDTO.getNum());
                        productList.add(productListVO);
                    }
                }
                vo.setProductList(productList);
            }

        }
        return list;
    }

    @Override
    public List<FsStoreOrder> selectFsStoreOrderByCompanyId(Long companyId) {
        return fsStoreOrderMapper.selectFsStoreOrderByCompanyId(companyId);
    }

    @Override
    public List<FsStoreOrder> selectFsStoreOrderListByDeliveryId(String logisticCode) {
        return fsStoreOrderMapper.selectFsStoreOrderListByDeliveryId(logisticCode);
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public R refundOrderMoney(Long orderId) {
        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(orderId);
        if(order.getStatus()==-2){
            return R.error("已退款");
        }
        if(order.getStatus()!=1&&order.getStatus()!=2){
            return R.error("非法操作");
        }
        if(StringUtils.isNotEmpty(order.getExtendOrderId())){
            ErpRefundUpdateRequest request=new ErpRefundUpdateRequest();
            request.setTid(order.getOrderCode());
            request.setOid(order.getOrderCode());
            request.setRefund_state(1);

            // 根据仓库code找erp
            if(StringUtils.isNotBlank(order.getStoreHouseCode())){
                String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
                ErpContextHolder.setErpType(erp);
            }
            BaseResponse response=erpOrderService.refundUpdate(request);
            if(ObjectUtil.isNull(response) || !response.getSuccess()){
                logger.error("调用erp退款接口失败! {}",JSON.toJSONString(response));
                throw new CustomException("调用erp退款接口失败："+response.getErrorDesc());
            }
        }
        order.setStatus(-2);
        order.setRefundPrice(order.getPayMoney());
        order.setRefundStatus(OrderInfoEnum.REFUND_STATUS_2.getValue());
        fsStoreOrderMapper.updateFsStoreOrder(order);

        //退库存
        //获取订单下的商品
        List<FsStoreOrderItemVO> orderItemVOS=fsStoreOrderItemMapper.selectFsStoreOrderItemListByOrderId(order.getId());
        for(FsStoreOrderItemVO vo:orderItemVOS){
            if(vo.getIsAfterSales()==1){
                productService.incProductStock(vo.getNum(), vo.getProductId(), vo.getProductAttrValueId());
            }

        }
        if(order.getPayType().equals(3)){
            //货到付款
        }
        else{
            //将钱退还给用户
            List<FsStorePayment> payments=paymentService.selectFsStorePaymentByOrderId(order.getId());
            if(payments!=null){
                for(FsStorePayment payment:payments){
                    PaymentHandler best = PaymentHandlerHolder.findBest(payment.getPayMode());
                    if(ObjectUtil.isNull(best)){
                        throw new CustomException("支付类型异常!");
                    }
                    PayProcessContext payProcessContext = new PayProcessContext();
                    payProcessContext.setOrderId(orderId);
                    payProcessContext.setPaymentId(payment.getPaymentId());
                    payProcessContext.setPayCode(payment.getPayCode());
                    payProcessContext.setUserId(order.getUserId());
                    payProcessContext.setOrderPrefix("refund-");
                    best.refundOrder(payProcessContext);
                }
            }
        }
        orderStatusService.create(order.getId(), OrderLogEnum.REFUND_ORDER_SUCCESS.getValue(),
                OrderLogEnum.REFUND_ORDER_SUCCESS.getDesc());
        if(order.getTuiUserId()!=null&&order.getTuiUserId()>0){
            userService.subTuiMoney(order);
        }
        return R.ok();

    }

    @Override
    public R updateExpress(FsStoreOrderExpressEditParam param) {
        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
        if(order.getStatus()!=1){
            return R.error("只有待发货状态可以同步");
        }
        if(order.getExtendOrderId()==null){
            return R.error("未生成管易云订单");
        }
        ErpOrderQueryRequert request = new ErpOrderQueryRequert();
        request.setCode(order.getExtendOrderId());
        // 根据仓库code找erp
        if(com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())){
            String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode());
            ErpContextHolder.setErpType(erp);
        }
        ErpOrderQueryResponse response = erpOrderService.getOrder(request);
        if(response.getOrders()!=null&&response.getOrders().size()>0){
            for(ErpOrderQuery orderQuery : response.getOrders()){
                if(orderQuery.getDeliverys()!=null&&orderQuery.getDeliverys().size()>0){
                    for(ErpDeliverys delivery:orderQuery.getDeliverys()){
                        if(delivery.getDelivery()&& StringUtils.isNotEmpty(delivery.getMail_no())){
                            FsStoreOrder map=new FsStoreOrder();
                            map.setStatus(OrderInfoEnum.STATUS_2.getValue());
                            map.setId(order.getId());
                            map.setDeliveryId(response.getOrders().get(0).getDeliverys().get(0).getMail_no());
                            fsStoreOrderMapper.updateFsStoreOrder(map);
                            orderStatusService.create(order.getId(), OrderLogEnum.DELIVERY_GOODS.getValue(),
                                    OrderLogEnum.DELIVERY_GOODS.getDesc());
                            TemplateBean templateBean = TemplateBean.builder()
                                    .orderId(order.getId().toString())
                                    .orderCode(order.getOrderCode().toString())
                                    .deliveryId(order.getDeliveryId())
                                    .deliveryName(order.getDeliveryName())
                                    .userId(order.getUserId())
                                    .templateType(TemplateListenEnum.TYPE_2.getValue())
                                    .build();
                            publisher.publishEvent(new TemplateEvent(this, templateBean));
                            return R.ok();
                        }
                    }

                }
            }
        }
        return R.error("未生成运单信息");
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public R syncExpress(FsStoreOrderExpressEditParam param) {

        fsStoreDeliversService.syncDeliverInfo(param.getOrderId());
        fsStoreDeliversService.finishOrder(param.getOrderId());

        return R.ok();
    }

    @Override
    @Synchronized
    public R addTuiMoney(FsStoreOrderAddTuiMoneyParam param) {
        FsStoreOrder order = fsStoreOrderMapper.selectFsStoreOrderById(param.getOrderId());
        if(order.getStatus()!=OrderInfoEnum.STATUS_3.getValue()) {
            return R.error("订单未完成，不能分佣金");
        }
        if (order.getCompanyId() != null && order.getCompanyId() > 0 && order.getPayDelivery().compareTo(new BigDecimal(0)) == 0) {
            if (order.getTuiMoneyStatus() == null || order.getTuiMoneyStatus() != 1) {
                companyService.addCompanyMoney(order);
                return R.ok();
            }
            else{
                return R.error("此订单已分佣，不能重复分佣");
            }
        }
        else{
            return R.error("此订单不能手动分佣");
        }
    }

    @Override
    public R createSalesOrder(CompanyUser companyUser, String cateIds) {
        List<FsStoreCartQueryVO> carts=cartMapper.selectFsStoreCartListByIds(cateIds);
        String uuid = IdUtil.randomUUID();
        redisCache.setCacheObject("createOrderKey:"+uuid, companyUser.getCompanyId()+"-"+companyUser.getUserId(), 24, TimeUnit.HOURS);
        redisCache.setCacheObject("orderCarts:"+uuid, carts, 24, TimeUnit.HOURS);
        //计算总价
        BigDecimal totalMoney= BigDecimal.ZERO;
        for(FsStoreCartQueryVO vo:carts){
            totalMoney=totalMoney.add(vo.getPrice().multiply(new BigDecimal(vo.getCartNum().toString())));
        }
        redisCache.setCacheObject("createOrderMoney:"+uuid, totalMoney, 24, TimeUnit.HOURS);
        return R.ok().put("orderKey",uuid).put("carts",carts);
    }

    @Override
    public R getSalesOrder(String createOrderKey) {
        String key=redisCache.getCacheObject("createOrderKey:"+createOrderKey);
        List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + createOrderKey);
        BigDecimal money=redisCache.getCacheObject("createOrderMoney:"+createOrderKey);
        if (StringUtils.isEmpty(key)) {
            throw new CustomException("订单已过期",501);
        }
        return R.ok().put("carts",carts).put("totalMoney",money);
    }

    @Override
    @Transactional
    public R addUserCart(long userId, String createOrderKey) {
        String key=redisCache.getCacheObject("createOrderKey:"+createOrderKey);
        List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + createOrderKey);
        if (StringUtils.isEmpty(key)) {
            throw new CustomException("订单已过期",501);
        }
        List<Long> ids=new ArrayList<>();
        for(FsStoreCartQueryVO vo : carts){
            FsStoreCart storeCart = FsStoreCart.builder()
                    .cartNum(vo.getCartNum())
                    .productAttrValueId(vo.getProductAttrValueId())
                    .productId(vo.getProductId())
                    .userId(userId)
                    .isPay(0)
                    .isDel(0)
                    .isBuy(1)
                    .build();
            storeCart.setCreateTime(new Date());
            cartMapper.insertFsStoreCart(storeCart);
            ids.add(storeCart.getId());
        }
        String[] idArr=key.split("-");
        return R.ok().put("cartIds",ids).put("companyId",idArr[0]).put("companyUserId",idArr[1]);
    }

    @Override
    public R updateSalseOrderMoney(String createOrderKey, BigDecimal money) {
        if(money==null){
            return R.error("请输入价格");
        }
        if(money.compareTo(BigDecimal.ZERO)<=0){
            return R.error("价格应大于0");
        }
        String key=redisCache.getCacheObject("createOrderKey:"+createOrderKey);
        if (StringUtils.isEmpty(key)) {
            throw new CustomException("订单已过期",501);
        }
        List<FsStoreCartQueryVO> carts = redisCache.getCacheObject("orderCarts:" + createOrderKey);
        BigDecimal totalMoney= BigDecimal.ZERO;
        for(FsStoreCartQueryVO vo:carts){
            totalMoney=totalMoney.add(vo.getPrice().multiply(new BigDecimal(vo.getCartNum().toString())));
        }
        if(money.compareTo(totalMoney)==1){
            throw new CustomException("价格不能大于商品总价",501);
        }
        String json=configService.selectConfigByKey("store.config");
        StoreConfig config= JSONUtil.toBean(json,StoreConfig.class);
        if(config.getCreateMoneyRate()!=null){
            totalMoney=totalMoney.multiply(new BigDecimal(config.getCreateMoneyRate())).divide(new BigDecimal(100));
            if(money.compareTo(totalMoney)==-1){
                throw new CustomException("价格必须大于商品总价"+config.getCreateMoneyRate()+"%",501);
            }
        }
        redisCache.setCacheObject("createOrderMoney:"+createOrderKey, money, 24, TimeUnit.HOURS);
        return R.ok();
    }

    @Override
    public Integer selectFsStoreOrderCountByType(Long companyId, long userId, int type) {
        return fsStoreOrderMapper.selectFsStoreOrderCountByType(companyId,userId,type);
    }

    @Override
    public List<FsCustomerStoreOrderListQueryVO> selectFsCustomerStoreOrderListQuery(FsCustomerStoreOrderListQueryParam param) {
        List<FsCustomerStoreOrderListQueryVO> list= fsStoreOrderMapper.selectFsCustomerStoreOrderListQuery(param);
        for(FsCustomerStoreOrderListQueryVO vo:list){
            List<FsStoreOrderItemVO> items=fsStoreOrderItemMapper.selectMyFsStoreOrderItemListByOrderId(vo.getId());
            vo.setItems(items);
        }
        return list;
    }

    @Override
    public List<JSONObject> selectFsStoreOrderCounts(Map<String, Object> toMap) {
        return fsStoreOrderMapper.selectFsStoreOrderCounts(toMap);
    }

    @Override
    public List<FsStoreOrderStatisticsVO> selectFsStoreOrderStatisticsList(FsStoreStatisticsParam param) {
        return fsStoreOrderMapper.selectFsStoreOrderStatisticsList(param);
    }

    @Override
    public List<FsStoreOrderExportVO> selectFsStoreOrderListVOByExport(FsStoreOrderParam param) {
        return fsStoreOrderMapper.selectFsStoreOrderListVOByExport(param);
    }

    @Override
    public List<FsStoreOrderPromotionExportVO> selectFsPromotionOrderListVOByExport(FsStoreOrderParam param) {
        List<FsStoreOrderPromotionExportVO> list = fsStoreOrderMapper.selectFsPromotionOrderListVOByExport(param);
        for (FsStoreOrderPromotionExportVO vo : list){
           FsStoreOrderBrokerageVO brokerageVO = fsStoreOrderMapper.selectBrokerage(vo.getId());
           vo.setBrokerage(brokerageVO.getBrokerage());
           vo.setBrokerageTwo(brokerageVO.getBrokerageTwo());
           vo.setBrokerageThree(brokerageVO.getBrokerageThree());
        }
        return list;
    }

    @Override
    public List<FsStorePayRemainOrderExportVO> selectFsStorePayRemainOrderListVOByExport(FsStoreOrderParam param) {
        return fsStoreOrderMapper.selectFsStorePayRemainOrderListVOByExport(param);
    }

    @Override
    public List<FsStoreOrder> selectFsStoreOrderListByFinish7Day() {
        return fsStoreOrderMapper.selectFsStoreOrderListByFinish7Day();
    }

    @Override
    public List<FsStoreOrderVO> selectFsCustomerStoreOrderListVO(FsStoreOrderParam param) {
        return fsStoreOrderMapper.selectFsCustomerStoreOrderListVO(param);
    }

    @Override
    @Transactional
    @Synchronized
    public String payRemainConfirm( String payCode, String tradeNo, String bankTransactionId, String bankSerialNo) {
        //支付订单
        FsStoreOrder order=null;
        FsStorePayment storePayment=paymentService.selectFsStorePaymentByCode(payCode);
        if(storePayment==null||!storePayment.getStatus().equals(0)){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return "";
        }
        storePayment.setStatus(1);
        storePayment.setPayTime(new Date());
        storePayment.setTradeNo(tradeNo);
        storePayment.setBankSerialNo(bankSerialNo);
        storePayment.setBankTransactionId(bankTransactionId);
        storePayment.setIsPayRemain(1);
        paymentService.updateFsStorePayment(storePayment);
        order=fsStoreOrderMapper.selectFsStoreOrderById(storePayment.getOrderId());
        //增加状态
        orderStatusService.create(order.getId(), OrderLogEnum.PAY_REMAIN_ORDER_SUCCESS.getValue(),
                OrderLogEnum.PAY_REMAIN_ORDER_SUCCESS.getDesc());

        FsStoreOrder storeOrder = new FsStoreOrder();
        storeOrder.setId(order.getId());
        storeOrder.setIsPayRemain(1);
        fsStoreOrderMapper.updateFsStoreOrder(storeOrder);

        return "SUCCESS";
    }

    @Override
    public R auditPayRemain(Long orderId) {
        FsStoreOrder order=fsStoreOrderMapper.selectFsStoreOrderById(orderId);
        if(order.getIsPayRemain()==1){
            FsStoreOrder storeOrder = new FsStoreOrder();
            storeOrder.setId(order.getId());
            storeOrder.setIsPayRemain(2);
            storeOrder.setPayType("1");
            storeOrder.setPayMoney(order.getPayPrice());
            storeOrder.setPayDelivery(new BigDecimal(0));
            fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
            return R.ok("操作成功");
        }
        else{
            return R.error("非法操作");
        }
    }

    @Override
    public Integer selectFsStoreOrderCount(long userId, int status) {
        return fsStoreOrderMapper.selectFsStoreOrderCount(userId,status);
    }

    @Override
    public R computedPackageOrder(long userId, FsStoreComputedPackageIdOrderParam param) {
        FsStoreProductPackage storeProductPackage=productPackageService.selectFsStoreProductPackageById(param.getPackageId());
        BigDecimal totalMoney=storeProductPackage.getPayMoney();
        if(param.getCouponUserId()!=null){
            FsStoreCouponUser couponUser=couponUserService.selectFsStoreCouponUserById(param.getCouponUserId());
            if(couponUser!=null&&couponUser.getStatus()==0){
                if(couponUser.getUserId()!=userId){
                    return R.error("非法操作");
                }
                if(couponUser.getUseMinPrice().compareTo(storeProductPackage.getPayMoney())==-1){
                    totalMoney=totalMoney.subtract(couponUser.getCouponPrice());
                }
            }
        }
        return R.ok().put("totalMoney",totalMoney);
    }

    @Override
    public FsStoreOrder selectFsStoreOrderByDeliveryId(String logisticCode) {
        return fsStoreOrderMapper.selectFsStoreOrderByDeliveryId(logisticCode);
    }




    @Synchronized
    @Override
    //@Async
    public String importExpress(List<StoreOrderExpressExportDTO> list, boolean updateSupport) {
        if (StringUtils.isNull(list) || list.size() == 0) {
            throw new CustomException("导入数据不能为空！");
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder importSuccessMsg = new StringBuilder();
        StringBuilder importErrorMsg = new StringBuilder();
        StringBuilder importMsg = new StringBuilder();
        for (StoreOrderExpressExportDTO dto : list)
        {
            try
            {
//                Thread.sleep(1000);
                FsStoreOrder order=fsStoreOrderMapper.selectFsStoreOrderByDeliveryId(dto.getDeliveryId());
                if (StringUtils.isNull(order))
                {
                    String msg = "<br/>" + failureNum + "、快递单号 " + dto.getDeliveryId() + "不存在";
                    importErrorMsg.append(msg);
                    failureNum++;
                }
                else
                {
                    //订单状态为已签收并且未导入过
                    if(order.getDeliveryStatus().equals(3)&& order.getDeliveryImportTime()==null&&(order.getPayType().equals("2")||order.getPayType().equals("3"))){
                        FsStoreOrder orderMap=new FsStoreOrder();
                        orderMap.setId(order.getId());
                        orderMap.setDeliveryTime(dto.getDeliveryTime());
                        orderMap.setDeliveryPayStatus(Integer.parseInt(dto.getDeliveryPayStatus()));
                        orderMap.setDeliveryPayMoney(dto.getDeliveryPayMoney());
                        orderMap.setDeliveryPayTime(dto.getDeliveryPayTime());
                        orderMap.setDeliveryImportTime(new Date());
                        this.updateFsStoreOrder(orderMap);
                        //未分佣写入分佣
                        if(order.getCompanyId()!=null&&order.getCompanyId()>0){
                            companyService.addCompanyMoney(order);
                        }
                        successNum++;
                        importSuccessMsg.append("<br/>" + successNum + "、快递单号 " +dto.getDeliveryId() + " 导入成功");
                    }
                    else{
                        String msg = "<br/>" + failureNum + "、快递单号 " + dto.getDeliveryId() + " 未签收或已导入,不能导入";
                        importErrorMsg.append(msg);
                        failureNum++;
                    }
                }
            }
            catch (Exception e)
            {
                String msg = "<br/>" + failureNum + "、快递单号 " + dto.getDeliveryId() + " 导入异常：";
                importErrorMsg.append(msg+e.getMessage());
                failureNum++;
            }
        }
        importMsg.insert(0, "导入完成！成功" + successNum + " 条，失败"+failureNum+"条。");
        importMsg.append(importErrorMsg.toString());
        importMsg.append(importSuccessMsg.toString());
        return importMsg.toString();
    }


    /**
     * 退回积分
     */
    private void refundIntegral(FsStoreOrder order) {

        if (order.getPayIntegral().compareTo(BigDecimal.ZERO) > 0) {
            order.setUseIntegral(order.getPayIntegral());
        }
        if (order.getUseIntegral().compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }
        if ( order.getBackIntegral().compareTo(BigDecimal.ZERO) > 0) {
            return;
        }
        FsUser user = userService.selectFsUserById(order.getUserId());
        //增加积分
        BigDecimal newIntegral = NumberUtil.add(order.getUseIntegral(), user.getIntegral());
        user.setIntegral(newIntegral);
        userService.updateFsUser(user);
        //增加流水
        billService.addBill(user.getUserId(),BillDetailEnum.CATEGORY_2.getValue(),1, BillDetailEnum.TYPE_5.getDesc(),
                order.getUseIntegral().doubleValue(),
                newIntegral.doubleValue(),
                "购买商品失败,回退积分" + order.getUseIntegral(), order.getId().toString(),0l);
        //更新订单回退积分
        FsStoreOrder storeOrder = new FsStoreOrder();
        storeOrder.setBackIntegral(order.getUseIntegral());
        storeOrder.setId(order.getId());
        fsStoreOrderMapper.updateFsStoreOrder(storeOrder);
    }


    /**
     * 退回库存
     */
    private void refundStock(FsStoreOrder order) {
        //获取订单下的商品
        List<FsStoreOrderItemVO> orderItemVOS=fsStoreOrderItemMapper.selectFsStoreOrderItemListByOrderId(order.getId());
        for(FsStoreOrderItemVO vo:orderItemVOS){
            productService.incProductStock(vo.getNum(), vo.getProductId()
                    , vo.getProductAttrValueId());
        }

    }



    /**
     * 获取订单价格
     */
    private FsStoreOrderPriceDTO getOrderPriceGroup(List<FsStoreCartQueryVO> cartInfo, FsUserAddress userAddress) {
        BigDecimal storePostage = BigDecimal.ZERO;

        BigDecimal totalPrice = this.getOrderSumPrice(cartInfo, "truePrice");//获取订单总金额
        BigDecimal costPrice = this.getOrderSumPrice(cartInfo, "costPrice");//获取订单成本价
        BigDecimal payIntegral = this.getOrderSumPrice(cartInfo, "payIntegral");//获取订单需要的积分



        storePostage = this.handlePostage(cartInfo, userAddress);

        FsStoreOrderPriceDTO priceGroupDTO = new FsStoreOrderPriceDTO();
        priceGroupDTO.setStorePostage(storePostage);
        priceGroupDTO.setTotalPrice(totalPrice);
        priceGroupDTO.setCostPrice(costPrice);
        priceGroupDTO.setPayIntegral(payIntegral);
        return priceGroupDTO;
    }

    /**
     * 根据运费模板算法返回邮费
     *
     * @param cartInfo    购物车
     * @param userAddress 地址
     * @return double
     */
    private BigDecimal handlePostage(List<FsStoreCartQueryVO> cartInfo, FsUserAddress userAddress) {
        BigDecimal storePostage = BigDecimal.ZERO;
        if (userAddress != null) {
            if (userAddress.getCityId() == null) {
                return storePostage;
            }
            Long cityId = userAddress.getCityId();
            List<Long> citys = new ArrayList<>();
            citys.add(cityId);
            citys.add(0l);//城市包括默认
            List<Long> tempIds = cartInfo
                    .stream()
                    .map(FsStoreCartQueryVO::getTempId)
                    .collect(Collectors.toList());
            //获取商品用到的运费模板
            String ids = String.join(",", tempIds.stream()
                    .map(String::valueOf).collect(Collectors.toList()));
            List<FsShippingTemplates> shippingTemplatesList =shippingTemplatesService.selectFsShippingTemplatesByIds(ids);
            String cityIds = String.join(",", citys.stream()
                    .map(String::valueOf).collect(Collectors.toList()));
            //获取运费模板区域列表按照城市排序
            List<FsShippingTemplatesRegion> shippingTemplatesRegionList = shippingTemplatesRegionService.selectFsShippingTemplatesRegionListByTempIdsAndCityIds(ids,cityIds);

            //提取运费模板类型
            Map<Long, Integer> shippingTemplatesMap = shippingTemplatesList
                    .stream()
                    .collect(Collectors.toMap(FsShippingTemplates::getId,
                            FsShippingTemplates::getType));
            //提取运费模板有相同值覆盖
            Map<Long, FsShippingTemplatesRegion> shippingTemplatesRegionMap =
                    shippingTemplatesRegionList.stream()
                            .collect(Collectors.toMap(FsShippingTemplatesRegion::getTempId,
                                    YxShippingTemplatesRegion -> YxShippingTemplatesRegion,
                                    (key1, key2) -> key2));


            Map<Long, TemplateDTO> templateDTOMap = new HashMap<>();
            for (FsStoreCartQueryVO storeCartVO : cartInfo) {
                Long tempId = storeCartVO.getTempId();
                //根据模板类型获取相应的数量
                double num = 0d;
                if (ShippingTempEnum.TYPE_1.getValue().equals(shippingTemplatesMap.get(tempId))) {
                    num = storeCartVO.getCartNum().doubleValue();
                } else if (ShippingTempEnum.TYPE_2.getValue().equals(shippingTemplatesMap.get(tempId))) {
                    num = NumberUtil.mul(storeCartVO.getCartNum(),
                            storeCartVO.getWeight()).doubleValue();
                } else if (ShippingTempEnum.TYPE_3.getValue().equals(shippingTemplatesMap.get(tempId))) {
                    num = NumberUtil.mul(storeCartVO.getCartNum(),
                            storeCartVO.getVolume()).doubleValue();
                }

                FsShippingTemplatesRegion shippingTemplatesRegion = shippingTemplatesRegionMap.get(tempId);
                BigDecimal price = NumberUtil.round(NumberUtil.mul(storeCartVO.getCartNum(),
                        storeCartVO.getPrice()), 2);
                if (!templateDTOMap.containsKey(tempId)) {
                    TemplateDTO templateDTO = TemplateDTO.builder()
                            .number(num)
                            .price(price)
                            .first(shippingTemplatesRegion.getFirst().doubleValue())
                            .firstPrice(shippingTemplatesRegion.getFirstPrice())
                            .continues(shippingTemplatesRegion.getContinues().doubleValue())
                            .continuePrice(shippingTemplatesRegion.getContinuePrice())
                            .tempId(tempId)
                            .cityId(cityId)
                            .build();
                    templateDTOMap.put(tempId, templateDTO);
                } else {
                    TemplateDTO templateDTO = templateDTOMap.get(tempId);
                    templateDTO.setNumber(templateDTO.getNumber() + num);
                    templateDTO.setPrice(NumberUtil.add(templateDTO.getPrice().doubleValue(), price));
                }
            }


            //处理区域邮费
            boolean isFirst = true; //用来是否多个产品的标识 false表示数量大于1
            for (TemplateDTO templateDTO : templateDTOMap.values()) {
                if (isFirst) {//首件
                    //只满足首件
                    if (Double.compare(templateDTO.getNumber(), templateDTO.getFirst()) <= 0) {
                        storePostage = NumberUtil.round(NumberUtil.add(storePostage,
                                templateDTO.getFirstPrice()), 2);
                    } else {
                        BigDecimal firstPrice = NumberUtil.add(storePostage, templateDTO.getFirstPrice());

                        if (templateDTO.getContinues() <= 0) {
                            storePostage = firstPrice;
                        } else {
                            //续件平均值且向上取整数
                            double average = Math.ceil(NumberUtil.div(NumberUtil.sub(templateDTO.getNumber(),
                                    templateDTO.getFirst()),
                                    templateDTO.getContinues().doubleValue()));
                            //最终邮费
                            storePostage = NumberUtil.add(firstPrice, NumberUtil.mul(average,
                                    templateDTO.getContinuePrice()));
                        }

                    }

                    isFirst = false;
                } else {
                    //多件直接在以前的基数继续续建
                    if (templateDTO.getContinues() > 0) {
                        //续件平均值且向上取整数
                        double average = Math.ceil(
                                NumberUtil.div(
                                        templateDTO.getNumber(),
                                        templateDTO.getContinues()
                                )
                        );
                        //最终邮费
                        storePostage = NumberUtil.add(storePostage.doubleValue(), NumberUtil.mul(average,
                                templateDTO.getContinuePrice()));
                    }
                }
            }
        }
        return storePostage;
    }

    /**
     * 获取某字段价格
     *
     * @param cartInfo 购物车
     * @param key      key值
     * @return Double
     */
    private BigDecimal getOrderSumPrice(List<FsStoreCartQueryVO> cartInfo, String key) {
        BigDecimal sumPrice = BigDecimal.ZERO;

        if ("truePrice".equals(key)) {
            for (FsStoreCartQueryVO storeCart : cartInfo) {
                sumPrice = NumberUtil.add(sumPrice, NumberUtil.mul(storeCart.getCartNum(), storeCart.getPrice()));
            }
        }
        else if ("costPrice".equals(key)) {
            for (FsStoreCartQueryVO storeCart : cartInfo) {
                sumPrice = NumberUtil.add(sumPrice,
                        NumberUtil.mul(storeCart.getCartNum(), storeCart.getCost()));
            }
        }else if ("payIntegral".equals(key)) {
            for (FsStoreCartQueryVO storeCart : cartInfo) {
                if (storeCart.getIntegral() != null) {
                    sumPrice = NumberUtil.add(sumPrice,
                            NumberUtil.mul(storeCart.getCartNum(), storeCart.getIntegral()));
                }

            }
        }
        return sumPrice;
    }

    @Override
    public int uploadCredentials(FsStoreOrder order) {
        order.setUploadTime(new Date());
        return fsStoreOrderMapper.uploadCredentials(order);
    }

    @Override
    public String getCredentialsById(Long id) {

        return fsStoreOrderMapper.getCredentialsById(id);
    }

    @Override
    public List<Long> selectFsStoreOrderToPushByIds(String startTime) {
        return fsStoreOrderMapper.selectFsStoreOrderToPushByIds(startTime);
    }

    @Override
    public List<FsStoreOrder> selectFsStoreOrderItemJson() {
        return fsStoreOrderMapper.selectFsStoreOrderItemJson();
    }

    @Override
    public int uploadItemJson(FsStoreOrder order) {
        return fsStoreOrderMapper.uploadItemJson(order);
    }

    @Override
    public ExpressResultDTO updateDeliveryItem(ExpressNotifyDTO notifyDTO) {
        //RequestData={"PushTime":"2022-09-06 09:59:26","EBusinessID":"1762981","Data":[{"StateEx":"0","LogisticCode":"SF1650775430012","ShipperCode":"SF","State":"0","OrderCode":"XCRTZH22090500435","EBusinessID":"1762981","Success":false}],"Count":"1"}&DataSign=YTEwMzAxMTAzNGI4ZjQ0OTU5MWE1Y2U0NzMzYTczNWM=&RequestType=102
        //RequestData={"PushTime":"2022-09-06 10:28:41","EBusinessID":"1762981","Data":[{"StateEx":"301","LogisticCode":"SF1372196615474","ShipperCode":"SF","Traces":[{"Action":"1","AcceptStation":"顺丰速运 已收取快件","AcceptTime":"2022-09-04 15:27:25","Remark":"","Location":"重庆"},{"Action":"1","AcceptStation":"顺丰速运 已收取快件","AcceptTime":"2022-09-04 15:34:27","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件在【重庆南岸区时代都汇营业点】完成分拣,准备发往 【重庆渝北中转场】","AcceptTime":"2022-09-04 17:17:16","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件已发车","AcceptTime":"2022-09-04 17:44:37","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件到达 【重庆渝北中转场】","AcceptTime":"2022-09-04 22:13:11","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件在【重庆渝北中转场】完成分拣,准备发往 【郑州港区中转场】","AcceptTime":"2022-09-05 00:04:51","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件已发车","AcceptTime":"2022-09-05 04:45:47","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"车辆当前所在位置道路管控，等待通行中，请您耐心等待\n","AcceptTime":"2022-09-05 19:35:55","Remark":"","Location":"重庆市"},{"Action":"2","AcceptStation":"快件到达 【郑州港区中转场】","AcceptTime":"2022-09-05 22:43:06","Remark":"","Location":"郑州市"},{"Action":"2","AcceptStation":"快件在【郑州港区中转场】完成分拣,准备发往 【焦作丰收集散点】","AcceptTime":"2022-09-05 23:16:24","Remark":"","Location":"郑州市"},{"Action":"2","AcceptStation":"快件已发车","AcceptTime":"2022-09-06 00:43:25","Remark":"","Location":"郑州市"},{"Action":"2","AcceptStation":"车辆当前所在位置道路管控，等待通行中，请您耐心等待\n","AcceptTime":"2022-09-06 01:03:39","Remark":"","Location":"郑州市"},{"Action":"2","AcceptStation":"快件到达 【焦作丰收集散点】","AcceptTime":"2022-09-06 03:03:35","Remark":"","Location":"焦作市"},{"Action":"2","AcceptStation":"快件在【焦作丰收集散点】完成分拣,准备发往 【济源市济源市汤帝路营业点】","AcceptTime":"2022-09-06 06:41:58","Remark":"","Location":"焦作市"},{"Action":"2","AcceptStation":"快件已发车","AcceptTime":"2022-09-06 06:42:17","Remark":"","Location":"焦作市"},{"Action":"2","AcceptStation":"车辆当前所在位置道路管控，等待通行中，请您耐心等待\n","AcceptTime":"2022-09-06 07:58:17","Remark":"","Location":"济源市"},{"Action":"2","AcceptStation":"快件到达 【济源市济源市汤帝路营业点】","AcceptTime":"2022-09-06 08:27:59","Remark":"","Location":"济源市"},{"Action":"202","AcceptStation":"正在派送途中,请您准备签收(派件人：刘亚飞，电话：18439188789)","AcceptTime":"2022-09-06 08:28:00","Remark":"","Location":"济源市"},{"Action":"202","AcceptStation":"快件交给刘亚飞，正在派送途中（联系电话：18439188789，顺丰已开启“安全呼叫”保护您的电话隐私,请放心接听！）（主单总件数：1件）","AcceptTime":"2022-09-06 08:38:03","Remark":"","Location":"济源市"},{"Action":"301","AcceptStation":"您的快件已签收，如有疑问请电联快递员【刘亚飞，电话：18439188789】。疫情期间顺丰每日对网点消毒、快递员每日测温、配戴口罩，感谢您使用顺丰，期待再次为您服务。（主单总件数：1件）","AcceptTime":"2022-09-06 08:54:05","Remark":"","Location":"济源市"}],"State":"3","OrderCode":"SKP012000681762","EBusinessID":"1762981","Success":true,"Location":"济源市"}],"Count":"1"}&DataSign=MTNlYTA5OTJmMjgxYjhiY2FjMTZjNTYyOGYxYjVhODA=&RequestType=102
        //https://api.hospital.ifeiyu100.com/app/common/expressNotify
        String data= URLDecoder.decode(notifyDTO.getRequestData(), Charset.forName("UTF-8"));
        //ExpressInfoDTO
        logger.info("快递跟踪回调: {}",data);
        ExpressDataDTO expressDataDTO=JSONUtil.toBean(data,ExpressDataDTO.class);

        if(ObjectUtil.isNotNull(expressDataDTO)){
            List<ExpressInfoDTO> expressInfoDTOList = expressDataDTO.getData();
            List<FsStoreDelivers> delivers = new ArrayList<>();
            for (ExpressInfoDTO express : expressInfoDTOList) {
                FsStoreDelivers deliver = fsStoreDeliversService
                        .findByOrderCodeAndDeliverId(express.getLogisticCode());
                if(ObjectUtil.isNotNull(express) && express.isSuccess()){
                    if(ObjectUtil.isNotNull(deliver)){
                        deliver.setStatus(Integer.valueOf(express.getState()));
                        deliver.setStateEx(Integer.valueOf(express.getStateEx()));

                        delivers.add(deliver);
                    }
                }

                //如果无轨迹重新订阅
                if ((!express.isSuccess()&&express.getReason().equals("三天无轨迹"))||(!express.isSuccess()&&express.getReason().equals("七天内无轨迹变化"))){
                    FsStoreOrder fsStoreOrder = orderService.selectFsStoreOrderByOrderCode(express.getOrderCode());
                    String lastFourNumber = "";
                    if(StringUtils.equals(deliver.getDeliverSn(), ShipperCodeEnum.SF.getValue())){
                        lastFourNumber = PhoneUtils.getLastFourNum(fsStoreOrder.getUserPhone());
                    }
                    logger.info("物流重新订阅：{}",fsStoreOrder.getDeliveryId());
                    if(ObjectUtil.isNotNull(deliver)){
                        expressService.subscribeEspress(fsStoreOrder.getOrderCode(),deliver.getDeliverSn(),deliver.getDeliverId(),lastFourNumber);
                    }
                }
            }
            // 更新物流状态
            if(CollectionUtils.isNotEmpty(delivers)){
                fsStoreDeliversMapper.updateBatch(delivers);
                List<Long> collect = delivers.stream().map(FsStoreDelivers::getOrderId)
                        .filter(ObjectUtil::isNotNull)
                        .collect(Collectors.toList());

                for (Long orderId : collect) {
                    fsStoreDeliversService.finishOrder(orderId);
                }
            }
        }
        return ExpressResultDTO.success(sysConfig.getKdnId().trim());
    }

    @Override
    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
    public R otherPayment(FsStoreOrderOtherPayParam param) {

        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
        try {
            String ip = IpUtil.getRequestIp();
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            FsUser user=userService.selectFsUserByMaOpenId(session.getOpenid());
            if(user==null){
                //创建
                user=new FsUser();
                user.setUsername("");
                user.setNickname("微信用户");
                user.setStatus(1);
                user.setMaOpenId(session.getOpenid());
                user.setUnionId(session.getUnionid());
                user.setIsWeixinAuth(0);
                user.setLastIp(ip);
                user.setCreateTime(new Date());
                userService.insertFsUser(user);
            }
            FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
            if(order==null){
                return R.error("订单不存在");
            }
            if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
                return R.error("此订单不能支付");
            }
            if(order.getPayMoney().compareTo(new BigDecimal(0))<1){
                return R.error("此订单没有可支付的金额");
            }

            String orderId=redisCache.getCacheObject("isPaying:"+order.getId());
            if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
                return R.error("正在支付中...");
            }


            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
            String json = configService.selectConfigByKey("store.pay");
            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
            List<FsStorePayment> fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrderIdNew(order.getId());

            FsStorePayment storePayment;
            if(CollectionUtils.isEmpty(fsStorePayments)){
                storePayment=new FsStorePayment();
                storePayment.setCompanyId(order.getCompanyId());
                storePayment.setCompanyUserId(order.getCompanyUserId());
                storePayment.setStatus(0);
                storePayment.setPayMode(fsPayConfig.getType());
                storePayment.setPayCode(payCode);
                storePayment.setPayMoney(order.getPayMoney());
                storePayment.setCreateTime(new Date());
                storePayment.setPayTypeCode("weixin");
                storePayment.setBusinessType(2);
                storePayment.setRemark("商城订单支付");
                storePayment.setOpenId(session.getOpenid());
                storePayment.setUserId(user.getUserId());
                storePayment.setBusinessOrderId(order.getId().toString());
                storePayment.setOrderId(order.getId());
                fsStorePaymentMapper.insertFsStorePayment(storePayment);
            } else {
                storePayment = fsStorePayments.get(0);
                storePayment.setPayMoney(order.getPayMoney());
                storePayment.setCreateTime(new Date());
                storePayment.setPayTypeCode("weixin");
                storePayment.setBusinessType(2);
                storePayment.setRemark("商城订单支付");
                storePayment.setOpenId(session.getOpenid());
                storePayment.setUserId(user.getUserId());
                storePayment.setBusinessOrderId(order.getId().toString());
                storePayment.setOrderId(order.getId());
            }

            PaymentHandler payment = PaymentHandlerHolder.findBest(fsPayConfig.getType());
            if(ObjectUtil.isNull(payment)){
                throw new CustomException("支付方式不存在");
            }
            PayProcessContext processContext = new PayProcessContext();
            processContext.setOrderId(param.getOrderId());
            processContext.setPayType(null);
            processContext.setPaymentId(storePayment.getPaymentId());
            processContext.setPayCode(storePayment.getPayCode());
            processContext.setFsPayConfig(fsPayConfig);
            processContext.setUserId(order.getUserId());
            processContext.setGoodsInfo("商城订单支付");
            processContext.setOrderPrefix("store-");

            R process = payment.createOrder(processContext);
            if("200".equals(String.valueOf(process.get("code")))){
                redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                return process;
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }
        return R.error("无支付类型");
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
    public R otherPaymentRemain(FsStoreOrderOtherPayParam param) {
        final WxMaService wxService = WxMaConfiguration.getMaService(properties.getConfigs().get(0).getAppid());
        try {
            String ip = IpUtil.getRequestIp();
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            FsUser user=userService.selectFsUserByMaOpenId(session.getOpenid());
            if(user==null){
                //创建
                user=new FsUser();
                user.setUsername("");
                user.setNickname("微信用户");
                user.setStatus(1);
                user.setMaOpenId(session.getOpenid());
                user.setUnionId(session.getUnionid());
                user.setIsWeixinAuth(0);
                user.setLastIp(ip);
                user.setCreateTime(new Date());
                userService.insertFsUser(user);
            }
            FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
            if(order==null){
                return R.error("订单不存在");
            }
            if(order.getStatus()!= OrderInfoEnum.STATUS_2.getValue()){
                return R.error("待收货订单可申请支付尾款");
            }
            if(order.getPayType().equals(1)){
                return R.error("此订单已支付");
            }
            //只有顺风才可以付尾
            if(!order.getDeliverySn().trim().equals("SF")){
                return R.error("只有顺丰物流支持尾款支付");
            }

            if(!order.getIsPayRemain().equals(0)){
                return R.error("此订单已支付");
            }
            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
            //易宝支付
            String json = configService.selectConfigByKey("store.pay");
            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);
            FsStorePayment storePayment=new FsStorePayment();
            storePayment.setCompanyId(order.getCompanyId());
            storePayment.setCompanyUserId(order.getCompanyUserId());
            storePayment.setStatus(0);
            storePayment.setPayCode(payCode);
            storePayment.setPayMoney(order.getPayDelivery());
            storePayment.setCreateTime(new Date());
            storePayment.setPayTypeCode("weixin");
            storePayment.setBusinessType(2);
            storePayment.setRemark("商城订单尾款支付");
            storePayment.setOpenId(user.getRealName());
            storePayment.setUserId(user.getUserId());
            storePayment.setBusinessOrderId(order.getId().toString());
            storePayment.setOrderId(order.getId());
            storePayment.setIsPayRemain(1);
            storePayment.setPayMode(fsPayConfig.getType());
            fsStorePaymentMapper.insertFsStorePayment(storePayment);
            if (fsPayConfig.getType().equals("hf")){
                HuiFuCreateOrder o = new HuiFuCreateOrder();
                o.setTradeType("T_MINIAPP");
                o.setOpenid(user.getMaOpenId());
                o.setReqSeqId("store_remain-"+storePayment.getPayCode());
                o.setTransAmt(storePayment.getPayMoney().toString());
                o.setGoodsDesc("支付订单尾款");
                HuifuCreateOrderResult result = huiFuService.createOrder(o);
                if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
                    FsStorePayment mt=new FsStorePayment();
                    mt.setPaymentId(storePayment.getPaymentId());
                    mt.setTradeNo(result.getHf_seq_id());
                    fsStorePaymentMapper.updateFsStorePayment(mt);
                    redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                    return R.ok().put("result",result.getPay_info());
                }else{
                    return R.error(result.getResp_desc());
                }
            }else if (fsPayConfig.getType().equals("yb")){
                WxJspayDTO p = new WxJspayDTO();
                // 使用setter方法为对象赋值
                p.setPayMoney(order.getPayDelivery().toString());
                p.setLowOrderId("store_remain-"+payCode);
                p.setBody("支付订单尾款");
                p.setIsMinipg("1");
                p.setReturnUrl(fsPayConfig.getYbNotifyUrl());
                p.setOpenId(user.getMaOpenId());
                p.setAttach("");
                p.setStoreid("0");
                CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);
                if(wxOrder.getStatus().equals("100")){
                    FsStorePayment ment=new FsStorePayment();
                    ment.setPaymentId(storePayment.getPaymentId());
                    ment.setTradeNo(wxOrder.getUpOrderId());
                    fsStorePaymentMapper.updateFsStorePayment(ment);
                    return R.ok().put("result",wxOrder.getPay_info());
                }
                else{
                    return R.error(wxOrder.getMessage());
                }
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
            return R.error(e.getMessage());
        }

        return R.error("无支付类型");
    }

    @Override
    public R getStoreOrderByOrderIdTz(Long orderId, String payCode) {
        // 根据订单查询payment
        if(ObjectUtil.isNull(orderId)&&ObjectUtil.isNull(payCode)){
            return R.error("参数错误");
        }

        List<FsStorePayment> fsStorePayments;
        if(ObjectUtil.isNotNull(orderId)){
            fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByOrder(orderId);
        } else{
            fsStorePayments = fsStorePaymentMapper.selectFsStorePaymentByPayCode(payCode);
        }
        // 如果已经有支付成功的记录
        if(CollectionUtils.isNotEmpty(fsStorePayments)){
            for (FsStorePayment fsStorePayment : fsStorePayments) {
                // 如果状态为已支付或者已经退款
                if(ObjectUtil.equal(fsStorePayment.getStatus(),1) || ObjectUtil.equal(fsStorePayment.getStatus(), -1)){
                    return R.ok().put("orderId", orderId)
                            .put("payCode", payCode)
                            .put("status", fsStorePayment.getStatus());
                }
            }
        }
        // 如果没找到，查看付款信息是否有未支付的 且 类型为tzbank 且 trade_no 不为空的数据
        // 调用台州银行接口查询订单信息
        List<FsStorePayment> fsStorePayments1;
        if(ObjectUtil.isNotNull(orderId)){
            fsStorePayments1 = fsStorePaymentMapper.selectFsStorePaymentTzUnpayByOrder(orderId);
        } else {
            fsStorePayments1 = fsStorePaymentMapper.selectFsStorePaymentTzUnpayByPayCode(payCode);
        }

        if(CollectionUtils.isNotEmpty(fsStorePayments1)){
            FsStorePayment fsStorePayment = fsStorePayments1.get(0);

            RequestDTO<QueryOrderRestDTO> requestDTO = new RequestDTO<>();

            QueryOrderRestDTO queryOrderRestDTO = new QueryOrderRestDTO();

            queryOrderRestDTO.setOrderFlowNo(fsStorePayment.getTradeNo());
            TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();

            queryOrderRestDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());

            requestDTO.setReqBody(queryOrderRestDTO);
            requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(fsStorePayment.getPayCode()));

            TzReqResultDTO<QueryOrderInfoDTO> resultDTO = null;
            try {
                resultDTO = tzBankService.payQueryOrder(requestDTO);
                String retCode = resultDTO.getRetCode();
                // 如果查询支付成功
                if(retCode.equals("00000000")){
                    QueryOrderInfoDTO body = resultDTO.getBody();
                    String status = body.getStatus();
                    if("90".equals(status)){
                        // 如果查询支付成功 更新订单状态
                        orderService.payConfirm(1,orderId,fsStorePayment.getPayCode(),
                                fsStorePayment.getTradeNo(),body.getChlTrxId(),fsStorePayment.getTradeNo());
                        return R.ok().put("orderId", orderId)
                                .put("payCode", payCode)
                                .put("status", 1);
                    } else if("70".equals(status)) {
                        return R.ok().put("orderId", orderId)
                                .put("payCode", payCode)
                                .put("status", -1);
                    }

                }
            } catch (Exception e) {
                logger.error("台州银行支付回调查询失败:",e);
            }

        }
        FsStoreOrder order=orderService.selectFsStoreOrderById(orderId);

        if(ObjectUtil.isNotNull(order)){
            return R.ok().put("orderId",orderId)
                    .put("payCode", payCode)
                    .put("status", order.getStatus());
        } else {
            // 如果没有订单信息可能是从微信收款而来
            return R.ok().put("orderId", orderId)
                    .put("payCode", payCode)
                    .put("status", 0);
        }
    }

    @Override
    public R getStoreOrderById(Long orderId) {
        FsStoreOrder order=orderService.selectFsStoreOrderById(orderId);
        if(ObjectUtil.isNull(order)){
            return R.error("订单不存在");
        }
        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
        order.setUserAddress(ParseUtils.parseIdCard(order.getUserAddress()));
        String json=configService.selectConfigByKey("store.config");
        StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(order.getCreateTime());
        calendar.add(Calendar.MINUTE,config.getUnPayTime());
        String payLimitTime = DateUtil.format(calendar.getTime(),"yyyy-MM-dd HH:mm:ss");
        FsStoreProductPackage productPackage=null;
        if(order.getIsPackage()!=null&&order.getIsPackage()==1){

            productPackage= productPackageService.selectFsStoreProductPackageById(order.getPackageId());
        }
        return R.ok().put("order",order).put("productPackage",productPackage).put("payLimitTime",payLimitTime);
    }

    @Override
    public R getMyStoreOrderById(Long orderId) {
        FsStoreOrder order=orderService.selectFsStoreOrderById(orderId);
        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
        order.setUserAddress(ParseUtils.parseIdCard(order.getUserAddress()));
        List<FsStoreOrderItemVO> list=itemService.selectFsStoreOrderItemListByOrderId(orderId);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(order.getCreateTime());
        String json=configService.selectConfigByKey("store.config");
        StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
        calendar.add(Calendar.MINUTE,config.getUnPayTime());
        SimpleDateFormat format = new   SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String payLimitTime = format.format(calendar.getTime() );
        FsPrescribe prescribe=null;
        if(order.getPrescribeId()!=null){
            prescribe=prescribeService.selectFsPrescribeById(order.getPrescribeId());
        }
        //处理是否可以申请售后
        Integer isAfterSales=0;
        if(order.getStatus().equals(OrderInfoEnum.STATUS_3.getValue())) {
            //已完成订单 如果是私域用户就不允许售后
            if(ObjectUtil.isNotNull(order.getCompanyId())){
                isAfterSales=0;
            } else {
                isAfterSales=1;
                if (order.getFinishTime() != null) {
                    if (config.getStoreAfterSalesDay() != null && config.getStoreAfterSalesDay() > 0) {
                        //判断完成时间是否超过指定时间
                        Calendar calendarAfterSales = new GregorianCalendar();
                        calendarAfterSales.setTime(order.getFinishTime());
                        calendarAfterSales.add(calendarAfterSales.DATE, config.getStoreAfterSalesDay()); //把日期往后增加一天,整数  往后推,负数往前移动
                        if (calendarAfterSales.getTime().getTime() < new Date().getTime()) {
                            isAfterSales = 0;
                        }
                    }
                }
            }
        }
        else if(order.getStatus()==1||order.getStatus()==2){
            isAfterSales=1;
        }
//        Integer payment = paymentService.selectFsStorePaymentByOrderIdExists(order.getId());

        return R.ok().put("isAfterSales",isAfterSales)
                .put("order",order)
                .put("items",list)
                .put("payLimitTime",payLimitTime)
//                .put("showCancelOrder", (payment==null?0:payment) != 0)
                .put("prescribe",prescribe);
    }

    @Override
    public R getMyStoreOrderByIdOrOrderCode(Long orderId, String orderCode) {
        FsStoreOrder order;
        if(orderCode != null){
            order=orderService.selectFsStoreOrderByOrderCode(orderCode);
        } else {
            order=orderService.selectFsStoreOrderById(orderId);
        }

        order.setUserPhone(ParseUtils.parsePhone(order.getUserPhone()));
        order.setUserAddress(ParseUtils.parseIdCard(order.getUserAddress()));
        List<FsStoreOrderItemVO> list=itemService.selectFsStoreOrderItemListByOrderId(orderId);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(order.getCreateTime());
        String json=configService.selectConfigByKey("store.config");
        StoreConfig config=JSONUtil.toBean(json,StoreConfig.class);
        calendar.add(Calendar.MINUTE,config.getUnPayTime());
        SimpleDateFormat format = new   SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String payLimitTime = format.format(calendar.getTime() );
        FsPrescribe prescribe=null;
        if(order.getPrescribeId()!=null){
            prescribe=prescribeService.selectFsPrescribeById(order.getPrescribeId());
        }
        //处理是否可以申请售后
        Integer isAfterSales=0;
        if(order.getStatus().equals(OrderInfoEnum.STATUS_3.getValue())) {
            //已完成订单 如果是私域用户就不允许售后
            if(ObjectUtil.isNotNull(order.getCompanyId())){
                isAfterSales=0;
            } else {
                isAfterSales=1;
                if (order.getFinishTime() != null) {
                    if (config.getStoreAfterSalesDay() != null && config.getStoreAfterSalesDay() > 0) {
                        //判断完成时间是否超过指定时间
                        Calendar calendarAfterSales = new GregorianCalendar();
                        calendarAfterSales.setTime(order.getFinishTime());
                        calendarAfterSales.add(calendarAfterSales.DATE, config.getStoreAfterSalesDay()); //把日期往后增加一天,整数  往后推,负数往前移动
                        if (calendarAfterSales.getTime().getTime() < new Date().getTime()) {
                            isAfterSales = 0;
                        }
                    }
                }
            }
        }
        else if(order.getStatus()==1||order.getStatus()==2){
            isAfterSales=1;
        }
//        Integer payment = paymentService.selectFsStorePaymentByOrderIdExists(order.getId());

        return R.ok().put("isAfterSales",isAfterSales)
                .put("order",order)
                .put("items",list)
                .put("payLimitTime",payLimitTime)
//                .put("showCancelOrder", (payment==null?0:payment) != 0)
                .put("prescribe",prescribe);
    }

    @Override
    @Transactional(rollbackFor = Throwable.class,propagation = Propagation.REQUIRED)
    public R editPayType(FsStoreOrderPayParam param) {
        FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
        if(order==null){
            return R.error("订单不存在");
        }
        if(order.getStatus()!= OrderInfoEnum.STATUS_0.getValue()){
            return R.error("订单状态不正确");
        }

        String orderId=redisCache.getCacheObject("isPaying:"+order.getId());
        if(StringUtils.isNotEmpty(orderId)&&orderId.equals(order.getId().toString())){
            return R.error("正在支付中...");
        }
        List<FsStorePayment>  payments=fsStorePaymentMapper.selectFsStorePaymentByOrder(order.getId());
        if(payments.size()>0){
            for(FsStorePayment payment : payments){
                if(StringUtils.isEmpty(payment.getTradeNo())){
                    continue;
                }
                OrderQueryDTO orderQueryDTO = new OrderQueryDTO();
                orderQueryDTO.setLowOrderId("store-"+payment.getPayCode());
                RequestDTO<QueryOrderRestDTO> requestDTO = new RequestDTO<>();

                QueryOrderRestDTO queryOrderRestDTO = new QueryOrderRestDTO();

                queryOrderRestDTO.setOrderFlowNo(payment.getTradeNo());
                TzConfigInfoDTO tzConfigInfoDTO = TzConfigUtils.getConfig();

                queryOrderRestDTO.setPlatMerCstNo(tzConfigInfoDTO.getPlatMerCstNo());

                requestDTO.setReqBody(queryOrderRestDTO);
                requestDTO.setReqHeader(TzReqHeaderDTO.getInstance(payment.getPayCode()));
                try {
                    TzReqResultDTO<QueryOrderInfoDTO> resultDTO = tzBankService.payQueryOrder(requestDTO);
                    if(ObjectUtil.isNotNull(resultDTO)){
                        QueryOrderInfoDTO body = resultDTO.getBody();
                        if(ObjectUtil.isNotNull(body)){
                            if("80".equals(body.getStatus()) || "90".equals(body.getStatus())){
                                // 更新订单状态和支付状态
//                                payment.setStatus(1);
//                                fsStorePaymentMapper.updateFsStorePayment(payment);
                                orderService.payConfirm(1, order.getId(), payment.getPayCode(),
                                        payment.getTradeNo(),
                                        body.getChlTrxId(),
                                        payment.getTradeNo());
                                return R.error("订单已支付，请刷新页面");
                            }
                        }
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        FsUser user=userService.selectFsUserById(order.getUserId());
        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
            //已改价处理
            if(order.getIsEditMoney()!=null&&order.getIsEditMoney()==1){
                //改过价不做处理
            }
            else{
                String config=configService.selectConfigByKey("store.config");
                StoreConfig storeConfig= JSONUtil.toBean(config,StoreConfig.class);
                if(param.getPayType().equals(1)){
                    order.setPayType("1");
                    order.setPayMoney(order.getPayPrice());
                    order.setPayDelivery(BigDecimal.ZERO);
                }
                else if(param.getPayType().equals(2)){

                    order.setPayType("2");
                    BigDecimal payMoney=order.getPayPrice().multiply(new BigDecimal(storeConfig.getPayRate())).divide(new BigDecimal(100));
                    payMoney=new BigDecimal(payMoney.setScale(0, BigDecimal.ROUND_HALF_UP).longValue());
                    order.setPayDelivery(order.getPayPrice().subtract(payMoney));
                    order.setPayMoney(payMoney);
                }
                else if(param.getPayType().equals(3)){
                    //货到付款
                    order.setPayType("3");
                    order.setPayDelivery(order.getPayPrice() );
                    order.setPayMoney(BigDecimal.ZERO);
                }
                orderService.updateFsStoreOrder(order);
            }
            return R.ok().put("order",order);
        }
        else{
            return R.error("用户OPENID不存在");
        }
    }

    @Override
    @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
    public R payRemain(FsStoreOrderPayParam param) {
        FsStoreOrder order=orderService.selectFsStoreOrderById(param.getOrderId());
        if(order==null){
            return R.error("订单不存在");
        }
        if(order.getStatus()!= OrderInfoEnum.STATUS_2.getValue()){
            return R.error("待收货订单可申请支付尾款");
        }
        if(order.getPayType().equals(1)){
            return R.error("此订单已支付");
        }
        //只有顺风才可以付尾
        if(!order.getDeliverySn().trim().equals("SF")){
            return R.error("只有顺丰物流支持尾款支付");
        }

        if(!order.getIsPayRemain().equals(0)){
            return R.error("此订单已支付");
        }
        FsUser user=userService.selectFsUserById(order.getUserId());
        if(user!=null&& StringUtils.isNotEmpty(user.getMaOpenId())){
            String payCode = IdUtil.getSnowflake(0, 0).nextIdStr();
            String json = configService.selectConfigByKey("store.pay");
            FsPayConfig fsPayConfig = JSON.parseObject(json, FsPayConfig.class);

            FsStorePayment storePayment=new FsStorePayment();
            storePayment.setCompanyId(order.getCompanyId());
            storePayment.setCompanyUserId(order.getCompanyUserId());
            storePayment.setStatus(0);
            storePayment.setPayMode(fsPayConfig.getType());
            storePayment.setPayCode(payCode);
            storePayment.setPayMoney(order.getPayDelivery());
            storePayment.setCreateTime(new Date());
            storePayment.setPayTypeCode("weixin");
            storePayment.setBusinessType(2);
            storePayment.setRemark("商城订单尾款支付");
            storePayment.setOpenId(user.getRealName());
            storePayment.setUserId(user.getUserId());
            storePayment.setBusinessOrderId(order.getId().toString());
            storePayment.setOrderId(order.getId());
            storePayment.setIsPayRemain(1);
            fsStorePaymentMapper.insertFsStorePayment(storePayment);
            if (fsPayConfig.getType().equals("hf")){
                HuiFuCreateOrder o = new HuiFuCreateOrder();
                o.setTradeType("T_MINIAPP");
                o.setOpenid(user.getMaOpenId());
                o.setReqSeqId("store_remain-"+storePayment.getPayCode());
                o.setTransAmt(storePayment.getPayMoney().toString());
                o.setGoodsDesc("商城订单尾款支付");
                HuifuCreateOrderResult result = huiFuService.createOrder(o);
                //创建订单
                if(result.getResp_code()!=null&&(result.getResp_code().equals("00000000")||result.getResp_code().equals("00000100"))){
                    FsStorePayment mt=new FsStorePayment();
                    mt.setPaymentId(storePayment.getPaymentId());
                    mt.setTradeNo(result.getHf_seq_id());
                    fsStorePaymentMapper.updateFsStorePayment(mt);
                    redisCache.setCacheObject("isPaying:"+order.getId(),order.getId().toString(),1, TimeUnit.MINUTES);
                    return R.ok().put("result",result.getPay_info());
                }
                else{
                    return R.error(result.getResp_desc());
                }
            }else if(fsPayConfig.getType().equals("yb")){
                WxJspayDTO p = new WxJspayDTO();
                // 使用setter方法为对象赋值
                p.setPayMoney(order.getPayDelivery().toString());
                p.setLowOrderId("store_remain-"+payCode);
                p.setBody("商城订单尾款支付");
                p.setIsMinipg("1");
                p.setReturnUrl(fsPayConfig.getYbNotifyUrl());
                p.setOpenId(user.getMaOpenId());
                p.setAttach("");
                p.setStoreid("0");
                CreateWxOrderResult wxOrder = ybPayService.createWxOrder(p);
                if(wxOrder.getStatus().equals("100")){
                    FsStorePayment ment=new FsStorePayment();
                    ment.setPaymentId(storePayment.getPaymentId());
                    ment.setTradeNo(wxOrder.getUpOrderId());
                    fsStorePaymentMapper.updateFsStorePayment(ment);
                    return R.ok().put("result",wxOrder.getPay_info());
                }
                else{
                    return R.error(wxOrder.getMessage());
                }
            }
        }
        else{
            return R.error("用户OPENID不存在");
        }
        return R.error("无支付类型");
    }

    /**
     * 校验支付请求中的 payType 与下单时一致，禁止支付环节修改支付方式。
     */
    private R validatePayTypeNotModified(FsStoreOrder order, Integer requestPayType) {
        if (requestPayType == null) {
            return R.error("支付类型不能为空");
        }
        if (StringUtils.isEmpty(order.getPayType())) {
            return R.error("订单支付类型异常");
        }
        if (!Objects.equals(String.valueOf(requestPayType), order.getPayType())) {
            return R.error("不允许修改支付类型");
        }
        return null;
    }

}
