package com.ruoyi.logistics.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lop.open.api.sdk.DefaultDomainApiClient;
import com.lop.open.api.sdk.LopException;
import com.lop.open.api.sdk.domain.ECAP.CommonBusinessApi.commonGetQRCodeV1.CommonBusinessGetQRCodeRequest;
import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.CommonCreateOrderRequest;
import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.CommonProductInfo;
import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCheckPreCreateOrderV1.Contact;
import com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCargoInfo;
import com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonCancelOrderV1.CommonOrderCancelRequest;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetActualFeeInfoV1.CommonActualFeeRequest;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderByMonthSettleQRV1.CommonMonthSettleQRQueryRequest;
import com.lop.open.api.sdk.domain.ECAP.CommonQueryOrderApi.commonGetOrderInfoV1.CommonOrderInfoRequest;
import com.lop.open.api.sdk.domain.jdcloudprint.RenderService.render4Outer.OutputConfigDTO;
import com.lop.open.api.sdk.domain.jdcloudprint.RenderService.render4Outer.PrintDataDTO;
import com.lop.open.api.sdk.domain.jdcloudprint.RenderService.render4Outer.QueryRenderDTO;
import com.lop.open.api.sdk.plugin.LopPlugin;
import com.lop.open.api.sdk.plugin.factory.OAuth2PluginFactory;
import com.lop.open.api.sdk.request.ECAP.*;
import com.lop.open.api.sdk.request.jdcloudprint.CloudPrintRenderLopRequest;
import com.lop.open.api.sdk.response.ECAP.*;
import com.lop.open.api.sdk.response.jdcloudprint.CloudPrintRenderLopResponse;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.bean.BeanUtils;
import com.ruoyi.common.redis.service.RedisIdGenerator;
import com.ruoyi.front.request.CommonBusinessGetQRCodeExtendRequest;
import com.ruoyi.front.request.CommonMonthSettleQRQueryExtendRequest;
import com.ruoyi.logistics.config.JDExpressConfig;
import com.ruoyi.logistics.constant.JDDictConstants;
import com.ruoyi.logistics.constant.SysConfigConstants;
import com.ruoyi.logistics.domain.BizWaybillOrder;
import com.ruoyi.logistics.response.CommonOrderInfoResponse;
import com.ruoyi.logistics.service.LogisticsService;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class JDLogisticsService  implements LogisticsService {

    @Autowired
    private JDExpressConfig jdExpressConfig;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private RedisIdGenerator redisIdGenerator;

    @Override
    public JSONObject precheckOrder(BizWaybillOrder bizWaybillOrder) {
        log.info("京东开放平台订单预校验接口，入参：{}", bizWaybillOrder);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersPrecheckLopRequest request = new EcapV1OrdersPrecheckLopRequest();

            //发货人
            Contact senderContact  = new Contact();
            senderContact.setName(bizWaybillOrder.getSenderName());
            senderContact.setMobile(bizWaybillOrder.getSenderPhone());
            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());
//            senderContact.setFullAddress("北京市大兴区亦庄经济开发区abc");

            //收货人
            Contact receiverContact = new Contact();
            receiverContact.setName(bizWaybillOrder.getReceiverName());
            receiverContact.setMobile(bizWaybillOrder.getReceiverPhone());
            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());
//            receiverContact.setFullAddress("河南省洛阳市西工区正大国际西区");

            //订单信息
            CommonCreateOrderRequest requestDTO = new  CommonCreateOrderRequest();
            requestDTO.setOrderOrigin(getOrderOrigin(bizWaybillOrder.getProductCode()));
            if (requestDTO.getOrderOrigin() == 1) {
                requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            } else {
                requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            }
            requestDTO.setPickupStartTime(bizWaybillOrder.getSendStartTime().getTime());
            requestDTO.setPickupEndTime(bizWaybillOrder.getSendEndTime().getTime());

            CommonProductInfo productInfo = new CommonProductInfo();
            productInfo.setProductCode(bizWaybillOrder.getProductCode());

            requestDTO.setProductsReq(productInfo);
            requestDTO.setReceiverContact(receiverContact);
            requestDTO.setSenderContact(senderContact);
            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台订单预校验接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersPrecheckLopResponse response = client.execute(request);
            log.info("京东开放平台订单预校验接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", "");
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台订单预校验！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台订单预校验！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台订单预校验接口异常：{}", e);
            throw new ServiceException("京东开放平台订单预校验接口异常");
        }
        return result;
    }

    @Override
    public JSONObject createOrder(BizWaybillOrder bizWaybillOrder) {
        log.info("京东开放平台下单接口，入参：{}", bizWaybillOrder);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersCreateLopRequest request = new EcapV1OrdersCreateLopRequest();

            //发货人
            com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact senderContact  = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact();
            senderContact.setName(bizWaybillOrder.getSenderName());
            senderContact.setMobile(bizWaybillOrder.getSenderPhone());
            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());
//            senderContact.setFullAddress("北京市大兴区亦庄经济开发区abc");

            //收货人
            com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact receiverContact = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.Contact();
            receiverContact.setName(bizWaybillOrder.getReceiverName());
            receiverContact.setMobile(bizWaybillOrder.getReceiverPhone());
            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());
//            receiverContact.setFullAddress("河南省洛阳市西工区正大国际西区");

            //订单信息
            com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCreateOrderRequest requestDTO = new  com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonCreateOrderRequest();
            requestDTO.setOrderId(bizWaybillOrder.getWaybillNo());
            requestDTO.setOrderOrigin(getOrderOrigin(bizWaybillOrder.getProductCode()));
            if (requestDTO.getOrderOrigin() == 1) {
                requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            } else {
                requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            }
            requestDTO.setSettleType(3);
            requestDTO.setPickupStartTime(bizWaybillOrder.getSendStartTime().getTime());
            requestDTO.setPickupEndTime(bizWaybillOrder.getSendEndTime().getTime());
            requestDTO.setPickupType(1);

            //产品信息
            com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo productInfo = new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo();
            productInfo.setProductCode(bizWaybillOrder.getProductCode());
            productInfo.setAddedProducts(getAddedProducts(requestDTO.getOrderOrigin(), bizWaybillOrder.getAddedService()));


            //货物信息
            List<CommonCargoInfo> cargoes = new ArrayList<>();
            CommonCargoInfo cargoInfo = new CommonCargoInfo();
            cargoInfo.setName(bizWaybillOrder.getGoodsName());
            cargoInfo.setQuantity(bizWaybillOrder.getGoodsQty().intValue());
            cargoInfo.setWeight(bizWaybillOrder.getGoodsWeight());
            cargoInfo.setVolume(bizWaybillOrder.getGoodsVolume());
            cargoes.add(cargoInfo);

            //扩展信息
            Map<String, String> extendProps = new HashMap<>();
            extendProps.put("autoSubscribe", "1");
            extendProps.put("universalFeePush", "1");

            requestDTO.setExtendProps(extendProps);
            requestDTO.setCargoes(cargoes);
            requestDTO.setProductsReq(productInfo);
            requestDTO.setReceiverContact(receiverContact);
            requestDTO.setSenderContact(senderContact);
            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台下单接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersCreateLopResponse response = client.execute(request);
            log.info("京东开放平台下单接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    // 返回京东物流单号
                    bizWaybillOrder.setExternalWaybillNo(response.getResult().getData().getWaybillCode());
                    result.put("data", response.getResult().getData().getWaybillCode());
                    result.put("msg", "");
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台下单！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台下单！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台下单接口异常：{}", e);
            throw new ServiceException("京东开放平台下单接口异常");
        }
        return result;
    }

    @Override
    public JSONObject cancelOrder(BizWaybillOrder bizWaybillOrder) {
        log.info("京东开放平台取消订单接口，入参：{}", bizWaybillOrder);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersCancelLopRequest request = new EcapV1OrdersCancelLopRequest();

            //取消订单入参对象
            CommonOrderCancelRequest requestDTO = new CommonOrderCancelRequest();
            requestDTO.setWaybillCode(bizWaybillOrder.getExternalWaybillNo());
            requestDTO.setCustomerOrderId(bizWaybillOrder.getWaybillNo());
            requestDTO.setOrderOrigin(getOrderOrigin(bizWaybillOrder.getProductCode()));
            if (requestDTO.getOrderOrigin() == 1) {
                requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            } else {
                requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            }
            requestDTO.setCancelReason(bizWaybillOrder.getCancelReason());
            requestDTO.setCancelReasonCode("1");
            requestDTO.setCancelType(1);

            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台取消订单接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersCancelLopResponse response = client.execute(request);
            log.info("京东开放平台取消订单接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", "");
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台取消订单！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台取消订单！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台取消订单接口异常：{}", e);
            throw new ServiceException("京东开放平台取消订单接口异常");
        }
        return result;
    }

    @Override
    public JSONObject modifyOrder(BizWaybillOrder bizWaybillOrder) {
        log.info("京东开放平台修改订单接口，入参：{}", bizWaybillOrder);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersModifyLopRequest request = new EcapV1OrdersModifyLopRequest();

            //发货人
            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact senderContact  = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact();
            senderContact.setFullAddress(bizWaybillOrder.getSenderProvince() + bizWaybillOrder.getSenderCity() + bizWaybillOrder.getSenderCounty() + bizWaybillOrder.getSenderAddress());

            //收货人
            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact receiverContact = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.Contact();
            receiverContact.setFullAddress(bizWaybillOrder.getReceiverProvince() + bizWaybillOrder.getReceiverCity() + bizWaybillOrder.getReceiverCounty() + bizWaybillOrder.getReceiverAddress());

            //订单信息
            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonModifyCancelOrderRequest requestDTO = new  com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonModifyCancelOrderRequest();
            requestDTO.setOrderId(bizWaybillOrder.getWaybillNo());
            requestDTO.setOrderOrigin(1);
            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            requestDTO.setSettleType(3);
            requestDTO.setPickupStartTime(bizWaybillOrder.getPickupTime().getTime());
            requestDTO.setPickupEndTime(DateUtils.addHours(bizWaybillOrder.getPickupTime(), 1).getTime());

            //产品信息
            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonProductInfoRequest productInfo = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonProductInfoRequest();
            productInfo.setProductCode(bizWaybillOrder.getProductCode());

            //货物信息
            List<com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo> cargoes = new ArrayList<>();
            com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo cargoInfo = new com.lop.open.api.sdk.domain.ECAP.CommonModifyCancelOrderApi.commonModifyOrderV1.CommonCargoInfo();
            cargoInfo.setName(bizWaybillOrder.getGoodsName());
            cargoInfo.setQuantity(bizWaybillOrder.getGoodsQty().intValue());
            cargoInfo.setWeight(bizWaybillOrder.getGoodsWeight());
            cargoInfo.setVolume(bizWaybillOrder.getGoodsVolume());
            cargoes.add(cargoInfo);

            //扩展信息
            Map<String, String> extendProps = new HashMap<>();
            extendProps.put("autoSubscribe", "1");
            extendProps.put("universalFeePush", "1");

            requestDTO.setExtendProps(extendProps);
            requestDTO.setCargoes(cargoes);
            requestDTO.setProductsReq(productInfo);
            requestDTO.setReceiverContact(receiverContact);
            requestDTO.setSenderContact(senderContact);
            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台修改订单接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersModifyLopResponse response = client.execute(request);
            log.info("京东开放平台修改订单接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", "");
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台修改订单！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台修改订单！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台修改订单接口异常：{}", e);
            throw new ServiceException("京东开放平台修改订单接口异常");
        }
        return result;
    }

    private Integer getOrderOrigin(String productCode) {
        int orderOrigin = 1;
        if (productCode.equals(JDDictConstants.PRODUCT_CODE_ED_M_0001) || productCode.equals(JDDictConstants.PRODUCT_CODE_ED_M_0002)) {
            orderOrigin = 1;
        } else if (productCode.equals(JDDictConstants.PRODUCT_CODE_FR_M_0004)) {
            orderOrigin = 4;
        }
        return orderOrigin;
    }

    // 增值服务配置映射表
    private static final Map<Integer, Map<String, ProductConfig>> SERVICE_CONFIG_MAP = new HashMap<>();
    
    static {
        // 订单来源为1的配置
        Map<String, ProductConfig> origin1Config = new HashMap<>();
        origin1Config.put("isPack", new ProductConfig("ed-a-0011", false, true));
        origin1Config.put("guaranteeMoney", new ProductConfig("ed-a-0002", true, false));
        origin1Config.put("isReceiptCollect", new ProductConfig("ed-a-0010", true, true));
        SERVICE_CONFIG_MAP.put(1, origin1Config);
        
        // 订单来源为4的配置
        Map<String, ProductConfig> origin4Config = new HashMap<>();
        origin4Config.put("isPack", new ProductConfig("fr-a-0005", false, true));
        origin4Config.put("guaranteeMoney", new ProductConfig("fr-a-0002", true, false));
        origin4Config.put("isReceiptCollect", new ProductConfig("fr-a-0007", true, true));
        SERVICE_CONFIG_MAP.put(4, origin4Config);
    }
    
    /**
     * 产品配置类
     */
    private static class ProductConfig {
        private final String productCode;
        private final boolean hasAttrs;
        private final boolean valueType;
        
        public ProductConfig(String productCode, boolean hasAttrs, boolean valueType) {
            this.productCode = productCode;
            this.hasAttrs = hasAttrs;
            this.valueType = valueType;
        }
        
        public String getProductCode() {
            return productCode;
        }
        
        public boolean isHasAttrs() {
            return hasAttrs;
        }

        public boolean getValueType() {
            return valueType;
        }
    }
    
    /**
     * 封装增值服务参数
     * @param orderOrigin 订单来源
     * @param addedService 增值服务JSON字符串
     * @return 增值服务产品列表
     */
    private List<com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo> getAddedProducts(Integer orderOrigin, String addedService) {
        if (StringUtils.isBlank(addedService)) {
            return null;
        }

        JSONObject addedJson = JSON.parseObject(addedService);
        List<com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo> addedProducts = new ArrayList<>();
        
        // 获取当前订单来源的配置
        Map<String, ProductConfig> configMap = SERVICE_CONFIG_MAP.get(orderOrigin);
        if (configMap == null) {
            return addedProducts;
        }
        
        // 遍历配置中的所有增值服务键
        for (Map.Entry<String, ProductConfig> entry : configMap.entrySet()) {
            String serviceKey = entry.getKey();
            ProductConfig config = entry.getValue();
            if (StringUtils.isBlank(addedJson.getString(serviceKey))) {
                continue;
            }
            
            // 检查JSON中是否包含该增值服务
            if (addedJson.containsKey(serviceKey)) {
                com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo addedProduct = 
                    createProductInfo(config.getProductCode(), config.isHasAttrs() ? 
                        addedJson.getString(serviceKey) : null);
                addedProducts.add(addedProduct);
            }
        }

        return addedProducts;
    }
    
    /**
     * 创建产品信息对象
     * @param productCode 产品编码
     * @param attrValue 属性值（可为空）
     * @return 产品信息对象
     */
    private com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo 
        createProductInfo(String productCode, String attrValue) {
        com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo addedProduct = 
            new com.lop.open.api.sdk.domain.ECAP.CommonCreateOrderApi.commonCreateOrderV1.CommonProductInfo();
        addedProduct.setProductCode(productCode);
        
        // 如果需要设置属性，则添加属性
        if (attrValue != null) {
            addedProduct.setProductAttrs(getProductAttrs(productCode, attrValue));
        }
        
        return addedProduct;
    }

    /**
     * 获取产品属性
     * @param productCode 产品编码
     * @param value 属性值
     * @return 产品属性映射
     */
    private Map<String, String> getProductAttrs(String productCode, String value) {
        Map<String, String> productAttrs = new HashMap<>();
        
        switch (productCode) {
            case "ed-a-0002":
            case "fr-a-0002":
                productAttrs.put("guaranteeMoney", value);
                break;
            case "ed-a-0010":
                productAttrs.put("reReceiveMode", "[\"electronic\"]");
                productAttrs.put("reReceiveType", "[\"electronicStubForm\"]");
                break;
            case "fr-a-0007":
                productAttrs.put("reReceiveMode", "[\"electronic\"]");
                break;
            default:
                return null;
        }
        
        return productAttrs;
    }

    @Override
    public JSONObject getMonthQRCode(Integer type) {
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1BusinessQrcodeLopRequest request = new EcapV1BusinessQrcodeLopRequest();

            //取消订单入参对象
            CommonBusinessGetQRCodeExtendRequest requestDTO = new CommonBusinessGetQRCodeExtendRequest();
            if (type == 1) {
                requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            } else if (type == 2) {
                requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            }

            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台获取商家二维码接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1BusinessQrcodeLopResponse response = client.execute(request);
            log.info("京东开放平台获取商家二维码接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResponse().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", response.getResponse().getData().getVerifyMessage());
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台获取商家二维码！失败原因：" + response.getResponse().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台获取商家二维码！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台获取商家二维码接口异常：{}", e);
            throw new ServiceException("京东开放平台获取商家二维码接口异常");
        }
        return result;
    }

    @Override
    public JSONObject queryOrderByQRCode(String qrCode, Integer qrcodeType) {
        log.info("京东开放平台根据二维码查询运单号接口，入参：{}", qrCode);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            CommonqueryorderapiCommongetorderbymonthsettleqrv1LopRequest request = new CommonqueryorderapiCommongetorderbymonthsettleqrv1LopRequest();

            CommonMonthSettleQRQueryExtendRequest requestDTO = new CommonMonthSettleQRQueryExtendRequest();
            if (1 == qrcodeType) {
                requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            } else if (2 == qrcodeType) {
                requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            }
            requestDTO.setMonthSettleQR(qrCode);
            requestDTO.setAppKey(jdExpressConfig.getAppKey());

            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台根据二维码查询运单号接口，请求参数：{}", JSON.toJSONString(request));
            CommonqueryorderapiCommongetorderbymonthsettleqrv1LopResponse response = client.execute(request);
            log.info("京东开放平台根据二维码查询运单号接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResponse().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", response.getResponse().getData());
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台根据二维码查询运单号接口！失败原因：" + response.getResponse().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台根据二维码查询运单号接口！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台根据二维码查询运单号接口异常：{}", e);
            throw new ServiceException("京东开放平台根据二维码查询运单号接口异常");
        }
        return result;
    }

    @Override
    public JSONObject queryOrderDetailByWaybillCode(String waybillCode) {
        log.info("京东开放平台根据运单号查询运单详情接口，入参：{}", waybillCode);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersDetailsQueryLopRequest request = new EcapV1OrdersDetailsQueryLopRequest();

            CommonOrderInfoRequest requestDTO = new CommonOrderInfoRequest();
            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            requestDTO.setWaybillCode(waybillCode);

            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台根据运单号查询运单详情接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersDetailsQueryLopResponse response = client.execute(request);
            log.info("京东开放平台根据运单号查询运单详情接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    JSONObject msgJson = JSON.parseObject(response.getMsg());
                    JSONObject responseJson = msgJson.getJSONObject("response");
                    JSONObject contentJson = responseJson.getJSONObject("content");
                    CommonOrderInfoResponse commonOrderInfoResponse = JSON.parseObject(contentJson.getString("data"), CommonOrderInfoResponse.class);
                    result.put("msg", commonOrderInfoResponse);
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台根据运单号查询运单详情接口！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台根据运单号查询运单详情接口！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台根据运单号查询运单详情接口异常：{}", e);
            throw new ServiceException("京东开放平台根据运单号查询运单详情接口异常");
        }
        return result;
    }

    @Override
    public JSONObject queryOrderFeeInfo(String waybillCode) {
        log.info("京东开放平台根据运单号查询运单费用接口，入参：{}", waybillCode);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            EcapV1OrdersActualfeeQueryLopRequest request = new EcapV1OrdersActualfeeQueryLopRequest();

            CommonActualFeeRequest requestDTO = new CommonActualFeeRequest();
            requestDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
            requestDTO.setBusinessUnitCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
            requestDTO.setWaybillCode(waybillCode);

            request.setRequest(requestDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台根据运单号查询运单费用接口，请求参数：{}", JSON.toJSONString(request));
            EcapV1OrdersActualfeeQueryLopResponse response = client.execute(request);
            log.info("京东开放平台根据运单号查询运单费用接口，响应结果：{}", JSON.toJSONString(response));

            if (response.getCode().equals("0")) {
                if (response.getResult().getCode() == 0) {
                    result.put("success", true);
                    result.put("msg", response.getResult().getData());
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台根据运单号查询运单费用接口！失败原因：" + response.getResult().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台根据运单号查询运单费用接口！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台根据运单号查询运单费用接口异常：{}", e);
            throw new ServiceException("京东开放平台根据运单号查询运单费用接口异常");
        }
        return result;
    }

    @Override
    public JSONObject queryWaybillPdf(BizWaybillOrder bizWaybillOrder) {
        log.info("京东开放平台根据运单信息查询面单pdf接口，入参：{}", bizWaybillOrder);
        JSONObject result = new JSONObject();
        try {
            //设置接口域名(有的对接方案同时支持生产和沙箱环境，有的仅支持生产，具体以对接方案中的【API文档-请求地址】为准)，生产域名：https://api.jdl.com 预发环境域名：https://uat-api.jdl.com
            //DefaultDomainApiClient对象全局只需要创建一次
            DefaultDomainApiClient client = new DefaultDomainApiClient(jdExpressConfig.getServerUrl(),500,15000);

            //入参对象
            CloudPrintRenderLopRequest request = new CloudPrintRenderLopRequest();

            QueryRenderDTO queryRenderDTO = new QueryRenderDTO();
            if (getOrderOrigin(bizWaybillOrder.getProductCode()) == 1) {
                queryRenderDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_CUSTOMERCODE));
                queryRenderDTO.setTemplateCode("jdkd100x113");
            } else {
                queryRenderDTO.setCustomerCode(sysConfigService.selectConfigByKey(SysConfigConstants.JD_LOGISTICS_BUSINESSUNITCODE));
                queryRenderDTO.setTemplateCode("jdky100x113");
            }
            queryRenderDTO.setOperator("瑞鲸速达");
            queryRenderDTO.setTaskId(redisIdGenerator.generateUniqueId("JDMDTASK"));

            List<PrintDataDTO> printDataDTOList = new ArrayList<>();
            PrintDataDTO printDataDTO = new PrintDataDTO();

            printDataDTO.setOrderNumber(redisIdGenerator.generateUniqueId("JDMD"));
            if (getOrderOrigin(bizWaybillOrder.getProductCode()) == 1) {
                printDataDTO.setCarrierCode("JD");
                printDataDTO.setScene(4);
            } else {
                printDataDTO.setCarrierCode("JDKY");
                printDataDTO.setScene(5);
            }
            printDataDTO.setBillCodeValue(bizWaybillOrder.getExternalWaybillNo());
            printDataDTO.setBillCodeType("waybillCode");

            printDataDTOList.add(printDataDTO);
            queryRenderDTO.setPrintData(printDataDTOList);

            List<OutputConfigDTO> outputConfigDTOList = new ArrayList<>();
            OutputConfigDTO outputConfigDTO = new OutputConfigDTO();
            outputConfigDTO.setOutputType(1);
            outputConfigDTO.setDataFormat(1);
            outputConfigDTO.setFileFormat(1);
            outputConfigDTOList.add(outputConfigDTO);
            queryRenderDTO.setOutputConfig(outputConfigDTOList);

            request.setQueryRenderDTO(queryRenderDTO);

            //设置插件，必须的操作，不同类型的应用入参不同，请看入参注释，公共参数按顺序分别为AppKey、AppSecret、AccessToken
            //使用开放平台ISV/自研商家应用调用接口
            LopPlugin lopPlugin = OAuth2PluginFactory.produceLopPlugin(jdExpressConfig.getAppKey(), jdExpressConfig.getAppSecret(), jdExpressConfig.getAccessToken());
            request.addLopPlugin(lopPlugin);

            log.info("京东开放平台根据运单信息查询面单pdf接口，请求参数：{}", JSON.toJSONString(request));
            CloudPrintRenderLopResponse response = client.execute(request);
            log.info("京东开放平台根据运单信息查询面单pdf接口，响应结果：{}", JSON.toJSONString(response));

            result.put("url", "");
            if (response.getCode().equals("0")) {
                if (response.getPrintResultDTO().getCode() == 1000) {
                    result.put("success", true);
                    result.put("msg", response.getPrintResultDTO().getResult().get(0).getUrl());
                    result.put("url", response.getPrintResultDTO().getResult().get(0).getUrl());
                } else {
                    result.put("success", false);
                    result.put("msg", "京东开放平台根据运单信息查询面单pdf接口！失败原因：" + response.getPrintResultDTO().getMsg());
                }
            } else {
                result.put("success", false);
                result.put("msg", "京东开放平台根据运单信息查询面单pdf接口！失败原因：" + response.getMsg());
            }
        } catch (LopException e) {
            log.error("京东开放平台根据运单信息查询面单pdf接口异常：{}", e);
            throw new ServiceException("京东开放平台根据运单信息查询面单pdf接口异常");
        }
        return result;
    }
}
