zhou zhou
3 天以前 5cdd91e98acebbb4ff2c88cd6897896dbed6a8da
rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/phyz/impl/ErpReportServiceImpl.java
@@ -1,5 +1,6 @@
package com.vincent.rsf.openApi.service.phyz.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -8,25 +9,43 @@
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.openApi.config.PlatformProperties;
import com.vincent.rsf.openApi.entity.constant.WmsConstant;
import com.vincent.rsf.openApi.entity.dto.CommonResponse;
import com.vincent.rsf.openApi.entity.phyz.ErpReportParams;
import com.vincent.rsf.openApi.entity.phyz.Order;
import com.vincent.rsf.openApi.service.WmsErpService;
import com.vincent.rsf.openApi.service.phyz.ErpReportService;
import com.vincent.rsf.openApi.utils.ParamsMapUtils;
import com.vincent.rsf.openApi.utils.SslUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.client.config.RequestConfig;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.lang.reflect.Field;
import java.security.cert.X509Certificate;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Objects;
import java.util.*;
@Slf4j
@Service
@@ -34,8 +53,14 @@
    private static String ERP_REPORT_URL;
    private CloseableHttpClient httpClient;
    @Resource
    private PlatformProperties.ErpApi erpApi;
    @Resource
    private PlatformProperties.WmsApi wmsApi;
    @Resource
    private WmsErpService wmsErpService;
    @Resource
    private RestTemplate restTemplate;
@@ -47,16 +72,91 @@
    // 登录参数依次为账套ID、用户名、应用ID、时间戳、签名信息、语言ID
    public void loginBySign() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String url = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginBySign.common.kdsvc";
        JSONObject params = new JSONObject();
        params.put("parameters", loginParams());
        JSONObject result = postRequest(url, params, false);
    public String addOrderToServer(Order order) {
        if (Objects.isNull(order.getOrderNo()) || order.getOrderNo().isEmpty()) {
            throw new CoolException("订单号不能为空!!");
        }
        /**WMS基础配置链接*/
        String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.MODIFY_ORDER_DETLS;
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        List<Map<String, Object>> maps = new ArrayList<>();
        Map<String, Object> mapParams = new HashMap<>();
//        mapParams.put("orderNo", params.getOrderNo());
//        mapParams.put("anfme", params.getAnfme());
//        mapParams.put("type", params.getType());
//        mapParams.put("wkType", params.getWkType());
//        mapParams.put("exceStatus", params.getExceStatus());
//        mapParams.put("orderItems", params.getOrderItems());
//        maps.add(mapParams);
        JSONObject params = JSONObject.parseObject(JSON.toJSONString(order));
        JSONObject mappedData = ParamsMapUtils.apiMaps("erp", "orderId", params);
        mapParams = objectToMap(mappedData);
        maps.add(mapParams);
        log.info("修改订单信息及状态: {}, 请求参数: {}", wmsUrl, JSONArray.toJSONString(maps));
        HttpEntity<List<Map<String, Object>>> httpEntity = new HttpEntity<>(maps, headers);
        ArrayList<Order> orders = new ArrayList<>();
        orders.add(order);
        HttpEntity httpEntity2 = new HttpEntity<>(orders, headers);//cs
        // asnOrder/items/save
        ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity2, String.class);//cs
        log.info("订单修改返回结果: {}", exchange);
        if (Objects.isNull(exchange.getBody())) {
            throw new CoolException("查询失败!!");
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                if (result.getCode() == 200) {
//                    JSONObject object = JSONObject.parseObject(JSONObject.toJSONString(result.getData()));
                    return "200";
                } else {
                    return result.getMsg();
//                    throw new CoolException("查询失败!!");
                }
            } catch (JsonProcessingException e) {
                return e.getMessage();
//                throw new CoolException(e.getMessage());
            }
        }
//        ErpOpParams erpOpParams = new ErpOpParams();
//        erpOpParams.set
//
//        wmsErpService.updateOrderDetl(ErpOpParams params);
//        CommonResponse updateOrderDetl()
//
//        asnOrderService.saveOrderAndItems(params, getLoginUserId());
    }
    public static Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true); // 设置私有字段也可以访问
            try {
                map.put(field.getName(), field.get(obj));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
    // 入/出库任务完成上报
    /**
     * 入/出库任务完成上报
     *
     * @param params
     * @return
     */
    public CommonResponse reportInOrOutBound(Object params) {
        if (Objects.isNull(params)) {
            throw new CoolException("入/出库任务信息参数不能为空!!");
@@ -64,29 +164,172 @@
        // TODO:参数转换
        ErpReportParams erpReportParams = new ErpReportParams();
        erpReportParams = (ErpReportParams) params;
        String erpUrl = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc";
        log.info("Erp入/出库任务完成上报: {}, 请求参数: {}", erpUrl, JSONObject.toJSONString(erpReportParams));
        try {
            JSONObject jsonObject = postRequest(erpUrl, erpReportParams, true);
            boolean sendSuccess = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getBoolean("IsSuccess");
            // TODO:转换后返回
            if (sendSuccess) {
                return CommonResponse.ok();
            } else {
                JSONArray errors = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getJSONArray("Errors");
                String errorMsg = "";
                for (int i = 0; i < errors.size(); i++) {
                    errorMsg += errors.getJSONObject(i).getString("Message") + " ";
        if (params instanceof ErpReportParams) {
            erpReportParams = (ErpReportParams) params;
        } else if (params instanceof java.util.Map) {
            java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
            // 设置基本属性
            erpReportParams.setFDate((String) paramMap.get("FDate"));
            erpReportParams.setF_OHDL_BillnoType((String) paramMap.get("F_OHDL_BillnoType"));
            erpReportParams.setFStockOrgId(paramMap.get("FStockOrgId"));
            erpReportParams.setFPrdOrgId(paramMap.get("FPrdOrgId"));
            erpReportParams.setF_OHDL_ProPlan((String) paramMap.get("F_OHDL_ProPlan"));
            // 处理FEntity列表
            Object fEntityObj = paramMap.get("FEntity");
            if (fEntityObj instanceof java.util.List) {
                java.util.List<?> fEntityList = (java.util.List<?>) fEntityObj;
                java.util.List<ErpReportParams.FEntityItem> entityItems = new java.util.ArrayList<>();
                for (Object item : fEntityList) {
                    if (item instanceof java.util.Map) {
                        java.util.Map<String, Object> itemMap = (java.util.Map<String, Object>) item;
                        ErpReportParams.FEntityItem entityItem = new ErpReportParams.FEntityItem();
                        // 使用反射设置属性值
                        try {
                            // 使用反射直接访问字段并设置值
                            java.lang.reflect.Field field;
                            field = entityItem.getClass().getDeclaredField("FMaterialId");
                            field.setAccessible(true);
                            field.set(entityItem, itemMap.get("FMaterialId"));
                            field = entityItem.getClass().getDeclaredField("FUnitID");
                            field.setAccessible(true);
                            field.set(entityItem, itemMap.get("FUnitID"));
                            // 处理数值类型
                            Object fAppQty = itemMap.get("FAppQty");
                            if (fAppQty instanceof Number) {
                                field = entityItem.getClass().getDeclaredField("FAppQty");
                                field.setAccessible(true);
                                field.set(entityItem, ((Number) fAppQty).doubleValue());
                            } else if (fAppQty != null) {
                                field = entityItem.getClass().getDeclaredField("FAppQty");
                                field.setAccessible(true);
                                field.set(entityItem, Double.parseDouble(fAppQty.toString()));
                            }
                            Object fActualQty = itemMap.get("FActualQty");
                            if (fActualQty instanceof Number) {
                                field = entityItem.getClass().getDeclaredField("FActualQty");
                                field.setAccessible(true);
                                field.set(entityItem, ((Number) fActualQty).doubleValue());
                            } else if (fActualQty != null) {
                                field = entityItem.getClass().getDeclaredField("FActualQty");
                                field.setAccessible(true);
                                field.set(entityItem, Double.parseDouble(fActualQty.toString()));
                            }
                            field = entityItem.getClass().getDeclaredField("FStockId");
                            field.setAccessible(true);
                            field.set(entityItem, itemMap.get("FStockId"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_BworkShop");
                            field.setAccessible(true);
                            field.set(entityItem, itemMap.get("F_OHDL_BworkShop"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_Pallet");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_Pallet"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_ConPoint");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_ConPoint"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_PlanNo");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_PlanNo"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_MONo");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_MONo"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_MOId");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_MOId"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_MOLine");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_MOLine"));
                            field = entityItem.getClass().getDeclaredField("F_OHDL_MOLineId");
                            field.setAccessible(true);
                            field.set(entityItem, (String) itemMap.get("F_OHDL_MOLineId"));
                        } catch (Exception e) {
                            log.error("设置FEntityItem属性时发生错误: " + e.getMessage());
                            throw new CoolException("设置FEntityItem属性失败: " + e.getMessage());
                        }
                        entityItems.add(entityItem);
                    } else if (item instanceof ErpReportParams.FEntityItem) {
                        entityItems.add((ErpReportParams.FEntityItem) item);
                    }
                }
                return CommonResponse.error(errorMsg);
                erpReportParams.setFEntity(entityItems);
            }
        } else {
            throw new CoolException("无法处理的参数类型: " + params.getClass().getName());
        }
        JSONObject model = new JSONObject();
        model.put("Model", erpReportParams);
        JSONObject data = new JSONObject();
        data.put("data", model);
        data.put("formid", "ke3d5adc0bbe64eceafd5891400adf40e");
        try {
            JSONObject loginResult = loginBySign();
            if (loginResult.getInteger("LoginResultType") == 1) {
                String erpUrl = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.Save.common.kdsvc";
                log.info("Erp入/出库任务完成上报: {}, 请求参数: {}", erpUrl, JSONObject.toJSONString(data));
                String result2 = httpPostExample(erpUrl, data.toJSONString());
                JSONObject jsonObject = JSONObject.parseObject(result2);
                log.info("Erp入/出库任务完成上报返回" + jsonObject.toJSONString());
                boolean sendSuccess = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getBoolean("IsSuccess");
                // TODO:转换后返回
                if (sendSuccess) {
                    return CommonResponse.ok();
                } else {
                    JSONArray errors = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getJSONArray("Errors");
                    String errorMsg = "";
                    for (int i = 0; i < errors.size(); i++) {
                        errorMsg += errors.getJSONObject(i).getString("Message") + " ";
                    }
                    return CommonResponse.error(errorMsg);
                }
            }
        } catch (Exception e) {
            log.error("Erp入/出库任务上报响应失败", e);
            throw new CoolException("Erp解析响应失败:" + e.getMessage());
            log.error("loginBySign", e);
        }
//        try {
//            JSONObject jsonObject = postRequest(erpUrl, data, true);
//            log.info(jsonObject.toJSONString());
//            boolean sendSuccess = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getBoolean("IsSuccess");
//
//            // TODO:转换后返回
//            if (sendSuccess) {
//                return CommonResponse.ok();
//            } else {
//                JSONArray errors = jsonObject.getJSONObject("Result").getJSONObject("ResponseStatus").getJSONArray("Errors");
//                String errorMsg = "";
//                for (int i = 0; i < errors.size(); i++) {
//                    errorMsg += errors.getJSONObject(i).getString("Message") + " ";
//                }
//                return CommonResponse.error(errorMsg);
//            }
//        } catch (Exception e) {
//            log.error("Erp入/出库任务上报响应失败", e);
//            throw new CoolException("Erp解析响应失败:" + e.getMessage());
//        }
        return null;
    }
@@ -96,10 +339,28 @@
    // 盘点结果上报
    // region 登录
    /**
     * 登录,登录参数依次为账套ID、用户名、应用ID、时间戳、签名信息、语言ID
     *
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    public JSONObject loginBySign() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        String url = ERP_REPORT_URL + "/Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginBySign.common.kdsvc";
        JSONObject params = new JSONObject();
        params.put("parameters", loginParams());
        String result = httpPostExample(url, params.toJSONString());
        return JSONObject.parseObject(result);
    }
    /**
     * 登录参数整理
     *
     * @return
     * @throws UnsupportedEncodingException
     * @throws NoSuchAlgorithmException
     */
    private Object[] loginParams() throws UnsupportedEncodingException, NoSuchAlgorithmException {
        //时间戳
        long timestamp = System.currentTimeMillis() / 1000;
@@ -137,16 +398,16 @@
        }
        return hashString.toString();
    }
    // endregion
    /**
     * 通用HTTP POST请求方法
     *
     * @param url 请求URL
     * @param params 请求参数
     * @param needToken 是否需要token认证
     * @return 响应结果
     */
    public JSONObject postRequest(String url, Object params, boolean needToken) {
    public JSONObject postRequest(String url, Object params) {
        if (StringUtils.isBlank(url)) {
            throw new CoolException("请求URL不能为空!!");
        }
@@ -159,13 +420,21 @@
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json;charset=utf-8");
        if (needToken) {
//            String token = getToken();
//            headers.add("Authorization", "Bearer " + token);
        }
        HttpEntity<Object> httpEntity = new HttpEntity<>(params, headers);
        ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        // 创建支持忽略SSL证书验证的RestTemplate
        RestTemplate sslRestTemplate = SslUtils.createIgnoreSSLRestTemplate();
        // 设置错误处理器,不抛出异常,而是返回响应体
        sslRestTemplate.setErrorHandler(new org.springframework.web.client.DefaultResponseErrorHandler() {
            @Override
            public boolean hasError(ClientHttpResponse response) throws IOException {
                // 不管状态码如何,都不视为错误
                return false;
            }
        });
        ResponseEntity<String> exchange = sslRestTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
        log.info("Erp POST请求响应结果: {}", exchange);
        if (Objects.isNull(exchange.getBody())) {
@@ -181,4 +450,143 @@
            throw new CoolException("Erp解析响应失败:" + e.getMessage());
        }
    }
    /**
     * HTTP POST请求示例 - 支持HTTPS
     *
     * @param url    请求URL
     * @param params 请求参数
     * @return 响应结果
     */
    public String httpPostExample(String url, String params) {
        if (httpClient == null) {
            httpClient = createHttpsClient();
        }
        HttpPost httpPost = new HttpPost(url);
        try {
            StringEntity entity = new StringEntity(params, "UTF-8");
            httpPost.setEntity(entity);
            httpPost.setHeader("Content-type", "application/json;charset=utf-8");
            httpPost.setHeader("Accept", "application/json");
            return EntityUtils.toString(httpClient.execute(httpPost).getEntity());
        } catch (Exception e) {
            log.error("HTTP POST请求失败: {}", e.getMessage(), e);
            throw new CoolException("HTTP POST请求失败: " + e.getMessage());
        }
    }
    /**
     * 使用RestTemplate的HTTPS POST请求示例
     *
     * @param url    请求URL
     * @param params 请求参数
     * @return 响应结果
     */
    public String httpsPostWithRestTemplate(String url, String params) {
        try {
            log.info("HTTPS POST请求: {}, 请求参数: {}", url, params);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Type", "application/json;charset=utf-8");
            headers.add("Accept", "application/json");
            HttpEntity<String> httpEntity = new HttpEntity<>(params, headers);
            // 使用项目中已有的SSL工具类创建忽略SSL证书验证的RestTemplate
            RestTemplate sslRestTemplate = SslUtils.createIgnoreSSLRestTemplate();
            // 设置错误处理器,不抛出异常,而是返回响应体
            sslRestTemplate.setErrorHandler(new org.springframework.web.client.DefaultResponseErrorHandler() {
                @Override
                public boolean hasError(ClientHttpResponse response) throws IOException {
                    // 不管状态码如何,都不视为错误
                    return false;
                }
            });
            ResponseEntity<String> exchange = sslRestTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
            log.info("HTTPS POST请求响应结果: {}", exchange);
            if (Objects.isNull(exchange.getBody())) {
                throw new CoolException("请求失败!!");
            }
            return exchange.getBody();
        } catch (Exception e) {
            log.error("HTTPS POST请求失败: {}", e.getMessage(), e);
            throw new CoolException("HTTPS POST请求失败: " + e.getMessage());
        }
    }
    /**
     * 创建支持HTTPS的HttpClient
     *
     * @return CloseableHttpClient实例
     */
    private CloseableHttpClient createHttpsClient() {
        try {
            // 创建信任所有证书的TrustManager
            TrustManager[] trustAllCerts = new TrustManager[] {
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() { return null; }
                    public void checkClientTrusted(X509Certificate[] certs, String authType) { }
                    public void checkServerTrusted(X509Certificate[] certs, String authType) { }
                }
            };
            // 初始化SSLContext
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            // 创建SSL连接管理器
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    sslContext,
                    (hostname, session) -> true // 允许所有主机名
            );
            // 创建HttpClientBuilder并设置SSL配置
            RequestConfig config = RequestConfig.custom()
                    .setConnectTimeout(30000)  // 连接超时时间
                    .setSocketTimeout(60000)   // 读取超时时间
                    .build();
            return HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .setDefaultRequestConfig(config)
                    .build();
        } catch (Exception e) {
            log.error("创建HTTPS客户端失败: {}", e.getMessage(), e);
            return HttpClients.createDefault(); // 回退到默认客户端
        }
    }
//    /**
//     * 示例:如何使用HTTPS POST方法
//     *
//     * @param url    目标URL
//     * @param jsonData JSON数据
//     * @return 响应结果
//     */
//    public String exampleUsage(String url, String jsonData) {
//        log.info("开始调用HTTPS POST请求示例");
//
//        try {
//            // 方法1: 使用Apache HttpClient
//            String result1 = httpPostExample(url, jsonData);
//            log.info("使用HttpClient的POST请求结果: {}", result1);
//
//            // 方法2: 使用RestTemplate
//            String result2 = httpsPostWithRestTemplate(url, jsonData);
//            log.info("使用RestTemplate的POST请求结果: {}", result2);
//
//            // 根据实际需要选择返回结果
//            return result1;
//        } catch (Exception e) {
//            log.error("HTTPS POST请求示例执行失败: {}", e.getMessage(), e);
//            throw e;
//        }
//    }
}