package com.slodon.b2b2c.controller.integral.seller;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.slodon.b2b2c.core.constant.OrderConst;
import com.slodon.b2b2c.core.constant.StoreConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.express.ExpressInfo;
import com.slodon.b2b2c.core.express.FaceSheetAPI;
import com.slodon.b2b2c.core.facesheet.GenerateFaceSheetRequest;
import com.slodon.b2b2c.core.facesheet.PrintFaceSheetRequest;
import com.slodon.b2b2c.core.response.JsonResult;
import com.slodon.b2b2c.core.response.SldResponse;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.core.util.Md5;
import com.slodon.b2b2c.core.util.StringUtil;
import com.slodon.b2b2c.core.util.UserUtil;
import com.slodon.b2b2c.integral.pojo.IntegralOrder;
import com.slodon.b2b2c.integral.pojo.IntegralOrderProduct;
import com.slodon.b2b2c.model.integral.IntegralOrderModel;
import com.slodon.b2b2c.model.seller.StoreAddressModel;
import com.slodon.b2b2c.model.seller.StoreBindExpressModel;
import com.slodon.b2b2c.model.seller.StoreExpressSettingModel;
import com.slodon.b2b2c.model.system.RegionCityModel;
import com.slodon.b2b2c.model.system.RegionDistrictModel;
import com.slodon.b2b2c.seller.example.StoreAddressExample;
import com.slodon.b2b2c.seller.example.StoreBindExpressExample;
import com.slodon.b2b2c.seller.example.StoreExpressSettingExample;
import com.slodon.b2b2c.seller.pojo.StoreAddress;
import com.slodon.b2b2c.seller.pojo.StoreBindExpress;
import com.slodon.b2b2c.seller.pojo.StoreExpressSetting;
import com.slodon.b2b2c.seller.pojo.Vendor;
import com.slodon.b2b2c.system.example.RegionCityExample;
import com.slodon.b2b2c.system.example.RegionDistrictExample;
import com.slodon.b2b2c.system.pojo.RegionCity;
import com.slodon.b2b2c.system.pojo.RegionDistrict;
import com.slodon.b2b2c.util.FaceSheet100NeedField;
import com.slodon.b2b2c.util.FaceSheetNeedField;
import com.slodon.b2b2c.vo.integral.FaceSheetCheckOrderVO;
import com.slodon.b2b2c.vo.integral.FaceSheetPrintCheckOrderVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Api(tags = "seller-电子面单")
@RestController
@Slf4j
@RequestMapping("v3/integral/seller/integral/faceSheet")
public class SellerIntegralFaceSheetController extends BaseController {

    @Resource
    private IntegralOrderModel integralOrderModel;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private StoreBindExpressModel storeBindExpressModel;
    @Resource
    private StoreExpressSettingModel storeExpressSettingModel;
    @Resource
    private StoreAddressModel storeAddressModel;
    @Resource
    private RegionCityModel regionCityModel;
    @Resource
    private RegionDistrictModel regionDistrictModel;

    @ApiOperation("获取物流单号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderSn", value = "订单号", required = true),
            @ApiImplicitParam(name = "expressId", value = "快递公司id", required = true)
    })
    @GetMapping("getLogisticCode")
    public JsonResult<Object> getLogisticCode(HttpServletRequest request,
                                              @RequestParam("orderSn") String orderSn,
                                              @RequestParam("expressId") Integer expressId) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        //获取订单信息
        IntegralOrder order = integralOrderModel.getOrdersWithOpByOrderSn(orderSn);
        AssertUtil.isTrue(!order.getStoreId().equals(vendor.getStoreId()), "非法操作");

        //获取快递信息
        StoreBindExpress expressInfo = this.getExpressInfo(vendor.getStoreId(), expressId);

        String expressType = stringRedisTemplate.opsForValue().get("express_type");
        if ("1".equals(expressType)) {
            //快递鸟
            if (!FaceSheetNeedField.isHasExpressCode(expressInfo.getExpressCode())) {
                return SldResponse.fail("暂不支持该快递公司");
            }
        } else {
            //快递100
            if (!FaceSheet100NeedField.isHasExpressCode(expressInfo.getExpressCode())) {
                return SldResponse.fail("暂不支持该快递公司");
            }
        }

        //商家默认发货地址
        StoreAddress storeAddress = this.getStoreAddress(vendor.getStoreId());

        //物流单号
        String logisticCode;
        //任务id
        String taskId = null;
        if ("1".equals(expressType)) {
            //快递鸟
            //获取快递配置信息
            Map<String, String> map = this.getExpressSetting(vendor.getStoreId());
            String eBusinessId = map.get("eBusinessId");
            String appKey = map.get("appKey");
            JSONObject jsonObject = this.getExpressNumber1(order, expressInfo, storeAddress, eBusinessId, appKey);
            String resultCode = jsonObject.getString("ResultCode");
            if ("100".equals(resultCode)) {
                //获取物流单号
                JSONObject object = JSON.parseObject(jsonObject.getString("Order"));
                logisticCode = object.getString("LogisticCode");
            } else {
                String reason = jsonObject.getString("Reason");
                throw new MallException("获取物流单号失败，原因：" + reason);
            }
        } else {
            //快递100
            JSONObject jsonObject = this.getExpressNumber2(order, expressInfo, storeAddress);
            String code = jsonObject.getString("code");
            if ("200".equals(code)) {
                //获取物流单号
                JSONObject data = jsonObject.getJSONObject("data");
                logisticCode = data.getString("kuaidinum");
                taskId = data.getString("taskId");
            } else {
                String reason = jsonObject.getString("message");
                throw new MallException("获取物流单号失败，原因：" + reason);
            }
        }

        //更新订单电子面单状态
        IntegralOrder orderUpdate = new IntegralOrder();
        orderUpdate.setOrderId(order.getOrderId());
        orderUpdate.setExpressId(expressId);
        orderUpdate.setExpressCode(expressInfo.getExpressCode());
        orderUpdate.setExpressName(expressInfo.getExpressName());
        orderUpdate.setExpressNumber(logisticCode);
        orderUpdate.setIsGenerateFacesheet(OrderConst.IS_GENERATE_FACE__SHEET_1);
        orderUpdate.setTaskId(taskId);
        integralOrderModel.updateIntegralOrder(orderUpdate);

        Map<String, String> map = new HashMap<>();
        map.put("logisticCode", logisticCode);
        return SldResponse.success("获取物流单号成功", map);
    }

    /**
     * 获取快递信息
     *
     * @param storeId   店铺id
     * @param expressId 快递公司id
     * @return 快递信息
     */
    public StoreBindExpress getExpressInfo(Long storeId, Integer expressId) {
        //获取快递信息
        StoreBindExpressExample example = new StoreBindExpressExample();
        example.setStoreId(storeId);
        example.setExpressId(expressId);
        List<StoreBindExpress> list = storeBindExpressModel.getStoreBindExpressList(example, null);
        AssertUtil.notEmpty(list, "未获取到电子面单信息");
        return list.get(0);
    }

    /**
     * 获取默认发货地址
     *
     * @param storeId 店铺id
     * @return 发货地址
     */
    public StoreAddress getStoreAddress(Long storeId) {
        //商家默认发货地址
        StoreAddressExample addressExample = new StoreAddressExample();
        addressExample.setStoreId(storeId);
        addressExample.setIsDefault(StoreConst.ADDRESS_IS_DEFAULT);
        List<StoreAddress> storeAddressList = storeAddressModel.getStoreAddressList(addressExample, null);
        AssertUtil.notEmpty(storeAddressList, "请设置默认发货地址");
        return storeAddressList.get(0);
    }

    /**
     * 获取快递配置信息
     *
     * @param storeId 店铺id
     * @return 配置信息
     */
    public Map<String, String> getExpressSetting(Long storeId) {
        //快递鸟电商ID
        String eBusinessId;
        //快递鸟电商加密私钥
        String appKey;
        String accountSetting = stringRedisTemplate.opsForValue().get("express_account_setting");
        if (StringUtil.isEmpty(accountSetting) || "1".equals(accountSetting)) {
            eBusinessId = stringRedisTemplate.opsForValue().get("express_ebusinessid");
            appKey = stringRedisTemplate.opsForValue().get("express_apikey");
        } else {
            StoreExpressSettingExample example = new StoreExpressSettingExample();
            example.setStoreId(storeId);
            List<StoreExpressSetting> list = storeExpressSettingModel.getStoreExpressSettingList(example, null);
            AssertUtil.notEmpty(list, "请完善快递鸟配置信息：");

            eBusinessId = list.get(0).getBusinessId();
            appKey = list.get(0).getAppKey();
        }
        Map<String, String> map = new HashMap<>();
        map.put("eBusinessId", eBusinessId);
        map.put("appKey", appKey);
        return map;
    }

    /**
     * 获取快递鸟物流单号
     *
     * @param order        订单信息
     * @param expressInfo  快递信息
     * @param storeAddress 店铺地址
     * @param eBusinessId  快递鸟电商ID
     * @param appKey       快递鸟电商加密私钥
     * @return 物流单号
     */
    @SneakyThrows
    public JSONObject getExpressNumber1(IntegralOrder order, StoreBindExpress expressInfo, StoreAddress storeAddress, String eBusinessId, String appKey) {
        //请求url
        String reqUrl;
        String expressTest = stringRedisTemplate.opsForValue().get("express_test");
        if (StringUtil.isEmpty(expressTest) || "1".equals(expressTest)) {
            //测试环境地址：
            reqUrl = "http://sandboxapi.kdniao.com:8080/kdniaosandbox/gateway/exterfaceInvoke.json";
        } else {
            //正式环境地址
            reqUrl = "http://api.kdniao.com/api/Eorderservice";
        }

        // 封装快递鸟接口所需数据
        String requestData = getRequestData(order, expressInfo, storeAddress);
        GenerateFaceSheetRequest fsq = new GenerateFaceSheetRequest();
        fsq.setRequestData(FaceSheetAPI.urlEncoder(requestData, "UTF-8"));
        fsq.setEBusinessID(eBusinessId);
        fsq.setRequestType("1007");
        String dataSign = FaceSheetAPI.encrypt(requestData, appKey, "UTF-8");
        fsq.setDataSign(FaceSheetAPI.urlEncoder(dataSign, "UTF-8"));
        fsq.setDataType("2");
        String result = FaceSheetAPI.sendPost(reqUrl, fsq);
        log.info("快递鸟生成电子面单获取物流单号:================================================================" + result);
        return JSON.parseObject(result);
    }

    /**
     * 获取快递100物流单号
     *
     * @param order        订单信息
     * @param expressInfo  快递信息
     * @param storeAddress 店铺地址
     * @return 物流单号
     */
    public JSONObject getExpressNumber2(IntegralOrder order, StoreBindExpress expressInfo, StoreAddress storeAddress) {
        String url = "https://api.kuaidi100.com/label/order";

        String templateId = expressInfo.getTemplateId();
        AssertUtil.notEmpty(templateId, "请设置快递100 电子面单模板编码");
        String key = stringRedisTemplate.opsForValue().get("express_100_key");
        AssertUtil.notNull(key, "请设置快递100 授权key");
        String secret = stringRedisTemplate.opsForValue().get("express_100_secret");
        AssertUtil.notNull(secret, "请设置快递100 secret");

        //查询商户配置
        StoreExpressSetting expressSetting = this.getStoreExpressSetting(order.getStoreId());
        AssertUtil.notEmpty(expressSetting.getPrinterName(), "请设置快递100 打印设备");

        //拼接订单商品名称信息
        StringBuilder productInfo = new StringBuilder();
        for (IntegralOrderProduct orderProduct : order.getOrderProductList()) {
            productInfo.append(",'").append(orderProduct.getGoodsName());
        }

        //请求header
        Map<String, String> headers = new HashMap<>(1);
        headers.put("Content-Type", "application/x-www-form-urlencoded");

        //请求参数
        ExpressInfo info = new ExpressInfo();
        info.setPrintType("CLOUD");
        info.setPartnerId(expressInfo.getCustomerName());
        info.setPartnerKey(expressInfo.getCustomerPwd());
        info.setPartnerName(expressInfo.getPartnerName());
        info.setNet(expressInfo.getSendSite());
        info.setCheckMan(expressInfo.getSendStaff());
        if ("shentong".equals(expressInfo.getExpressCode())) {
            //申通快递默认值 44
            info.setCode("44");
        } else if ("zhongtong".equals(expressInfo.getExpressCode())) {
            //中通快递默认值 ztoOpen
            info.setCode("ztoOpen");
        } else {
            info.setCode(expressInfo.getCode());
        }
        info.setKuaidicom(expressInfo.getExpressCode());
        if (productInfo.length() > 20) {
            info.setCargo(productInfo.substring(1, 19) + "等");
        } else {
            info.setCargo(productInfo.substring(1));
        }
        if (expressInfo.getExpressCode().contains("kuaiyun")) {
            //快运默认两个包裹
            info.setCount(2);
            info.setNeedChild("1");
        } else {
            //快递默认一个包裹
            info.setCount(1);
            info.setNeedChild("0");
        }
        info.setPayType(ExpressInfo.dealPayTypeValue(expressInfo.getPayType()));
        info.setExpType(expressInfo.getExpType());
        info.setRemark("");
        info.setSiid(expressSetting.getPrinterName());
        info.setDirection("0");
        String[] split = templateId.split(",");
        if (split.length == 1) {
            info.setTempId(templateId);
            info.setChildTempId(templateId);
        } else {
            info.setTempId(split[0]);
            info.setChildTempId(split[1]);
        }
        info.setOrderId(order.getOrderSn());
        ExpressInfo.RecManInfo recMan = new ExpressInfo.RecManInfo();
        recMan.setName(order.getReceiverName());
        recMan.setMobile(order.getReceiverMobile());
        recMan.setPrintAddr(order.getReceiverAreaInfo() + order.getReceiverAddress());
        info.setRecMan(recMan);
        ExpressInfo.SendManInfo sendMan = new ExpressInfo.SendManInfo();
        sendMan.setName(storeAddress.getContactName());
        sendMan.setMobile(storeAddress.getTelphone());
        sendMan.setPrintAddr(storeAddress.getAreaInfo() + storeAddress.getAddress());
        info.setSendMan(sendMan);

        Map<String, Object> body = new HashMap<>(5);
        body.put("method", "order");
        body.put("key", key);
        String t = System.currentTimeMillis() + "";
        body.put("t", t);
        String param = JSON.toJSONString(info);
        String msg = param + t + key + secret;
        String sign = Md5.printSign(msg);
        body.put("sign", sign);
        body.put("param", param);
        log.info("快递100电子面单下单入参信息：" + JSON.toJSON(body));
        HttpResponse execute = HttpUtil.createPost(url).headerMap(headers, true).form(body).execute();
        String result = execute.body();
        log.info("快递100电子面单下单返回信息：" + result);
        return JSON.parseObject(result);
    }

    @ApiOperation("校验是否能生成电子面单订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderSns", value = "订单号字符串,以逗号隔开", required = true)
    })
    @GetMapping("restrictOrders")
    public JsonResult<List<FaceSheetCheckOrderVO>> getRestrictOrders(HttpServletRequest request, @RequestParam("orderSns") String orderSns) {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);
        AssertUtil.notFormatFrontIds(orderSns, "格式错误,请重试");
        String[] orderSnArr = orderSns.split(",");
        List<FaceSheetCheckOrderVO> vos = new ArrayList();
        for (String orderSn : orderSnArr) {
            IntegralOrder order = integralOrderModel.getIntegralOrderByOrderSn(orderSn);
            AssertUtil.isTrue(!vendor.getStoreId().equals(order.getStoreId()), "非法操作");

            vos.add(new FaceSheetCheckOrderVO(order));
        }
        return SldResponse.success(vos);
    }

    @ApiOperation("生成电子面单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderSns", value = "订单号字符串,以逗号隔开", required = true),
            @ApiImplicitParam(name = "expressId", value = "快递公司id", required = true)
    })
    @GetMapping("generate")
    public JsonResult generateFaceSheet(HttpServletRequest request,
                                        @RequestParam("orderSns") String orderSns,
                                        @RequestParam("expressId") Integer expressId) throws Exception {
        AssertUtil.notFormatFrontIds(orderSns, "格式错误,请重试");

        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        //获取快递信息
        StoreBindExpress expressInfo = this.getExpressInfo(vendor.getStoreId(), expressId);

        String expressType = stringRedisTemplate.opsForValue().get("express_type");
        if ("1".equals(expressType)) {
            //快递鸟
            if (!FaceSheetNeedField.isHasExpressCode(expressInfo.getExpressCode())) {
                return SldResponse.fail("暂不支持该快递公司");
            }
        } else {
            //快递100
            if (!FaceSheet100NeedField.isHasExpressCode(expressInfo.getExpressCode())) {
                return SldResponse.fail("暂不支持该快递公司");
            }
        }

        //商家默认发货地址
        StoreAddress storeAddress = this.getStoreAddress(vendor.getStoreId());

        //正常订单
        List<IntegralOrder> orderList = new ArrayList<>();
        //异常订单
        List<FaceSheetCheckOrderVO> errorList = new ArrayList<>();
        String[] orderSnArr = orderSns.split(",");
        for (String orderSn : orderSnArr) {
            IntegralOrder order = integralOrderModel.getOrdersWithOpByOrderSn(orderSn);
            AssertUtil.isTrue(!vendor.getStoreId().equals(order.getStoreId()), "非法操作");
            if (order.getOrderState() != OrderConst.ORDER_STATE_20 || order.getIsGenerateFacesheet() == OrderConst.IS_GENERATE_FACE__SHEET_1) {
                errorList.add(new FaceSheetCheckOrderVO(order));
            } else {
                orderList.add(order);
            }
        }

        //更新订单物流信息
        IntegralOrder orderUpdate = new IntegralOrder();
        orderUpdate.setExpressId(expressId);
        orderUpdate.setExpressCode(expressInfo.getExpressCode());
        orderUpdate.setExpressName(expressInfo.getExpressName());
        orderUpdate.setIsGenerateFacesheet(OrderConst.IS_GENERATE_FACE__SHEET_1);

        //获取快递配置信息
        Map<String, String> map = new HashMap<>();
        if ("1".equals(expressType)) {
            map = this.getExpressSetting(vendor.getStoreId());
        }
        for (IntegralOrder order : orderList) {
            if ("1".equals(expressType)) {
                //快递鸟
                String eBusinessId = map.get("eBusinessId");
                String appKey = map.get("appKey");
                JSONObject jsonObject = this.getExpressNumber1(order, expressInfo, storeAddress, eBusinessId, appKey);
                String resultCode = jsonObject.getString("ResultCode");
                if ("100".equals(resultCode)) {
                    //获取物流单号
                    JSONObject object = JSON.parseObject(jsonObject.getString("Order"));
                    //物流单号
                    String logisticCode = object.getString("LogisticCode");

                    orderUpdate.setOrderId(order.getOrderId());
                    orderUpdate.setExpressNumber(logisticCode);
                    integralOrderModel.updateIntegralOrder(orderUpdate);
                } else {
                    String reason = jsonObject.getString("Reason");
                    log.error("电子面单生成失败，原因：" + reason);
                    if (!errorList.contains(new FaceSheetCheckOrderVO(order))) {
                        order.setIsGenerateFacesheet(OrderConst.IS_GENERATE_FACE__SHEET_1);
                        FaceSheetCheckOrderVO orderVO = new FaceSheetCheckOrderVO(order);
                        orderVO.setRestrictReason(reason);
                        errorList.add(orderVO);
                    }
                }
            } else {
                //快递100
                JSONObject jsonObject = this.getExpressNumber2(order, expressInfo, storeAddress);
                String code = jsonObject.getString("code");
                if ("200".equals(code)) {
                    //获取物流单号
                    JSONObject data = jsonObject.getJSONObject("data");
                    //物流单号
                    String logisticCode = data.getString("kuaidinum");
                    //任务id
                    String taskId = data.getString("taskId");

                    orderUpdate.setOrderId(order.getOrderId());
                    orderUpdate.setExpressNumber(logisticCode);
                    orderUpdate.setTaskId(taskId);
                    integralOrderModel.updateIntegralOrder(orderUpdate);
                } else {
                    String reason = jsonObject.getString("message");
                    log.error("电子面单生成失败，原因：" + reason);
                    if (!errorList.contains(new FaceSheetCheckOrderVO(order))) {
                        order.setIsGenerateFacesheet(OrderConst.IS_GENERATE_FACE__SHEET_1);
                        FaceSheetCheckOrderVO orderVO = new FaceSheetCheckOrderVO(order);
                        orderVO.setRestrictReason(reason);
                        errorList.add(orderVO);
                    }
                }
            }
        }
        return SldResponse.success("电子面单生成成功", errorList);
    }

    @ApiOperation("打印电子面单校验订单列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderSns", value = "订单号字符串,以逗号隔开", required = true)
    })
    @GetMapping("printCheckOrders")
    public JsonResult<List<FaceSheetPrintCheckOrderVO>> getPrintCheckList(HttpServletRequest request, @RequestParam("orderSns") String orderSns) {

        AssertUtil.notFormatFrontIds(orderSns, "格式错误,请重试");
        String[] orderSnArr = orderSns.split(",");
        List<FaceSheetPrintCheckOrderVO> vos = new ArrayList();
        for (String orderSn : orderSnArr) {
            IntegralOrder order = integralOrderModel.getIntegralOrderByOrderSn(orderSn);
            vos.add(new FaceSheetPrintCheckOrderVO(order));
        }
        return SldResponse.success(vos);
    }

    @ApiOperation("打印电子面单接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "orderSns", value = "订单号字符串,以逗号隔开", required = true)
    })
    @PostMapping("print")
    public JsonResult printFaceSheet(HttpServletRequest request, @RequestParam("orderSns") String orderSns) throws Exception {
        AssertUtil.notFormatFrontIds(orderSns, "格式错误,请重试");

        Vendor vendor = UserUtil.getUser(request, Vendor.class);

        //key-订单号，value-积分订单信息
        Map<String, IntegralOrder> map = new HashMap<>();
        String[] orderSnArr = orderSns.split(",");
        for (String orderSn : orderSnArr) {
            IntegralOrder order = integralOrderModel.getIntegralOrderByOrderSn(orderSn);
            AssertUtil.isTrue(!vendor.getStoreId().equals(order.getStoreId()), "非法操作");
            AssertUtil.isTrue(order.getIsGenerateFacesheet() != OrderConst.IS_GENERATE_FACE__SHEET_1, "订单号：" + orderSn + " 未生成电子面单");

            map.put(orderSn, order);
        }

        //查询商户配置
        StoreExpressSetting expressSetting = this.getStoreExpressSetting(vendor.getStoreId());

        String expressType = stringRedisTemplate.opsForValue().get("express_type");
        if ("1".equals(expressType)) {
            String url = this.getPrintUrl(request, expressSetting, orderSns);
            return SldResponse.success("打印成功", url);
        } else {
            for (String orderSn : orderSnArr) {
                this.reprint(map.get(orderSn));
            }
            return SldResponse.success("打印成功");
        }
    }

    /**
     * 获取商户配置
     *
     * @param storeId 店铺id
     * @return 商户配置
     */
    public StoreExpressSetting getStoreExpressSetting(Long storeId) {
        //查询商户配置
        StoreExpressSettingExample example = new StoreExpressSettingExample();
        example.setStoreId(storeId);
        List<StoreExpressSetting> list = storeExpressSettingModel.getStoreExpressSettingList(example, null);
        AssertUtil.notEmpty(list, "请完善打印配置信息");
        return list.get(0);
    }

    /**
     * 获取快递鸟打印地址
     *
     * @param request        请求信息
     * @param expressSetting 商户配置
     * @param orderSns       订单号集合,以英文逗号隔开
     * @return 打印地址
     */
    @SneakyThrows
    public String getPrintUrl(HttpServletRequest request, StoreExpressSetting expressSetting, String orderSns) {
        //快递鸟电商ID
        String eBusinessId;
        //快递鸟电商加密私钥
        String appKey;
        String accountSetting = stringRedisTemplate.opsForValue().get("express_account_setting");
        if (StringUtil.isEmpty(accountSetting) || "1".equals(accountSetting)) {
            eBusinessId = stringRedisTemplate.opsForValue().get("express_ebusinessid");
            appKey = stringRedisTemplate.opsForValue().get("express_apikey");
        } else {
            eBusinessId = expressSetting.getBusinessId();
            appKey = expressSetting.getAppKey();
        }
        String url = "http://www.kdniao.com/External/PrintOrder.aspx";
        String ip = FaceSheetAPI.getIpAddress(request);
        PrintFaceSheetRequest printParam = FaceSheetAPI.getPrintParam(ip, eBusinessId, appKey, expressSetting.getPrinterName(), orderSns);
        return url + "?" + printParam.toString();
    }

    /**
     * 封装快递鸟接口所需数据
     *
     * @param order        订单信息
     * @param expressInfo  快递公司信息
     * @param storeAddress 店铺地址
     * @return 快递鸟信息
     */
    private String getRequestData(IntegralOrder order, StoreBindExpress expressInfo, StoreAddress storeAddress) {
        //获取发货地址信息
        RegionDistrict district;
        //等于0说明没有三级地区
        if ("0".equals(storeAddress.getAreaCode())) {
            RegionCityExample example = new RegionCityExample();
            example.setRemarkCode(storeAddress.getCityCode());
            RegionCity regionCity = regionCityModel.getRegionCityList(example, null).get(0);
            district = new RegionDistrict();
            district.setProvinceName(regionCity.getProvinceName());
            district.setCityName(regionCity.getCityName());
            district.setDistrictName("");
        } else {
            RegionDistrictExample example = new RegionDistrictExample();
            example.setRemarkCode(storeAddress.getAreaCode());
            List<RegionDistrict> regionDistrictList = regionDistrictModel.getRegionDistrictList(example, null);
            district = regionDistrictList.get(0);
        }
        //获取收货地址信息
        RegionDistrict receiveDistrict = null;
        //等于0说明没有三级地区
        if ("0".equals(order.getReceiverDistrictCode())) {
            RegionCityExample example = new RegionCityExample();
            example.setRemarkCode(order.getReceiverCityCode());
            RegionCity regionCity = regionCityModel.getRegionCityList(example, null).get(0);
            receiveDistrict = new RegionDistrict();
            receiveDistrict.setProvinceName(regionCity.getProvinceName());
            receiveDistrict.setCityName(regionCity.getCityName());
            receiveDistrict.setDistrictName("");
        } else {
            RegionDistrictExample example = new RegionDistrictExample();
            example.setRemarkCode(order.getReceiverDistrictCode());
            List<RegionDistrict> regionDistrictList = regionDistrictModel.getRegionDistrictList(example, null);
            receiveDistrict = regionDistrictList.get(0);
        }
        //拼接订单商品名称信息
        StringBuilder productInfo = new StringBuilder();
        for (IntegralOrderProduct orderProduct : order.getOrderProductList()) {
            productInfo.append(",{" + "'GoodsName':'").append(orderProduct.getGoodsName()).append("'}");
        }
        String requestData = "{'OrderCode':" + order.getOrderSn() + "," +
                "'ShipperCode':'" + expressInfo.getExpressCode() + "'," +
                "'PayType':" + expressInfo.getPayType() + "," +
                "'TemplateSize':'" + expressInfo.getTemplateSize() + "'," +
                "'Remark':'" + order.getOrderSn() + "'," +
                "'CurrencyCode':'CNY'," +
                "'Dutiable':" +
                "{" +
                "'DeclaredValue':" + order.getOrderAmount() + "}," +
                "'IsNotice':1," +
                "'CustomerName':'" + (expressInfo.getCustomerName() == null ? "" : expressInfo.getCustomerName()) + "'," +
                "'CustomerPwd':'" + (expressInfo.getCustomerPwd() == null ? "" : expressInfo.getCustomerPwd()) + "'," +
                "'MonthCode':'" + (expressInfo.getMonthCode() == null ? "" : expressInfo.getMonthCode()) + "'," +
                "'SendSite':'" + (expressInfo.getSendSite() == null ? "" : expressInfo.getSendSite()) + "'," +
                "'SendStaff':'" + (expressInfo.getSendStaff() == null ? "" : expressInfo.getSendStaff()) + "'," +
                "'ExpType':1," +
                "'Sender':" +
                "{" +
                "'Name':'" + storeAddress.getContactName() + "','Mobile':'" + storeAddress.getTelphone() + "','ProvinceName':'" + district.getProvinceName() + "','CityName':'" + district.getCityName() + "','ExpAreaName':'" + district.getDistrictName() + "','Address':'" + storeAddress.getAddress() + "'}," +
                "'Receiver':" +
                "{" +
                "'Name':'" + order.getReceiverName() + "','Mobile':'" + order.getReceiverMobile() + "','ProvinceName':'" + receiveDistrict.getProvinceName() + "','CityName':'" + receiveDistrict.getCityName() + "','ExpAreaName':'" + receiveDistrict.getDistrictName() + "','Address':'" + order.getReceiverAddress() + "'}," +
                "'Commodity':" +
                "[" + productInfo.toString().substring(1) + "]," +
                "'IsReturnPrintTemplate':0}";
        return requestData;
    }

    /**
     * 快递100 电子面单复打
     *
     * @param order 积分订单信息
     */
    public void reprint(IntegralOrder order) {
        String url = "https://api.kuaidi100.com/label/order";

        AssertUtil.notEmpty(order.getTaskId(), "快递100云打印任务id为空");

        String key = stringRedisTemplate.opsForValue().get("express_100_key");
        AssertUtil.notNull(key, "请设置快递100 授权key");
        String secret = stringRedisTemplate.opsForValue().get("express_100_secret");
        AssertUtil.notNull(secret, "请设置快递100 secret");

        //请求header
        Map<String, String> headers = new HashMap<>(1);
        headers.put("Content-Type", "application/x-www-form-urlencoded");

        //请求参数
        Map<String, String> params = new HashMap<>(1);
        params.put("taskId", order.getTaskId());

        Map<String, Object> body = new HashMap<>(5);
        body.put("method", "printOld");
        body.put("key", key);
        String t = System.currentTimeMillis() + "";
        body.put("t", t);
        String param = JSON.toJSONString(params);
        body.put("sign", Md5.printSign(param + t + key + secret));
        body.put("param", param);
        log.info("快递100电子面单复打入参信息：" + JSON.toJSON(body));
        HttpResponse execute = HttpUtil.createPost(url).headerMap(headers, true).form(body).execute();
        String result = execute.body();
        log.info("快递100电子面单复打返回信息：" + result);
        JSONObject jsonObject = JSON.parseObject(result);
        String code = jsonObject.getString("code");
        if (!"200".equals(code)) {
            String reason = jsonObject.getString("message");
            throw new MallException("快递100 电子面单复打失败，原因：" + reason);
        }
    }
}
