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; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.cfg.CoercionAction; 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.*; @Slf4j @Service public class ErpReportServiceImpl implements ErpReportService { 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; @PostConstruct public void init() { ERP_REPORT_URL = erpApi.getErpUrl(); } 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> maps = new ArrayList<>(); Map 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>> httpEntity = new HttpEntity<>(maps, headers); ArrayList orders = new ArrayList<>(); orders.add(order); HttpEntity httpEntity2 = new HttpEntity<>(orders, headers);//cs // asnOrder/items/save ResponseEntity 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 objectToMap(Object obj) { Map 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("入/出库任务信息参数不能为空!!"); } // TODO:参数转换 ErpReportParams erpReportParams = new ErpReportParams(); if (params instanceof ErpReportParams) { erpReportParams = (ErpReportParams) params; } else if (params instanceof java.util.Map) { java.util.Map paramMap = (java.util.Map) 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 entityItems = new java.util.ArrayList<>(); for (Object item : fEntityList) { if (item instanceof java.util.Map) { java.util.Map itemMap = (java.util.Map) 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); } } 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("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; } // 其他入/出库主动上报 // 盘点结果上报 // 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; //数据中心ID String dbId = "69368c1051a322"; //用户名称 String userName = "楼坚伟"; //第三方系统应用Id String appId = "330678_w2eBwdkp0oCW2XxuW16D4w/NRhTaTPKp"; //第三方系统应用秘钥 String appSecret = "31c9e5da6472456193e0c8a7dd2160d9"; //将账套ID、用户名、应用ID、应用秘钥、时间戳 放到数组里面 String[] arr = new String[] { dbId, userName, appId, appSecret, String.valueOf(timestamp) }; //生成签名信息 String sign = getSha256(arr); return new Object[] { dbId, userName, appId, String.valueOf(timestamp), sign, 2052}; } public static String getSha256(String[] input) throws UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchAlgorithmException { Arrays.sort(input); //SHA1加密的话改成MessageDigest.getInstance("SHA-1"); MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); for (String str : input) { sha256.update(str.getBytes("UTF-8")); } byte[] hashBytes = sha256.digest(); StringBuilder hashString = new StringBuilder(); for (byte b : hashBytes) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hashString.append('0'); } hashString.append(hex); } return hashString.toString(); } // endregion /** * 通用HTTP POST请求方法 * * @param url 请求URL * @param params 请求参数 * @return 响应结果 */ public JSONObject postRequest(String url, Object params) { if (StringUtils.isBlank(url)) { throw new CoolException("请求URL不能为空!!"); } if (Objects.isNull(params)) { throw new CoolException("请求参数不能为空!!"); } log.info("Erp POST请求: {}, 请求参数: {}", url, JSONObject.toJSONString(params)); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json;charset=utf-8"); HttpEntity httpEntity = new HttpEntity<>(params, headers); // 创建支持忽略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 exchange = sslRestTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class); log.info("Erp POST请求响应结果: {}", exchange); if (Objects.isNull(exchange.getBody())) { throw new CoolException("请求失败!!"); } try { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); return objectMapper.readValue(exchange.getBody(), JSONObject.class); } catch (JsonProcessingException e) { log.error("Erp解析响应失败", e); 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 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 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; // } // } }