haogh 11 ay önce
işleme
69abd6b615
70 değiştirilmiş dosya ile 4365 ekleme ve 0 silme
  1. 54 0
      .gitignore
  2. 3 0
      WebRoot/META-INF/MANIFEST.MF
  3. BIN
      WebRoot/WEB-INF/lib/baidu-aip-sdk-4.11.1.jar
  4. BIN
      WebRoot/WEB-INF/lib/hmsoft-mvc-common-2.0.0.jar
  5. BIN
      WebRoot/WEB-INF/lib/hmsoft-mvc-core-2.0.0.jar
  6. BIN
      WebRoot/WEB-INF/lib/hmsoft-weixin-2.0.0.jar
  7. BIN
      WebRoot/WEB-INF/lib/httpasyncclient-4.1.jar
  8. BIN
      WebRoot/WEB-INF/lib/httpclient-4.5.7.jar
  9. BIN
      WebRoot/WEB-INF/lib/httpcore-4.4.11.jar
  10. BIN
      WebRoot/WEB-INF/lib/httpcore-nio-4.4.1.jar
  11. BIN
      WebRoot/WEB-INF/lib/httpmime-4.5.11.jar
  12. BIN
      WebRoot/WEB-INF/lib/mysql-connector-java-8.0.13.jar
  13. 4 0
      src/app.properties
  14. 16 0
      src/cn/hmsoft/hmplatform/constants/ArtParamType.java
  15. 31 0
      src/cn/hmsoft/hmplatform/constants/StdResType.java
  16. 495 0
      src/cn/hmsoft/hmplatform/helper/HttpClientHelper.java
  17. 196 0
      src/cn/hmsoft/hmplatform/helper/ParamHelper.java
  18. 47 0
      src/cn/hmsoft/hmplatform/helper/PlatformParamHelper.java
  19. 96 0
      src/cn/hmsoft/hmplatform/identity/baidu/BaiduOpenApiTokenService.java
  20. 15 0
      src/cn/hmsoft/hmplatform/identity/baidu/OpenApiParam.java
  21. 122 0
      src/cn/hmsoft/hmplatform/identity/baidu/OpenApiParamUtil.java
  22. 68 0
      src/cn/hmsoft/hmplatform/identity/control/FaceMatchControl.java
  23. 171 0
      src/cn/hmsoft/hmplatform/identity/control/IdentifyControl.java
  24. 45 0
      src/cn/hmsoft/hmplatform/identity/control/VoiceControl.java
  25. 24 0
      src/cn/hmsoft/hmplatform/identity/data/dao/PStdRegDao.java
  26. 21 0
      src/cn/hmsoft/hmplatform/identity/data/dao/PStdResDao.java
  27. 10 0
      src/cn/hmsoft/hmplatform/identity/data/dao/PStdResLogDao.java
  28. 90 0
      src/cn/hmsoft/hmplatform/identity/data/model/PStdReg.java
  29. 96 0
      src/cn/hmsoft/hmplatform/identity/data/model/PStdRes.java
  30. 139 0
      src/cn/hmsoft/hmplatform/identity/data/model/PStdResLog.java
  31. 180 0
      src/cn/hmsoft/hmplatform/identity/service/FaceMatchService.java
  32. 162 0
      src/cn/hmsoft/hmplatform/identity/service/IdentifyService.java
  33. 12 0
      src/cn/hmsoft/hmplatform/identity/service/PStdRegService.java
  34. 12 0
      src/cn/hmsoft/hmplatform/identity/service/PStdResLogService.java
  35. 13 0
      src/cn/hmsoft/hmplatform/identity/service/PStdResService.java
  36. 58 0
      src/cn/hmsoft/hmplatform/identity/util/EncodeHelper.java
  37. 39 0
      src/cn/hmsoft/hmplatform/monitor/control/StdRegControl.java
  38. 48 0
      src/cn/hmsoft/hmplatform/project/control/ProjectControl.java
  39. 37 0
      src/cn/hmsoft/hmplatform/project/control/ProjectRemarkControl.java
  40. 53 0
      src/cn/hmsoft/hmplatform/project/control/SchoolControl.java
  41. 29 0
      src/cn/hmsoft/hmplatform/project/data/dao/PProjectDao.java
  42. 18 0
      src/cn/hmsoft/hmplatform/project/data/dao/PProjectRemarkDao.java
  43. 24 0
      src/cn/hmsoft/hmplatform/project/data/dao/PSchoolDao.java
  44. 76 0
      src/cn/hmsoft/hmplatform/project/data/model/PProject.java
  45. 41 0
      src/cn/hmsoft/hmplatform/project/data/model/PProjectRemark.java
  46. 40 0
      src/cn/hmsoft/hmplatform/project/data/model/PSchool.java
  47. 29 0
      src/cn/hmsoft/hmplatform/project/service/PProjectRemarkService.java
  48. 27 0
      src/cn/hmsoft/hmplatform/project/service/PProjectService.java
  49. 27 0
      src/cn/hmsoft/hmplatform/project/service/PSchoolService.java
  50. 79 0
      src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenControl.java
  51. 48 0
      src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenDefineControl.java
  52. 20 0
      src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenDeployControl.java
  53. 20 0
      src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenRequestControl.java
  54. 29 0
      src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxDefineDao.java
  55. 56 0
      src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxDeployDao.java
  56. 10 0
      src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxTokenNoticeDao.java
  57. 31 0
      src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxTokenRequestDao.java
  58. 308 0
      src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDefine.java
  59. 101 0
      src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDeploy.java
  60. 150 0
      src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDeployLog.java
  61. 133 0
      src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxTokenNotice.java
  62. 172 0
      src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxTokenRequest.java
  63. 45 0
      src/cn/hmsoft/hmplatform/wxtoken/service/PlatformTokenDefineService.java
  64. 107 0
      src/cn/hmsoft/hmplatform/wxtoken/service/PlatformWeixinTokenService.java
  65. 42 0
      src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleConfig.java
  66. 9 0
      src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleParamUtil.java
  67. 58 0
      src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleUtil.java
  68. 75 0
      src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenNoticeThread.java
  69. 196 0
      src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenRequestThread.java
  70. 8 0
      src/jdbc.properties

+ 54 - 0
.gitignore

@@ -0,0 +1,54 @@
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+*.class
+*.log
+/out/
+
+
+### Eclipse & STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+/logs/
+/log/
+/data/
+
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+
+### VS Code ###
+.vscode
+node_modules
+package-lock.json
+yarn.lock
+
+
+### Package Files ###
+*.zip
+*.war
+*.ear
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+target/
+
+.flattened-pom.xml
+.DS_Store
+

+ 3 - 0
WebRoot/META-INF/MANIFEST.MF

@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

BIN
WebRoot/WEB-INF/lib/baidu-aip-sdk-4.11.1.jar


BIN
WebRoot/WEB-INF/lib/hmsoft-mvc-common-2.0.0.jar


BIN
WebRoot/WEB-INF/lib/hmsoft-mvc-core-2.0.0.jar


BIN
WebRoot/WEB-INF/lib/hmsoft-weixin-2.0.0.jar


BIN
WebRoot/WEB-INF/lib/httpasyncclient-4.1.jar


BIN
WebRoot/WEB-INF/lib/httpclient-4.5.7.jar


BIN
WebRoot/WEB-INF/lib/httpcore-4.4.11.jar


BIN
WebRoot/WEB-INF/lib/httpcore-nio-4.4.1.jar


BIN
WebRoot/WEB-INF/lib/httpmime-4.5.11.jar


BIN
WebRoot/WEB-INF/lib/mysql-connector-java-8.0.13.jar


+ 4 - 0
src/app.properties

@@ -0,0 +1,4 @@
+AppDebug=true
+AppParamUtil=cn.hmsoft.hmplatform.helper.ParamHelper
+AppListener=cn.hmsoft.art.control.ArtInitializeLisener
+AppName=HmPlatform

+ 16 - 0
src/cn/hmsoft/hmplatform/constants/ArtParamType.java

@@ -0,0 +1,16 @@
+package cn.hmsoft.hmplatform.constants;
+
+/****************
+ * 全局参数类型
+ * @author zxq
+ * @create 2019-08-21 23:07:46
+ * @version 2.0.0
+ * @email: revisit@126.com
+ * @Company: www.hmsoft.cn
+ */
+public class ArtParamType {
+
+	public final static String Gobal = "Gobal";
+	public final static String Enrol = "Enrol";
+	public final static String Exam = "Exam";
+}

+ 31 - 0
src/cn/hmsoft/hmplatform/constants/StdResType.java

@@ -0,0 +1,31 @@
+package cn.hmsoft.hmplatform.constants;
+
+/*********************
+ * 考生的资源类型
+ *
+ */
+public enum StdResType {
+
+	/*******************
+	 * 身份证ocr识别
+	 */
+	OcrIdCard("OcrIdCard"),
+	/*******************
+	 * 身份证识别-公安部认证
+	 */
+	Identify("Identify"),
+	/*******************
+	 * 在线人脸比对
+	 */
+	FaceMatch("FaceMatch");
+	
+	private String value;
+
+	private StdResType(String value) {
+		this.value = value;
+	}
+
+	public String toString() {
+		return this.value;
+	}
+}

+ 495 - 0
src/cn/hmsoft/hmplatform/helper/HttpClientHelper.java

@@ -0,0 +1,495 @@
+package cn.hmsoft.hmplatform.helper;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpEntityEnclosingRequest;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.NoHttpResponseException;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.CookieStore;
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.ConnectTimeoutException;
+import org.apache.http.conn.routing.HttpRoute;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+
+import com.google.gson.Gson;
+
+import cn.hmsoft.helper.LocalDateHelper;
+import cn.hmsoft.hmplatform.identity.baidu.OpenApiParamUtil;
+import cn.hmsoft.log.LogHelper;
+
+public class HttpClientHelper {
+	
+	private static final int TIMEOUT = 10 * 1000;
+	private static CloseableHttpClient httpClient = null;
+	private final static Object syncLock = new Object();
+	public static CookieStore cookieStore = new BasicCookieStore();
+	
+	private HttpClientHelper() {
+		
+	}
+	
+	private static void config(HttpRequestBase base) {
+		RequestConfig requestConfig = RequestConfig.custom()
+                .setConnectionRequestTimeout(TIMEOUT)
+                .setConnectTimeout(TIMEOUT)
+                .setSocketTimeout(TIMEOUT)
+                .build();
+		//base.setProtocolVersion(HttpVersion.HTTP_1_0);
+		base.setConfig(requestConfig);
+	}
+	
+	public static CloseableHttpClient getHttpClient(String url) {
+        if (httpClient == null) {
+            synchronized (syncLock) {
+                if (httpClient == null) {
+                    httpClient = createHttpClient(200, 40, 100, url);
+                }
+            }
+        }
+        return httpClient;
+    }
+	
+	public static CloseableHttpClient createHttpClient(int maxTotal,
+            int maxPerRoute, int maxRoute, String url) {
+        ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
+        LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
+        Registry<ConnectionSocketFactory> registry = RegistryBuilder
+                .<ConnectionSocketFactory> create()
+                .register("http", plainsf)
+                .register("https", sslsf)
+                .build();
+        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
+        // 将最大连接数增加
+        cm.setMaxTotal(maxTotal);
+        // 将每个路由基础的连接增加
+        cm.setDefaultMaxPerRoute(maxPerRoute);
+        HttpHost httpHost = new HttpHost(url);
+        // 将目标主机的最大连接数增加
+        cm.setMaxPerRoute(new HttpRoute(httpHost), maxRoute);
+ 
+        // 请求重试处理
+        HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() {
+            public boolean retryRequest(IOException exception,
+                    int executionCount, HttpContext context) {
+                if (executionCount >= 5) {// 如果已经重试了5次,就放弃
+                    return false;
+                }
+                if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试
+                    return true;
+                }
+                if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常
+                    return false;
+                }
+                if (exception instanceof InterruptedIOException) {// 超时
+                    return false;
+                }
+                if (exception instanceof UnknownHostException) {// 目标服务器不可达
+                    return false;
+                }
+                if (exception instanceof ConnectTimeoutException) {// 连接被拒绝
+                    return false;
+                }
+                if (exception instanceof SSLException) {// SSL握手异常
+                    return false;
+                }
+ 
+                HttpClientContext clientContext = HttpClientContext
+                        .adapt(context);
+                HttpRequest request = clientContext.getRequest();
+                // 如果请求是幂等的,就再次尝试
+                if (!(request instanceof HttpEntityEnclosingRequest)) {
+                    return true;
+                }
+                return false;
+            }
+        };
+ 
+        CloseableHttpClient httpClient = HttpClients.custom()
+                .setConnectionManager(cm)
+                .setRetryHandler(httpRequestRetryHandler)
+                .build();
+ 
+        return httpClient;
+    }
+	
+	private static void setPostParams(HttpPost httpost, Map<String, Object> params) {
+        //List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+        Set<String> keySet = params.keySet();
+        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+        for (String key : keySet) {
+        	Object param = params.get(key);
+    		if (param.getClass().isArray()) {
+				//字符串数组
+    			Object[] arr = (Object[])param;
+    			for (Object val : arr) {
+    				builder.addPart(key, new StringBody(val.toString(), ContentType.TEXT_PLAIN));
+    			}
+    		} else {
+    			//nvps.add(new BasicNameValuePair(key, params.get(key).toString()));
+    			builder.addPart(key, new StringBody(params.get(key).toString(), ContentType.TEXT_PLAIN));
+    		}
+        }
+        httpost.setEntity(builder.build());//new UrlEncodedFormEntity(nvps, "UTF-8")
+    }
+	
+	/**
+	 * post请求.
+	 * @param url
+	 * @param params
+	 * @param headers
+	 * @return
+	 * @throws IOException
+	 */
+	public static String post(String url, Map<String, Object> params) throws IOException {
+        HttpPost httppost = new HttpPost(url);
+        config(httppost);
+        setPostParams(httppost, params);
+        CloseableHttpResponse response = null;
+        //httppost.setHeader("Content-type", "application/x-www-form-urlencoded");
+        try {
+            response = getHttpClient(url).execute(httppost, HttpClientContext.create());
+            HttpEntity entity = response.getEntity();
+            String result = EntityUtils.toString(entity, "utf-8");
+            EntityUtils.consume(entity);
+            return result;
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            try {
+                if (response != null) {
+                	response.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+	
+	/**
+	 * post请求json.
+	 * @param url
+	 * @param requestBody
+	 * @param headers
+	 * @return
+	 * @throws IOException
+	 */
+	public static String postJson(String url, String requestBody, Map<String, Object> headers) throws IOException {
+        HttpPost httppost = new HttpPost(url);
+        config(httppost);
+        StringEntity requestEntity = new StringEntity(requestBody, "utf-8");
+        requestEntity.setContentEncoding("UTF-8");
+        httppost.setHeader("Content-type", "application/json");
+        httppost.setEntity(requestEntity);
+        
+        for (String key : headers.keySet()) {
+        	httppost.setHeader(key, headers.get(key).toString());
+        }
+        
+        CloseableHttpResponse response = null;
+        try {
+            response = getHttpClient(url).execute(httppost, HttpClientContext.create());
+            HttpEntity entity = response.getEntity();
+            String result = EntityUtils.toString(entity, "utf-8");
+            EntityUtils.consume(entity);
+            return result;
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            try {
+                if (response != null) {
+                	response.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+	
+	/**
+	 * get请求.
+	 * @param url
+	 * @return
+	 * @throws IOException 
+	 */
+	public static String get(String url) throws IOException {
+        HttpGet httpget = new HttpGet(url);
+        config(httpget);
+        CloseableHttpResponse response = null;
+        try {
+            response = getHttpClient(url).execute(httpget, HttpClientContext.create());
+            HttpEntity entity = response.getEntity();
+            String result = EntityUtils.toString(entity, "utf-8");
+            EntityUtils.consume(entity);
+            return result;
+        } catch (IOException e) {
+            throw e;
+        } finally {
+            try {
+                if (response != null) {
+                	response.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+	
+	/**
+	 * get请求.
+	 * @param url
+	 * @param params
+	 * @return
+	 * @throws IOException 
+	 * @throws URISyntaxException 
+	 */
+	public static String get(String url, Map<String, Object> params) throws IOException, URISyntaxException {
+        CloseableHttpResponse response = null;
+        try {
+			final URIBuilder builder = new URIBuilder(url);
+			for (String key : params.keySet()) {
+				builder.setParameter(key, params.get(key).toString());
+			}
+            HttpGet httpget = new HttpGet(builder.build());
+            config(httpget);
+            response = getHttpClient(url).execute(httpget, HttpClientContext.create());
+            HttpEntity entity = response.getEntity();
+            String result = EntityUtils.toString(entity, "utf-8");
+            EntityUtils.consume(entity);
+            return result;
+        } catch (IOException e) {
+            throw e;
+        } catch (URISyntaxException e) {
+        	throw e;
+		} finally {
+            try {
+                if (response != null) {
+                	response.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+	
+	public static void download(String url, Map<String, Object> params, String storePath) {
+		CloseableHttpResponse response = null;
+		try {
+			final URIBuilder builder = new URIBuilder(url);
+			for (String key : params.keySet()) {
+				builder.setParameter(key, params.get(key).toString());
+			}
+			final HttpGet httpGet = new HttpGet(builder.build());
+			response = getHttpClient(url).execute(httpGet);
+			HttpEntity httpEntity = response.getEntity();
+			InputStream is = httpEntity.getContent();
+			/*ByteArrayOutputStream output = new ByteArrayOutputStream();
+			byte[] buffer = new byte[4096];
+			int r = 0;
+            while ((r = is.read(buffer)) > 0) {
+                output.write(buffer, 0, r);
+            }
+            FileOutputStream fos = new FileOutputStream(filePath);
+            output.writeTo(fos);
+            output.flush();
+            output.close();
+            fos.close();*/
+			FileOutputStream fos = new FileOutputStream(storePath);
+            IOUtils.copy(is, fos);
+            fos.flush();
+            fos.close();
+            EntityUtils.consume(httpEntity);
+		} catch (ClientProtocolException e) {
+			e.printStackTrace();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (URISyntaxException e) {
+			e.printStackTrace();
+		} finally {
+            try {
+				response.close();
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+        }
+	}
+	
+	
+	public static void main1(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, FileNotFoundException, IOException {
+		String url = "https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=24.220d96af439f0e4988592bd4c6ffa5be.2592000.1601110163.282335-17794270";
+		//头部参数
+		Map<String, Object> headerMap = new HashMap<String, Object>();
+		//创建请求参数
+		Set<Object> param = new HashSet<Object>();
+		
+		Map<String, Object> pic1Map = new HashMap<String, Object>();
+		pic1Map.put("image", Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File("C:\\Users\\Lenovo\\Desktop\\1.png")))));
+		pic1Map.put("image_type", "BASE64");
+		pic1Map.put("face_type", "LIVE");
+		pic1Map.put("quality_control", "NONE");//质量要求要低
+		pic1Map.put("liveness_control", "NONE");
+		
+		Map<String, Object> pic2Map = new HashMap<String, Object>();
+		pic2Map.put("image", Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File("C:\\Users\\Lenovo\\Desktop\\2.png")))));
+		pic2Map.put("image_type", "BASE64");
+		pic2Map.put("face_type", "LIVE");
+		pic2Map.put("quality_control", "NONE");//质量要求要低
+		pic2Map.put("liveness_control", "NONE");
+		
+		param.add(pic1Map);
+		param.add(pic2Map);
+		
+		Gson gson = new Gson();
+		String requestBody = gson.toJson(param);
+		System.out.println(requestBody);
+		//执行请求
+		try {
+			long startTime = System.currentTimeMillis();
+			String json = HttpClientHelper.postJson(url, requestBody, headerMap);
+			long endTime = System.currentTimeMillis();
+			
+			System.out.println("比对结果-----> " + json);
+			System.out.println("执行时间: " + (endTime-startTime)/1000.0);
+			
+		} catch(Exception e) {
+			LogHelper.error(e);
+		}
+	}
+	
+	public static void main2(String[] args) {
+		String url = "https://tsn.baidu.com/text2audio";
+		//创建请求参数
+		Map<String, Object> paramMap = new HashMap<String, Object>();
+		paramMap.put("tex", "测试百度语音播放功能,注意音量和速度变化。");
+		paramMap.put("tok", "24.43b4d25d924343bc66d12d578dd63668.2592000.1601800544.282335-22552887");
+		paramMap.put("cuid", "195842001485244520");
+		paramMap.put("ctp", "1");//web端固定为1
+		paramMap.put("lan", "zh");
+		paramMap.put("spd", "5");
+		paramMap.put("pit", "5");
+		paramMap.put("vol", "5");
+		paramMap.put("per", "0");
+		paramMap.put("aue", "3");//默认MP3
+		//执行请求
+		try {
+			long startTime = System.currentTimeMillis();
+			String json = HttpClientHelper.post(url, paramMap);
+			long endTime = System.currentTimeMillis();
+			
+			System.out.println("比对结果-----> " + json);
+			System.out.println("执行时间: " + (endTime-startTime)/1000.0);
+			
+		} catch(Exception e) {
+			LogHelper.error(e);
+		}
+	}
+	
+	public static void main3(String[] args) {
+		String url = "http://tsn.baidu.com/text2audio";
+	    String params = "tex=" + OpenApiParamUtil.urlEncode(OpenApiParamUtil.urlEncode("测试百度语音播放功能,注意音量和速度变化。"));
+        params += "&per=0";
+        params += "&spd=5";
+        params += "&pit=5";
+        params += "&vol=5";
+        params += "&cuid=195842001485244520";
+        params += "&tok=" + "24.43b4d25d924343bc66d12d578dd63668.2592000.1601800544.282335-22552887";
+        params += "&aue=3";//下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
+        params += "&lan=zh&ctp=1";
+        try {
+	        //执行请求
+	        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
+	        conn.setDoInput(true);
+	        conn.setDoOutput(true);
+	        conn.setConnectTimeout(5000);
+	        PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
+	        printWriter.write(params);
+	        printWriter.close();
+	        String contentType = conn.getContentType();
+	        if (contentType.contains("audio/")) {
+	            byte[] bytes = OpenApiParamUtil.getResponseBytes(conn);
+	            String format = getFormat(3);
+	            File file = new File("result." + format); // 打开mp3文件即可播放
+	            // System.out.println( file.getAbsolutePath());
+	            FileOutputStream os = new FileOutputStream(file);
+	            os.write(bytes);
+	            os.close();
+	            System.out.println("audio file write to " + file.getAbsolutePath());
+	        } else {
+	            System.err.println("ERROR: content-type= " + contentType);
+	            String res = OpenApiParamUtil.getResponseString(conn);
+	            System.err.println(res);
+	        }
+        } catch(Exception e) {
+        	e.printStackTrace();
+        }
+	}
+	
+    // 下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
+    private static String getFormat(int aue) {
+        String[] formats = {"mp3", "pcm", "pcm", "wav"};
+        return formats[aue - 3];
+    }
+    
+    public static void main(String[] args) {
+//		String str = "{\"login\":true,\"success\":true,\"entity\":{\"access_token\":\"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJxbWhtIiwiY2VydF9pZCI6IjY1MjMwMjE5ODUxMDAxMTUzNCIsInN0ZF9pZCI6MSwiZXhwIjoxNjAyNzI2MDU3LCJpYXQiOjE2MDI3MjUzMzd9.se-kYC0T-Vgt85YhBGl8dvRuKDVBDDp_QNVbJVBjKjs\",\"std_id\":1,\"cert_id\":\"652302198510011534\",\"std_name\":\"陈永生\",\"expire_time\":\"2020-10-15 09:40:57\",\"mills\":720000,\"login_times\":0,\"oss_encrypt_json\":\"iiNvZ/z9doFzLiGjpGfPjgn5VPOcj01mJWUSrg69jHC8cv+Uor3CRmhc+3w2cFhHw73y3t+/Gvr4/0hk9SAWN8pNCuOiYEX/n8gahxwAtge876KnRxneWtpGGxQsqLvNKw9R/ZD7EMrpgaRBdKoOE4DN0hhbKXsXd/Tt/Kk6lLJG3QAVyjAgyFKHDH+vUjNzicCA+r5LiJVENbL8Ip+ujg==\"},\"errorCode\":0}";
+//	
+//		String date = LocalDateHelper.format(LocalDateTime.now());
+//		System.out.println(date);
+//		
+//		long expireMills = System.currentTimeMillis() + 5000;
+//		String date2 = LocalDateHelper.format(LocalDateTime.ofEpochSecond(expireMills/1000, 0, ZoneOffset.ofHours(8)));
+//		System.out.println(date2);
+    	String url = "https://qmhm.oss-cn-beijing.aliyuncs.com/mr2022/10048/12345678/6087/hJCikkdbcX.pdf";
+    	Map<String, Object> params = new HashMap<>();
+    	download(url, params, "D:/data/1.pdf");
+		
+    }
+}

+ 196 - 0
src/cn/hmsoft/hmplatform/helper/ParamHelper.java

@@ -0,0 +1,196 @@
+package cn.hmsoft.hmplatform.helper;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cn.hmsoft.application.AppHelper;
+import cn.hmsoft.frame.constants.FrameStatus;
+import cn.hmsoft.frame.data.model.FrameParam;
+import cn.hmsoft.frame.util.FrameParamUtil;
+import cn.hmsoft.helper.BeanHelper;
+import cn.hmsoft.helper.CollectionHelper;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.constants.ArtParamType;
+import cn.hmsoft.weixin.data.model.WxDefine;
+import cn.hmsoft.weixin.util.WeiXinUtil;
+
+public class ParamHelper extends FrameParamUtil {
+
+	public final static String SessionName_EnrolWeixinCode = "EnrolWeixinCode";
+	public final static String SessionName_EnrolWeixinUser = "EnrolWeixinUser";
+	public final static String SessionName_EnrolStdReg = "EnrolStdReg";
+	public static String AppEncryptKey = "gKrSAKfxQywOTi";
+	/*******************
+	 * 当前年份
+	 */
+	private static String ArtShortYear = "";
+	/******************
+	 * 加载参数密钥
+	 */
+	public static String ReloadParamPassword = "2020";
+	/*******************
+	 * 参数加载时长
+	 */
+	public static int ReloadParamInterval = 10;
+	/*******************
+	 * 当前年份
+	 */
+	public static String ArtYear = "2020";
+
+	/*******************
+	 * 当前状态
+	 */
+	public static String ArtStatus = "Config";
+
+	/*****************
+	 * 业务名称
+	 */
+	public static String BusinessName = "本科校考";
+
+	/*****************
+	 * 学校所在省份
+	 */
+	public static String SchoolProvince = "";
+
+	/*****************
+	 * 学校微信地址
+	 */
+	public static String SchoolWeixinUrl = "";
+
+	/*****************
+	 * 学校的公众号信息,必须有
+	 */
+	public static String SchoolWeixinAppId = "";
+	/*****************
+	 * 学校的商户编号
+	 */
+	public static String SchoolMerchantId = "";
+	/*****************
+	 * 是否启用二级学院
+	 */
+	public static String TwoLevelCollege = "InActive";
+
+	/******************
+	 * 特权ip
+	 */
+	public static String PrivilegeAddress = "";
+	/******************
+	 * 报名系统开放时间
+	 */
+	public static String EnrolOpenTime = "";
+	/******************
+	 * 报名系统关闭时间
+	 */
+	public static String EnrolCloseTime = "";
+	/******************
+	 * 大陆地区行政区划代码最大值
+	 */
+	public static Integer MainlandMaxProvinceId = 69;
+
+	/*****************
+	 * 默认公众号
+	 */
+	private static WxDefine SchoolWxDefine = null;
+
+	/******************
+	 * 报名app 考生材料本地路径
+	 */
+	public static String EnrolMaterialLocalPath = "";
+	/******************
+	 * 报名app 考生材料web路径
+	 */
+	public static String EnrolMaterialWebPath = "";
+	/******************
+	 * 视频路径
+	 */
+	public static String EnrolMaterialVideoPath = "";
+	/******************
+	 * 本省考点过期后是否允许省外考点
+	 */
+	public static String EnrolAllowOutsideProvince = "Active";
+	/******************
+	 * 考生最大专业数量
+	 */
+	public static int EnrolStdAspectLimit = 5;
+	/******************
+	 * 考生最大大类数量
+	 */
+	public static int EnrolStdCategoryLimit = 5;
+	/******************
+	 * 划线是否只针对大陆地区
+	 */
+	public static String PlanMainlandOnly = FrameStatus.Active.toString();
+	
+	/******************
+	 * 录制视频最大可以断掉的秒数
+	 */
+	public static Integer VideoInterview = 30;
+
+	/***************
+	 * 获取短年份
+	 */
+	public static String getShortYear() {
+		if (StringHelper.isEmpty(ArtShortYear)) {
+			synchronized (ParamHelper.class) {
+				if (StringHelper.isEmpty(ArtShortYear)) {
+					ArtShortYear = ArtYear.substring(0, 2);
+				}
+			}
+		}
+		return ArtShortYear;
+	}
+
+	/****************
+	 * 获取公众号
+	 */
+	public static WxDefine getSchoolWeixin() {
+		if (SchoolWxDefine == null) {
+			synchronized (ParamHelper.class) {
+				if (SchoolWxDefine == null) {
+					SchoolWxDefine = WeiXinUtil.getWxDefine(SchoolWeixinAppId);
+				}
+			}
+		}
+		return SchoolWxDefine;
+	}
+
+	private static Map<String, List<FrameParam>> paramMap = null;
+
+	/**********************
+	 * 初始化参数信息
+	 */
+	public static void instanceParams(boolean refresh) {
+		if (paramMap == null || refresh) {
+			synchronized (ParamHelper.class) {
+				paramMap = new HashMap<String, List<FrameParam>>();
+				// 全局的
+				paramMap.put(ArtParamType.Gobal, new ArrayList<FrameParam>());
+				for (FrameParam p : AppHelper.FrameParamArray) {
+					paramMap.get(ArtParamType.Gobal).add(p);
+				}
+				BeanHelper.setStaticFields(ParamHelper.class, AppHelper.GobalParamMap);
+			}
+		}
+
+	}
+
+	/**********************
+	 * 获取某一类型的所有参数
+	 * 
+	 * @param param_type
+	 *            参数类型
+	 * @return
+	 */
+	public static List<FrameParam> listParams(String param_type) {
+		instanceParams(false);
+		if (paramMap.containsKey(param_type))
+			return paramMap.get(param_type);
+		return new ArrayList<FrameParam>();
+	}
+
+	public static <T> T getParamValue(String param_name, T default_value) {
+		return CollectionHelper.getParamValue(ParamHelper.GobalParamMap, param_name, default_value);
+	}
+}

+ 47 - 0
src/cn/hmsoft/hmplatform/helper/PlatformParamHelper.java

@@ -0,0 +1,47 @@
+package cn.hmsoft.hmplatform.helper;
+
+import java.io.File;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.helper.RandomHelper;
+
+public class PlatformParamHelper {
+
+	/**********************
+	 * 获取token密码
+	 */
+	public static String FetchWeixinTokenPass = "hm2020";
+	
+	/**********************
+	 * 获取token密码
+	 */
+	public static String IdentifyVerifyPass = "hm2020";
+	/**
+	 * 人脸比对秘钥md5
+	 */
+	public static String FaceMatchPass = "hm2020";
+	/**************************
+	 * 创建临时文件
+	 */
+	/**************************
+	 * 创建临时文件
+	 */
+	public static File createTempFile() {
+		try {
+			return File.createTempFile("Platform" + RandomHelper.getRandomValue(32),
+					".tmp");
+		} catch (Exception e) {
+			throw new BusinessException("无法创建临时文件,请联系系统管理员!");
+		}
+	}
+	/*
+	 * 创建临时文件
+	 */
+	public static File createTempFile(String suffix) {
+		try {
+			return File.createTempFile("Platform" + RandomHelper.getRandomValue(32),
+					"."+suffix);
+		} catch (Exception e) {
+			throw new BusinessException("无法创建临时文件,请联系系统管理员!");
+		}
+	}
+}

+ 96 - 0
src/cn/hmsoft/hmplatform/identity/baidu/BaiduOpenApiTokenService.java

@@ -0,0 +1,96 @@
+package cn.hmsoft.hmplatform.identity.baidu;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.time.LocalDateTime;
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import cn.hmsoft.ai.util.AiParamUtil;
+import cn.hmsoft.frame.data.dao.FrameModuleDao;
+import cn.hmsoft.frame.data.model.FrameModule;
+import cn.hmsoft.helper.CollectionHelper;
+import cn.hmsoft.helper.LocalDateHelper;
+import cn.hmsoft.helper.StringHelper;
+
+/**************************
+ * 获取百度openapi toketn的服务,确保唯一访问
+ */
+@Service
+public class BaiduOpenApiTokenService {
+	public static String ACCESS_TOKEN = "";
+	public static LocalDateTime ACCESS_TOKEN_EXPIRES = null;
+
+	@Autowired
+	private FrameModuleDao daoModule;
+
+	@Transactional(isolation = Isolation.SERIALIZABLE)
+	public boolean getBaiduToken() {
+		if (ACCESS_TOKEN == null || ACCESS_TOKEN_EXPIRES == null
+				|| ACCESS_TOKEN_EXPIRES.isBefore(LocalDateTime.now())) {
+			
+		} else {
+			return true;
+		}
+		FrameModule module = this.daoModule.find(FrameModule.class, "module_name", AiParamUtil.ModuleName);
+		Map<String, String> paramMap = StringHelper.toMap(module.getModule_param());
+		String access_token = CollectionHelper.getParamValue(paramMap, OpenApiParam.ParamName_BaiduOpenApiToken, "");
+		String access_token_expired = CollectionHelper.getParamValue(paramMap,
+				OpenApiParam.ParamName_BaiduOpenApiTokenExpireTime, "");
+		ACCESS_TOKEN = access_token;
+		ACCESS_TOKEN_EXPIRES = LocalDateHelper.parseDateTime(access_token_expired);
+
+		if (ACCESS_TOKEN == null || ACCESS_TOKEN_EXPIRES == null
+				|| ACCESS_TOKEN_EXPIRES.isBefore(LocalDateTime.now())) {
+			String authHost = "https://openapi.baidu.com/oauth/2.0/token?";
+			String getAccessTokenUrl = authHost
+					// 1. grant_type为固定参数
+					+ "grant_type=client_credentials"
+					// 2. 官网获取的 API Key
+					+ "&client_id=" + AiParamUtil.ParamMap.get(OpenApiParam.ParamName_BaiduOpenApiAppKey).trim()
+					// 3. 官网获取的 Secret Key
+					+ "&client_secret=" + AiParamUtil.ParamMap.get(OpenApiParam.ParamName_BaiduOpenApiSecretKey).trim();
+			try {
+				URL realUrl = new URL(getAccessTokenUrl);
+				// 打开和URL之间的连接
+				HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
+				connection.setRequestMethod("GET");
+				connection.connect();
+
+				// 定义 BufferedReader输入流来读取URL的响应
+				BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+				String result = "";
+				String line;
+				while ((line = in.readLine()) != null) {
+					result += line;
+				}
+				/**
+				 * 返回结果示例
+				 */
+				JsonObject jsonObject = new JsonParser().parse(result).getAsJsonObject();
+				ACCESS_TOKEN = jsonObject.get("access_token").getAsString();
+				ACCESS_TOKEN_EXPIRES = LocalDateTime.now().plusSeconds(jsonObject.get("expires_in").getAsInt());
+				// 更新数据库
+				module.setModule_param(module.getModule_param()
+						.replace("BaiduOpenApiAppId:" + access_token, "BaiduOpenApiAppId:" + ACCESS_TOKEN)
+						.replace("BaiduOpenApiTokenExpireTime:" + access_token_expired,
+								"BaiduOpenApiTokenExpireTime:" + LocalDateHelper.format(ACCESS_TOKEN_EXPIRES)));
+				this.daoModule.update(module);
+				return true;
+			} catch (Exception e) {
+				System.err.printf("获取token失败!");
+				e.printStackTrace();
+			}
+			return false;
+		}
+		return true;
+
+	}
+
+}

+ 15 - 0
src/cn/hmsoft/hmplatform/identity/baidu/OpenApiParam.java

@@ -0,0 +1,15 @@
+package cn.hmsoft.hmplatform.identity.baidu;
+
+import java.util.Map;
+
+public class OpenApiParam {
+
+	public static Map<String, String> ParamMap;
+	
+	//TODO 
+	public final static String ParamName_BaiduOpenApiAppId = "BaiduOpenApiAppId";
+	public final static String ParamName_BaiduOpenApiAppKey = "BaiduOpenApiAppKey";
+	public final static String ParamName_BaiduOpenApiSecretKey = "BaiduOpenApiSecretKey";
+	public final static String ParamName_BaiduOpenApiToken = "BaiduOpenApiToken";
+	public final static String ParamName_BaiduOpenApiTokenExpireTime = "BaiduOpenApiTokenExpireTime";
+}

+ 122 - 0
src/cn/hmsoft/hmplatform/identity/baidu/OpenApiParamUtil.java

@@ -0,0 +1,122 @@
+package cn.hmsoft.hmplatform.identity.baidu;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URLEncoder;
+import java.util.Map;
+
+/******************
+ * ai 参数信息
+ * 
+ * @author zxq
+ * @create 2019-08-23 16:39:01
+ * @version 2.0.0
+ * @email: revisit@126.com
+ * @Company: www.hmsoft.cn
+ */
+public class OpenApiParamUtil {
+	
+	/********************
+	 * 插件参数集合
+	 */
+	public static Map<String, String> ParamMap;
+
+	/**********************
+	 * 使用身份证识别用哪个
+	 */
+	public static String IdCardOcrClass = "";
+	/**********************
+	 * 免冠照用那一家的clazz
+	 */
+	public static String IdPhotoAIClass = "cn.hmsoft.ai.face.baidu.BaiduIdPhotoAI";
+	/**********************
+	 * 身份实名认证
+	 */
+	public static String IdentityAIClass = "cn.hmsoft.ai.identity.baidu.BaiduIdentityAI";
+
+    /**
+     * UrlEncode, UTF-8 编码
+     *
+     * @param str 原始字符串
+     * @return
+     */
+    public static String urlEncode(String str) {
+        String result = null;
+        try {
+            result = URLEncoder.encode(str, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return result;
+    }
+
+    /**
+     * 从HttpURLConnection 获取返回的字符串
+     *
+     * @param conn
+     * @return
+     * @throws IOException
+     * @throws DemoException
+     */
+    public static String getResponseString(HttpURLConnection conn) throws IOException, Exception {
+        return new String(getResponseBytes(conn));
+    }
+
+    /**
+     * 从HttpURLConnection 获取返回的bytes
+     * 注意 HttpURLConnection自身问题, 400类错误,会直接抛出异常。不能获取conn.getInputStream();
+     *
+     * @param conn
+     * @return
+     * @throws IOException   http请求错误
+     * @throws DemoException http 的状态码不是 200
+     */
+    public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException, Exception {
+        int responseCode = conn.getResponseCode();
+        InputStream inputStream = conn.getInputStream();
+        if (responseCode != 200) {
+            System.err.println("http 请求返回的状态码错误,期望200, 当前是 " + responseCode);
+            if (responseCode == 401) {
+                System.err.println("可能是appkey appSecret 填错");
+            }
+            System.err.println("response headers" + conn.getHeaderFields());
+            if (inputStream == null) {
+                inputStream = conn.getErrorStream();
+            }
+            byte[] result = getInputStreamContent(inputStream);
+            System.err.println(new String(result));
+
+            throw new Exception("http response code is" + responseCode);
+        }
+
+        byte[] result = getInputStreamContent(inputStream);
+        return result;
+    }
+
+    /**
+     * 将InputStream内的内容全部读取,作为bytes返回
+     *
+     * @param is
+     * @return
+     * @throws IOException @see InputStream.read()
+     */
+    public static byte[] getInputStreamContent(InputStream is) throws IOException {
+        byte[] b = new byte[1024];
+        // 定义一个输出流存储接收到的数据
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        // 开始接收数据
+        int len = 0;
+        while (true) {
+            len = is.read(b);
+            if (len == -1) {
+                // 数据读完
+                break;
+            }
+            byteArrayOutputStream.write(b, 0, len);
+        }
+        return byteArrayOutputStream.toByteArray();
+    }
+}

+ 68 - 0
src/cn/hmsoft/hmplatform/identity/control/FaceMatchControl.java

@@ -0,0 +1,68 @@
+package cn.hmsoft.hmplatform.identity.control;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Base64;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import cn.hmsoft.ai.identity.IdentifiedResult;
+import cn.hmsoft.application.web.AjaxControl;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.frame.util.FrameAssertUtil;
+import cn.hmsoft.helper.SecureHelper;
+import cn.hmsoft.hmplatform.helper.PlatformParamHelper;
+import cn.hmsoft.hmplatform.identity.service.FaceMatchService;
+
+@RestController
+public class FaceMatchControl extends AjaxControl {
+
+	@Autowired
+	private FaceMatchService serviceMatch;
+	
+	/**
+	 * @人脸比对.
+	 * @param cert_id 身份证号
+	 * @param img1 照片1
+	 * @param img2照片2
+	 * @param key_pass 秘钥
+	 * @return
+	 */
+	@RequestMapping("baidu/face/match") 
+	public IdentifiedResult baduMatch(String img1, String img2, String key_pass) {
+		FrameAssertUtil.isNotNull(img1, "参数img1不能为空");
+		FrameAssertUtil.isNotNull(img2, "参数img2不能为空");
+		FrameAssertUtil.isNotNull(key_pass, "参数key_pass不能为空");
+		if (!key_pass.equals(SecureHelper.md5(PlatformParamHelper.FaceMatchPass))) {
+			throw new BusinessException("秘钥错误,没有操作权限!");
+		}
+		return this.serviceMatch.baiduMatch(img1, img2); 
+	}
+	
+	/**
+	 * @人脸比对.
+	 * @param cert_id 身份证号
+	 * @param img1 照片1
+	 * @param img2照片2
+	 * @param key_pass 秘钥
+	 * @return
+	 */
+	@RequestMapping("hm/face/match") 
+	public IdentifiedResult hmMatch(String img1, String img2, String key_pass) {
+		FrameAssertUtil.isNotNull(img1, "参数img1不能为空");
+		FrameAssertUtil.isNotNull(img2, "参数img2不能为空");
+		FrameAssertUtil.isNotNull(key_pass, "参数key_pass不能为空");
+		if (!key_pass.equals(SecureHelper.md5(PlatformParamHelper.FaceMatchPass))) {
+			throw new BusinessException("秘钥错误,没有操作权限!");
+		}
+		return this.serviceMatch.hmFaceMatch(img1, img2, key_pass); 
+	}
+	
+	public static void main(String[] args) throws FileNotFoundException, IOException {
+		System.out.println(Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File("C:/Users/Lenovo/Desktop/1.png")))));
+
+	}
+}

+ 171 - 0
src/cn/hmsoft/hmplatform/identity/control/IdentifyControl.java

@@ -0,0 +1,171 @@
+package cn.hmsoft.hmplatform.identity.control;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardOpenOption;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.ai.idcard.IdCard;
+import cn.hmsoft.ai.idcard.IdCardOcr;
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.application.web.AjaxControl;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.frame.util.FrameAssertUtil;
+import cn.hmsoft.helper.CollectionHelper;
+import cn.hmsoft.helper.SecureHelper;
+import cn.hmsoft.hmplatform.constants.StdResType;
+import cn.hmsoft.hmplatform.helper.ParamHelper;
+import cn.hmsoft.hmplatform.helper.PlatformParamHelper;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdRegDao;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdResLogDao;
+import cn.hmsoft.hmplatform.identity.data.model.PStdReg;
+import cn.hmsoft.hmplatform.identity.data.model.PStdResLog;
+import cn.hmsoft.hmplatform.identity.service.IdentifyService;
+import cn.hmsoft.hmplatform.identity.service.PStdRegService;
+import cn.hmsoft.hmplatform.identity.util.EncodeHelper;
+
+/**
+ * @公安部身份认证
+ *
+ */
+@RestController
+public class IdentifyControl extends AjaxControl {
+
+	@Autowired
+	private PStdRegDao daoStd;
+	@Autowired
+	private PStdResLogDao daoResLog;
+	@Autowired
+	private IdentifyService serviceIden;
+	
+	/**
+	 * ocr身份证识别.
+	 * @param request_key
+	 * @param cert_image url、base64
+	 * @return
+	 */
+	@RequestMapping("/platform/identity/idcard/ocr")
+	public Ajax ocrIdCard(String request_key, String cert_image) {
+		FrameAssertUtil.isNotEmpty(request_key, "秘钥不能为空!");
+		FrameAssertUtil.isNotEmpty(cert_image, "身份证证明照不能为空!");
+		File certFile = PlatformParamHelper.createTempFile();
+		String base64Str = cert_image;
+		if (cert_image.startsWith("http")) {
+			base64Str = EncodeHelper.encodeUrlImageToBase64(cert_image);
+		}
+		try {
+			int startPos = base64Str.indexOf(";base64");
+			if (startPos > 0) {
+				base64Str = base64Str.substring(startPos + 8, base64Str.length());
+			}
+			base64Str = base64Str.replaceAll("\n", "");
+			byte[] bytes = Base64.getDecoder().decode(base64Str);
+			Files.write(Paths.get(certFile.getAbsolutePath()), bytes, StandardOpenOption.CREATE);
+			IdCard idcard = IdCardOcr.instance().ocrIdCard(certFile);
+			if (idcard.isOcr_success()) {
+				idcard.setBirthday(null);
+				Map<String, Object> map = new HashMap<String, Object>();
+				map.put("IdCardInfo", idcard);
+				map.put("IdCardFileName", idcard.getPerson_code() + ".jpg");
+				return new Ajax(map);
+			} else {
+				throw new BusinessException("无法识别居民身份证信息,请重新上传清晰的含居民照片的一面");
+			}
+		} catch (Exception e) {
+			throw new BusinessException("ocr异常,获取正面照片失败:" + e.getMessage());
+		}
+	}
+	
+	/**
+	 * @检查并返回认证 .
+	 * @param request_key
+	 * @param cert_id 身份证号-必须
+	 * @param std_name 姓名号-必须
+	 * @param image_file 头像照片url、base64
+	 * @return
+	 */
+	@RequestMapping("platform/identity/verify")
+	public Ajax check(String request_key, String cert_id, String std_name, 
+			String image, String from_project) {
+		FrameAssertUtil.isNotEmpty(request_key, "秘钥不能为空!");
+		FrameAssertUtil.isNotEmpty(cert_id, "身份证号不能为空!");
+		FrameAssertUtil.isNotNull(std_name, "考生姓名不能为空!");
+		FrameAssertUtil.isNotEmpty(image, "认证头像不能为空!");
+		FrameAssertUtil.isEqual(request_key, SecureHelper.md5(PlatformParamHelper.IdentifyVerifyPass), "秘钥错误!");
+		Map<String, Object> map = this.serviceIden.verify(cert_id, std_name, image, from_project);
+		return new Ajax(map);
+	}
+	
+	/**
+	 * @公安部身份认证.
+	 * @param request_key
+	 * @param cert_id 身份证号-必须
+	 * @param std_name 姓名号-必须
+	 * @param image_file 头像照片url、base64
+	 * @return
+	 */
+	@RequestMapping("platform/identity/check")
+	public Ajax check(String request_key, String cert_id) {
+		FrameAssertUtil.isNotEmpty(request_key, "秘钥不能为空!");
+		FrameAssertUtil.isNotEmpty(cert_id, "身份证号不能为空!");
+		Map<String, Object> map = new HashMap<String, Object>();
+		PStdReg std = this.daoStd.findBySql("select * from p_std_reg where cert_id=?", cert_id);
+		if (std != null) {
+			List<PStdResLog> resLogList = this.daoResLog.listBySql("select * from p_std_res_log where res_type=? and std_id=? order by res_time desc", 
+					StdResType.Identify.toString(), std.getStd_id());
+			if (std.getVerify_status().equals("Active")) {
+				if (resLogList.size() > 0) {
+					map.put("success", true);
+					map.put("error_msg", "成功!");
+					map.put("percent", Double.valueOf(resLogList.get(0).getRes_result()));
+					map.put("image_url", std.getStd_image());
+					return new Ajax(map);
+				}
+			} else {
+				if (resLogList.size() > 0) {
+					map.put("success", false);
+					map.put("error_msg", resLogList.get(0).getRes_desc());
+					map.put("percent", Double.valueOf(resLogList.get(0).getRes_result()));
+					map.put("image_url", std.getStd_image());
+					return new Ajax(map);
+				}
+			}
+
+		}
+		map.put("success", false);
+		map.put("error_msg", "没有认证记录!");
+		map.put("percent", 0);
+		map.put("image_url", "");
+		return new Ajax(map);
+	}
+	
+	public static void main2(String[] args) throws FileNotFoundException, IOException {
+		String str = Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File("C:/Users/Lenovo/Desktop/2.png"))));
+		System.err.println(str);
+
+	}
+	public static void main(String[] args) {
+		Map<String,Object> map = new HashMap<String, Object>();
+		map.put("success", true);
+		map.put("error_msg", "该考生今天身份证超限,明天再试!");
+		map.put("percent", 0);
+		System.out.println(map.get("success"));
+		if (Boolean.valueOf(map.get("success").toString()) == true) {
+			System.out.println(77);
+		}
+		
+	}
+}

+ 45 - 0
src/cn/hmsoft/hmplatform/identity/control/VoiceControl.java

@@ -0,0 +1,45 @@
+package cn.hmsoft.hmplatform.identity.control;
+
+import java.util.UUID;
+
+import javax.servlet.ServletOutputStream;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import cn.hmsoft.application.web.AjaxControl;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.identity.service.FaceMatchService;
+
+@RestController
+public class VoiceControl extends AjaxControl {
+	@Autowired
+	private FaceMatchService serviceMatch;
+	
+	/**
+	 * @语音输出mp3.
+	 * @param text
+	 * @param cuid
+	 * @return
+	 * @throws BusinessException 
+	 */
+	@RequestMapping("voice/text2audio")
+	public void text2Audio(String text, String cuid) throws BusinessException {
+		if (StringHelper.isEmpty(cuid)) {
+			cuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
+		}
+        ServletOutputStream os = null;
+		try {
+			os = this.getResponse().getOutputStream();
+	        this.getResponse().setContentType("application/x-download");
+	        this.getResponse().addHeader("Content-Disposition",
+					"attachment;filename=\"" + new String("au.mp3".getBytes("utf8"), "ISO_8859_1") + "\"");
+	        byte[] bytes = this.serviceMatch.text2AudioBytes(text, cuid);
+	        os.write(bytes);
+	        os.close();
+		} catch (Exception e) {
+			throw new BusinessException(e.getMessage());
+		}
+	}
+}

+ 24 - 0
src/cn/hmsoft/hmplatform/identity/data/dao/PStdRegDao.java

@@ -0,0 +1,24 @@
+package cn.hmsoft.hmplatform.identity.data.dao;
+
+import org.springframework.stereotype.Repository;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.identity.data.model.PStdReg;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PStdRegDao extends PlatformDaoSupport<PStdReg> {
+
+	public Pager pageStd(Integer start, Integer limit, String query, QueryOrder queryOrder) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select s.* from p_std_reg s ");
+		sql.append("where 1=1 ");
+		if (StringHelper.isEmpty(query)) {
+			return this.pageMapBySql(queryOrder, start, limit, sql.toString());
+		}
+		sql.append(" and (s.std_name like ? or s.cert_id like ? or s.from_project like ?)");
+		return this.pageMapBySql(queryOrder, start, limit, sql.toString(), "%" + query + "%", "%" + query + "%", "%" + query + "%");
+	}
+
+}

+ 21 - 0
src/cn/hmsoft/hmplatform/identity/data/dao/PStdResDao.java

@@ -0,0 +1,21 @@
+package cn.hmsoft.hmplatform.identity.data.dao;
+
+import java.time.LocalDate;
+import org.springframework.stereotype.Repository;
+import cn.hmsoft.hmplatform.identity.data.model.PStdRes;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+
+@Repository
+public class PStdResDao extends PlatformDaoSupport<PStdRes> {
+
+	public PStdRes findRes(String cert_id, LocalDate res_date, String res_type) {
+		String sql = "select * from p_std_res where cert_id=? and res_date=? and res_type=? ";
+		return this.findBySql(sql, cert_id, res_date, res_type);
+	}
+
+	public void updateRes(PStdRes res) {
+		String sql = "update std_res set res_number=? where res_date=? and res_type=? and std_id=? ";
+		this.updateBySql(sql, res.getRes_number(), res.getRes_date(), res.getRes_type(), res.getStd_id());
+	}
+
+}

+ 10 - 0
src/cn/hmsoft/hmplatform/identity/data/dao/PStdResLogDao.java

@@ -0,0 +1,10 @@
+package cn.hmsoft.hmplatform.identity.data.dao;
+
+import org.springframework.stereotype.Repository;
+import cn.hmsoft.hmplatform.identity.data.model.PStdResLog;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+
+@Repository
+public class PStdResLogDao extends PlatformDaoSupport<PStdResLog> {
+
+}

+ 90 - 0
src/cn/hmsoft/hmplatform/identity/data/model/PStdReg.java

@@ -0,0 +1,90 @@
+package cn.hmsoft.hmplatform.identity.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_STD_REG", keyColumn =  "STD_ID" , sequenceName = "STD_ID")
+public class PStdReg implements Serializable {
+	private static final long serialVersionUID = 8395786223936762943L;
+	private Integer std_id;
+	private String cert_id;
+	private String std_name;
+	private String std_sex;
+	private String std_nation;
+	private String cert_addr;
+	private LocalDateTime std_birthday;
+	private String from_project;
+	private String std_image;//考生免冠证件照地址
+	private String verify_status;
+	private LocalDateTime verify_time;
+	
+	public Integer getStd_id() {
+		return std_id;
+	}
+	public String getCert_id() {
+		return cert_id;
+	}
+	public String getStd_name() {
+		return std_name;
+	}
+	public String getStd_sex() {
+		return std_sex;
+	}
+	public String getStd_nation() {
+		return std_nation;
+	}
+	public String getCert_addr() {
+		return cert_addr;
+	}
+	public LocalDateTime getStd_birthday() {
+		return std_birthday;
+	}
+	public String getFrom_project() {
+		return from_project;
+	}
+	public String getStd_image() {
+		return std_image;
+	}
+	public String getVerify_status() {
+		return verify_status;
+	}
+	public LocalDateTime getVerify_time() {
+		return verify_time;
+	}
+	public void setStd_id(Integer std_id) {
+		this.std_id = std_id;
+	}
+	public void setCert_id(String cert_id) {
+		this.cert_id = cert_id;
+	}
+	public void setStd_name(String std_name) {
+		this.std_name = std_name;
+	}
+	public void setStd_sex(String std_sex) {
+		this.std_sex = std_sex;
+	}
+	public void setStd_nation(String std_nation) {
+		this.std_nation = std_nation;
+	}
+	public void setCert_addr(String cert_addr) {
+		this.cert_addr = cert_addr;
+	}
+	public void setStd_birthday(LocalDateTime std_birthday) {
+		this.std_birthday = std_birthday;
+	}
+	public void setFrom_project(String from_project) {
+		this.from_project = from_project;
+	}
+	public void setStd_image(String std_image) {
+		this.std_image = std_image;
+	}
+	public void setVerify_status(String verify_status) {
+		this.verify_status = verify_status;
+	}
+	public void setVerify_time(LocalDateTime verify_time) {
+		this.verify_time = verify_time;
+	}
+	
+}

+ 96 - 0
src/cn/hmsoft/hmplatform/identity/data/model/PStdRes.java

@@ -0,0 +1,96 @@
+package cn.hmsoft.hmplatform.identity.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_STD_RES", keyColumn =  "" , sequenceName = "")
+public class PStdRes implements Serializable{
+	private static final long serialVersionUID = 2998191970737840266L;
+	//资源类型
+	private String res_type;
+	//考生编号
+	private Integer std_id;
+	//身份证验证日期
+	private LocalDate res_date;
+	//cert_id
+	private String cert_id;
+	//验证次数
+	private Integer res_number;
+	//人工干预阀值
+	private Integer res_plus;
+
+	/****
+	 * 资源类型
+	 */
+	public String getRes_type() {
+		return this.res_type;
+	}
+
+	/****
+	 * 资源类型
+	 */
+	public void setRes_type(String res_type) {
+		this.res_type = res_type;
+	}
+
+	/****
+	 * 考生编号
+	 */
+	public Integer getStd_id() {
+		return this.std_id;
+	}
+
+	/****
+	 * 考生编号
+	 */
+	public void setStd_id(Integer std_id) {
+		this.std_id = std_id;
+	}
+
+	/****
+	 * 身份证验证日期
+	 */
+	public LocalDate getRes_date() {
+		return this.res_date;
+	}
+
+	/****
+	 * 身份证验证日期
+	 */
+	public void setRes_date(LocalDate res_date) {
+		this.res_date = res_date;
+	}
+
+	/****
+	 * 验证次数
+	 */
+	public Integer getRes_number() {
+		return this.res_number;
+	}
+
+	/****
+	 * 验证次数
+	 */
+	public void setRes_number(Integer res_number) {
+		this.res_number = res_number;
+	}
+
+	public Integer getRes_plus() {
+		return res_plus;
+	}
+
+	public void setRes_plus(Integer res_plus) {
+		this.res_plus = res_plus;
+	}
+
+	public String getCert_id() {
+		return cert_id;
+	}
+
+	public void setCert_id(String cert_id) {
+		this.cert_id = cert_id;
+	}
+
+}

+ 139 - 0
src/cn/hmsoft/hmplatform/identity/data/model/PStdResLog.java

@@ -0,0 +1,139 @@
+package cn.hmsoft.hmplatform.identity.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_STD_RES_LOG", keyColumn = "LOG_ID", sequenceName = "LOG_ID")
+public class PStdResLog implements Serializable {
+	private static final long serialVersionUID = 639961272006448742L;
+	//日志内部编号
+	private Integer log_id;
+	//使用资源的时间
+	private LocalDateTime res_time;
+	//微信公众号编号
+	private String weixin_id;
+	//使用的资源类型
+	private String res_type;
+	//使用资源后的反馈
+	private String res_result;
+	//备注信息
+	private String res_desc;
+	//资源参数信息
+	private String res_param;
+	//考生内部编号
+	private Integer std_id;
+
+	/****
+	 * 日志内部编号
+	 */
+	public Integer getLog_id() {
+		return this.log_id;
+	}
+
+	/****
+	 * 日志内部编号
+	 */
+	public void setLog_id(Integer log_id) {
+		this.log_id = log_id;
+	}
+
+	/****
+	 * 使用资源的时间
+	 */
+	public LocalDateTime getRes_time() {
+		return this.res_time;
+	}
+
+	/****
+	 * 使用资源的时间
+	 */
+	public void setRes_time(LocalDateTime res_time) {
+		this.res_time = res_time;
+	}
+
+	/****
+	 * 微信公众号编号
+	 */
+	public String getWeixin_id() {
+		return this.weixin_id;
+	}
+
+	/****
+	 * 微信公众号编号
+	 */
+	public void setWeixin_id(String weixin_id) {
+		this.weixin_id = weixin_id;
+	}
+
+	/****
+	 * 使用的资源类型
+	 */
+	public String getRes_type() {
+		return this.res_type;
+	}
+
+	/****
+	 * 使用的资源类型
+	 */
+	public void setRes_type(String res_type) {
+		this.res_type = res_type;
+	}
+
+	/****
+	 * 使用资源后的反馈
+	 */
+	public String getRes_result() {
+		return this.res_result;
+	}
+
+	/****
+	 * 使用资源后的反馈
+	 */
+	public void setRes_result(String res_result) {
+		this.res_result = res_result;
+	}
+
+	/****
+	 * 备注信息
+	 */
+	public String getRes_desc() {
+		return this.res_desc;
+	}
+
+	/****
+	 * 备注信息
+	 */
+	public void setRes_desc(String res_desc) {
+		this.res_desc = res_desc;
+	}
+
+	/****
+	 * 资源参数信息
+	 */
+	public String getRes_param() {
+		return this.res_param;
+	}
+
+	/****
+	 * 资源参数信息
+	 */
+	public void setRes_param(String res_param) {
+		this.res_param = res_param;
+	}
+
+	/****
+	 * 考生内部编号
+	 */
+	public Integer getStd_id() {
+		return this.std_id;
+	}
+
+	/****
+	 * 考生内部编号
+	 */
+	public void setStd_id(Integer std_id) {
+		this.std_id = std_id;
+	}
+
+}

+ 180 - 0
src/cn/hmsoft/hmplatform/identity/service/FaceMatchService.java

@@ -0,0 +1,180 @@
+package cn.hmsoft.hmplatform.identity.service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import org.springframework.stereotype.Service;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import cn.hmsoft.ai.baidu.BaiduTokenService;
+import cn.hmsoft.ai.identity.IdentifiedResult;
+import cn.hmsoft.application.SpringHelper;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.frame.util.FrameAssertUtil;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.helper.HttpClientHelper;
+import cn.hmsoft.hmplatform.helper.ParamHelper;
+import cn.hmsoft.hmplatform.identity.baidu.BaiduOpenApiTokenService;
+import cn.hmsoft.hmplatform.identity.baidu.OpenApiParamUtil;
+import cn.hmsoft.hmplatform.identity.util.EncodeHelper;
+import cn.hmsoft.log.LogHelper;
+
+@Service
+public class FaceMatchService {
+	/**
+	 * @百度比对.
+	 * @param image_file1 照片文件1
+	 * @param image_file2 照片文件2
+	 * @return
+	 */
+	public IdentifiedResult baiduMatch(String img1, String img2) {
+		IdentifiedResult result = new IdentifiedResult();
+		SpringHelper.getBean(BaiduTokenService.class).getBaiduToken();
+		String url = "https://aip.baidubce.com/rest/2.0/face/v3/match?access_token=" + BaiduTokenService.ACCESS_TOKEN;
+		//头部参数
+		Map<String, Object> headerMap = new HashMap<String, Object>();
+		//创建请求参数
+		Set<Object> param = new HashSet<Object>();
+		//执行请求
+		try {
+			Map<String, Object> pic1Map = new HashMap<String, Object>();
+			if (img1.startsWith("http")) {
+				pic1Map.put("image", EncodeHelper.encodeUrlImageToBase64(img1));
+			} else {
+				pic1Map.put("image", Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File(img1)))));
+			}
+			pic1Map.put("image_type", "BASE64");
+			pic1Map.put("face_type", "LIVE");
+			pic1Map.put("quality_control", "NONE");//质量要求要低
+			pic1Map.put("liveness_control", "NONE");
+			
+			Map<String, Object> pic2Map = new HashMap<String, Object>();
+			if (img2.startsWith("http")) {
+				pic2Map.put("image", EncodeHelper.encodeUrlImageToBase64(img2));
+			} else {
+				pic2Map.put("image", Base64.getEncoder().encodeToString(org.apache.commons.io.IOUtils.toByteArray(new FileInputStream(new File(img2)))));
+			}
+			pic2Map.put("image_type", "BASE64");
+			pic2Map.put("face_type", "LIVE");
+			pic2Map.put("quality_control", "NONE");//质量要求要低
+			pic2Map.put("liveness_control", "NONE");
+			
+			param.add(pic1Map);
+			param.add(pic2Map);
+			
+			Gson gson = new Gson();
+			String requestBody = gson.toJson(param);
+			LogHelper.info(requestBody);
+			//提交请求
+			long startTime = System.currentTimeMillis();
+			String json = HttpClientHelper.postJson(url, requestBody, headerMap);
+			long endTime = System.currentTimeMillis();
+			
+			JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
+			LogHelper.info("比对结果-----> " + json);
+			LogHelper.info("执行时间: " + (endTime-startTime) / 1000.0);
+			
+			result.setError_msg(jsonObject.get("error_msg").getAsString());
+			result.setSuccess(jsonObject.get("error_code").getAsInt() == 0 ? true : false);
+			result.setPercent(jsonObject.getAsJsonObject("result").get("score").getAsDouble());
+		} catch(Exception e) {
+			result.setSuccess(false);
+			result.setError_msg(e.getMessage());
+			LogHelper.error(e);
+		}
+		return result;
+	}
+	
+	/**
+	 * 公司离线比对
+	 * @param img1
+	 * @param img2
+	 * @param key_pass
+	 * @return
+	 */
+	public IdentifiedResult hmFaceMatch(String img1, String img2, String key_pass) {
+		IdentifiedResult result = new IdentifiedResult();
+		result.setError_msg("");
+		Map<String, Object> params = new HashMap<String, Object>();
+		params.put("key_pass", key_pass);
+		try {
+			if (img1.startsWith("http")) {
+				params.put("img1", EncodeHelper.encodeUrlImageToBase64(img1));
+			} else {
+				params.put("img1", img1);
+			}
+			
+			if (img2.startsWith("http")) {
+				params.put("img2", EncodeHelper.encodeUrlImageToBase64(img2));
+			} else {
+				params.put("img2", img2);
+			}
+			String hmFaceUrl = ParamHelper.getParamValue("HmFaceUrl", "http://39.98.40.30:8080/f/platform/face/match.htm");
+			String json = HttpClientHelper.post(hmFaceUrl, params);
+			JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
+			if (jsonObject.get("errorCode").getAsInt() == 0) {
+				double score = Double.valueOf(jsonObject.get("entity") != null ? jsonObject.get("entity").getAsString() : "0");
+				result.setPercent(score);
+				result.setSuccess(true);
+			} else {
+				result.setSuccess(false);
+				result.setError_msg(jsonObject.get("errorMsg").getAsString());
+			}
+			
+		} catch (Exception e) {
+			result.setSuccess(false);
+			result.setError_msg(e.getMessage());
+		}
+		return result;
+	}
+	
+	/**
+	 * @语音字节数据.
+	 * @param text
+	 * @param cuid
+	 * @return
+	 * @throws Exception 
+	 */
+	public byte[] text2AudioBytes(String text, String cuid) throws BusinessException {
+		byte[] bytes = null;
+		FrameAssertUtil.isNotEmpty(text, "语音文件不能为空!");
+		if (StringHelper.isEmpty(cuid)) {
+			cuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
+		}
+		SpringHelper.getBean(BaiduOpenApiTokenService.class).getBaiduToken();
+	    String params = "tex=" + OpenApiParamUtil.urlEncode(OpenApiParamUtil.urlEncode(text));
+        params += "&lan=zh&ctp=1&aue=3&per=0&spd=5&pit=5&vol=5&cuid=" + cuid + "&tok=" + BaiduOpenApiTokenService.ACCESS_TOKEN;
+        //aue-下载的文件格式, 3:mp3(default) 4: pcm-16k 5: pcm-8k 6. wav
+        String url = "http://tsn.baidu.com/text2audio?" + params;
+        try {
+	        //执行请求
+	        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
+	        conn.setDoInput(true);
+	        conn.setDoOutput(true);
+	        conn.setConnectTimeout(5000);
+	        PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
+	        printWriter.write(params);
+	        printWriter.close();
+	        String contentType = conn.getContentType();
+	        if (contentType.contains("audio/")) {
+	           bytes = OpenApiParamUtil.getResponseBytes(conn);
+	        } else {
+	        	LogHelper.info("ERROR: content-type= " + contentType);
+	            String res = OpenApiParamUtil.getResponseString(conn);
+	            throw new BusinessException(res);
+	        }
+        } catch(Exception e) {
+        	throw new BusinessException(e.getMessage());
+        }
+        return bytes;
+	}
+}

+ 162 - 0
src/cn/hmsoft/hmplatform/identity/service/IdentifyService.java

@@ -0,0 +1,162 @@
+package cn.hmsoft.hmplatform.identity.service;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.ai.identity.IdentifiedResult;
+import cn.hmsoft.ai.identity.IdentityAI;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.helper.CollectionHelper;
+import cn.hmsoft.hmplatform.constants.StdResType;
+import cn.hmsoft.hmplatform.helper.ParamHelper;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdRegDao;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdResDao;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdResLogDao;
+import cn.hmsoft.hmplatform.identity.data.model.PStdReg;
+import cn.hmsoft.hmplatform.identity.data.model.PStdRes;
+import cn.hmsoft.hmplatform.identity.data.model.PStdResLog;
+import cn.hmsoft.hmplatform.identity.util.EncodeHelper;
+import cn.hmsoft.log.LogHelper;
+
+@Service
+public class IdentifyService {
+	
+	@Autowired
+	private PStdRegDao daoStd;
+	@Autowired
+	private PStdResDao daoRes;
+	@Autowired
+	private PStdResLogDao daoResLog;
+	
+	/**
+	 * @公安部身份认证.
+	 * @param cert_id
+	 * @param std_name
+	 * @param image_file 待写入的路径
+	 * @param image 客户端传入的照片
+	 * @return
+	 */
+	public Map<String, Object> verify(String cert_id, String std_name, String image, String from_project) {
+		IdentifiedResult result = null;
+		PStdRes res = this.daoRes.findRes(cert_id, LocalDate.now(), StdResType.Identify.toString());
+		String max = CollectionHelper.getParamValue(ParamHelper.GobalParamMap, "IdentifyCallNumber", "5");
+		Map<String, Object> map = new HashMap<String, Object>();
+		if (res != null && res.getRes_number() != null && res.getRes_number() >= (Integer.parseInt(max) + res.getRes_plus())) {
+			map.put("success", false);
+			map.put("error_msg", "该考生今天身份证超限,明天再试!");
+			map.put("percent", 0);
+			map.put("image_url", "");
+			return map;
+		}
+		PStdReg std = this.daoStd.findBySql("select * from p_std_reg where cert_id=?", cert_id);
+		if (std != null && std.getVerify_status().equals("Active")) {
+			List<PStdResLog> resLogList = this.daoResLog.listBySql("select * from p_std_res_log where res_type=? and std_id=? order by res_time desc", 
+					StdResType.Identify.toString(), std.getStd_id());
+			//LogHelper.info("--------88------" + std.getCert_id() + "," + resLogList.size());			
+			if (resLogList.size() > 0) {
+				//LogHelper.info("----------99------" + resLogList.get(0).getRes_result());					
+				map.put("success", true);
+				map.put("error_msg", resLogList.get(0).getRes_desc());
+				map.put("percent", Double.valueOf(resLogList.get(0).getRes_result()));
+				map.put("image_url", std.getStd_image());
+				return map;
+			}
+		} else {
+			String localDir = CollectionHelper.getParamValue(ParamHelper.GobalParamMap, "MaterialLocalPath", "/data/uploadfile/image/");
+			File dir = new File(localDir);
+			if (!dir.exists()) {
+				dir.mkdirs();
+			}
+			File imageFile = new File(localDir + cert_id + ".jpg");
+			this.saveStdImage(imageFile, image);//先写入照片
+			result = IdentityAI.instance().verify(imageFile, cert_id, std_name);//比对
+			if (std == null) {
+				std = new PStdReg();
+				std.setStd_name(std_name);
+				std.setCert_id(cert_id);
+				std.setFrom_project(from_project);
+				std.setStd_birthday(null);
+				std.setStd_nation(null);
+				std.setStd_sex(null);
+				std.setVerify_time(LocalDateTime.now());
+				std.setVerify_status("InActive");//默认
+				this.daoStd.insert(std);
+			}
+			PStdResLog log = new PStdResLog();
+			log.setStd_id(std.getStd_id());
+			log.setRes_desc(result.getError_msg());
+			if (result.getPercent() >= 70 && result.isSuccess()) {
+				log.setRes_desc("成功!");
+				std.setVerify_status("Active");
+				String std_image = CollectionHelper.getParamValue(ParamHelper.GobalParamMap, "MaterialWebPath", 
+						"http://p.hmsoft.cn/image/") + cert_id + ".jpg";
+				std.setStd_image(std_image);
+				this.daoStd.update(std);
+				map.put("success", true);
+				map.put("error_msg", result.getError_msg());
+				map.put("percent", result.getPercent());
+				map.put("image_url", std_image);
+			} else {
+				std.setVerify_status("InActive");
+				this.daoStd.update(std);
+				map.put("success", false);
+				map.put("error_msg", result.getError_msg());
+				map.put("percent", result.getPercent());
+				map.put("image_url", "");
+			}
+			log.setRes_result(String.valueOf(result.getPercent()));
+			log.setRes_time(LocalDateTime.now());
+			log.setRes_param(cert_id + "," + std_name);
+			log.setRes_type(StdResType.Identify.toString());
+			this.daoResLog.insert(log);
+		}
+		//更新限制
+		if (res == null) {
+			res = new PStdRes();
+			res.setRes_date(LocalDate.now());
+			res.setRes_number(1);
+			res.setRes_plus(0);
+			res.setCert_id(cert_id);
+			res.setRes_type(StdResType.Identify.toString());
+			res.setStd_id(std.getStd_id());
+			this.daoRes.insert(res);
+		} else {
+			res.setRes_number(res.getRes_number() + 1);
+			this.daoRes.updateBySql("update p_std_res set res_number=? where res_date=? and std_id=? and res_type=?", 
+					res.getRes_number() + 1,LocalDate.now(), std.getStd_id(), StdResType.Identify.toString());
+		}
+		return map;
+	}
+	
+	private void saveStdImage(File imageFile, String image) {
+		String base64Str = image;
+		if (image.startsWith("http")) {
+			base64Str = EncodeHelper.encodeUrlImageToBase64(image);
+		}
+		try {
+			int startPos = base64Str.indexOf(";base64");
+			if (startPos > 0) {
+				base64Str = base64Str.substring(startPos + 8, base64Str.length());
+			}
+			base64Str = base64Str.replaceAll("\n", "");
+			byte[] bytes = Base64.getDecoder().decode(base64Str);
+			OutputStream out = new FileOutputStream(imageFile);
+			out.write(bytes);
+			out.flush();
+			out.close();
+		} catch (Exception e) {
+			throw new BusinessException("认证异常,获取认证照片失败:" + e.getMessage());
+		}
+	}
+	
+}

+ 12 - 0
src/cn/hmsoft/hmplatform/identity/service/PStdRegService.java

@@ -0,0 +1,12 @@
+package cn.hmsoft.hmplatform.identity.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdRegDao;
+
+@Service
+public class PStdRegService {
+
+	@Autowired
+	private PStdRegDao daoStd;
+}

+ 12 - 0
src/cn/hmsoft/hmplatform/identity/service/PStdResLogService.java

@@ -0,0 +1,12 @@
+package cn.hmsoft.hmplatform.identity.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdResLogDao;
+
+@Service
+public class PStdResLogService {
+
+	@Autowired
+	private PStdResLogDao daoResLog;
+}

+ 13 - 0
src/cn/hmsoft/hmplatform/identity/service/PStdResService.java

@@ -0,0 +1,13 @@
+package cn.hmsoft.hmplatform.identity.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.hmplatform.identity.data.dao.PStdResDao;
+
+@Service
+public class PStdResService {
+
+	@Autowired
+	private PStdResDao daoRes;
+}

+ 58 - 0
src/cn/hmsoft/hmplatform/identity/util/EncodeHelper.java

@@ -0,0 +1,58 @@
+package cn.hmsoft.hmplatform.identity.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Base64;
+import cn.hmsoft.log.LogHelper;
+
+public class EncodeHelper {
+
+	public static String encodeUrlImageToBase64(String path) {
+        String remark = path.replace("https", "http");
+        InputStream inputStream = null;
+        ByteArrayOutputStream outputStream = null;
+        byte[] buffer = null;
+        try {
+            // 创建URL
+            URL url = new URL(remark);
+            // 创建链接
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            conn.setRequestMethod("GET");
+            conn.setConnectTimeout(100000);
+            inputStream = conn.getInputStream();
+            outputStream = new ByteArrayOutputStream();
+            // 将内容读取内存中
+            buffer = new byte[1024];
+            int len = -1;
+            while ((len = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, len);
+            }
+            buffer = outputStream.toByteArray();
+        } catch (IOException e) {
+        	LogHelper.error(e);
+        } finally {
+            if (inputStream != null) {
+                try {
+                    // 关闭inputStream流
+                    inputStream.close();
+                } catch (IOException e) {
+                	LogHelper.error(e);
+                }
+            }
+            if (outputStream != null) {
+                try {
+                    // 关闭outputStream流
+                    outputStream.close();
+                } catch (IOException e) {
+                    LogHelper.error(e);
+                }
+            }
+        }
+        // 对字节数组Base64编码
+        return Base64.getEncoder().encodeToString(buffer);
+    }
+}

+ 39 - 0
src/cn/hmsoft/hmplatform/monitor/control/StdRegControl.java

@@ -0,0 +1,39 @@
+package cn.hmsoft.hmplatform.monitor.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.identity.data.dao.PStdRegDao;
+import cn.hmsoft.hmplatform.identity.data.model.PStdRes;
+
+@RestController
+public class StdRegControl extends FrameControl {
+
+	@Autowired
+	private PStdRegDao daoStd;
+	
+	@RequestMapping("platform/monitor/std/page")
+	public Ajax page(String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoStd.pageStd(start, limit, query, getQueryOrder(order, type)));
+	}
+	
+	@RequestMapping("platform/monitor/stdreslog/list")
+	public Ajax listStdResLog(Integer std_id) {
+		return new Ajax(this.daoStd.listMapBySql("select * from p_std_res_log where std_id=? order by res_type,res_time desc", std_id));
+	}
+	
+	@RequestMapping("platform/monitor/stdres/list")
+	public Ajax listStdRes(Integer std_id) {
+		return new Ajax(this.daoStd.listMapBySql("select * from p_std_res where std_id=? order by res_type,res_date desc", std_id));
+	}
+	
+	@RequestMapping("platform/monitor/stdres/adjust")
+	public Ajax adjust(PStdRes res) {
+		this.daoStd.updateBySql("update p_std_res set res_plus=? where res_type=? and res_date=? and std_id=?", res.getRes_plus(), 
+				res.getRes_type(), res.getRes_date(), res.getStd_id());
+		return new Ajax();
+	}
+}

+ 48 - 0
src/cn/hmsoft/hmplatform/project/control/ProjectControl.java

@@ -0,0 +1,48 @@
+package cn.hmsoft.hmplatform.project.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.project.data.dao.PProjectDao;
+import cn.hmsoft.hmplatform.project.data.model.PProject;
+import cn.hmsoft.hmplatform.project.service.PProjectService;
+
+@RestController
+public class ProjectControl extends FrameControl {
+
+	@Autowired
+	private PProjectService serviceProject;
+	@Autowired
+	private PProjectDao daoProject;
+	
+	@RequestMapping("platform/conf/project/page")
+	public Ajax page(Integer school_id, String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoProject.pageProject(school_id, start, limit, query, getQueryOrder(order, type)));
+	}
+
+	@RequestMapping("platform/conf/project/find")
+	public Ajax find(int project_id) {
+		return new Ajax(this.daoProject.find(project_id));
+	}
+
+	@RequestMapping("platform/conf/project/add")
+	public Ajax add(PProject project) {
+		this.serviceProject.addProject(project, this.getFrameOptr());
+		return new Ajax(project);
+	}
+
+	@RequestMapping("platform/conf/project/edit")
+	public Ajax edit(PProject project) {
+		this.serviceProject.editProject(project, this.getFrameOptr());
+		return new Ajax(project);
+	}
+
+	@RequestMapping("platform/conf/project/delete")
+	public Ajax delete(Integer subject_id) {
+		this.serviceProject.deleteProject(subject_id, this.getFrameOptr());
+		return new Ajax();
+	}
+}

+ 37 - 0
src/cn/hmsoft/hmplatform/project/control/ProjectRemarkControl.java

@@ -0,0 +1,37 @@
+package cn.hmsoft.hmplatform.project.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.project.data.dao.PProjectRemarkDao;
+import cn.hmsoft.hmplatform.project.data.model.PProjectRemark;
+import cn.hmsoft.hmplatform.project.service.PProjectRemarkService;
+
+@RestController
+public class ProjectRemarkControl extends FrameControl {
+
+	@Autowired
+	private PProjectRemarkService serviceRemark;
+	@Autowired
+	private PProjectRemarkDao daoRemark;
+	
+	@RequestMapping("platform/conf/projectremark/list")
+	public Ajax list(Integer project_id) {
+		return new Ajax(this.daoRemark.listRemark(project_id));
+	}
+	
+	@RequestMapping("platform/conf/projectremark/save")
+	public Ajax save(PProjectRemark remark) {
+		this.serviceRemark.saveRemark(remark);
+		return new Ajax();
+	}
+	
+	@RequestMapping("platform/conf/projectremark/delete")
+	public Ajax delete(Integer remark_id) {
+		this.serviceRemark.deleteRemark(remark_id);
+		return new Ajax();
+	}
+}

+ 53 - 0
src/cn/hmsoft/hmplatform/project/control/SchoolControl.java

@@ -0,0 +1,53 @@
+package cn.hmsoft.hmplatform.project.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.project.data.dao.PSchoolDao;
+import cn.hmsoft.hmplatform.project.data.model.PSchool;
+import cn.hmsoft.hmplatform.project.service.PSchoolService;
+
+@RestController
+public class SchoolControl extends FrameControl {
+
+	@Autowired
+	private PSchoolService serviceSchool;
+	@Autowired
+	private PSchoolDao daoSchool;
+	
+	@RequestMapping("platform/conf/school/page")
+	public Ajax page(String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoSchool.pageSchool(start, limit, query, getQueryOrder(order, type)));
+	}
+
+	@RequestMapping("platform/conf/school/find")
+	public Ajax find(int daoSchool) {
+		return new Ajax(this.daoSchool.find(daoSchool));
+	}
+
+	@RequestMapping("platform/conf/school/add")
+	public Ajax add(PSchool school) {
+		this.serviceSchool.addSchool(school, this.getFrameOptr());
+		return new Ajax(school);
+	}
+
+	@RequestMapping("platform/conf/school/edit")
+	public Ajax edit(PSchool school) {
+		this.serviceSchool.editSchool(school, this.getFrameOptr());
+		return new Ajax(school);
+	}
+
+	@RequestMapping("platform/conf/school/delete")
+	public Ajax delete(Integer daoSchool) {
+		this.serviceSchool.deleteSchool(daoSchool, this.getFrameOptr());
+		return new Ajax();
+	}
+	
+	@RequestMapping("platform/conf/school/list")
+	public Ajax list(Integer daoSchool) {
+		return new Ajax(this.daoSchool.all());
+	}
+}

+ 29 - 0
src/cn/hmsoft/hmplatform/project/data/dao/PProjectDao.java

@@ -0,0 +1,29 @@
+package cn.hmsoft.hmplatform.project.data.dao;
+
+import org.springframework.stereotype.Repository;
+
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.project.data.model.PProject;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PProjectDao extends PlatformDaoSupport<PProject> {
+
+	public Pager pageProject(Integer school_id, Integer start, Integer limit, String query, 
+			QueryOrder queryOrder) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select p.*,s.school_name,s.school_code from p_project p left join p_school s on p.school_id=s.school_id  ");
+		sql.append("where 1=1 ");
+		if (school_id != null) {
+			sql.append(" and p.school_id=").append(school_id);
+		}
+		if (StringHelper.isEmpty(query)) {
+			return this.pageMapBySql(queryOrder, start, limit, sql.toString());
+		}
+		sql.append(" and (s.school_code = ? or p.manager like ? or s.school_name like ?)");
+		return this.pageMapBySql(queryOrder, start, limit, sql.toString(), query, "%" + query + "%", "%" + query + "%");
+	}
+
+}

+ 18 - 0
src/cn/hmsoft/hmplatform/project/data/dao/PProjectRemarkDao.java

@@ -0,0 +1,18 @@
+package cn.hmsoft.hmplatform.project.data.dao;
+
+import java.util.List;
+import org.springframework.stereotype.Repository;
+import cn.hmsoft.hmplatform.project.data.model.PProjectRemark;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+
+@Repository
+public class PProjectRemarkDao extends PlatformDaoSupport<PProjectRemark> {
+
+	public List<PProjectRemark> listRemark(Integer project_id) {
+			StringBuilder sql = new StringBuilder();
+			sql.append("select * from p_project_remark where project_id=? order by remark_time desc");
+			return this.listBySql(sql.toString(), project_id);
+	}
+
+
+}

+ 24 - 0
src/cn/hmsoft/hmplatform/project/data/dao/PSchoolDao.java

@@ -0,0 +1,24 @@
+package cn.hmsoft.hmplatform.project.data.dao;
+
+import org.springframework.stereotype.Repository;
+
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.project.data.model.PSchool;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PSchoolDao extends PlatformDaoSupport<PSchool> {
+
+	public Pager pageSchool(Integer start, Integer limit, String query, 
+			QueryOrder queryOrder) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select * from p_school where 1=1 ");
+		if (StringHelper.isEmpty(query)) {
+			return this.pageMapBySql(queryOrder, start, limit, sql.toString());
+		}
+		sql.append(" and (school_code = ? or school_name like ?)");
+		return this.pageMapBySql(queryOrder, start, limit, sql.toString(), query, "%" + query + "%");
+	}
+}

+ 76 - 0
src/cn/hmsoft/hmplatform/project/data/model/PProject.java

@@ -0,0 +1,76 @@
+package cn.hmsoft.hmplatform.project.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_PROJECT", keyColumn =  "PROJECT_ID" , sequenceName = "PROJECT_ID")
+public class PProject implements Serializable {
+
+	private static final long serialVersionUID = -4001944383195054153L;
+	private Integer project_id;
+	private String project_name;
+	private Integer school_id;
+	private Integer year;
+	private LocalDate start_date;
+	private LocalDate end_date;
+	private String manager;
+	private String project_desc;
+	private String project_status;
+	
+	public Integer getProject_id() {
+		return project_id;
+	}
+	public String getProject_name() {
+		return project_name;
+	}
+	public Integer getSchool_id() {
+		return school_id;
+	}
+	public Integer getYear() {
+		return year;
+	}
+	public LocalDate getStart_date() {
+		return start_date;
+	}
+	public LocalDate getEnd_date() {
+		return end_date;
+	}
+	public String getManager() {
+		return manager;
+	}
+	public void setProject_id(Integer project_id) {
+		this.project_id = project_id;
+	}
+	public void setProject_name(String project_name) {
+		this.project_name = project_name;
+	}
+	public void setSchool_id(Integer school_id) {
+		this.school_id = school_id;
+	}
+	public void setYear(Integer year) {
+		this.year = year;
+	}
+	public void setStart_date(LocalDate start_date) {
+		this.start_date = start_date;
+	}
+	public void setEnd_date(LocalDate end_date) {
+		this.end_date = end_date;
+	}
+	public void setManager(String manager) {
+		this.manager = manager;
+	}
+	public String getProject_desc() {
+		return project_desc;
+	}
+	public String getProject_status() {
+		return project_status;
+	}
+	public void setProject_desc(String project_desc) {
+		this.project_desc = project_desc;
+	}
+	public void setProject_status(String project_status) {
+		this.project_status = project_status;
+	}
+
+}

+ 41 - 0
src/cn/hmsoft/hmplatform/project/data/model/PProjectRemark.java

@@ -0,0 +1,41 @@
+package cn.hmsoft.hmplatform.project.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_PROJECT_REMARK", keyColumn =  "REMARK_ID" , sequenceName = "REMARK_ID")
+public class PProjectRemark implements Serializable {
+
+	private static final long serialVersionUID = 5267224479833033372L;
+	private Integer remark_id;
+	private Integer project_id;
+	private LocalDateTime remark_time;
+	private String remark;
+	
+	public Integer getRemark_id() {
+		return remark_id;
+	}
+	public Integer getProject_id() {
+		return project_id;
+	}
+	public LocalDateTime getRemark_time() {
+		return remark_time;
+	}
+	public String getRemark() {
+		return remark;
+	}
+	public void setRemark_id(Integer remark_id) {
+		this.remark_id = remark_id;
+	}
+	public void setProject_id(Integer project_id) {
+		this.project_id = project_id;
+	}
+	public void setRemark_time(LocalDateTime remark_time) {
+		this.remark_time = remark_time;
+	}
+	public void setRemark(String remark) {
+		this.remark = remark;
+	}
+	
+}

+ 40 - 0
src/cn/hmsoft/hmplatform/project/data/model/PSchool.java

@@ -0,0 +1,40 @@
+package cn.hmsoft.hmplatform.project.data.model;
+
+import java.io.Serializable;
+
+import cn.hmsoft.jdbc.entity.Table;
+
+@Table(tableName = "P_SCHOOL", keyColumn =  "SCHOOL_ID" , sequenceName = "SCHOOL_ID")
+public class PSchool implements Serializable {
+
+	private static final long serialVersionUID = -950778542472543471L;
+	private Integer school_id;
+	private String school_name;
+	private String school_code;
+	private String school_addr;
+	public Integer getSchool_id() {
+		return school_id;
+	}
+	public String getSchool_name() {
+		return school_name;
+	}
+	public String getSchool_code() {
+		return school_code;
+	}
+	public String getSchool_addr() {
+		return school_addr;
+	}
+	public void setSchool_id(Integer school_id) {
+		this.school_id = school_id;
+	}
+	public void setSchool_name(String school_name) {
+		this.school_name = school_name;
+	}
+	public void setSchool_code(String school_code) {
+		this.school_code = school_code;
+	}
+	public void setSchool_addr(String school_addr) {
+		this.school_addr = school_addr;
+	}
+	
+}

+ 29 - 0
src/cn/hmsoft/hmplatform/project/service/PProjectRemarkService.java

@@ -0,0 +1,29 @@
+package cn.hmsoft.hmplatform.project.service;
+
+import java.time.LocalDateTime;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import cn.hmsoft.hmplatform.project.data.dao.PProjectRemarkDao;
+import cn.hmsoft.hmplatform.project.data.model.PProjectRemark;
+
+@Service
+public class PProjectRemarkService {
+
+	@Autowired
+	private PProjectRemarkDao daoRemark;
+
+	public void saveRemark(PProjectRemark remark) {
+		if (remark.getRemark_id() == null) {
+			remark.setRemark_time(LocalDateTime.now());
+			this.daoRemark.insert(remark);
+		} else {
+			this.daoRemark.update(remark);
+		}
+		
+	}
+
+	public void deleteRemark(Integer remark_id) {
+		this.daoRemark.delete(remark_id);
+	}
+}

+ 27 - 0
src/cn/hmsoft/hmplatform/project/service/PProjectService.java

@@ -0,0 +1,27 @@
+package cn.hmsoft.hmplatform.project.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.frame.data.model.FrameOptr;
+import cn.hmsoft.hmplatform.project.data.dao.PProjectDao;
+import cn.hmsoft.hmplatform.project.data.model.PProject;
+
+@Service
+public class PProjectService {
+
+	@Autowired
+	private PProjectDao daoProject;
+
+	public void addProject(PProject project, FrameOptr frameOptr) {
+		this.daoProject.insert(project);
+	}
+
+	public void editProject(PProject project, FrameOptr frameOptr) {
+		this.daoProject.update(project);
+	}
+
+	public void deleteProject(Integer project_id, FrameOptr frameOptr) {
+		this.daoProject.delete(project_id);
+	}
+}

+ 27 - 0
src/cn/hmsoft/hmplatform/project/service/PSchoolService.java

@@ -0,0 +1,27 @@
+package cn.hmsoft.hmplatform.project.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.frame.data.model.FrameOptr;
+import cn.hmsoft.hmplatform.project.data.dao.PSchoolDao;
+import cn.hmsoft.hmplatform.project.data.model.PSchool;
+
+@Service
+public class PSchoolService {
+
+	@Autowired
+	private PSchoolDao daoSchool;
+
+	public void addSchool(PSchool school, FrameOptr frameOptr) {
+		this.daoSchool.insert(school);
+	}
+
+	public void editSchool(PSchool school, FrameOptr frameOptr) {
+		this.daoSchool.update(school);
+	}
+
+	public void deleteSchool(Integer school_id, FrameOptr frameOptr) {
+		this.daoSchool.delete(school_id);
+	}
+}

+ 79 - 0
src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenControl.java

@@ -0,0 +1,79 @@
+package cn.hmsoft.hmplatform.wxtoken.control;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.application.web.AjaxControl;
+import cn.hmsoft.frame.exception.BusinessException;
+import cn.hmsoft.frame.util.FrameAgentUtil;
+import cn.hmsoft.helper.JsonHelper;
+import cn.hmsoft.helper.LocalDateHelper;
+import cn.hmsoft.helper.SecureHelper;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.service.PlatformWeixinTokenService;
+import cn.hmsoft.hmplatform.wxtoken.util.WeixinTokenModuleParamUtil;
+import cn.hmsoft.hmplatform.wxtoken.util.WeixinTokenNoticeThread;
+import cn.hmsoft.log.LogHelper;
+
+@RestController
+public class WeixinTokenControl extends AjaxControl {
+
+	@Autowired
+	private PWxDefineDao daoDefine;
+	@Autowired
+	private PlatformWeixinTokenService sToken;
+
+	@RequestMapping("platform/weixin/token/fetch")
+	public void fetch(PWxDefine w, String request_key, String internet_addr, String deploy_addr) {
+		if (StringHelper.isEmpty(request_key) || StringHelper.isEmpty(internet_addr)
+				|| StringHelper.isEmpty(deploy_addr))
+			return;
+		if (!request_key.equals(SecureHelper.md5(WeixinTokenModuleParamUtil.FetchWeixinTokenPass)))
+			return;
+		LogHelper.info("--公众号应用上线:[" + w.getWx_name() + "][" + internet_addr + "][" + deploy_addr + "]");
+
+		String request_addr = FrameAgentUtil.getUserAddr(this.getRequest());
+		this.sToken.fetchToken(w, internet_addr, deploy_addr, request_addr);
+		PWxDefine wx = null;
+		int tryTimes = 1;
+		do {
+			tryTimes++;
+			wx = daoDefine.findWxDefine(w.getApp_id());
+			if (wx == null || wx.getApp_token_expired() == null
+					|| wx.getApp_token_expired().isBefore(LocalDateTime.now())) {
+				try {
+					Thread.sleep(1000);
+				} catch (Exception e) {
+
+				}
+				wx = null;
+			} else
+				break;
+		} while (wx == null && tryTimes < 10);
+		Map<String, String> map = new HashMap<String, String>();
+		if (wx != null) {
+			map.put("app_id", wx.getApp_id());
+			map.put("app_accesstoken", wx.getApp_accesstoken());
+			map.put("app_jsapi", wx.getApp_jsapi());
+			map.put("app_token_expired", LocalDateHelper.format(wx.getApp_token_expired()));
+		}
+		this.writeText(JsonHelper.fromObject(map));
+	}
+
+	@RequestMapping("platform/weixin/token/notice")
+	public Ajax notice(String app_id) {
+		PWxDefine wx = daoDefine.findWxDefine(app_id);
+		if (wx == null)
+			throw new BusinessException("公众号未加入该平台");
+		new WeixinTokenNoticeThread(wx).start();
+		return new Ajax();
+	}
+}

+ 48 - 0
src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenDefineControl.java

@@ -0,0 +1,48 @@
+package cn.hmsoft.hmplatform.wxtoken.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.service.PlatformTokenDefineService;
+
+@RestController
+public class WeixinTokenDefineControl extends FrameControl {
+
+	@Autowired
+	private PWxDefineDao daoDefine;
+	@Autowired
+	private PlatformTokenDefineService sToken;
+
+	@RequestMapping("platform/wxtoken/page")
+	public Ajax page(String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoDefine.pageDefine(start, limit, query, getQueryOrder(order, type)));
+	}
+
+	@RequestMapping("platform/wxtoken/add")
+	public Ajax add(final PWxDefine define) {
+		this.sToken.addDefine(define);
+		return new Ajax(define);
+	}
+
+	@RequestMapping("platform/wxtoken/edit")
+	public Ajax edit(final PWxDefine define) {
+		this.sToken.editDefine(define);
+		return new Ajax();
+	}
+
+	@RequestMapping("platform/wxtoken/find")
+	public Ajax find(final int token_id) {
+		return new Ajax(this.daoDefine.find(token_id));
+	}
+
+	@RequestMapping("platform/wxtoken/delete")
+	public Ajax delete(final int token_id) {
+		this.sToken.deleteDefine(token_id);
+		return new Ajax();
+	}
+}

+ 20 - 0
src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenDeployControl.java

@@ -0,0 +1,20 @@
+package cn.hmsoft.hmplatform.wxtoken.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDeployDao;
+
+@RestController
+public class WeixinTokenDeployControl extends FrameControl {
+
+	@Autowired
+	private PWxDeployDao daoDeploy;
+	
+	@RequestMapping("platform/wxtoken/deploy/page")
+	public Ajax page(Integer token_id, String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoDeploy.pageDeploy(token_id, start, limit, query, getQueryOrder(order, type)));
+	}
+}

+ 20 - 0
src/cn/hmsoft/hmplatform/wxtoken/control/WeixinTokenRequestControl.java

@@ -0,0 +1,20 @@
+package cn.hmsoft.hmplatform.wxtoken.control;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.control.FrameControl;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxTokenRequestDao;
+
+@RestController
+public class WeixinTokenRequestControl extends FrameControl {
+
+	@Autowired
+	private PWxTokenRequestDao daoRequest;
+	
+	@RequestMapping("platform/wxtoken/request/page")
+	public Ajax page(Integer token_id, String query, Integer limit, Integer start, String order, String type) {
+		return new Ajax(this.daoRequest.pageRequest(token_id, start, limit, query, getQueryOrder(order, type)));
+	}
+}

+ 29 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxDefineDao.java

@@ -0,0 +1,29 @@
+package cn.hmsoft.hmplatform.wxtoken.data.dao;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.util.StringUtils;
+
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PWxDefineDao extends PlatformDaoSupport<PWxDefine> {
+	private final static String FIND_BY_APPID = "select * from p_wx_define where app_id=?";
+
+	public PWxDefine findWxDefine(String app_id) {
+		return this.findBySql(FIND_BY_APPID, app_id);
+	}
+
+	public Pager pageDefine(Integer start, Integer limit, String query, QueryOrder order) {
+		final StringBuilder sql = new StringBuilder();
+		sql.append(
+				"select d.*,pd.deploy_total from p_wx_define d left join (select token_id,count(1) deploy_total from p_wx_deploy pd group by token_id) pd on d.token_id=pd.token_id where 1=1");
+		if (StringUtils.isEmpty(query)) {
+			return this.pageBySql(order, start, limit, sql.toString());
+		}
+		sql.append(" and (app_id=? or app_name like ? or wx_name like ?)");
+		return super.pageMapBySql(order, start, limit, sql.toString(), query, "%" + query + "%", "%" + query + "%");
+	}
+}

+ 56 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxDeployDao.java

@@ -0,0 +1,56 @@
+package cn.hmsoft.hmplatform.wxtoken.data.dao;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeploy;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PWxDeployDao extends PlatformDaoSupport<PWxDeploy> {
+	private final static String LIST_INTERNET_ADDR = "select internet_addr from p_wx_deploy where token_id=? and (notice_time is null or notice_time>?) group by internet_addr";
+
+	/****************
+	 * 列出通知目标,一天以内的都认为需要通知
+	 */
+	public List<PWxDeploy> listInternetAddr(int token_id) {
+		return this.listBySql(LIST_INTERNET_ADDR, token_id, LocalDateTime.now().minusDays(1));
+	}
+
+	private final static String FIND_DEPLOY = "select * from p_wx_deploy where token_id=? and internet_addr=? and deploy_addr=?";
+
+	/*****************
+	 * 判断是否由此部署了
+	 */
+	public PWxDeploy findDeploy(int token_id, String internet_addr, String deploy_addr) {
+		return this.findBySql(FIND_DEPLOY, token_id, internet_addr, deploy_addr);
+	}
+
+	private final static String NOTICE_DEPLOY = "update p_wx_deploy set notice_time=? where token_id=? and internet_addr=?";
+
+	/*****************
+	 * 更新通知
+	 */
+	public void noticeDeploy(int token_id, String internet_addr) {
+		this.updateBySql(NOTICE_DEPLOY, LocalDateTime.now(), token_id, internet_addr);
+	}
+
+	public Pager pageDeploy(Integer token_id, Integer start, Integer limit, String query, QueryOrder queryOrder) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select * from p_wx_deploy ");
+		sql.append("where 1=1 ");
+		if (token_id != null) {
+			sql.append(" and token_id=").append(token_id);
+		}
+		if (StringHelper.isEmpty(query)) {
+			return this.pageMapBySql(queryOrder, start, limit, sql.toString());
+		}
+		sql.append(" and (internet_addr like ?)");
+		return this.pageMapBySql(queryOrder, start, limit, sql.toString(), "%" + query + "%");
+	}
+}

+ 10 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxTokenNoticeDao.java

@@ -0,0 +1,10 @@
+package cn.hmsoft.hmplatform.wxtoken.data.dao;
+
+import org.springframework.stereotype.Repository;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenNotice;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+
+@Repository
+public class PWxTokenNoticeDao extends PlatformDaoSupport<PWxTokenNotice> {
+
+}

+ 31 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/dao/PWxTokenRequestDao.java

@@ -0,0 +1,31 @@
+package cn.hmsoft.hmplatform.wxtoken.data.dao;
+
+import org.springframework.stereotype.Repository;
+
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenRequest;
+import cn.hmsoft.jdbc.core.PlatformDaoSupport;
+import cn.hmsoft.jdbc.entity.Pager;
+import cn.hmsoft.jdbc.entity.QueryOrder;
+
+@Repository
+public class PWxTokenRequestDao extends PlatformDaoSupport<PWxTokenRequest> {
+
+	public Pager pageRequest(Integer token_id, Integer start, Integer limit, String query,
+			QueryOrder queryOrder) {
+		StringBuilder sql = new StringBuilder();
+		sql.append("select * from p_wx_token_request ");
+		sql.append("where 1=1 ");
+		if (token_id != null) {
+			sql.append(" and token_id=").append(token_id);
+		}
+		if (StringHelper.isEmpty(query)) {
+			sql.append(" order by request_time desc");
+			return this.pageMapBySql(queryOrder, start, limit, sql.toString());
+		}
+		sql.append(" and (error_code = ? or error_msg like ?) ");
+		sql.append(" order by request_time desc ");
+		return this.pageMapBySql(queryOrder, start, limit, sql.toString(), query, "%" + query + "%");
+	}
+
+}

+ 308 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDefine.java

@@ -0,0 +1,308 @@
+package cn.hmsoft.hmplatform.wxtoken.data.model;
+
+import java.io.Serializable;
+import cn.hmsoft.jdbc.entity.Table;
+import java.time.LocalDateTime;
+
+/**********************************************
+ * 微信公众号(小程序)定义表
+ * 
+ * @author: zxq
+ * @date: 2020-04-30 19:28:59
+ * @version: 2.0.0
+ * @email: revisit@126.com
+ * @Company: www.hmsoft.cn
+ */
+@Table(tableName = "P_WX_DEFINE", keyColumn = "TOKEN_ID", sequenceName = "WX_ID")
+public class PWxDefine implements Serializable {
+	private static final long serialVersionUID = 6030942864906421645L;
+	// 微信内部编号
+	private Integer token_id;
+	// 微信公众号
+	private String app_id;
+	// 微信公众号密钥
+	private String app_secrect;
+	// 微信公众号密钥,消息加密
+	private String app_aeskey;
+	// 微信图标文件
+	private String app_qrcode;
+	// App默认Token
+	private String app_accesstokenkey;
+	// app实时的access_token
+	private String app_accesstoken;
+	// token超时时间
+	private LocalDateTime app_token_expired;
+	// JSAPI需要使用的Ticket
+	private String app_jsapi;
+	// 是否启用
+	private String app_status;
+	// 是否记录用户日志
+	private String record_user_log;
+	// 原始微信号
+	private String wx_code;
+	// 哪个系统使用,空为所有系哦他能够
+	private String app_name;
+	// 微信公众号主体
+	private String wx_name;
+	// 微信类型
+	private String wx_type;
+	// 创建时间
+	private LocalDateTime app_create_time;
+	// 更新时间
+	private LocalDateTime app_update_time;
+	// 请求token时间
+	private LocalDateTime app_token_time;
+
+	/****
+	 * 微信内部编号
+	 */
+	public Integer getToken_id() {
+		return this.token_id;
+	}
+
+	/****
+	 * 微信内部编号
+	 */
+	public void setToken_id(Integer token_id) {
+		this.token_id = token_id;
+	}
+
+	/****
+	 * 微信公众号
+	 */
+	public String getApp_id() {
+		return this.app_id;
+	}
+
+	/****
+	 * 微信公众号
+	 */
+	public void setApp_id(String app_id) {
+		this.app_id = app_id;
+	}
+
+	/****
+	 * 微信公众号密钥
+	 */
+	public String getApp_secrect() {
+		return this.app_secrect;
+	}
+
+	/****
+	 * 微信公众号密钥
+	 */
+	public void setApp_secrect(String app_secrect) {
+		this.app_secrect = app_secrect;
+	}
+
+	/****
+	 * 微信公众号密钥,消息加密
+	 */
+	public String getApp_aeskey() {
+		return this.app_aeskey;
+	}
+
+	/****
+	 * 微信公众号密钥,消息加密
+	 */
+	public void setApp_aeskey(String app_aeskey) {
+		this.app_aeskey = app_aeskey;
+	}
+
+	/****
+	 * 微信图标文件
+	 */
+	public String getApp_qrcode() {
+		return this.app_qrcode;
+	}
+
+	/****
+	 * 微信图标文件
+	 */
+	public void setApp_qrcode(String app_qrcode) {
+		this.app_qrcode = app_qrcode;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public String getApp_accesstokenkey() {
+		return this.app_accesstokenkey;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public void setApp_accesstokenkey(String app_accesstokenkey) {
+		this.app_accesstokenkey = app_accesstokenkey;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public String getApp_accesstoken() {
+		return this.app_accesstoken;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public void setApp_accesstoken(String app_accesstoken) {
+		this.app_accesstoken = app_accesstoken;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public LocalDateTime getApp_token_expired() {
+		return this.app_token_expired;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public void setApp_token_expired(LocalDateTime app_token_expired) {
+		this.app_token_expired = app_token_expired;
+	}
+
+	/****
+	 * JSAPI需要使用的Ticket
+	 */
+	public String getApp_jsapi() {
+		return this.app_jsapi;
+	}
+
+	/****
+	 * JSAPI需要使用的Ticket
+	 */
+	public void setApp_jsapi(String app_jsapi) {
+		this.app_jsapi = app_jsapi;
+	}
+
+	/****
+	 * 是否启用
+	 */
+	public String getApp_status() {
+		return this.app_status;
+	}
+
+	/****
+	 * 是否启用
+	 */
+	public void setApp_status(String app_status) {
+		this.app_status = app_status;
+	}
+
+	/****
+	 * 是否记录用户日志
+	 */
+	public String getRecord_user_log() {
+		return this.record_user_log;
+	}
+
+	/****
+	 * 是否记录用户日志
+	 */
+	public void setRecord_user_log(String record_user_log) {
+		this.record_user_log = record_user_log;
+	}
+
+	/****
+	 * 原始微信号
+	 */
+	public String getWx_code() {
+		return this.wx_code;
+	}
+
+	/****
+	 * 原始微信号
+	 */
+	public void setWx_code(String wx_code) {
+		this.wx_code = wx_code;
+	}
+
+	/****
+	 * 哪个系统使用,空为所有系哦他能够
+	 */
+	public String getApp_name() {
+		return this.app_name;
+	}
+
+	/****
+	 * 哪个系统使用,空为所有系哦他能够
+	 */
+	public void setApp_name(String app_name) {
+		this.app_name = app_name;
+	}
+
+	/****
+	 * 微信公众号主体
+	 */
+	public String getWx_name() {
+		return this.wx_name;
+	}
+
+	/****
+	 * 微信公众号主体
+	 */
+	public void setWx_name(String wx_name) {
+		this.wx_name = wx_name;
+	}
+
+	/****
+	 * 微信类型
+	 */
+	public String getWx_type() {
+		return this.wx_type;
+	}
+
+	/****
+	 * 微信类型
+	 */
+	public void setWx_type(String wx_type) {
+		this.wx_type = wx_type;
+	}
+
+	/****
+	 * 创建时间
+	 */
+	public LocalDateTime getApp_create_time() {
+		return this.app_create_time;
+	}
+
+	/****
+	 * 创建时间
+	 */
+	public void setApp_create_time(LocalDateTime app_create_time) {
+		this.app_create_time = app_create_time;
+	}
+
+	/****
+	 * 更新时间
+	 */
+	public LocalDateTime getApp_update_time() {
+		return this.app_update_time;
+	}
+
+	/****
+	 * 更新时间
+	 */
+	public void setApp_update_time(LocalDateTime app_update_time) {
+		this.app_update_time = app_update_time;
+	}
+
+	/****
+	 * 请求token时间
+	 */
+	public LocalDateTime getApp_token_time() {
+		return this.app_token_time;
+	}
+
+	/****
+	 * 请求token时间
+	 */
+	public void setApp_token_time(LocalDateTime app_token_time) {
+		this.app_token_time = app_token_time;
+	}
+
+}

+ 101 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDeploy.java

@@ -0,0 +1,101 @@
+package cn.hmsoft.hmplatform.wxtoken.data.model;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import cn.hmsoft.jdbc.entity.Table;
+
+/**********************************************
+* 微信公众号部署地址
+* @author: zxq
+* @date: 2020-05-02 17:39:12
+* @version: 2.0.0
+* @email: revisit@126.com
+* @Company: www.hmsoft.cn
+*/
+@Table(tableName = "P_WX_DEPLOY", keyColumn =  "DEPLOY_ID" , sequenceName = "DEPLOY_ID")
+public class PWxDeploy implements Serializable{
+	private static final long serialVersionUID = 1736965632538061498L;
+	private Integer deploy_id;
+	private Integer token_id;
+	//互联网访问地址
+	private String internet_addr;
+	//部署地址,唯一
+	private String deploy_addr;
+	//最后请求时间
+	private LocalDateTime request_time;
+	//最后成功通知时间
+	private LocalDateTime notice_time;
+
+	public Integer getDeploy_id() {
+		return this.deploy_id;
+	}
+
+	public void setDeploy_id(Integer deploy_id) {
+		this.deploy_id = deploy_id;
+	}
+
+	public Integer getToken_id() {
+		return this.token_id;
+	}
+
+	public void setToken_id(Integer token_id) {
+		this.token_id = token_id;
+	}
+
+	/****
+	 * 互联网访问地址
+	 */
+	public String getInternet_addr() {
+		return this.internet_addr;
+	}
+
+	/****
+	 * 互联网访问地址
+	 */
+	public void setInternet_addr(String internet_addr) {
+		this.internet_addr = internet_addr;
+	}
+
+	/****
+	 * 部署地址,唯一
+	 */
+	public String getDeploy_addr() {
+		return this.deploy_addr;
+	}
+
+	/****
+	 * 部署地址,唯一
+	 */
+	public void setDeploy_addr(String deploy_addr) {
+		this.deploy_addr = deploy_addr;
+	}
+
+	/****
+	 * 最后请求时间
+	 */
+	public LocalDateTime getRequest_time() {
+		return this.request_time;
+	}
+
+	/****
+	 * 最后请求时间
+	 */
+	public void setRequest_time(LocalDateTime request_time) {
+		this.request_time = request_time;
+	}
+
+	/****
+	 * 最后成功通知时间
+	 */
+	public LocalDateTime getNotice_time() {
+		return this.notice_time;
+	}
+
+	/****
+	 * 最后成功通知时间
+	 */
+	public void setNotice_time(LocalDateTime notice_time) {
+		this.notice_time = notice_time;
+	}
+}

+ 150 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxDeployLog.java

@@ -0,0 +1,150 @@
+package cn.hmsoft.hmplatform.wxtoken.data.model;
+
+import java.io.Serializable;
+import cn.hmsoft.jdbc.entity.Table;
+import java.time.LocalDateTime;
+
+/**********************************************
+* 请求记录
+* @author: zxq
+* @date: 2020-05-02 17:40:03
+* @version: 2.0.0
+* @email: revisit@126.com
+* @Company: www.hmsoft.cn
+*/
+@Table(tableName = "P_WX_DEPLOY_LOG", keyColumn =  "LOG_ID" , sequenceName = "LOG_ID")
+public class PWxDeployLog implements Serializable{
+	private static final long serialVersionUID = 3081305330286871401L;
+	private Integer log_id;
+	private Integer token_id;
+	//请求时间
+	private LocalDateTime request_time;
+	//请求地址
+	private String request_addr;
+	//互联网访问地址
+	private String internet_addr;
+	//部署地址,唯一
+	private String deploy_addr;
+	//App默认Token
+	private String app_accesstokenkey;
+	//app实时的access_token
+	private String app_accesstoken;
+	//token超时时间
+	private LocalDateTime app_token_expired;
+
+	public Integer getLog_id() {
+		return this.log_id;
+	}
+
+	public void setLog_id(Integer log_id) {
+		this.log_id = log_id;
+	}
+
+	public Integer getToken_id() {
+		return this.token_id;
+	}
+
+	public void setToken_id(Integer token_id) {
+		this.token_id = token_id;
+	}
+
+	/****
+	 * 请求时间
+	 */
+	public LocalDateTime getRequest_time() {
+		return this.request_time;
+	}
+
+	/****
+	 * 请求时间
+	 */
+	public void setRequest_time(LocalDateTime request_time) {
+		this.request_time = request_time;
+	}
+
+	/****
+	 * 请求地址
+	 */
+	public String getRequest_addr() {
+		return this.request_addr;
+	}
+
+	/****
+	 * 请求地址
+	 */
+	public void setRequest_addr(String request_addr) {
+		this.request_addr = request_addr;
+	}
+
+	/****
+	 * 互联网访问地址
+	 */
+	public String getInternet_addr() {
+		return this.internet_addr;
+	}
+
+	/****
+	 * 互联网访问地址
+	 */
+	public void setInternet_addr(String internet_addr) {
+		this.internet_addr = internet_addr;
+	}
+
+	/****
+	 * 部署地址,唯一
+	 */
+	public String getDeploy_addr() {
+		return this.deploy_addr;
+	}
+
+	/****
+	 * 部署地址,唯一
+	 */
+	public void setDeploy_addr(String deploy_addr) {
+		this.deploy_addr = deploy_addr;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public String getApp_accesstokenkey() {
+		return this.app_accesstokenkey;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public void setApp_accesstokenkey(String app_accesstokenkey) {
+		this.app_accesstokenkey = app_accesstokenkey;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public String getApp_accesstoken() {
+		return this.app_accesstoken;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public void setApp_accesstoken(String app_accesstoken) {
+		this.app_accesstoken = app_accesstoken;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public LocalDateTime getApp_token_expired() {
+		return this.app_token_expired;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public void setApp_token_expired(LocalDateTime app_token_expired) {
+		this.app_token_expired = app_token_expired;
+	}
+
+
+}

+ 133 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxTokenNotice.java

@@ -0,0 +1,133 @@
+package cn.hmsoft.hmplatform.wxtoken.data.model;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+import cn.hmsoft.jdbc.entity.Table;
+
+/**********************************************
+* 回传token信息
+* @author: zxq
+* @date: 2020-05-02 17:42:02
+* @version: 2.0.0
+* @email: revisit@126.com
+* @Company: www.hmsoft.cn
+*/
+@Table(tableName = "P_WX_TOKEN_NOTICE", keyColumn =  "LOG_ID" , sequenceName = "LOG_ID")
+public class PWxTokenNotice implements Serializable{
+	private static final long serialVersionUID = -8579037364189622935L;
+	private Integer log_id;
+	private Integer token_id;
+	//通知token时间
+	private LocalDateTime notice_time;
+	//通知token地址
+	private String notice_addr;
+	//是否成功
+	private String notice_status;
+	//App默认Token
+	private String app_accesstokenkey;
+	//app实时的access_token
+	private String app_accesstoken;
+	//token超时时间
+	private LocalDateTime app_token_expired;
+
+	public Integer getLog_id() {
+		return this.log_id;
+	}
+
+	public void setLog_id(Integer log_id) {
+		this.log_id = log_id;
+	}
+
+	public Integer getToken_id() {
+		return this.token_id;
+	}
+
+	public void setToken_id(Integer token_id) {
+		this.token_id = token_id;
+	}
+
+	/****
+	 * 通知token时间
+	 */
+	public LocalDateTime getNotice_time() {
+		return this.notice_time;
+	}
+
+	/****
+	 * 通知token时间
+	 */
+	public void setNotice_time(LocalDateTime notice_time) {
+		this.notice_time = notice_time;
+	}
+
+	/****
+	 * 通知token地址
+	 */
+	public String getNotice_addr() {
+		return this.notice_addr;
+	}
+
+	/****
+	 * 通知token地址
+	 */
+	public void setNotice_addr(String notice_addr) {
+		this.notice_addr = notice_addr;
+	}
+
+	/****
+	 * 是否成功
+	 */
+	public String getNotice_status() {
+		return this.notice_status;
+	}
+
+	/****
+	 * 是否成功
+	 */
+	public void setNotice_status(String notice_status) {
+		this.notice_status = notice_status;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public String getApp_accesstokenkey() {
+		return this.app_accesstokenkey;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public void setApp_accesstokenkey(String app_accesstokenkey) {
+		this.app_accesstokenkey = app_accesstokenkey;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public String getApp_accesstoken() {
+		return this.app_accesstoken;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public void setApp_accesstoken(String app_accesstoken) {
+		this.app_accesstoken = app_accesstoken;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public LocalDateTime getApp_token_expired() {
+		return this.app_token_expired;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public void setApp_token_expired(LocalDateTime app_token_expired) {
+		this.app_token_expired = app_token_expired;
+	}
+
+}

+ 172 - 0
src/cn/hmsoft/hmplatform/wxtoken/data/model/PWxTokenRequest.java

@@ -0,0 +1,172 @@
+package cn.hmsoft.hmplatform.wxtoken.data.model;
+
+import java.io.Serializable;
+import cn.hmsoft.jdbc.entity.Table;
+import java.time.LocalDateTime;
+
+/**********************************************
+ * TOKEN获取日志
+ * 
+ * @author: zxq
+ * @date: 2020-05-02 17:43:55
+ * @version: 2.0.0
+ * @email: revisit@126.com
+ * @Company: www.hmsoft.cn
+ */
+@Table(tableName = "P_WX_TOKEN_REQUEST", keyColumn = "LOG_ID", sequenceName = "LOG_ID")
+public class PWxTokenRequest implements Serializable {
+	private static final long serialVersionUID = -408548612825290243L;
+	private Integer log_id;
+	// 微信内部编号
+	private Integer token_id;
+	// App默认Token
+	private String app_accesstokenkey;
+	// app实时的access_token
+	private String app_accesstoken;
+	// token超时时间
+	private LocalDateTime app_token_expired;
+	// JSAPI需要使用的Ticket
+	private String app_jsapi;
+	// 请求时间
+	private LocalDateTime request_time;
+	// 返回时间
+	private LocalDateTime response_time;
+	// 返回代码
+	private String error_code;
+	// 错误提示
+	private String error_msg;
+
+	public Integer getLog_id() {
+		return this.log_id;
+	}
+
+	public void setLog_id(Integer log_id) {
+		this.log_id = log_id;
+	}
+
+	/****
+	 * 微信内部编号
+	 */
+	public Integer getToken_id() {
+		return this.token_id;
+	}
+
+	/****
+	 * 微信内部编号
+	 */
+	public void setToken_id(Integer token_id) {
+		this.token_id = token_id;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public String getApp_accesstokenkey() {
+		return this.app_accesstokenkey;
+	}
+
+	/****
+	 * App默认Token
+	 */
+	public void setApp_accesstokenkey(String app_accesstokenkey) {
+		this.app_accesstokenkey = app_accesstokenkey;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public String getApp_accesstoken() {
+		return this.app_accesstoken;
+	}
+
+	/****
+	 * app实时的access_token
+	 */
+	public void setApp_accesstoken(String app_accesstoken) {
+		this.app_accesstoken = app_accesstoken;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public LocalDateTime getApp_token_expired() {
+		return this.app_token_expired;
+	}
+
+	/****
+	 * token超时时间
+	 */
+	public void setApp_token_expired(LocalDateTime app_token_expired) {
+		this.app_token_expired = app_token_expired;
+	}
+
+	/****
+	 * JSAPI需要使用的Ticket
+	 */
+	public String getApp_jsapi() {
+		return this.app_jsapi;
+	}
+
+	/****
+	 * JSAPI需要使用的Ticket
+	 */
+	public void setApp_jsapi(String app_jsapi) {
+		this.app_jsapi = app_jsapi;
+	}
+
+	/****
+	 * 请求时间
+	 */
+	public LocalDateTime getRequest_time() {
+		return this.request_time;
+	}
+
+	/****
+	 * 请求时间
+	 */
+	public void setRequest_time(LocalDateTime request_time) {
+		this.request_time = request_time;
+	}
+
+	/****
+	 * 返回时间
+	 */
+	public LocalDateTime getResponse_time() {
+		return this.response_time;
+	}
+
+	/****
+	 * 返回时间
+	 */
+	public void setResponse_time(LocalDateTime response_time) {
+		this.response_time = response_time;
+	}
+
+	/****
+	 * 返回代码
+	 */
+	public String getError_code() {
+		return this.error_code;
+	}
+
+	/****
+	 * 返回代码
+	 */
+	public void setError_code(String error_code) {
+		this.error_code = error_code;
+	}
+
+	/****
+	 * 错误提示
+	 */
+	public String getError_msg() {
+		return this.error_msg;
+	}
+
+	/****
+	 * 错误提示
+	 */
+	public void setError_msg(String error_msg) {
+		this.error_msg = error_msg;
+	}
+}

+ 45 - 0
src/cn/hmsoft/hmplatform/wxtoken/service/PlatformTokenDefineService.java

@@ -0,0 +1,45 @@
+package cn.hmsoft.hmplatform.wxtoken.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.frame.util.FrameAssertUtil;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeploy;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeployLog;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenNotice;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenRequest;
+
+@Service
+public class PlatformTokenDefineService {
+	@Autowired
+	private PWxDefineDao daoDefine;
+
+	public void checkValues(PWxDefine define) {
+		FrameAssertUtil.isNotEmpty(define.getApp_id(), "app_id不允许为空");
+		FrameAssertUtil.isNotEmpty(define.getApp_status(), "公众号状态不允许为空");
+
+	}
+
+	public void addDefine(PWxDefine define) {
+		this.checkValues(define);
+		this.daoDefine.insert(define);
+	}
+
+	public void editDefine(PWxDefine define) {
+		this.checkValues(define);
+		PWxDefine tr2 = this.daoDefine.find("app_id", define.getApp_id());
+		FrameAssertUtil.isNotNull(tr2, "该app_id" + tr2.getApp_id() + "已经存在,请检查");
+		this.daoDefine.update(define);
+	}
+
+	public void deleteDefine(int token_id) {
+		this.daoDefine.delete(PWxDefine.class, token_id);
+		this.daoDefine.delete(PWxDeploy.class, "token_id", token_id);
+		this.daoDefine.delete(PWxDeployLog.class, "token_id", token_id);
+		this.daoDefine.delete(PWxTokenRequest.class, "token_id", token_id);
+		this.daoDefine.delete(PWxTokenNotice.class, "token_id", token_id);
+	}
+
+}

+ 107 - 0
src/cn/hmsoft/hmplatform/wxtoken/service/PlatformWeixinTokenService.java

@@ -0,0 +1,107 @@
+package cn.hmsoft.hmplatform.wxtoken.service;
+
+import java.time.LocalDateTime;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.frame.constants.FrameStatus;
+import cn.hmsoft.helper.BeanHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDeployDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeploy;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeployLog;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenNotice;
+import cn.hmsoft.hmplatform.wxtoken.util.WeixinTokenModuleUtil;
+import cn.hmsoft.log.LogHelper;
+
+@Service
+public class PlatformWeixinTokenService {
+
+	@Autowired
+	private PWxDefineDao daoDefine;
+	@Autowired
+	private PWxDeployDao daoDeploy;
+
+	public void fetchToken(PWxDefine w, String internet_addr, String deploy_addr, String request_addr) {
+		PWxDefine wx = this.daoDefine.findWxDefine(w.getApp_id());
+		
+		WeixinTokenModuleUtil util = WeixinTokenModuleUtil.instance(false);
+		if (wx == null) {
+			// 如果是新的,自动添加
+			wx = BeanHelper.copy(PWxDefine.class, w);
+			wx.setApp_accesstoken(null);
+			wx.setApp_jsapi(null);
+			wx.setApp_token_expired(null);
+			wx.setApp_create_time(LocalDateTime.now());
+			this.daoDefine.insert(wx);
+		} else {
+			wx.setApp_secrect(w.getApp_secrect());
+			wx.setWx_name(w.getWx_name());
+			wx.setApp_name(w.getWx_name());
+			wx.setApp_update_time(LocalDateTime.now());
+			this.daoDefine.update(wx);
+		}
+		PWxDeploy deploy = this.daoDeploy.findDeploy(wx.getToken_id(), internet_addr, deploy_addr);
+		if (deploy == null) {
+			deploy = new PWxDeploy();
+			deploy.setDeploy_addr(deploy_addr);
+			deploy.setInternet_addr(internet_addr);
+			deploy.setToken_id(wx.getToken_id());
+			deploy.setRequest_time(LocalDateTime.now());
+			this.daoDefine.insert(deploy);
+		} else {
+			deploy.setRequest_time(LocalDateTime.now());
+			this.daoDefine.update(deploy);
+		}
+
+		PWxDeployLog log = new PWxDeployLog();
+		log.setApp_accesstoken(wx.getApp_accesstoken());
+		log.setApp_accesstokenkey(wx.getApp_accesstokenkey());
+		log.setApp_token_expired(wx.getApp_token_expired());
+		log.setDeploy_addr(deploy.getDeploy_addr());
+		log.setInternet_addr(deploy.getInternet_addr());
+		log.setRequest_addr(request_addr);
+		log.setRequest_time(LocalDateTime.now());
+		log.setToken_id(wx.getToken_id());
+		this.daoDefine.insert(log);
+		// 加入到线程中
+		final PWxDefine ww = BeanHelper.copy(PWxDefine.class, wx);
+		new Thread(() -> {
+			// 等待写入服务器
+			try {
+				Thread.sleep(500);
+			}catch(Exception e) {
+				
+			}
+			util.addWxDefine(ww);
+		}).start();
+
+	}
+
+	/********************************
+	 * 通知记录
+	 * 
+	 * @param deploy
+	 * @param ajax
+	 */
+	public void logTokenNotice(PWxDefine wx, PWxDeploy deploy, Ajax ajax) {
+		PWxTokenNotice notice = new PWxTokenNotice();
+		notice.setApp_accesstoken(wx.getApp_accesstoken());
+		notice.setApp_accesstokenkey(wx.getApp_accesstokenkey());
+		notice.setApp_token_expired(wx.getApp_token_expired());
+		notice.setNotice_addr(deploy.getInternet_addr());
+		notice.setNotice_status((ajax != null && ajax.isSuccess()) ? FrameStatus.Active.toString() : FrameStatus.InActive.toString());
+		notice.setToken_id(wx.getToken_id());
+		notice.setNotice_time(LocalDateTime.now());
+		try {
+			this.daoDefine.insert(notice);
+			this.daoDeploy.noticeDeploy(wx.getToken_id(), deploy.getInternet_addr());
+		} catch (Exception e) {
+			LogHelper.error(e);
+
+		}
+	}
+}

+ 42 - 0
src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleConfig.java

@@ -0,0 +1,42 @@
+package cn.hmsoft.hmplatform.wxtoken.util;
+
+import cn.hmsoft.frame.module.FrameModuleConfig;
+import cn.hmsoft.helper.BeanHelper;
+
+public class WeixinTokenModuleConfig extends FrameModuleConfig {
+
+
+	@Override
+	public String setModule_name() {
+		return WeixinTokenModuleParamUtil.ModuleName;
+	}
+
+	@Override
+	public String setModule_version() {
+		return WeixinTokenModuleParamUtil.ModuleVersion;
+	}
+
+	@Override
+	public boolean restart() throws Exception {
+		this.stop();
+		Thread.sleep(5000);
+		return this.start();
+	}
+
+	@Override
+	protected boolean start() throws Exception {
+		// 设置参数
+		BeanHelper.setStaticFields(WeixinTokenModuleParamUtil.class, this.module.getParamMap());
+		// 启动线程
+		WeixinTokenModuleUtil.instance(true);
+		return true;
+
+	}
+
+	@Override
+	protected boolean stop() throws Exception {
+
+		return true;
+	}
+
+}

+ 9 - 0
src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleParamUtil.java

@@ -0,0 +1,9 @@
+package cn.hmsoft.hmplatform.wxtoken.util;
+
+public class WeixinTokenModuleParamUtil {
+
+	public static String ModuleName = "WeixinTokenCenter";
+	public static String ModuleVersion = "1.0.0-20201021";
+	
+	public static String FetchWeixinTokenPass = "hm2020";
+}

+ 58 - 0
src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenModuleUtil.java

@@ -0,0 +1,58 @@
+package cn.hmsoft.hmplatform.wxtoken.util;
+
+import java.util.HashMap;
+
+import cn.hmsoft.application.SpringHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+
+/**********************
+ * token
+ *
+ */
+public class WeixinTokenModuleUtil {
+
+	private static WeixinTokenModuleUtil util = null;
+	private static HashMap<String, PWxDefine> WxDefineMap = null;
+	private static HashMap<String, WeixinTokenRequestThread> TokenThreadMap = null;
+
+	private WeixinTokenModuleUtil() {
+
+	}
+
+	public static WeixinTokenModuleUtil instance(boolean refresh) {
+		if (util == null || refresh) {
+			synchronized (WeixinTokenModuleUtil.class) {
+				WxDefineMap = new HashMap<String, PWxDefine>();
+				TokenThreadMap = new HashMap<String, WeixinTokenRequestThread>();
+				for (PWxDefine p : SpringHelper.AppGobalDao.all(PWxDefine.class)) {
+					WxDefineMap.put(p.getApp_id(), p);
+					WeixinTokenRequestThread thread = new WeixinTokenRequestThread(p);
+					thread.start();
+					TokenThreadMap.put(p.getApp_id(), thread);
+				}
+				util = new WeixinTokenModuleUtil();
+			}
+		}
+		return util;
+	}
+
+	public void addWxDefine(PWxDefine p) {
+		if (!WxDefineMap.containsKey(p.getApp_id())) {
+			WxDefineMap.put(p.getApp_id(), p);
+			WeixinTokenRequestThread thread = new WeixinTokenRequestThread(p);
+			thread.start();
+			TokenThreadMap.put(p.getApp_id(), thread);
+
+		}
+	}
+
+	public PWxDefine getWxDefine(String app_id) {
+		try {
+			return TokenThreadMap.get(app_id).getWxDefine();
+		} catch (Exception e) {
+
+		}
+		return null;
+	}
+
+}

+ 75 - 0
src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenNoticeThread.java

@@ -0,0 +1,75 @@
+package cn.hmsoft.hmplatform.wxtoken.util;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cn.hmsoft.application.SpringHelper;
+import cn.hmsoft.application.web.Ajax;
+import cn.hmsoft.helper.LocalDateHelper;
+import cn.hmsoft.helper.SecureHelper;
+import cn.hmsoft.helper.http.HttpHelper;
+import cn.hmsoft.helper.http.HttpRequestEntity;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDeployDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDeploy;
+import cn.hmsoft.hmplatform.wxtoken.service.PlatformWeixinTokenService;
+import cn.hmsoft.weixin.util.WeiXinParamUtil;
+
+/*************************
+ * 获取线程token
+ *
+ */
+public class WeixinTokenNoticeThread extends Thread {
+
+	private List<PWxDeploy> targetArray = null;
+	private PWxDefine wx;
+	private PWxDeployDao daoDeploy;
+
+	public WeixinTokenNoticeThread(PWxDefine wx) {
+		this.wx = wx;
+		this.daoDeploy = SpringHelper.getBean(PWxDeployDao.class);
+		targetArray = this.daoDeploy.listInternetAddr(this.wx.getToken_id());
+	}
+
+	@Override
+	public void run() {
+		for (PWxDeploy r : targetArray) {
+			final PWxDeploy deploy = new PWxDeploy();
+			deploy.setToken_id(this.wx.getToken_id());
+			deploy.setInternet_addr(r.getInternet_addr());
+			new Thread(() -> {
+				HttpRequestEntity entity = new HttpRequestEntity();
+				entity.setHttp_url(deploy.getInternet_addr() + (deploy.getInternet_addr().endsWith("/") ? "" : "/")
+						+ "weixin/token/notice.htm");
+				Map<String, Object> map = new HashMap<String,Object>();
+				map.put("request_key", SecureHelper.md5(WeixinTokenModuleParamUtil.FetchWeixinTokenPass));
+				map.put("app_id", wx.getApp_id());
+				map.put("app_accesstoken", wx.getApp_accesstoken());
+				map.put("app_jsapi", wx.getApp_jsapi());
+				map.put("app_token_expired", LocalDateHelper.format(wx.getApp_token_expired()));
+				entity.setRequestMap(map);
+				entity.setRead_timeout(WeiXinParamUtil.HttpConnectTimeoutSeconds * 1000);
+				entity.setConnect_timeout(WeiXinParamUtil.HttpConnectTimeoutSeconds * 1000);
+				Ajax ajax = null;
+				int total = 0;
+				do {
+					try {
+						ajax = HttpHelper.jsonRequest(entity, Ajax.class);
+					} catch (Exception e) {
+						e.printStackTrace();
+						try {
+							Thread.sleep(3000);
+						} catch (Exception ex) {
+						}
+					}
+					total++;
+				} while (total < 10 && ajax == null);
+				SpringHelper.getBean(PlatformWeixinTokenService.class).logTokenNotice(this.wx, deploy, ajax);
+
+			}).start();
+
+		}
+	}
+
+}

+ 196 - 0
src/cn/hmsoft/hmplatform/wxtoken/util/WeixinTokenRequestThread.java

@@ -0,0 +1,196 @@
+package cn.hmsoft.hmplatform.wxtoken.util;
+
+import java.time.LocalDateTime;
+
+import cn.hmsoft.application.SpringHelper;
+import cn.hmsoft.helper.BeanHelper;
+import cn.hmsoft.helper.LocalDateHelper;
+import cn.hmsoft.helper.LocalDateHelper.LocalDateCompareType;
+import cn.hmsoft.helper.StringHelper;
+import cn.hmsoft.hmplatform.wxtoken.data.dao.PWxDefineDao;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxDefine;
+import cn.hmsoft.hmplatform.wxtoken.data.model.PWxTokenRequest;
+import cn.hmsoft.log.LogHelper;
+import cn.hmsoft.weixin.data.model.WxDefine;
+import cn.hmsoft.weixin.entity.response.TicketResponseJson;
+import cn.hmsoft.weixin.entity.response.TokenResponseJson;
+import cn.hmsoft.weixin.request.TicketGetRequest;
+import cn.hmsoft.weixin.request.TokenRequest;
+import cn.hmsoft.weixin.util.WeiXinParamUtil;
+
+/*************************
+ * 获取线程token
+ *
+ */
+public class WeixinTokenRequestThread extends Thread {
+
+	private PWxDefine wx;
+	private PWxDefineDao daoDefine;
+	private boolean requesting = false;
+	private LocalDateTime requestTime = null;
+
+	public WeixinTokenRequestThread(PWxDefine wx) {
+		this.wx = wx;
+		this.daoDefine = SpringHelper.getBean(PWxDefineDao.class);
+	}
+
+	@Override
+	public void run() {
+		while (true) {
+			this.checkToken();
+		}
+	}
+
+	/*********************************
+	 * 获取token
+	 */
+	private void checkToken() {
+
+		if (this.wx.getApp_token_expired() != null && this.wx.getApp_token_expired().isAfter(LocalDateTime.now())) {
+			try {
+				Thread.sleep(LocalDateHelper.calTimeDiff(wx.getApp_token_expired(), LocalDateTime.now(),
+						LocalDateCompareType.Millis));
+			} catch (Exception e) {
+
+			}
+		}
+		try {
+			// 重新获取密钥,防止在这之间更改过密钥
+			PWxDefine p = this.daoDefine.findWxDefine(this.wx.getApp_id());
+			if (p != null)
+				this.wx.setApp_secrect(p.getApp_secrect());
+			fetchToken();
+		} catch (Exception e) {
+			LogHelper.error(e);
+		}
+		if (this.wx.getApp_token_expired() == null || this.wx.getApp_token_expired().isBefore(LocalDateTime.now())) {
+			// 获取失败
+			try {
+				Thread.sleep(WeiXinParamUtil.TokenWaitSeconds * 3 * 1000);
+			} catch (Exception e) {
+
+			}
+		}
+	}
+
+	private void fetchToken() {
+		requesting = true;
+		TokenRequest rq = new TokenRequest();
+		WxDefine token = BeanHelper.copy(WxDefine.class, this.wx);
+		rq.setWxDefine(token);
+		TokenResponseJson response = null;
+		int requestTotal = 0;
+		requestTime = LocalDateTime.now();
+		String msg = "";
+		do {
+			try {
+				response = rq.request();
+			} catch (Exception e) {
+				msg = msg + "\n" + (requestTotal + 1) + ":" + e.getMessage();
+				response = null;
+			}
+			if (response != null) {
+				break;
+			}
+			// 没有返回,网络错误,重试
+			try {
+				Thread.sleep(WeiXinParamUtil.TokenIntervalSeconds * 1000);
+			} catch (Exception e) {
+			}
+			requestTotal++;
+		} while (response == null && requestTotal < WeiXinParamUtil.TokenRetryTimes);
+
+		this.recoredRequestToken(response);
+		if (response == null) {
+			LogHelper.error(
+					"------ Token获取失败,[" + this.wx.getWx_name() + "][" + this.wx.getApp_id() + "]-" + msg + "-----");
+			requesting = false;
+			return;
+		} else {
+			if (StringHelper.isNotEmpty(response.getAccess_token())) {
+				LogHelper.info("------ [" + this.wx.getWx_name() + "] Token获取成功------");
+			} else {
+				LogHelper.error("------ Token获取失败,[" + this.wx.getWx_name() + "][" + this.wx.getApp_id() + "],["
+						+ response.getErrmsg() + "]------");
+				requesting = false;
+				return;
+			}
+		}
+
+		// 取ticket
+		TicketGetRequest ticketRequest = new TicketGetRequest();
+		ticketRequest.setWxDefine(token);
+		TicketResponseJson ticketResponse = null;
+		requestTotal = 0;
+		do {
+			try {
+				ticketResponse = ticketRequest.request();
+			} catch (Exception e) {
+				ticketResponse = null;
+			}
+			if (ticketResponse != null && StringHelper.isNotEmpty(ticketResponse.getTicket())) {
+				break;
+			}
+			try {
+				Thread.sleep(WeiXinParamUtil.TokenIntervalSeconds * 1000);
+			} catch (Exception e) {
+
+			}
+			ticketResponse = null;
+			requestTotal++;
+		} while (ticketResponse == null && requestTotal < WeiXinParamUtil.TokenRetryTimes);
+		if (ticketResponse == null) {
+			LogHelper.error("------ jsapi获取失败,[" + this.wx.getApp_id() + "]------");
+			requesting = false;
+			// return;
+		}
+
+		try {
+			// 写入数据库
+			this.daoDefine.updateBySql(
+					"update p_wx_define set app_accesstoken=?,app_token_expired=?,app_jsapi=?,app_token_time=? where app_id=?",
+					token.getApp_accesstoken(), token.getApp_token_expired(), token.getApp_jsapi(), LocalDateTime.now(),
+					token.getApp_id());
+			this.wx.setApp_accesstoken(token.getApp_accesstoken());
+			this.wx.setApp_token_expired(token.getApp_token_expired());
+			this.wx.setApp_jsapi(token.getApp_jsapi());
+		} catch (Exception e) {
+			LogHelper.error(e);
+		}
+
+		this.requesting = false;
+		// 推送线程
+		new Thread(new WeixinTokenNoticeThread(wx)).start();
+	}
+
+	private void recoredRequestToken(TokenResponseJson response) {
+		// 记录日志
+
+		PWxTokenRequest log = new PWxTokenRequest();
+		log.setToken_id(this.wx.getToken_id());
+		log.setApp_accesstoken(this.wx.getApp_accesstoken());
+		log.setApp_accesstokenkey(this.wx.getApp_accesstokenkey());
+		log.setApp_jsapi(this.wx.getApp_jsapi());
+		log.setApp_token_expired(this.wx.getApp_token_expired());
+		log.setRequest_time(requestTime);
+		log.setResponse_time(LocalDateTime.now());
+		log.setError_code(response == null ? "-1" : (response.getErrcode() + ""));
+		log.setError_msg(response == null ? "无法访问微信服务器" : response.getErrmsg());
+		try {
+			this.daoDefine.insert(log);
+		} catch (Exception e) {
+			LogHelper.error(e);
+		}
+	}
+
+	public PWxDefine getWxDefine() {
+		while (this.requesting == true) {
+			try {
+				Thread.sleep(1000);
+			} catch (Exception e) {
+
+			}
+		}
+		return this.wx;
+	}
+}

+ 8 - 0
src/jdbc.properties

@@ -0,0 +1,8 @@
+JdbcDriverClass=com.mysql.cj.jdbc.Driver
+JdbcUrl=jdbc:mysql://127.0.0.1:3306/hmplatform?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true 
+#JdbcUrl=jdbc:mysql://39.105.12.211:3306/art2020?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&characterSetResults=utf8&useSSL=false&verifyServerCertificate=false&autoReconnct=true&autoReconnectForPools=true&allowMultiQueries=true 
+JdbcUser=root
+JdbcPassword=123456
+#JdbcPassword=hm@123456
+JdbcCheckouttimeout=30000
+JdbcMaxpoolsize=200