package com.emato.cus.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.emato.cus.config.CusCardConfiguration; import com.emato.cus.entity.ResponseMsg; import com.emato.cus.utils.HttpUtil; import com.emato.cus.utils.JacksonUtils; import com.emato.cus.utils.date.DateConstant; import com.emato.cus.utils.date.DateUtil; import com.emato.cus.utils.websocket.Callback; import com.emato.cus.utils.websocket.WebSocketClientHandle; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.Connection.Response; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; import java.util.*; /** * 读取操作员卡数据,获取互联网+海关登录信息 */ @RestController public class ReaderCardController { private static final Logger LOGGER = LoggerFactory.getLogger(ReaderCardController.class); @Autowired private CusCardConfiguration cusCardConfiguration; private static CloseableHttpClient httpClient; private static Object object; // 记录历史登录信息 private static StringBuilder cookieStr = new StringBuilder(); @RequestMapping(value = "/readCusCard", produces = "application/json;charset=utf-8") public ResponseMsg readCusCard() { // 读取互联网+海关的配置 String url = cusCardConfiguration.getCusLoginUrl(); String wssUrl = cusCardConfiguration.getCusCardUrl(); String password = cusCardConfiguration.getCusCardPassword(); // 判断登录信息是否失效 if(checkCookie(cookieStr.toString())) { try { //------------------------------ 登录信息已过期,执行以下模拟登录操作 ------------------------------ httpClient = HttpClients.createDefault(); cookieStr.delete(0, cookieStr.length()); //-------------------- 第一次请求登陆页面,获取页面信息(表单信息和cookie) -------------------- Connection con = Jsoup.connect(url); // 获取连接 con.header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0"); // 配置模拟浏览器 Response rs = con.execute(); // 获取响应 Document d1 = Jsoup.parse(rs.body()); // 转换为Dom树 List et = d1.select("#fm1"); // 获取登录form表单 String random = ""; // 获取表单随机码 // 获取页面已生成的随机码 for (Element e : et.get(0).getAllElements()) { if (e.attr("name").equals("random")) { random = e.attr("value"); } } //-------------------- 处理客户端交互业务 -------------------- // 获取签名信息方法 String content = "{\"_method\":\"security_SpcSignRandom\",\"_id\":1,\"args\":{\"passwd\":\"" + password + "\",\"random\":\"" + random + "\"}}"; object = null; // 处理客户端wss交互 WebSocketClientHandle.send( wssUrl, content, new Callback() { @Override public Object run(Object params) { LOGGER.info("连接客户端响应信息:" + params); object = params; return null; } }, new Callback() { @Override public Object run(Object params) { Exception e = (Exception) params; e.printStackTrace(); return null; } } ); // 等待5秒后执行以下操作 Thread.sleep(5000); // 读取操作员卡响应信息 JSONObject json = JSON.parseObject(object.toString()); json = JSON.parseObject(json.getString("_args")); // 判断是否读取成功 if (!json.getBoolean("Result")) { String errMsg = json.getString("Error").split(",")[0]; return new ResponseMsg(ResponseMsg.ERROR_CODE, errMsg.substring(2, errMsg.length() - 1)); } // 获取操作员卡信息 StringBuilder data = new StringBuilder(); data.append(json.getString("Data")); String[] dataArr = data.substring(1, data.indexOf("]")).split(","); // 获取操作员卡数据 String info = dataArr[1].replace("\"", ""); String[] infoArr = info.split("\\|\\|"); //-------------------- 第二次请求,提交表单数据业务逻辑 -------------------- // 设置登录请求参数 List params = new ArrayList<>(); for (Element e : et.get(0).getAllElements()) { if (e.attr("name").equals("icCard")) { e.attr("value", infoArr[5]); // 设置操作员卡编号 } if (e.attr("name").equals("certNo")) { e.attr("value", infoArr[0]); // 设置操作员卡认证编号 } if (e.attr("name").equals("signData")) { e.attr("value", dataArr[0].replace("\"", "")); // 设置签名 } if (e.attr("name").equals("userPin")) { e.attr("value", password); // 设置操作员卡密码 } // 排除空值表单属性 if (e.attr("name").length() > 0) { params.add(new BasicNameValuePair(e.attr("name"), e.attr("value"))); } } // 获取页面cookie信息 String cookie = rs.cookies().toString(); cookie = cookie.substring(1, cookie.indexOf("}")); CloseableHttpResponse response = null; try { // HttpClient的Post请求类 HttpPost post = new HttpPost(url); post.setHeader("Cookie", cookie); // params是包装请求参数的List if (params != null) { post.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); } // 执行请求用execute方法 response = httpClient.execute(post); // 打印响应的状态码 if (response.getStatusLine().getStatusCode() == 302) { Header firstHeader = response.getFirstHeader("Location"); LOGGER.info("执行登录请求,响应状态码:" + response.getStatusLine().getStatusCode() + ",重定向地址:" + firstHeader.getValue()); // 判断是否重定向 if (firstHeader.getValue() != null) { // 重定向请求 post = new HttpPost(firstHeader.getValue()); response = httpClient.execute(post); // 解析重定向地址响应,获取请求头Cookie信息 Header[] headerArr = response.getAllHeaders(); for (Header header : headerArr) { if (header.getName().equals("Set-Cookie")) { cookieStr.append(header.getValue().split(";")[0] + ";"); } } } LOGGER.info("获取互联网+海关登录信息:" + cookieStr); } } catch (IOException e) { e.printStackTrace(); return new ResponseMsg(ResponseMsg.ERROR_CODE, "调用互联网+海关接口异常!"); } finally { if (response != null) { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } } } catch (Exception e) { LOGGER.info("读取操作员卡异常!"); e.printStackTrace(); return new ResponseMsg(ResponseMsg.ERROR_CODE, "读取操作员卡异常!"); } } else { //------------------------------ 登录信息未过期,获取上一次登录数据 ------------------------------ LOGGER.info("获取上一次登录信息:" + cookieStr); } if(StringUtils.isNotBlank(cookieStr.toString())) { return new ResponseMsg(ResponseMsg.SUCCESS_CODE, cookieStr.toString()); } return new ResponseMsg(ResponseMsg.ERROR_CODE, "互联网+海关登录失败,请重试!"); } /** * 校验登录cookie是否有效 * * @param cookie * @return */ public boolean checkCookie(String cookie) { //-------------------- 模拟清单回执表单查询操作 -------------------- // 表单参数 Map formMap = new HashMap<>(); formMap.put("sysDateFrom", DateUtil.getDaysAgoStart(cusCardConfiguration.getInveQueryDate())); formMap.put("sysDateTo", DateUtil.dateConvertString(new Date(), DateConstant.DATE_TIME_SECOND)); // 查询参数 Map map = new HashMap<>(); map.put("formCondition", JacksonUtils.toJson(formMap)); map.put("limit", 10); map.put("offset", 0); map.put("order", "asc"); map.put("queryArea", "QUERY"); String requestParams = JSONObject.toJSONString(map); LOGGER.info("调用【互联网+海关】查询清单接口入参:" + requestParams); boolean ckFlag = true; try { // 调用清单回执查询接口 String result = HttpUtil.postRequet(cusCardConfiguration.getInveQueryUrl(), requestParams, cookie); LOGGER.info("调用【互联网+海关】查询清单接口出参:" + result); if(StringUtils.isNotBlank(result) && JacksonUtils.isJson(result)) { ckFlag = false; } } catch (Exception e) { e.printStackTrace(); } return ckFlag; } }