package com.liquidnet.service.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.UserPathDto;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.AddressVo;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderParam;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderSkuParam;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderStoreParam;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinOrderAttr;
import com.liquidnet.service.goblin.entity.GoblinOrderSku;
import com.liquidnet.service.goblin.entity.GoblinStoreOrder;
import com.liquidnet.service.goblin.param.*;
import com.liquidnet.service.goblin.param.BackCouponParam;
import com.liquidnet.service.goblin.service.IGoblinOrderService;
import com.liquidnet.service.order.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.liquidnet.commons.lang.util.DateUtil.*;

@Service
@Slf4j
public class GoblinOrderServiceImpl implements IGoblinOrderService {

    @Autowired
    GoblinRedisUtils redisUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinOrderUtils orderUtils;

    @Value("${liquidnet.service.order.url-pay.pay}")
    private String payUrl;
    @Value("${liquidnet.service.order.url-pay.check}")
    private String checkUrl;
    @Value("${liquidnet.service.order.url-pay.goblinUrl}")
    private String synUrl;

    @Override
    public ResponseDto<GoblinPayInnerResultVo> checkOrder(GoblinOrderParam param, String uid) {
        List<String> skuAndPreListAndNumber = CollectionUtil.arrayListString();
        List<String> platformCodeList = CollectionUtil.arrayListString();
        List<String> storeCodeList = CollectionUtil.arrayListString();
        List<String> storeSpuIds = CollectionUtil.linkedListString();
        List<GoblinOrderSqlParam> orderSqlParams = ObjectUtil.getGoblinOrderSqlParamArrayListList();
        String orderMasterCode = IDGenerator.storeMasterCode();//总订单id

        GoblinOrderPreParam preParam = GoblinOrderPreParam.getNew();
        preParam.setAuthCode(param.getAuthCode());
        preParam.setPayType(param.getPayType());
        preParam.setDeviceFrom(param.getDeviceFrom());
        preParam.setOpenId(param.getOpenId());
        preParam.setReturnUrl(param.getReturnUrl());
        preParam.setShowUrl(param.getShowUrl());
        preParam.setOrderMasterCode(orderMasterCode);
        preParam.setExpireTime(5);
        preParam.setPriceActual(BigDecimal.ZERO);
        preParam.setStoreName("");
        preParam.setSkuName("");
        preParam.setOrderIdList("");
        try {
            List<GoblinOrderStoreParam> goblinOrderStoreParamList = param.getGoblinOrderStoreParamList();//分订单
            boolean isMember;
            AddressVo addressesVo = null;
            if (orderUtils.noZhengzaiOrder(uid)) {
                addressesVo = param.getAddressesVo();
                if (orderUtils.getMember(uid) != null) {
                    isMember = true;
                } else {
                    isMember = false;
                }
            } else {
                isMember = false;
            }
            for (GoblinOrderStoreParam storeParam : goblinOrderStoreParamList) {//商铺维度循环
                String orderId = IDGenerator.nextSnowId();
                String orderCode = IDGenerator.storeCode(orderId);
                for (GoblinOrderSkuParam skuParam : storeParam.getGoblinOrderSkuParamArrayList()) {//商品维度循环
                    String skuId = skuParam.getSkuId();
                    int number = skuParam.getNumber();
                    String pre = GoblinStatusConst.MarketPreStatus.getPre(skuId);
                    int surplusGeneral = redisUtils.decrSkuStock(pre, skuId, number);
                    skuAndPreListAndNumber.add(skuId + "," + pre + "," + number);
                    // 判断库存
                    GoblinGoodsSkuInfoVo skuVo = redisUtils.getGoodsSkuInfoVo(skuParam.getSkuId());
                    int limitCount = skuVo.getBuyLimit() == 0 ? Integer.MAX_VALUE : skuVo.getBuyLimit();
                    //判断限购
                    if (orderUtils.noZhengzaiOrder(uid)) {
                        String res1 = orderUtils.judgeOrderLimit(uid, skuParam.getSkuId(), skuParam.getNumber(), limitCount);
                        if (!res1.equals("")) {
                            throw new Exception("已超出限购数量");
                        }
                        //权限限购
                        Boolean res2 = orderUtils.judgeOrderRose(isMember, skuParam.getSkuId(), StringUtils.defaultString(((String) CurrentUtil.getTokenClaims().get("mobile")), ""), Integer.parseInt(skuVo.getBuyFactor()));
                        if (!res2) {
                            throw new Exception("无权购买");
                        }
                    }
                    //库存回滚
                    if (surplusGeneral < 0) {
                        return orderUtils.orderException(skuAndPreListAndNumber, platformCodeList, storeCodeList, uid, "库存不足");
//                        throw new Exception("库存不足");
                    }
                }//GoblinOrderSkuParam
                //下单
                GoblinOrderPreParam pre = order(param, storeParam, uid, isMember, addressesVo, orderMasterCode, orderId, orderCode, platformCodeList, storeCodeList);
                preParam.setPriceActual(preParam.getPriceActual().add(pre.getPriceActual()));
                preParam.setStoreName(pre.getStoreName() + "," + preParam.getStoreName());
                preParam.setSkuName(preParam.getSkuName() + "," + pre.getSkuName());
                preParam.setOrderIdList(preParam.getOrderIdList() + "," + pre.getOrderIdList());
                preParam.setPlatformSpuIds(pre.getPlatformSpuIds());
                storeSpuIds.addAll(pre.getStoreSpuIds());
                preParam.setStoreSpuIds(storeSpuIds);

                GoblinOrderSqlParam sqlParam = GoblinOrderSqlParam.getNew();
                sqlParam.setStoreOrder(pre.getStoreOrder());
                sqlParam.setOrderAttr(pre.getOrderAttr());
                sqlParam.setOrderSkuList(pre.getOrderSkuList());
                orderSqlParams.add(sqlParam);
            }//GoblinOrderStoreParam
            if (preParam.getOrderIdList().equals("")) {
                return orderUtils.orderException(skuAndPreListAndNumber, platformCodeList, storeCodeList, uid, "参数异常");
//                throw new Exception("参数异常");
            }
            return payOrder(preParam, orderSqlParams, uid);
        } catch (Exception e) {
            log.error("Kylin Order Pay Error = {}", e);
            Long time3 = System.currentTimeMillis();
            //回顾限购 回滚库存
            for (String item : skuAndPreListAndNumber) {
                String[] array = item.split(",");
                String skuId = array[0];
                String pre = array[1];
                int number = Integer.parseInt(array[2]);
                redisUtils.incrSkuStock(pre, skuId, number);
                if (orderUtils.noZhengzaiOrder(uid)) {
                    redisUtils.decrSkuCountByUid(uid, skuId, number);
                }
            }
            //回退平台券
            for (String platformCode : platformCodeList) {
                orderUtils.backCoupon(platformCode, uid);
            }
            //回退店铺券
            List<BackCouponParam> params = ObjectUtil.getBackCouponParam();
            for (String storeCode : storeCodeList) {
                BackCouponParam backCouponParam = BackCouponParam.getNew();
                backCouponParam.setuCouponIds(storeCode);
                backCouponParam.setUid(uid);
                params.add(backCouponParam);
            }
            if (params.size() > 0) {
                orderUtils.backStoreCoupon(params);
            }
            if (e.getMessage() == null) {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            } else if (e.getMessage().equals("平台券不可用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("无权购买")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("平台券店铺券不可一起使用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("平台券店铺券不可一起使用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("跨店铺购物平台券不可用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("店铺券不可用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("不可购买")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("参数异常")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("库存不足")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("已超出限购数量")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("非法参数")) {
                return ResponseDto.failure(e.getMessage());
            } else {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            }
        }
    }

    private GoblinOrderPreParam order(GoblinOrderParam param, GoblinOrderStoreParam storeParam, String uid, boolean isMember, AddressVo addressesVo, String orderMasterCode, String orderId, String orderCode, List<String> platformCodeList, List<String> storeCodeList) throws Exception {
        String platVoucherCode = storeParam.getPlatVoucherCode();
        String storeVoucherCode = storeParam.getStoreVoucherCode();
        String storeId = storeParam.getStoreId();
        Map token = CurrentUtil.getTokenClaims();
        String headerCliSource = CurrentUtil.getHeaderCliSource(), headerCliVersion = CurrentUtil.getHeaderCliVersion();
        String source = headerCliSource == null ? "" : headerCliSource;
        String version = headerCliVersion == null ? "" : headerCliVersion;
        LocalDateTime now = LocalDateTime.now();
        String skuName = "";
        BigDecimal price;//sku应付价格
        BigDecimal priceBase;//sku原价
        BigDecimal storeTotalPrice = BigDecimal.ZERO;//订单总金额
        String writeOffCode = ""; //取货码
        List<GoblinOrderSku> goblinOrderSkuList = ObjectUtil.getGoblinOrderSkuArrayList();
        List<String> storeSpuIds = CollectionUtil.linkedListString();
        List<String> platformSpuIds = CollectionUtil.linkedListString();
        String marketId = "";
        String marketType = "";
        for (GoblinOrderSkuParam skuParam : storeParam.getGoblinOrderSkuParamArrayList()) {
            String pre = GoblinStatusConst.MarketPreStatus.getPre(skuParam.getSkuId());
            GoblinGoodsSkuInfoVo skuVo = redisUtils.getGoodsSkuInfoVo(skuParam.getSkuId());
            GoblinGoodsInfoVo spuVo = redisUtils.getGoodsInfoVo(skuParam.getSpuId());
            if (!spuVo.getStoreId().equals(storeParam.getStoreId()) || !skuVo.getStoreId().equals(storeParam.getStoreId())) {
                throw new Exception("非法参数");
            }
            if (!(skuVo.getStatus().equals("3") && skuVo.getShelvesStatus().equals("3")) || skuVo.getDelFlg().equals("1")) {
                throw new Exception("不可购买");
            }
            marketId = spuVo.getMarketId();
            marketType = pre;
            skuName = skuName.concat(skuVo.getName()).concat(",");
            if (pre != null && pre.equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {
                writeOffCode = "EMPTY";
            }
            //获得 活动原价
            price = skuVo.getPrice();
            if (isMember) {
                price = skuVo.getPriceMember();
            }
            //活动价格
//            if (pre != null) {
//                GoblinGoodsSkuInfoVo skuMarketVo = redisUtils.getGoodsSkuInfoVo(skuParam.getSkuId().split(pre)[0]);
//                priceBase = skuMarketVo.getPrice();
//                if (isMember) {
//                    priceBase = skuMarketVo.getPriceMember();
//                }
//            } else {
            priceBase = skuVo.getPrice();
            if (isMember) {
                priceBase = skuVo.getPriceMember();
            }
//            }
            //todo
            //获得活动优惠价格
//            priceBase = priceBase.multiply(BigDecimal.valueOf(skuParam.getNumber()));
            price = price.multiply(BigDecimal.valueOf(skuParam.getNumber()));
            storeTotalPrice = storeTotalPrice.add(price);
            //订单sku
            GoblinOrderSku orderSku = GoblinOrderSku.getNew();
            orderSku.setOrderSkuId(IDGenerator.nextTimeId2());
            orderSku.setOrderId(orderId);
            orderSku.setStatus(GoblinStatusConst.Status.ORDER_STATUS_0.getValue());
            orderSku.setSpuId(skuParam.getSpuId());
            orderSku.setSpuName(spuVo.getName());
            orderSku.setSkuId(skuParam.getSkuId());
            orderSku.setNum(skuParam.getNumber());
            orderSku.setSkuPrice(priceBase);
            orderSku.setSkuPriceActual(price);
            orderSku.setSkuName(skuVo.getName());
            orderSku.setSkuNo(skuVo.getSkuNo());
            orderSku.setSkuImage(skuVo.getSkuPic());
            orderSku.setSkuSpecs(JSON.toJSONString(skuVo.getSkuSpecList()));
            orderSku.setPriceVoucher(BigDecimal.ZERO);
//            orderSku.setPriceVoucher(priceBase.subtract(price));
            orderSku.setCreatedAt(now);
            orderSku.setSpuName(spuVo.getName());
            orderSku.setSpuPic(spuVo.getCoverPic());
            goblinOrderSkuList.add(orderSku);
        }


        if ((platVoucherCode != null && !platVoucherCode.equals("")) && (storeVoucherCode != null && !storeVoucherCode.equals(""))) {
            throw new Exception("平台券店铺券不可一起使用");
        }

        if (param.getGoblinOrderStoreParamList().size() > 1 && (platVoucherCode != null && !platVoucherCode.equals(""))) {
            throw new Exception("跨店铺购物平台券不可用");
        }

        //优惠券
        BigDecimal voucherPrice = BigDecimal.ZERO;
        if (platVoucherCode != null && !platVoucherCode.equals("")) {
            String spuIds = "";
            for (GoblinOrderSkuParam item : storeParam.getGoblinOrderSkuParamArrayList()) {
                String pre = GoblinStatusConst.MarketPreStatus.getPre(item.getSpuId());
                if (pre != null) {
                    spuIds = spuIds.concat(item.getSpuId().split(pre)[0] + ",");
                } else {
                    spuIds = spuIds.concat(item.getSpuId() + ",");
                }
            }
            HashMap<String, Object> hashMap = orderUtils.useCoupon(platVoucherCode, "购买商品[" + orderCode + "]", storeTotalPrice, spuIds, uid, goblinOrderSkuList);
            if (hashMap != null) {
                voucherPrice = (BigDecimal) hashMap.get("voucher");
                Integer typeVoucher = (Integer) hashMap.get("type");
                if (typeVoucher.equals(-1)) {
                    throw new Exception("平台券不可用");
                } else {
                    platformCodeList.add(platVoucherCode);
                    platformSpuIds = (List<String>) hashMap.get("spuIds");
                }
            }
        }
        //商铺券
        BigDecimal storeVoucherPrice = BigDecimal.ZERO;
        if (storeVoucherCode != null && !storeVoucherCode.equals("")) {
            GoblinUseResultVo storeCouponVo = orderUtils.useStoreCoupon(storeVoucherCode, "购买商品[" + orderCode + "]", storeTotalPrice, goblinOrderSkuList, uid);
            String typeVoucher;
            if (storeCouponVo != null) {
                storeVoucherPrice = storeCouponVo.getValue();
                typeVoucher = storeCouponVo.getCouType();
                if (typeVoucher.equals("-1")) {
                    throw new Exception("店铺券不可用");
                } else {
                    storeCodeList.add(storeVoucherCode);
                    storeSpuIds = storeCouponVo.getSpuIds();
                }
            }
        }

        GoblinStoreInfoVo storeInfoVo = redisUtils.getStoreInfoVo(storeId);
        //生成订单
        GoblinStoreOrder storeOrder = GoblinStoreOrder.getNew();
        storeOrder.setMasterOrderCode(orderMasterCode);
        storeOrder.setOrderId(orderId);
        storeOrder.setStoreId(storeId);
        storeOrder.setStoreName(storeInfoVo.getStoreName());
        storeOrder.setOrderCode(orderCode);
        storeOrder.setUserId(uid);
        storeOrder.setUserName(StringUtils.defaultString(((String) token.get("nickname")), ""));
        storeOrder.setUserMobile(StringUtils.defaultString(((String) token.get("mobile")), ""));
        if (addressesVo == null) {
            storeOrder.setPriceExpress(BigDecimal.ZERO);
        } else {
            storeOrder.setPriceExpress(BigDecimal.TEN);
        }
        storeOrder.setPriceTotal(storeTotalPrice.add(storeOrder.getPriceExpress()));
        BigDecimal priceActual = storeOrder.getPriceTotal().subtract(voucherPrice).subtract(storeVoucherPrice);
        if (priceActual.compareTo(storeOrder.getPriceExpress()) < 0) {
            priceActual = storeOrder.getPriceExpress();
        }
        storeOrder.setPriceActual(priceActual.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : priceActual);
        storeOrder.setPriceRefund(BigDecimal.ZERO);
        storeOrder.setPriceCoupon(voucherPrice);
        storeOrder.setStorePriceCoupon(storeVoucherPrice);
        storeOrder.setPriceVoucher(voucherPrice.add(storeVoucherPrice));
        storeOrder.setStatus(0);
        storeOrder.setUcouponId(platVoucherCode);
        storeOrder.setStoreCouponId(storeVoucherCode);
        storeOrder.setPayType(param.getPayType());
        storeOrder.setDeviceFrom(param.getDeviceFrom());
        storeOrder.setSource(source);
        storeOrder.setVersion(version);
        storeOrder.setIsMember(isMember ? 1 : 0);
        storeOrder.setOrderType(0);
        storeOrder.setWriteOffCode(writeOffCode);
        if (marketType != null && marketType.equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {
            storeOrder.setPayCountdownMinute(1);
        } else {
            storeOrder.setPayCountdownMinute(5);
        }
        storeOrder.setIpAddress(CurrentUtil.getCliIpAddr());
        storeOrder.setCreatedAt(now);
        storeOrder.setMarketId(marketId);
        storeOrder.setMarketType(marketType);

        //订单attr
        GoblinOrderAttr orderAttr = GoblinOrderAttr.getNew();
        orderAttr.setOrderAttrId(IDGenerator.nextTimeId2());
        orderAttr.setOrderId(orderId);
        if (!writeOffCode.equals("EMPTY")) {
            orderAttr.setExpressContacts(addressesVo.getName());
            orderAttr.setExpressAddress(addressesVo.getProvince() + " " + addressesVo.getCity() + " " + addressesVo.getCounty());
            orderAttr.setExpressAddressDetail(addressesVo.getAddress());
            orderAttr.setExpressPhone(addressesVo.getPhone());
            orderAttr.setExpressType(1);
            orderAttr.setCreatedAt(now);
        }
        //返回值
        GoblinOrderPreParam preParam = GoblinOrderPreParam.getNew();
        preParam.setPriceActual(storeOrder.getPriceActual());
        preParam.setStoreName(storeInfoVo.getStoreName());
        preParam.setSkuName(skuName);
        preParam.setOrderIdList(storeOrder.getOrderId());
        preParam.setStoreOrder(storeOrder);
        preParam.setOrderAttr(orderAttr);
        preParam.setOrderSkuList(goblinOrderSkuList);
        preParam.setStoreSpuIds(storeSpuIds);
        preParam.setPlatformSpuIds(platformSpuIds);
        return preParam;
    }

    private ResponseDto<GoblinPayInnerResultVo> payOrder(GoblinOrderPreParam preParam, List<GoblinOrderSqlParam> sqlParams, String uid) {
        //是否免费
        boolean isFree = false;
        GoblinPayInnerResultVo payInnerResultVo;
        String payCode;
        if (preParam.getPriceActual().compareTo(BigDecimal.valueOf(0)) > 0 && !preParam.getPayType().equals("huifu")) {
            // 调用支付
            LinkedMultiValueMap<String, String> httpData = CollectionUtil.linkedMultiValueMapStringString();
            httpData.add("type", "PRODUCT");
            httpData.add("price", preParam.getPriceActual().toString());
//            httpData.add("price","0.01");
            httpData.add("name", preParam.getStoreName());
            httpData.add("detail", preParam.getSkuName());
            httpData.add("orderCode", preParam.getOrderMasterCode());
            httpData.add("orderId", preParam.getOrderIdList().substring(1));
            httpData.add("clientIp", CurrentUtil.getCliIpAddr());
            httpData.add("notifyUrl", synUrl);
            httpData.add("createDate", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            httpData.add("expireTime", preParam.getExpireTime() + "");
            httpData.add("payType", preParam.getPayType());
            httpData.add("deviceFrom", preParam.getDeviceFrom());

            if (preParam.getDeviceFrom().equals("micropay")) {
                httpData.add("authCode", preParam.getAuthCode());
            }
            if (preParam.getDeviceFrom().equals("js") || preParam.getDeviceFrom().equals("applet")) {
                httpData.add("openId", preParam.getOpenId());
            }
//            if (preParam.getPayType().equals("alipay") && preParam.getDeviceFrom().equals("wap")) {
//                httpData.add("showUrl", preParam.getShowUrl() + preParam.getOrderMasterCode());
//                httpData.add("returnUrl", preParam.getReturnUrl() + preParam.getOrderMasterCode());
//            }
//            if (preParam.getPayType().equals("douyinpay")) {
//                httpData.add("showUrl", preParam.getShowUrl() + preParam.getOrderMasterCode());
//                httpData.add("returnUrl", preParam.getReturnUrl() + preParam.getOrderMasterCode());
//            }
//            if (preParam.getPayType().equals("unionpay")) {
//                httpData.add("returnUrl", preParam.getReturnUrl() + preParam.getOrderMasterCode());
//            }
            httpData.add("showUrl", preParam.getShowUrl() + preParam.getOrderMasterCode());
            httpData.add("returnUrl", preParam.getReturnUrl() + preParam.getOrderMasterCode());
            LinkedMultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
            header.add("Accept", "application/json;charset=UTF-8");
            String returnData = HttpUtil.post(payUrl, httpData, header);
            log.info("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setCode(dto.getData().getCode());
            payInnerResultVo.setOrderCode(dto.getData().getOrderCode());
            payInnerResultVo.setPayData(dto.getData().getPayData());
            payInnerResultVo.setPayType(preParam.getPayType());
            payInnerResultVo.setPrice(preParam.getPriceActual());
            payCode = payInnerResultVo.getCode();
            payInnerResultVo.setShowUrl(preParam.getShowUrl());
            payInnerResultVo.setReturnUrl(preParam.getReturnUrl());
        } else if (preParam.getPayType() == null) {
            isFree = true;
            preParam.setPayType("FREE");
            payCode = "FREE_PAY_CODE";
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setPrice(BigDecimal.valueOf(0));
            payInnerResultVo.setPayType(preParam.getPayType());
        } else if (preParam.getPayType().equals("huifu")) {
            isFree = true;
            preParam.setPayType("huifu");
            payCode = "HUIFU_PAY_CODE";
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setPrice(preParam.getPriceActual());
            payInnerResultVo.setPayType(preParam.getPayType());
        } else {
            isFree = true;
            preParam.setPayType("FREE");
            payCode = "FREE_PAY_CODE";
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setPrice(BigDecimal.valueOf(0));
            payInnerResultVo.setPayType(preParam.getPayType());
        }

        payInnerResultVo.setOrderMasterCode(preParam.getOrderMasterCode());
        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin.order.create.sku_insert"));
        sqls.add(SqlMapping.get("goblin.order.create.order_insert"));
        sqls.add(SqlMapping.get("goblin.order.create.attr_insert"));
        LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
        LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
        LinkedList<Object[]> sqlDataAttr = CollectionUtil.linkedListObjectArr();
        List<GoblinStoreOrderVo> orderVoList = ObjectUtil.getGoblinStoreOrderVoArrayList();
        List<GoblinOrderSkuVo> skuVoList = ObjectUtil.getGoblinOrderSkuVoArrayList();
        for (GoblinOrderSqlParam item : sqlParams) {
            List<String> goblinOrderSkuIdList = CollectionUtil.linkedListString();
            BigDecimal restVoucherPrice = item.getStoreOrder().getPriceVoucher();
            for (int i = 0; i < item.getOrderSkuList().size(); i++) {
                GoblinOrderSku orderSku = item.getOrderSkuList().get(i);
                if (item.getStoreOrder().getPriceVoucher().compareTo(BigDecimal.ZERO) > 0) {
                    if (preParam.getStoreSpuIds().size() > 0 || preParam.getPlatformSpuIds().size() > 0) {//指定范围商品券
                        String spuId = orderSku.getSpuId();
                        String pre = GoblinStatusConst.MarketPreStatus.getPre(spuId);
                        if (pre != null) {
                            spuId = spuId.split(pre)[0];
                        }
                        if (preParam.getStoreSpuIds().contains(spuId) || preParam.getPlatformSpuIds().contains(spuId)) {
                            if (restVoucherPrice.compareTo(BigDecimal.ZERO) <= 0) {
                                restVoucherPrice = BigDecimal.ZERO;
                            }
                            if (restVoucherPrice.compareTo(BigDecimal.ZERO) > 0) {
                                restVoucherPrice = restVoucherPrice.subtract(orderSku.getSkuPriceActual());
                                if (restVoucherPrice.compareTo(BigDecimal.ZERO) >= 0) {
                                    orderSku.setPriceVoucher(orderSku.getSkuPriceActual());
                                } else {
                                    orderSku.setPriceVoucher(restVoucherPrice.add(orderSku.getSkuPriceActual()));
                                }
                                BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                                orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                            } else if (restVoucherPrice.compareTo(BigDecimal.ZERO) == 0) {
                                orderSku.setPriceVoucher(BigDecimal.ZERO);
                                BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                                orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                            } else {
                                orderSku.setPriceVoucher(restVoucherPrice.add(orderSku.getSkuPriceActual()));
                                BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                                orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                            }
                        }
                    } else {//全部商品券
                        if (restVoucherPrice.compareTo(BigDecimal.ZERO) <= 0) {
                            restVoucherPrice = BigDecimal.ZERO;
                        }
                        if (restVoucherPrice.compareTo(BigDecimal.ZERO) > 0) {
                            restVoucherPrice = restVoucherPrice.subtract(orderSku.getSkuPriceActual());
                            if (restVoucherPrice.compareTo(BigDecimal.ZERO) >= 0) {
                                orderSku.setPriceVoucher(orderSku.getSkuPriceActual());
                            } else {
                                orderSku.setPriceVoucher(restVoucherPrice.add(orderSku.getSkuPriceActual()));
                            }
                            BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                            orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                        } else if (restVoucherPrice.compareTo(BigDecimal.ZERO) == 0) {
                            orderSku.setPriceVoucher(BigDecimal.ZERO);
                            BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                            orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                        } else {
                            orderSku.setPriceVoucher(restVoucherPrice.add(orderSku.getSkuPriceActual()));
                            BigDecimal skuPriceActual = orderSku.getSkuPriceActual().subtract(orderSku.getPriceVoucher());
                            orderSku.setSkuPriceActual(skuPriceActual.compareTo(BigDecimal.ZERO) > 0 ? skuPriceActual : BigDecimal.ZERO);
                        }
                    }
                }
                sqlDataSku.add(new Object[]{
                        orderSku.getOrderSkuId(), orderSku.getOrderId(), orderSku.getSpuId(), orderSku.getSpuName(), orderSku.getSpuPic(), orderSku.getSkuId(), orderSku.getNum(), orderSku.getSkuPrice(), orderSku.getSkuPriceActual(), orderSku.getSkuName(),
                        orderSku.getSkuNo(), orderSku.getSkuImage(), orderSku.getSkuSpecs(), orderSku.getPriceVoucher(), orderSku.getCreatedAt()
                });
                //订单 orderSku Vo
                GoblinOrderSkuVo orderSkuVo = GoblinOrderSkuVo.getNew().copy(orderSku);
                redisUtils.setGoblinOrderSku(orderSkuVo.getOrderSkuId(), orderSkuVo);
                goblinOrderSkuIdList.add(orderSkuVo.getOrderSkuId());
                skuVoList.add(orderSkuVo);
            }
            GoblinStoreOrder storeOrder = item.getStoreOrder();
            storeOrder.setPayCode(payCode);
            sqlDataOrder.add(new Object[]{
                    storeOrder.getMasterOrderCode(), storeOrder.getOrderId(), storeOrder.getStoreId(), storeOrder.getStoreName(), storeOrder.getOrderCode(), storeOrder.getUserId(), storeOrder.getUserName(), storeOrder.getUserMobile(), storeOrder.getPriceTotal(), storeOrder.getPayCode(),
                    storeOrder.getPriceActual(), storeOrder.getPriceRefund(), storeOrder.getPriceExpress(), storeOrder.getPriceCoupon(), storeOrder.getStorePriceCoupon(), storeOrder.getPriceVoucher(), storeOrder.getStatus(), storeOrder.getUcouponId(), storeOrder.getStoreCouponId(), storeOrder.getPayType(), storeOrder.getDeviceFrom(),
                    storeOrder.getSource(), storeOrder.getVersion(), storeOrder.getIsMember(), storeOrder.getOrderType(), storeOrder.getWriteOffCode(), storeOrder.getPayCountdownMinute(), storeOrder.getIpAddress(), storeOrder.getMarketId(), storeOrder.getMarketType(), storeOrder.getCreatedAt(), ""
            });
            GoblinOrderAttr orderAttr = item.getOrderAttr();
            sqlDataAttr.add(new Object[]{
                    orderAttr.getOrderAttrId(), orderAttr.getOrderId(), orderAttr.getExpressContacts(), orderAttr.getExpressAddress(), orderAttr.getExpressAddressDetail(), orderAttr.getExpressPhone(), orderAttr.getExpressType(), orderAttr.getCreatedAt()
            });
            //订单vo
            GoblinStoreOrderVo orderVo = GoblinStoreOrderVo.getNew().copy(storeOrder);
            //订单attr vo
            GoblinOrderAttrVo orderAttrVo = GoblinOrderAttrVo.getNew().copy(orderAttr);

            //待支付发送队列
            queueUtils.sendMsgByRedisGoblinStock(orderVo.getMasterOrderCode(), storeOrder.getCreatedAt(), "GOBLIN", 5);
            //redis 赋值
            orderVo.setOrderAttrVo(orderAttrVo);
            orderVo.setOrderSkuVoIds(goblinOrderSkuIdList);
            orderVo.setCreatedAt(getNowTime());
            redisUtils.setGoblinOrder(orderVo.getOrderId(), orderVo);
            redisUtils.setMasterCode(orderVo.getMasterOrderCode(), preParam.getOrderIdList().substring(1));
            orderVoList.add(orderVo);

            //redis 订单列表
            if (orderUtils.noZhengzaiOrder(uid)) {
                if (orderVo.getMarketType() == null) {
                    redisUtils.addOrderList(uid, orderVo.getOrderId());
                } else if (orderVo.getMarketType().equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {
                    redisUtils.addZhengzaiOrderList(uid, orderVo.getOrderId());
                }
            }
        }
        mongoUtils.insertGoblinOrderSkuVoList(skuVoList);
        mongoUtils.insertGoblinStoreOrderVos(orderVoList);

        //mysql  执行sql
        String sqlData = SqlMapping.gets(sqls, sqlDataSku, sqlDataOrder, sqlDataAttr);
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(), sqlData);

        log.info(UserPathDto.setData("下单(唤起支付)", preParam, payInnerResultVo));
        if (isFree && preParam.getPayType().equals("huifu")) {
//            SyncOrderParam syncOrderParam = SyncOrderParam.getNew();
//            syncOrderParam.setOrderCode(preParam.getOrderMasterCode());
//            syncOrderParam.setPaymentAt(DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmss));
//            syncOrderParam.setCode(payCode);
//            syncOrderParam.setPrice(preParam.getPriceActual());
//            syncOrderParam.setPaymentId("FREE_PAYMENT_ID");
//            syncOrderParam.setPaymentType(null);
//            syncOrderParam.setStatus(1);
//            syncOrder(syncOrderParam);
            return ResponseDto.success(payInnerResultVo);
        } else if (isFree) {
            SyncOrderParam syncOrderParam = SyncOrderParam.getNew();
            syncOrderParam.setOrderCode(preParam.getOrderMasterCode());
            syncOrderParam.setPaymentAt(DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmss));
            syncOrderParam.setCode(payCode);
            syncOrderParam.setPrice(preParam.getPriceActual());
            syncOrderParam.setPaymentId("FREE_PAYMENT_ID");
            syncOrderParam.setPaymentType(null);
            syncOrderParam.setStatus(1);
            syncOrder(syncOrderParam);
            return ResponseDto.success(payInnerResultVo);
        } else {
            return ResponseDto.success(payInnerResultVo);
        }
    }

    @Override
    public ResponseDto<GoblinPayInnerResultVo> payAgain(PayAgainParam param) {
        String uid = CurrentUtil.getCurrentUid();
        LocalDateTime now = LocalDateTime.now();
        //检查订单时间 是否关闭
        GoblinStoreOrderVo storeOrderVo = redisUtils.getGoblinOrder(param.getOrderId());

        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        }

        if (!storeOrderVo.getUserId().equals(uid)) {
            return ResponseDto.failure(ErrorMapping.get("20003"));
        }

        if (storeOrderVo.getStatus() != GoblinStatusConst.Status.ORDER_STATUS_0.getValue()) {
            return ResponseDto.failure("订单无法支付");//订单
        }
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null, header);
        ResponseDto<GoblinPayInnerResultVo> checkVo = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
        });
        if (checkVo.getData().getStatus() == 1) {
            return ResponseDto.failure("订单已支付");
        }
        BigDecimal price = BigDecimal.ZERO;
        String[] orderIds = redisUtils.getMasterCode(storeOrderVo.getMasterOrderCode());
        for (String orderId : orderIds) {
            GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
            price = price.add(orderVo.getPriceActual());
        }
        GoblinPayInnerResultVo payInnerResultVo = GoblinPayInnerResultVo.getNew();
//        if (!storeOrderVo.getPayType().equals("FREE") && storeOrderVo.getPayType().equals(param.getPayType()) && storeOrderVo.getDeviceFrom().equals(param.getDeviceFrom())) {
//            payInnerResultVo.setCode(checkVo.getData().getCode());
//            payInnerResultVo.setOrderCode(checkVo.getData().getOrderCode());
//            payInnerResultVo.setPayData(checkVo.getData().getPayData());
//            payInnerResultVo.setOrderId(param.getOrderId());
//            payInnerResultVo.setPayType(param.getPayType());
//            payInnerResultVo.setPrice(storeOrderVo.getPriceActual());
//            storeOrderVo.setPayCode(payInnerResultVo.getCode());
//            payInnerResultVo.setShowUrl(param.getShowUrl() + storeOrderVo.getOrderId());
//            payInnerResultVo.setReturnUrl(param.getReturnUrl() + storeOrderVo.getOrderId());
//            log.info(UserPathDto.setData("再次支付[原支付方式]", param, payInnerResultVo));
//        } else
        if (!storeOrderVo.getPayType().equals("FREE")) {
            // 调用支付
            LinkedMultiValueMap<String, String> httpData = CollectionUtil.linkedMultiValueMapStringString();
            httpData.add("type", "PRODUCT");
            httpData.add("price", price.toString());
            httpData.add("name", redisUtils.getStoreInfoVo(storeOrderVo.getStoreId()).getStoreName());
            httpData.add("detail", "查找最初订单");
            httpData.add("orderCode", storeOrderVo.getMasterOrderCode());
//            httpData.add("orderId", storeOrderVo.getOrderId());
            httpData.add("clientIp", storeOrderVo.getIpAddress());
            httpData.add("notifyUrl", synUrl);
            httpData.add("createDate", storeOrderVo.getCreatedAt());
            httpData.add("expireTime", storeOrderVo.getPayCountdownMinute().toString());
            httpData.add("payType", param.getPayType());
            httpData.add("deviceFrom", param.getDeviceFrom());

            if (param.getDeviceFrom().equals("js") || param.getDeviceFrom().equals("applet")) {
                httpData.add("openId", param.getOpenId());
            }
//            if (param.getPayType().equals("alipay") && param.getDeviceFrom().equals("wap")) {
//                httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
//            if (param.getPayType().equals("douyinpay")) {
//                httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
//            if (param.getPayType().equals("unionpay")) {
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
            httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
            httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
            String returnData = HttpUtil.post(payUrl, httpData);
            log.debug("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            payInnerResultVo.setCode(dto.getData().getCode());
            payInnerResultVo.setOrderCode(storeOrderVo.getMasterOrderCode());
            payInnerResultVo.setOrderMasterCode(storeOrderVo.getMasterOrderCode());
            payInnerResultVo.setPayData(dto.getData().getPayData());
            payInnerResultVo.setOrderId(storeOrderVo.getMasterOrderCode());
            payInnerResultVo.setPayType(param.getPayType());
            payInnerResultVo.setPrice(price);
            payInnerResultVo.setShowUrl(param.getShowUrl() + storeOrderVo.getMasterOrderCode());
            payInnerResultVo.setReturnUrl(param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
            //redis
            storeOrderVo.setPayType(param.getPayType());
            storeOrderVo.setDeviceFrom(param.getDeviceFrom());
            storeOrderVo.setPayCode(payInnerResultVo.getCode());
            redisUtils.setGoblinOrder(storeOrderVo.getOrderId(), storeOrderVo);
            //mongo
            mongoUtils.updateGoblinStoreOrderVo(storeOrderVo.getOrderId(), storeOrderVo);
            //mysql
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_AGAIN.getKey(),
                    SqlMapping.get("goblin_order.pay.again", param.getPayType(), param.getDeviceFrom(), payInnerResultVo.getCode(), param.getOrderId(), now, now));
            log.info(UserPathDto.setData("再次支付[新支付方式]", param, payInnerResultVo));
        }
        return ResponseDto.success(payInnerResultVo);
    }

    @Override
    public String syncOrder(SyncOrderParam syncOrderParam) {
        log.debug("SYNC PARAM = " + syncOrderParam.toString());
        //支付时间
        LocalDateTime now = LocalDateTime.now();
        String[] array = redisUtils.getMasterCode(syncOrderParam.getOrderCode());
        String uid;
        BigDecimal priceActual = BigDecimal.ZERO;
        for (String orderId : array) {
            GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
            if (orderVo == null) {
                log.error("订单号：" + syncOrderParam.getOrderCode() + " 订单不存在");
                return "fail";//订单不存在
            }
            if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_2.getValue()) {
                if (orderVo.getPayCode().equals(syncOrderParam.getCode())) {
                    log.error("订单号：" + syncOrderParam.getOrderCode() + " 重复支付");
                    return "fail";//重复支付
                }
            }
//            if (orderVo.getPriceActual().compareTo(syncOrderParam.getPrice()) != 0) {
//                log.error("订单号：" + syncOrderParam.getOrderCode() + " 价格不符");
//                return "fail";//价格不符
//            }
            priceActual = priceActual.add(orderVo.getPriceActual());
            uid = orderVo.getUserId();
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
            GoblinStoreOrder storeOrder = GoblinStoreOrder.getNew();
            if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_5.getValue() && syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单超时支付", syncOrderParam.getOrderCode());
                // 商铺退款逻辑
                orderUtils.refundOrderSku(orderId, syncOrderParam.getPaymentId(), syncOrderParam.getPaymentType());
//                orderVo.setStatus(GoblinStatusConst.OrderStatus.ORDER_STATUS_61.getValue());
//                redisUtils.setGoblinOrder(orderVo.getOrderId(),orderVo);
            } else if ((orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_6.getValue() || orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_7.getValue()) && syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正在退款 或者已退款", syncOrderParam.getOrderCode());
            } else if (syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正常流程", syncOrderParam.getOrderCode());
                storeOrder.setPaymentType(syncOrderParam.getPaymentType());
                storeOrder.setPaymentId(syncOrderParam.getPaymentId());
                storeOrder.setPayCode(syncOrderParam.getCode());
                LocalDateTime payTime = LocalDateTime.parse(syncOrderParam.getPaymentAt(), DTF_YMD_HMS);
                storeOrder.setPayTime(payTime);
                if (orderVo.getWriteOffCode().equals("EMPTY")) {
                    storeOrder.setWriteOffCode(IDGenerator.getWriteOffCode());
                } else {
                    storeOrder.setWriteOffCode("");
                }
                storeOrder.setStatus(GoblinStatusConst.Status.ORDER_STATUS_2.getValue());
                storeOrder.setUpdatedAt(now);
                sqls.add(SqlMapping.get("goblin_order.pay.order"));
                sqlDataOrder.add(new Object[]{
                        storeOrder.getPaymentType(), storeOrder.getPaymentId(), storeOrder.getPayCode(), storeOrder.getPayTime(), storeOrder.getWriteOffCode(), storeOrder.getStatus(), storeOrder.getUpdatedAt(),
                        orderId, now, now
                });
                sqls.add(SqlMapping.get("goblin_order.pay.sku"));
                List<String> skuList = orderVo.getOrderSkuVoIds();
                for (String orderSkuVoIds : skuList) {
                    GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuVoIds);
                    //增加销量
                    log.debug("增加销量 spuId=" + orderSkuVo.getSpuId() + ",skuId=" + orderSkuVo.getSkuId());
                    redisUtils.incrSkuSaleCount(orderSkuVo.getSpuId(), orderSkuVo.getSkuId(), orderSkuVo.getNum());
                    orderSkuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_2.getValue());
                    //redis
                    redisUtils.setGoblinOrderSku(orderSkuVo.getOrderSkuId(), orderSkuVo);
                    //mongo
                    mongoUtils.updateGoblinOrderSkuVo(orderSkuVo.getOrderSkuId(), orderSkuVo);
                    //mongo 添加操作日志
                    GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
                    logVo.setOrderId(orderVo.getOrderId());
                    logVo.setOrderCode(orderVo.getOrderCode());
                    logVo.setPayCode(orderVo.getPayCode());
                    logVo.setStoreId(orderVo.getStoreId());
                    if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()) > 0) {
                        logVo.setOrderType("zhengzai");
                    } else {
                        logVo.setOrderType("order");
                    }
                    logVo.setSpuId(orderSkuVo.getSpuId());
                    logVo.setSkuId(orderSkuVo.getSkuId());
                    logVo.setSkuPriceActual(orderSkuVo.getSkuPriceActual().multiply(new BigDecimal(100)).longValue());
                    logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue());
                    logVo.setRemark(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getDesc());
                    logVo.setOperationId(uid);
                    logVo.setOperationName(orderVo.getUserName());
                    logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_1.getValue());
                    logVo.setCreatedAt(LocalDateTime.now());
                    mongoUtils.insertGoblinOrderLogVo(logVo);
                    //mysql
                    sqlDataSku.add(new Object[]{
                            GoblinStatusConst.Status.ORDER_STATUS_2.getValue(), now,
                            orderSkuVo.getOrderSkuId(), now, now
                    });
                }
                //redis
                orderVo.setPayCode(storeOrder.getPayCode());
                orderVo.setPayTime(syncOrderParam.getPaymentAt());
                orderVo.setWriteOffCode(storeOrder.getWriteOffCode());
                orderVo.setStatus(storeOrder.getStatus());
                orderVo.setPaymentId(syncOrderParam.getPaymentId());
                orderVo.setPaymentType(syncOrderParam.getPaymentType());
                orderVo.setOrderSkuVoIds(skuList);
                redisUtils.setGoblinOrder(orderId, orderVo);
                redisUtils.setOffCode(orderVo.getWriteOffCode(), orderVo.getMasterOrderCode());
                //mongo
                mongoUtils.updateGoblinStoreOrderVo(orderId, orderVo);
                //mysql
                queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
                        SqlMapping.gets(sqls, sqlDataOrder, sqlDataSku));
            }
            //发短信
//            SmsEnum.ADTemplate adTemplate = null;
//            if (orderTicketData.getGetTicketType().equals("express")) {
//                adTemplate = SmsEnum.ADTemplate.SMS_225995308;
//            } else if (orderTicketData.getGetTicketType().equals("electronic")) {
//                adTemplate = ticketData.getIsShowCode() == 1 ? SmsEnum.ADTemplate.SMS_225995308 : SmsEnum.ADTemplate.SMS_225995308;
//            }
//
//            if (null != adTemplate) {
//                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SMS_NOTICE.getKey(),
//                        SmsMessage.builder().setPhone(orderTicketData.getUserMobile())
//                                .setSignName(SmsEnum.ADSignName.M02.getVal())
//                                .setTemplateCode(adTemplate.name())
//                                .setTemplateParam("name", orderTicketData.getPerformanceTitle())
//                                .setTemplateParam("time", time1 + " " + time2).toJson()
//                );
//            }
            //加分
            if (orderUtils.noZhengzaiOrder(uid)) {
                orderUtils.integral(uid, priceActual, "购买商品", 1);
            }
        }
        return "success";
    }

    @Override
    public ResponseDto<Integer> checkOrderResult(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        GoblinStoreOrderVo storeOrderVo = redisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        } else {
            if (!storeOrderVo.getUserId().equals(uid)) {
                return null;
            }
            String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null);
            ResponseDto<SyncOrderParam> syncOrderDtoParam = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<SyncOrderParam>>() {
            });
            if (syncOrderDtoParam.getData().getStatus() == 1) {
                //处理订单
                syncOrder(syncOrderDtoParam.getData());
                return ResponseDto.success(1);
            } else {
                return ResponseDto.success(0);
            }
        }
    }

    @Override
    public ResponseDto<Integer> checkOrderResultMaterCode(String masterCode) {
        String[] orderIds = redisUtils.getMasterCode(masterCode);
        if (orderIds == null) {
            return ResponseDto.failure("订单不存在");
        } else {
            for (String orderId : orderIds) {
                GoblinStoreOrderVo storeOrderVo = redisUtils.getGoblinOrder(orderId);
                String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null);
                ResponseDto<SyncOrderParam> syncOrderDtoParam = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<SyncOrderParam>>() {
                });
                if (syncOrderDtoParam.getData().getStatus() == 1) {
                    //处理订单
                    syncOrder(syncOrderDtoParam.getData());
                } else {
                    return ResponseDto.success(0);
                }
            }
            return ResponseDto.success(1);
        }
    }

    @Override
    public String refundSyncOrder(RefundCallbackParam refundCallbackParam) {
        LocalDateTime now = LocalDateTime.now();
        String nowStr = DateUtil.getNowTime();
        log.info("refundCallback订单退款回调参数: [RefundCallbackParam={}]", refundCallbackParam);
        GoblinBackOrderVo backOrderVo = mongoUtils.getGoblinBackOrderVoByBackCode(refundCallbackParam.getOrderRefundCode());
        if (backOrderVo == null) {
            log.info("refundCallback: 退款订单查询失败，编号{}", refundCallbackParam.getOrderRefundCode());
            return "fail";
        }
        if (backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_20.getValue() || backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_201.getValue()) {
            log.info("refundCallback: 退款订单已取消，编号{}", refundCallbackParam.getOrderRefundCode());
            return "fail";
        }
        if (backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue()) {
            log.info("refundCallback: 退款订单已完成，编号{}", refundCallbackParam.getOrderRefundCode());
            return "success";
        }
        Integer status = refundCallbackParam.getStatus();
        if (1 == status && (backOrderVo.getStatus() == 0 || backOrderVo.getStatus() == 10)) { // 退款成功
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlsOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlsOrderSku = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlsBackOrder = CollectionUtil.linkedListObjectArr();
            sqls.add(SqlMapping.get("goblin_order.store.refundPrice"));
            sqls.add(SqlMapping.get("goblin_order.store.refundSkuPrice"));
            sqls.add(SqlMapping.get("goblin_order.store.refundBackOrder"));
            String orderId = backOrderVo.getOrderId();
            List<GoblinBackOrderSkuVo> backOrderSkuVos = backOrderVo.getBackOrderSkuVos();
            GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
            orderVo.setPriceRefund(orderVo.getPriceRefund() == null ? BigDecimal.ZERO : orderVo.getPriceRefund().add(refundCallbackParam.getRefundPrice()));
            if (orderVo.getPriceRefund().compareTo(orderVo.getPriceActual()) >= 0) {
                //整单退款 退券
                orderVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_6.getValue());
                if (!(orderVo.getUcouponId() == null || orderVo.getUcouponId().equals(""))) {
                    orderUtils.backCoupon(orderVo.getUcouponId(), orderVo.getUserId());
                }

                if (!(orderVo.getStoreCouponId() == null || orderVo.getStoreCouponId().equals(""))) {
                    List<BackCouponParam> params = ObjectUtil.getBackCouponParam();
                    BackCouponParam backCouponParam = BackCouponParam.getNew();
                    backCouponParam.setuCouponIds(orderVo.getStoreCouponId());
                    backCouponParam.setUid(orderVo.getUserId());
                    params.add(backCouponParam);
                    orderUtils.backStoreCoupon(params);
                }
            }
            backOrderVo.setStatus(GoblinStatusConst.Status.ORDER_BACK_STATUS_2.getValue());
            backOrderVo.setRefundAt(nowStr);
            for (GoblinBackOrderSkuVo backOrderSkuVo : backOrderSkuVos) {
                GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(backOrderSkuVo.getOrderSkuId());
                BigDecimal refundSkuPrice = backOrderSkuVo.getRefundPrice();
                orderSkuVo.setPriceRefund(orderSkuVo.getPriceRefund() == null ? refundSkuPrice : orderSkuVo.getPriceRefund().add(refundSkuPrice));
                if (orderSkuVo.getPriceRefund().compareTo(orderSkuVo.getSkuPriceActual()) >= 0) {
                    orderSkuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_6.getValue());
                    String pre = GoblinStatusConst.MarketPreStatus.getPre(orderSkuVo.getSkuId());
                    String skuId = orderSkuVo.getSkuId();
                    //需要判断是否超时支付
                    if (!"超时支付自动退款".equals(backOrderVo.getDescribes())) {
                        redisUtils.incrSkuStock(pre, skuId, orderSkuVo.getNum());
                        redisUtils.decrSkuCountByUid(orderVo.getUserId(), skuId, orderSkuVo.getNum());
                    }

                }
                redisUtils.setGoblinOrderSku(backOrderSkuVo.getOrderSkuId(), orderSkuVo);
                mongoUtils.updateGoblinOrderSkuVo(backOrderSkuVo.getOrderSkuId(), orderSkuVo);
                sqlsOrderSku.add(new Object[]{
                        orderSkuVo.getPriceRefund(), orderSkuVo.getStatus(), now,
                        backOrderSkuVo.getOrderSkuId(), now, now
                });
                GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
                logVo.setOrderId(orderVo.getOrderId());
                logVo.setOrderCode(orderVo.getOrderCode());
                logVo.setPayCode(orderVo.getPayCode());
                if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()) > 0) {
                    logVo.setOrderType("zhengzai");
                } else {
                    logVo.setOrderType("order");
                }
                logVo.setStoreId(orderVo.getStoreId());
                logVo.setSpuId(orderSkuVo.getSpuId());
                logVo.setSpuName(backOrderSkuVo.getSpuName());
                logVo.setSkuId(backOrderSkuVo.getSkuId());
//                if (orderVo.getStatus().equals(GoblinStatusConst.Status.ORDER_STATUS_6.getValue())) {
//                    refundSkuPrice = refundSkuPrice.add(orderVo.getPriceExpress());
//                }
                logVo.setSkuPriceActual(refundSkuPrice.multiply(BigDecimal.valueOf(100)).negate().longValue());
                logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue());
                logVo.setRemark("订单退款");
                logVo.setOperationId(backOrderVo.getUserId());
                logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_2.getValue());
                logVo.setCreatedAt(now);
                mongoUtils.insertGoblinOrderLogVo(logVo);
            }
            //redis
            redisUtils.setGoblinOrder(orderId, orderVo);
            redisUtils.setBackOrderVo(backOrderVo.getBackOrderId(), backOrderVo);
            //mongo
            mongoUtils.updateGoblinStoreOrderVo(orderId, orderVo);
            mongoUtils.updateGoblinBackOrderVo(backOrderVo.getBackOrderId(), backOrderVo);
            //mysql
            sqlsOrder.add(new Object[]{
                    orderVo.getPriceRefund(), orderVo.getStatus(), now,
                    orderId, now, now
            });
            sqlsBackOrder.add(new Object[]{
                    backOrderVo.getStatus(), now, now, backOrderVo.getBackOrderId(), now, now
            });
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_ORDER_OPERA.getKey(),
                    SqlMapping.gets(sqls, sqlsOrder, sqlsOrderSku, sqlsBackOrder));
            //减积分
            orderUtils.integral(orderVo.getUserId(), backOrderVo.getRealBackPrice(), "商品退款", 2);
        } else if (0 == status) {
            return "fail";
        }
        return "success";
    }

    @Override
    public String huiFuSync(HttpServletRequest request) {
        try {
            // 验签请参data
            String responseData = request.getParameter("resp_data");
            // 验签请参sign
            String sign = request.getParameter("sign");
            // 使用汇付公钥验签
//            if (!RsaUtils.verify(responseData, PUBLIC_KEY, sign)) {
//                // 验签失败处理
//                return "";
//            }
            JSONObject dataObj = JSON.parseObject(responseData);
            String subRespCode = dataObj.getString("sub_resp_code");
            String reqSeqId = dataObj.getString("req_seq_id");
            String orderMasterCode = dataObj.getString("mer_ord_id");
            String payCode = dataObj.getString("mer_ord_id");
            String paymentType = dataObj.getString("trans_type");
            String paymentId = dataObj.getString("hf_seq_id");
            String paymentAt = dataObj.getString("end_time");
            if ("00000000".equals(subRespCode)) {
                log.debug("SYNC PARAM = " + responseData);
                //支付时间
                LocalDateTime now = LocalDateTime.now();
                String[] array = redisUtils.getMasterCode(orderMasterCode);
                String uid = "zhengzai";
                BigDecimal priceActual = BigDecimal.ZERO;
                for (String orderId : array) {
                    GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
                    if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_4.getValue()) {
                        continue;
                    }
                    uid = orderVo.getUserId();
                    priceActual = priceActual.add(orderVo.getPriceActual());
                    if (orderVo == null) {
                        log.error("订单号：" + orderMasterCode + " 订单不存在");
                        return "fail";//订单不存在
                    }
                    LinkedList<String> sqls = CollectionUtil.linkedListString();
                    LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
                    LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
                    GoblinStoreOrder storeOrder = GoblinStoreOrder.getNew();
                    storeOrder.setPaymentType(paymentType);
                    storeOrder.setPaymentId(paymentId);
                    storeOrder.setPayCode(payCode);
                    LocalDateTime payTime = LocalDateTime.parse(paymentAt, DTFYMDHMS);
                    storeOrder.setPayTime(payTime);
                    if (orderVo.getWriteOffCode().equals("EMPTY")) {
                        storeOrder.setWriteOffCode(IDGenerator.getWriteOffCode());
                    } else {
                        storeOrder.setWriteOffCode("");
                    }
                    storeOrder.setStatus(GoblinStatusConst.Status.ORDER_STATUS_4.getValue());
                    storeOrder.setUpdatedAt(now);
                    sqls.add(SqlMapping.get("goblin_order.pay.order"));
                    sqlDataOrder.add(new Object[]{
                            storeOrder.getPaymentType(), storeOrder.getPaymentId(), storeOrder.getPayCode(), storeOrder.getPayTime(), storeOrder.getWriteOffCode(), storeOrder.getStatus(), storeOrder.getUpdatedAt(),
                            orderId, now, now
                    });
                    sqls.add(SqlMapping.get("goblin_order.pay.sku"));
                    List<String> skuList = orderVo.getOrderSkuVoIds();
                    for (String orderSkuVoIds : skuList) {
                        GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuVoIds);
                        //增加销量
                        redisUtils.incrSkuSaleCount(orderSkuVo.getSpuId(), orderSkuVo.getSkuId(), orderSkuVo.getNum());
                        orderSkuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_4.getValue());
                        //redis
                        redisUtils.setGoblinOrderSku(orderSkuVo.getOrderSkuId(), orderSkuVo);
                        //mongo
                        mongoUtils.updateGoblinOrderSkuVo(orderSkuVo.getOrderSkuId(), orderSkuVo);
                        //mongo 添加操作日志
                        GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
                        logVo.setOrderId(orderVo.getOrderId());
                        logVo.setOrderCode(orderVo.getOrderCode());
                        logVo.setPayCode(orderVo.getPayCode());
                        logVo.setStoreId(orderVo.getStoreId());
                        if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()) > 0) {
                            logVo.setOrderType("zhengzai");
                        } else {
                            logVo.setOrderType("order");
                        }
                        logVo.setSpuId(orderSkuVo.getSpuId());
                        logVo.setSkuId(orderSkuVo.getSkuId());
                        logVo.setSkuPriceActual(orderSkuVo.getSkuPriceActual().multiply(new BigDecimal(100)).longValue());
                        logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue());
                        logVo.setRemark(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getDesc());
                        logVo.setOperationId(uid);
                        logVo.setOperationName(orderVo.getUserName());
                        logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_1.getValue());
                        logVo.setCreatedAt(LocalDateTime.now());
                        mongoUtils.insertGoblinOrderLogVo(logVo);
                        //mysql
                        sqlDataSku.add(new Object[]{
                                orderSkuVo.getStatus(), now,
                                orderSkuVo.getOrderSkuId(), now, now
                        });
                    }
                    //redis
                    orderVo.setPayCode(storeOrder.getPayCode());
                    orderVo.setPayTime(payTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    orderVo.setWriteOffCode(storeOrder.getWriteOffCode());
                    orderVo.setStatus(storeOrder.getStatus());
                    orderVo.setPaymentId(paymentId);
                    orderVo.setPaymentType(paymentType);
                    orderVo.setOrderSkuVoIds(skuList);
                    redisUtils.setGoblinOrder(orderId, orderVo);
                    redisUtils.setOffCode(orderVo.getWriteOffCode(), orderVo.getMasterOrderCode());
//                    //删除未支付订单
//                    redisUtils.removeGoblinOrder(orderVo.getRandomKey() + "", orderId);
                    //mongo
                    mongoUtils.updateGoblinStoreOrderVo(orderId, orderVo);
                    //mysql
                    queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
                            SqlMapping.gets(sqls, sqlDataOrder, sqlDataSku));
                }
                //加分
                if (orderUtils.noZhengzaiOrder(uid)) {
                    orderUtils.integral(uid, priceActual, "购买商品", 1);
                }
            } else {
                // 业务处理失败
                log.info("处理失败");
            }
            return "RECV_ORD_ID_" + reqSeqId;
        } catch (Exception e) {
            log.info("异步回调开始，参数，request={},异常={}", request, e);
            e.printStackTrace();
        }
        return "";
    }
}
