Browse Source

feat(app): 新增 e签宝 相关功能

- 添加 AESUtils 类实现 AES 加密解密功能
- 新增 AuthDemo 类实现个人和企业认证授权功能- 添加 EsignCoreSdkInfo 类提供 SDK 信息
- 新增 EsignDemoConfig 类配置 e签宝 相关参数
- 实现 EsignDemoException 自定义异常类
- 新增 EsignEncryption 类处理请求数据通用方法
SheepHy 1 week ago
parent
commit
dba58bd0fb
29 changed files with 3799 additions and 7 deletions
  1. 18 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java
  2. 161 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/auth/AuthDemo.java
  3. 99 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/AESUtils.java
  4. 24 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignCoreSdkInfo.java
  5. 372 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignEncryption.java
  6. 56 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignFileBean.java
  7. 483 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpCfgHelper.java
  8. 171 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpHelper.java
  9. 27 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpResponse.java
  10. 284 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/FileTransformation.java
  11. 13 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/constant/EsignDemoConfig.java
  12. 26 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/enums/EsignHeaderConstant.java
  13. 39 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/enums/EsignRequestType.java
  14. 107 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/ep/epDemo.java
  15. 36 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/exception/EsignDemoException.java
  16. 117 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/fileAndTemplate/FileDemo.java
  17. 160 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/fileAndTemplate/TemplateDemo.java
  18. 144 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/members/MembersDemo.java
  19. 182 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/scenedemo/PlatformSignToB.java
  20. 176 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/scenedemo/PlatformSignToC.java
  21. 314 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/seal/SealDemo.java
  22. 724 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/sign/SignDemo.java
  23. 10 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java
  24. 1 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/AppHomeServiceImpl.java
  25. 7 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java
  26. 14 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/OrderVO.java
  27. 12 5
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppTeachingTimeMapper.java
  28. 1 1
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppCoursesMapper.xml
  29. 21 0
      national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppTeachingTimeMapper.xml

+ 18 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/controller/OrderController.java

@@ -1,5 +1,6 @@
 package org.jeecg.modules.app.controller;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Schema;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -7,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.jeecg.common.api.vo.Result;
 import org.jeecg.modules.app.service.IOrderService;
 import org.jeecg.modules.app.vo.OrderVO;
+import org.springframework.format.annotation.DateTimeFormat;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import java.util.Date;
+import java.util.List;
 
 @Slf4j
 @Tag(name = "APP订单相关接口")
@@ -32,6 +35,8 @@ public class OrderController {
     @Operation(summary="学校场地预约-预览页")
     @GetMapping("/previewOrderPlaceSchool")
     public Result<OrderVO.PreviewOrderPlaceSchool> previewOrderPlaceSchool(@RequestParam("placeId") @Schema(description = "场地ID")String placeId,
+                                                                           @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
+                                                                           @DateTimeFormat(pattern = "yyyy-MM-dd")
                                                                            @RequestParam("startTime") @Schema(description = "当前选择日期(年月日)")Date startTime){
         return Result.ok(appOrderService.previewOrderPlaceSchool(placeId,startTime));
     }
@@ -89,4 +94,17 @@ public class OrderController {
                                                                          @RequestParam("userIds") @Schema(description = "使用用户IDS多个逗号拼接")String userIds){
         return Result.ok(appOrderService.createOrderPlaceSchool(rulesId, userIds));
     }
+
+    /**
+     * @Author SheepHy
+     * @Description 学校包场-预览时间选择
+     * @Date 14:45 2025/7/17
+     * @Param placeId
+     * @return OrderVO.PreviewOrderPlaceSchoolTime {@link OrderVO.PreviewOrderPlaceSchoolTime}
+     **/
+    @Operation(summary="学校包场-预览时间选择")
+    @GetMapping("/previewOrderPlaceSchoolTime")
+    public Result<List<OrderVO.PreviewOrderPlaceSchoolTime>> previewOrderPlaceSchoolTime(@RequestParam("placeId") @Schema(description = "当前选择场次ID")String placeId){
+        return Result.ok(appOrderService.previewOrderPlaceSchoolTime(placeId));
+    }
 }

+ 161 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/auth/AuthDemo.java

@@ -0,0 +1,161 @@
+package org.jeecg.modules.app.esign.auth;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+
+/**
+ * description 认证与授权服务
+ * @author 语冰
+ * datetime 2022年8月10日上午09:43:24
+ */
+public class AuthDemo extends Exception {
+
+	private static String eSignHost= EsignDemoConfig.EsignHost;
+	private static String eSignAppId=EsignDemoConfig.EsignAppId;
+	private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+	public static void main(String[] args) throws EsignDemoException {
+		Gson gson = new Gson();
+		/* 获取个人认证授权链接*/
+		EsignHttpResponse getPsnAuthUrl = getPsnAuthUrl();
+		JsonObject getPsnAuthUrlObject = gson.fromJson(getPsnAuthUrl.getBody(), JsonObject.class);
+		JsonObject data = getPsnAuthUrlObject.getAsJsonObject("data");
+		String authUrl = data.get("authUrl").getAsString();
+		System.err.println("个人授权链接:"+authUrl);
+		/* 查询个人认证授权状态*/
+		EsignHttpResponse getPsnIdentityInfo = getPsnIdentityInfo();
+		JsonObject getPsnIdentityInfoObject = gson.fromJson(getPsnIdentityInfo.getBody(), JsonObject.class);
+		String realnameStatus =getPsnIdentityInfoObject.getAsJsonObject("data").get("realnameStatus").getAsString();//授权状态authorizeUserInfo
+		System.err.println("个人认证状态:"+realnameStatus);
+		/* 获取企业认证授权链接*/
+		EsignHttpResponse getOrgAuthUrl = getOrgAuthUrl();
+		JsonObject getOrgAuthUrlObject = gson.fromJson(getOrgAuthUrl.getBody(), JsonObject.class);
+		String orgAuthUrl =	getOrgAuthUrlObject.getAsJsonObject("data").get("authUrl").getAsString();
+		System.err.println("企业授权链接:"+orgAuthUrl);
+		/* 查询企业认证授权状态*/
+		EsignHttpResponse getOrgIdentityInfo = getOrgIdentityInfo();
+		JsonObject getOrgIdentityInfoObject = gson.fromJson(getOrgIdentityInfo.getBody(), JsonObject.class);
+		String orgRealnameStatus =	getOrgIdentityInfoObject.getAsJsonObject("data").get("realnameStatus").getAsString();//授权状态authorizeUserInfo
+		System.err.println("企业认证状态:"+orgRealnameStatus);
+
+	}
+
+	/**
+	 * 获取个人认证链接
+	 * @return
+	 * @throws EsignDemoException
+	 */
+	public static EsignHttpResponse getPsnAuthUrl() throws EsignDemoException {
+		String apiaddr="/v3/psn-auth-url";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\n" +
+				"    \"psnAuthConfig\": {\n" +
+				"        \"psnAccount\": \"184xxxxx04\",\n" +
+				"        \"psnAuthPageConfig\": {\n" +
+				"            \"psnEditableFields\": [\n" +
+				"                \"name\",\n" +
+				"                \"IDCardNum\",\n" +
+				"                \"mobile\",\n" +
+				"                \"bankCardNum\"  \n" +
+				"            ]\n" +
+				"        }\n" +
+				"    },\n" +
+				"    \"clientType\": \"ALL\",\n" +
+				"    \"appScheme\":\"esign://demo/realBack\",\n" +
+				"    \"redirectConfig\": {\n" +
+				"        \"redirectDelayTime\": \"3\",\n" +
+				"        \"redirectUrl\": \"esign://demo/realBack\"\n" +
+				"    },\n" +
+				"    \"authorizeConfig\": {\n" +
+				"        \"authorizedScopes\": [\n" +
+				"            \"get_psn_identity_info\",\n" +
+				"            \"psn_initiate_sign\",\n" +
+				"            \"manage_psn_resource\"\n" +
+				"        ]\n" +
+				"    },\n" +
+				"    \"repeatableAuth\": true\n" +
+				"}";
+
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+
+	/**
+	 * 查询个人认证授权状态
+	 */
+	public static EsignHttpResponse getPsnIdentityInfo() throws EsignDemoException {
+		String psnAccount="184xxxxx04";
+		String apiaddr="/v3/persons/identity-info?psnAccount="+psnAccount;
+
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm=null;
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.GET;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+	/**
+	 * 获取企业认证链接
+	 * @return
+	 * @throws EsignDemoException
+	 *
+	 *
+	 */
+	public static EsignHttpResponse getOrgAuthUrl() throws EsignDemoException {
+		String apiaddr="/v3/org-auth-url";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\n" +
+				"    \"orgAuthConfig\": {\n" +
+				"        \"orgName\": \"语冰test\",\n" +
+				"        \"transactorInfo\": {\n" +
+				"            \"psnAccount\": \"184xxxx2104\"\n" +
+				"        }\n" +
+				"    },\n" +
+				"    \"clientType\": \"all\",\n" +
+				"    \"notifyUrl\":\"https://www.xxx.cn/notify\",\n" +
+				"    \"redirectConfig\": {\n" +
+				"        \"redirectUrl\": \"https://www.esign.cn\"\n" +
+				"    },\n" +
+				"    \"authorizeConfig\":{\n" +
+				"        \"authorizedScopes\":[\"get_org_identity_info\",\"get_psn_identity_info\",\"org_initiate_sign\",\"psn_initiate_sign\",\"manage_org_resource\",\"manage_psn_resource\",\"use_org_order\"]\n" +
+				"    }\n" +
+				"}";
+
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+
+	/**
+	 * 查询企业认证授权状态
+	 */
+	public static EsignHttpResponse getOrgIdentityInfo() throws EsignDemoException {
+		String orgName="语冰test";
+		String apiaddr="/v3/organizations/identity-info?orgName="+orgName;
+
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{}";
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.GET;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+}

+ 99 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/AESUtils.java

@@ -0,0 +1,99 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.jeecg.modules.app.esign.comm;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.spec.GCMParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * AES对称加密工具类
+ *
+ * @author 澄泓
+ * @date 2019年7月18日
+ */
+public class AESUtils {
+
+    private static final String KEY_ALGORITHM = "AES";
+    // AES/GCM加密算法,不用补位
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/GCM/NoPadding";
+
+    /**
+     * AES 加密操作
+     *
+     * @param content   待加密内容
+     * @param AESSecret AES秘钥
+     * @return 返回Base64转码后的加密数据
+     */
+    public static String encrypt(String content, String AESSecret) {
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(AESSecret), KEY_ALGORITHM));
+            byte[] iv = cipher.getIV();
+            assert iv.length == 12;
+            byte[] encryptData = cipher.doFinal(content.getBytes());
+            assert encryptData.length == content.getBytes().length + 16;
+            byte[] message = new byte[12 + content.getBytes().length + 16];
+            System.arraycopy(iv, 0, message, 0, 12);
+            System.arraycopy(encryptData, 0, message, 12, encryptData.length);
+            return Base64.encodeBase64URLSafeString(message);
+        } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException | IllegalBlockSizeException
+                | BadPaddingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * AES 解密操作
+     *
+     * @param base64Content
+     * @param AESSecret     AES秘钥
+     * @return
+     */
+    public static String decrypt(String base64Content, String AESSecret) {
+        byte[] content = Base64.decodeBase64(base64Content);
+        if (content.length < 12 + 16)
+            throw new IllegalArgumentException();
+        GCMParameterSpec params = new GCMParameterSpec(128, content, 0, 12);
+        try {
+            Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
+            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(AESSecret), KEY_ALGORITHM), params);
+            byte[] decryptData = cipher.doFinal(content, 12, content.length - 12);
+            return new String(decryptData);
+        } catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
+                | InvalidAlgorithmParameterException | IllegalBlockSizeException | BadPaddingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static void main(String[] args) {
+        // 待加密的字符串
+        String s = "{\"name\":\"张三\",\"idNo\":\"320333xxxxxxx12522\"}";
+        // 秘钥
+        String pass = "D/RA+2esbSbfSVOQsTGlpg==";
+        // 加密
+        String encoded = encrypt(s, pass);
+        System.out.println("加密之前:" + s);
+        System.out.println("加密结果:" + encoded);
+        System.out.println("解密结果:" + decrypt(encoded, pass));
+    }
+}

+ 24 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignCoreSdkInfo.java

@@ -0,0 +1,24 @@
+package org.jeecg.modules.app.esign.comm;
+/**
+ * esignSDK-core信息类
+ * @author  澄泓
+ * @date  2022/2/22 13:59
+ * @version
+ */
+public class EsignCoreSdkInfo {
+    private static final String SdkVersion="Esign-Sdk-Core1.0";
+    private static final String SupportedVersion="JDK1.7 MORE THAN";
+
+    private static final String Info="sdk-esign-api核心工具包,主要处理e签宝公有云产品接口调用时的签名计算以及网络请求,通过EsignHttpHelper.signAndBuildSignAndJsonHeader构造签名鉴权+json数据格式的请求头,通过HttpHelper.doCommHttp方法入参发起网络请求。让开发者无需关注具体的请求签名算法,专注于接口业务的json参数构造";
+    public static String getSdkVersion() {
+        return SdkVersion;
+    }
+
+    public static String getInfo() {
+        return Info;
+    }
+
+    public static String getSupportedVersion() {
+        return SupportedVersion;
+    }
+}

+ 372 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignEncryption.java

@@ -0,0 +1,372 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.jeecg.modules.app.esign.comm;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.message.BasicNameValuePair;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.UnsupportedEncodingException;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.text.Collator;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * @description 请求数据通用处理类
+ * @author 澄泓
+ * @date 2020年10月22日 下午14:25:31
+ * @since JDK1.7
+ */
+public class EsignEncryption {
+
+    /**
+     * 不允许外部创建实例
+     */
+    private EsignEncryption(){}
+
+    /**
+     * 拼接待签名字符串
+     * @param httpMethod
+     * @param url
+     * @return
+     */
+    public static String appendSignDataString(String httpMethod, String contentMd5,String accept,String contentType,String headers,String date, String url) throws EsignDemoException {
+        StringBuffer sb = new StringBuffer();
+        sb.append(httpMethod).append("\n").append(accept).append("\n").append(contentMd5).append("\n")
+                .append(contentType).append("\n");
+
+        if ("".equals(date) || date == null) {
+            sb.append("\n");
+        } else {
+            sb.append(date).append("\n");
+        }
+        if ("".equals(headers) || headers == null) {
+            sb.append(url);
+        } else {
+            sb.append(headers).append("\n").append(url);
+        }
+        return new String(sb);
+    }
+
+    /***
+     *  Content-MD5的计算方法
+     * @param str 待计算的消息
+     * @return MD5计算后摘要值的Base64编码(ContentMD5)
+     * @throws EsignDemoException 加密过程中的异常信息
+     */
+    public static String doContentMD5(String str) throws EsignDemoException {
+        byte[] md5Bytes = null;
+        MessageDigest md5 = null;
+        String contentMD5 = null;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            // 计算md5函数
+            md5.update(str.getBytes("UTF-8"));
+            // 获取文件MD5的二进制数组(128位)
+            md5Bytes = md5.digest();
+            // 把MD5摘要后的二进制数组md5Bytes使用Base64进行编码(而不是对32位的16进制字符串进行编码)
+            contentMD5 = Base64.encodeBase64String(md5Bytes);
+
+        } catch (NoSuchAlgorithmException e) {
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
+            ex.initCause(e);
+            throw ex;
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return contentMD5;
+    }
+
+    /***
+     * 计算请求签名值-HmacSHA256摘要
+     * @param message 待签名字符串
+     * @param secret  密钥APP KEY
+     * @return reqSignature HmacSHA256计算后摘要值的Base64编码
+     * @throws EsignDemoException 加密过程中的异常信息
+     */
+    public static String doSignatureBase64(String message, String secret) throws EsignDemoException {
+        String algorithm = "HmacSHA256";
+        Mac hmacSha256;
+        String digestBase64 = null;
+        try {
+            hmacSha256 = Mac.getInstance(algorithm);
+            byte[] keyBytes = secret.getBytes("UTF-8");
+            byte[] messageBytes = message.getBytes("UTF-8");
+            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
+            // 使用HmacSHA256对二进制数据消息Bytes计算摘要
+            byte[] digestBytes = hmacSha256.doFinal(messageBytes);
+            // 把摘要后的结果digestBytes使用Base64进行编码
+            digestBase64 = Base64.encodeBase64String(digestBytes);
+        } catch (NoSuchAlgorithmException e) {
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
+            ex.initCause(e);
+            throw ex;
+        } catch (InvalidKeyException e) {
+            EsignDemoException ex = new EsignDemoException("无效的密钥规范",e);
+            ex.initCause(e);
+            throw ex;
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        }
+        return digestBase64;
+    }
+
+    /**
+     * 获取时间戳
+     * @return
+     */
+    public static String timeStamp() {
+        long timeStamp = System.currentTimeMillis();
+        return String.valueOf(timeStamp);
+    }
+
+    /**
+     * byte字节数组转换成字符串
+     * @param b
+     * @return
+     */
+    public static String byteArrayToHexString(byte[] b) {
+        StringBuilder hs = new StringBuilder();
+        String stmp;
+        for (int n = 0; b != null && n < b.length; n++) {
+            stmp = Integer.toHexString(b[n] & 0XFF);
+            if (stmp.length() == 1)
+                hs.append('0');
+            hs.append(stmp);
+        }
+        return hs.toString().toLowerCase();
+    }
+
+    /**
+     * hash散列加密算法
+     * @return
+     */
+    public static String Hmac_SHA256(String message,String key) throws EsignDemoException {
+        byte[] rawHmac=null;
+        try {
+            SecretKeySpec sk = new SecretKeySpec(key.getBytes(), "HmacSHA256");
+            Mac mac = Mac.getInstance("HmacSHA256");
+            mac.init(sk);
+            rawHmac = mac.doFinal(message.getBytes());
+        }catch (InvalidKeyException e){
+            EsignDemoException ex = new EsignDemoException("无效的密钥规范",e);
+            ex.initCause(e);
+            throw ex;
+        } catch (NoSuchAlgorithmException e) {
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
+            ex.initCause(e);
+            throw ex;
+        }catch (Exception e){
+            EsignDemoException ex = new EsignDemoException("hash散列加密算法报错",e);
+            ex.initCause(e);
+            throw ex;
+        }finally {
+            return byteArrayToHexString(rawHmac);
+        }
+
+    }
+
+    /**
+     * MD5加密32位
+     */
+    public static String MD5Digest(String text) throws EsignDemoException {
+        byte[] digest=null;
+        try {
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            md5.update(text.getBytes());
+            digest = md5.digest();
+        }catch (NoSuchAlgorithmException e){
+            EsignDemoException ex = new EsignDemoException("不支持此算法",e);
+            ex.initCause(e);
+            throw ex;
+        }finally {
+            return byteArrayToHexString(digest);
+        }
+
+    }
+
+    public static void formDataSort(List<BasicNameValuePair> param) {
+        Collections.sort(param, new Comparator<BasicNameValuePair>() {
+            @Override
+            public int compare(BasicNameValuePair o1, BasicNameValuePair o2) {
+                Comparator<Object> com = Collator.getInstance(Locale.CHINA);
+                return com.compare(o1.getName(), o2.getName());
+            }
+        });
+    }
+
+    /***
+     * 字符串是否为空(含空格校验)
+     * @param str
+     * @return
+     */
+    public static boolean isBlank(String str) {
+        if (null == str || 0 == str.length()) {
+            return true;
+        }
+
+        int strLen = str.length();
+
+        for (int i = 0; i < strLen; i++) {
+            if (!Character.isWhitespace(str.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+
+    /***
+     * 对请求URL中的Query参数按照字段名的 ASCII 码从小到大排序(字典排序)
+     *
+     * @param apiUrl
+     * @return 排序后的API接口地址
+     * @throws Exception
+     */
+    public static String sortApiUrl(String apiUrl) throws EsignDemoException {
+
+        if (!apiUrl.contains("?")) {
+            return apiUrl;
+        }
+
+        int queryIndex = apiUrl.indexOf("?");
+        String apiUrlPath =apiUrl.substring(0,queryIndex+1);
+        String apiUrlQuery = apiUrl.substring(queryIndex+1);
+        //apiUrlQuery为空时返回
+        if(isBlank(apiUrlQuery)){
+            return apiUrl.substring(0,apiUrl.length()-1);
+             }
+        // 请求URL中Query参数转成Map
+        Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
+        String[] params = apiUrlQuery.split("&");
+        for (String str : params) {
+            int index = str.indexOf("=");
+            String key = str.substring(0, index);
+            String value = str.substring(index + 1);
+            if (queryParamsMap.containsKey(key)) {
+                String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
+                throw new EsignDemoException(msg);
+            }
+            queryParamsMap.put(key, value);
+        }
+
+        ArrayList<String> queryMapKeys = new ArrayList<String>();
+        for (Map.Entry<Object, Object> entry : queryParamsMap.entrySet()) {
+            queryMapKeys.add((String) entry.getKey());
+        }
+        // 按照字段名的 ASCII 码从小到大排序(字典排序)
+        Collections.sort(queryMapKeys, new Comparator<String>() {
+            @Override
+            public int compare(String o1, String o2) {
+                return (o1.compareToIgnoreCase(o2) == 0 ? -o1.compareTo(o2) : o1.compareToIgnoreCase(o2));
+            }
+        });
+
+        StringBuffer queryString = new StringBuffer();
+        // 构造Query参数键值对值对的格式
+        for (int i = 0; i < queryMapKeys.size(); i++) {
+            String key = queryMapKeys.get(i);
+            String value = (String) queryParamsMap.get(key);
+            queryString.append(key);
+            queryString.append("=");
+            queryString.append(value);
+            queryString.append("&");
+        }
+        if (queryString.length() > 0) {
+            queryString = queryString.deleteCharAt(queryString.length() - 1);
+        }
+
+        // Query参数排序后的接口请求地址
+        StringBuffer sortApiUrl = new StringBuffer();
+        sortApiUrl.append(apiUrlPath);
+        sortApiUrl.append(queryString.toString());
+        return sortApiUrl.toString();
+    }
+
+    /**
+     *获取query
+     * @param apiUrl
+     * @return
+     * @throws EsignDemoException
+     */
+    public static ArrayList<BasicNameValuePair> getQuery(String apiUrl) throws EsignDemoException {
+        ArrayList<BasicNameValuePair> BasicNameValuePairList = new ArrayList<>();
+
+        if (!apiUrl.contains("?")) {
+            return BasicNameValuePairList;
+        }
+
+        int queryIndex = apiUrl.indexOf("\\?");
+        String apiUrlQuery = apiUrl.substring(queryIndex,apiUrl.length());
+
+        // 请求URL中Query参数转成Map
+        Map<Object, Object> queryParamsMap = new HashMap<Object, Object>();
+        String[] params = apiUrlQuery.split("&");
+        for (String str : params) {
+            int index = str.indexOf("=");
+            String key = str.substring(0, index);
+            String value = str.substring(index + 1);
+            if (queryParamsMap.containsKey(key)) {
+                String msg = MessageFormat.format("请求URL中的Query参数的{0}重复", key);
+                throw new EsignDemoException(msg);
+            }
+            BasicNameValuePairList.add(new BasicNameValuePair(key,value));
+            queryParamsMap.put(key, value);
+        }
+        return BasicNameValuePairList;
+    }
+    /**
+     *
+     */
+    public static boolean callBackCheck(String timestamp,String requestQuery,String body,String key,String signature){
+        String algorithm="HmacSHA256";
+        String encoding="UTF-8";
+        Mac mac = null;
+        try {
+            String data = timestamp + requestQuery + body;
+            mac = Mac.getInstance(algorithm);
+            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(encoding), algorithm);
+            mac.init(secretKey);
+            mac.update(data.getBytes(encoding));
+        } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
+            e.printStackTrace();
+            System.out.println("获取Signature签名信息异常:" + e.getMessage());
+            return false;
+        }
+        return byte2hex(mac.doFinal()).equalsIgnoreCase(signature);
+    }
+
+    /***
+     * 将byte[]转成16进制字符串
+     *
+     * @param data
+     *
+     * @return 16进制字符串
+     */
+    public static String byte2hex(byte[] data) {
+        StringBuilder hash = new StringBuilder();
+        String stmp;
+        for (int n = 0; data != null && n < data.length; n++) {
+            stmp = Integer.toHexString(data[n] & 0XFF);
+            if (stmp.length() == 1)
+                hash.append('0');
+            hash.append(stmp);
+        }
+        return hash.toString();
+    }
+
+}

+ 56 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignFileBean.java

@@ -0,0 +1,56 @@
+package org.jeecg.modules.app.esign.comm;
+
+
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.io.File;
+
+/**
+ * @description  文件基础信息封装类
+ * @author  澄泓
+ * @date  2020/10/26 14:54
+ * @version JDK1.7
+ */
+public class EsignFileBean {
+    //文件名称
+    private String fileName;
+    //文件大小
+    private int fileSize;
+    //文件内容MD5
+    private String fileContentMD5;
+    //文件地址
+    private String filePath;
+
+
+    public EsignFileBean(String filePath) throws EsignDemoException {
+            this.filePath=filePath;
+            this.fileContentMD5 = FileTransformation.getFileContentMD5(filePath);
+            File file = new File(filePath);
+            if (!file.exists()) {
+                throw new EsignDemoException("文件不存在");
+            }
+            this.fileName = file.getName();
+            this.fileSize = (int) file.length();
+    }
+
+    public String getFileName() {
+        return fileName;
+    }
+
+    public int getFileSize() {
+        return fileSize;
+    }
+
+    public String getFileContentMD5() {
+        return fileContentMD5;
+    }
+
+    /**
+     * 传入本地文件地址获取二进制数据
+     * @return
+     * @throws EsignDemoException
+     */
+    public byte[] getFileBytes() throws EsignDemoException {
+        return FileTransformation.fileToBytes(filePath);
+    }
+}

+ 483 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpCfgHelper.java

@@ -0,0 +1,483 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.jeecg.modules.app.esign.comm;
+
+import org.apache.http.*;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpRequestRetryHandler;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.ConnectTimeoutException;
+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.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.EntityUtils;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.UnknownHostException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @description Http请求 辅助类
+ * @author 澄泓
+ * @since JDK1.7
+ */
+public class EsignHttpCfgHelper {
+
+	private static Logger LOGGER = LoggerFactory.getLogger(EsignHttpCfgHelper.class);
+	/**
+	 * 超时时间,默认15000毫秒
+	 */
+	private static int MAX_TIMEOUT = 15000;
+	/**
+	 * 请求池最大连接数,默认100个
+	 */
+	private static  int MAX_TOTAL=100;
+	/**
+	 * 单域名最大的连接数,默认50个
+	 */
+	private static  int ROUTE_MAX_TOTAL=50;
+	/**
+	 * 请求失败重试次数,默认3次
+	 */
+	private static   int MAX_RETRY = 3;
+	/**
+	 * 是否需要域名校验,默认不需要校验
+	 */
+	private static boolean SSL_VERIFY=false;
+
+	/**
+	 * 正向代理IP
+	 */
+	private static String PROXY_IP;
+	/**
+	 * 正向代理端口,默认8888
+	 */
+	private static int PROXY_PORT=8888;
+	/**
+	 * 代理协议,默认http
+	 */
+	private static String PROXY_AGREEMENT="http";
+
+	/**
+	 * 是否开启代理,默认false
+	 */
+	private static boolean OPEN_PROXY=false;
+
+	/**
+	 * 代理服务器用户名
+	 */
+	private static String PROXY_USERNAME="";
+
+	/**
+	 * 代理服务器密码
+	 */
+	private static String PROXY_PASSWORD="";
+
+
+	private static PoolingHttpClientConnectionManager connMgr; //连接池
+	private static HttpRequestRetryHandler retryHandler; //重试机制
+
+	private static CloseableHttpClient httpClient=null;
+
+	public static int getMaxTimeout() {
+		return MAX_TIMEOUT;
+	}
+
+	public static void setMaxTimeout(int maxTimeout) {
+		MAX_TIMEOUT = maxTimeout;
+	}
+
+	public static int getMaxTotal() {
+		return MAX_TOTAL;
+	}
+
+	public static void setMaxTotal(int maxTotal) {
+		MAX_TOTAL = maxTotal;
+	}
+
+	public static int getRouteMaxTotal() {
+		return ROUTE_MAX_TOTAL;
+	}
+
+	public static void setRouteMaxTotal(int routeMaxTotal) {
+		ROUTE_MAX_TOTAL = routeMaxTotal;
+	}
+
+	public static int getMaxRetry() {
+		return MAX_RETRY;
+	}
+
+	public static void setMaxRetry(int maxRetry) {
+		MAX_RETRY = maxRetry;
+	}
+
+	public static boolean isSslVerify() {
+		return SSL_VERIFY;
+	}
+
+	public static void setSslVerify(boolean sslVerify) {
+		SSL_VERIFY = sslVerify;
+	}
+
+	public static String getProxyIp() {
+		return PROXY_IP;
+	}
+
+	public static void setProxyIp(String proxyIp) {
+		PROXY_IP = proxyIp;
+	}
+
+	public static int getProxyPort() {
+		return PROXY_PORT;
+	}
+
+	public static void setProxyPort(int proxyPort) {
+		PROXY_PORT = proxyPort;
+	}
+
+	public static String getProxyAgreement() {
+		return PROXY_AGREEMENT;
+	}
+
+	public static void setProxyAgreement(String proxyAgreement) {
+		PROXY_AGREEMENT = proxyAgreement;
+	}
+
+	public static boolean getOpenProxy() {
+		return OPEN_PROXY;
+	}
+
+	public static void setOpenProxy(boolean openProxy) {
+		OPEN_PROXY = openProxy;
+	}
+
+	public static String getProxyUsername() {
+		return PROXY_USERNAME;
+	}
+
+	public static void setProxyUserame(String proxyUsername) {
+		PROXY_USERNAME = proxyUsername;
+	}
+
+	public static String getProxyPassword() {
+		return PROXY_PASSWORD;
+	}
+
+	public static void setProxyPassword(String proxyPassword) {
+		PROXY_PASSWORD = proxyPassword;
+	}
+
+
+
+
+	/**
+	 * 不允许外部创建实例
+	 */
+	private EsignHttpCfgHelper() {
+	}
+
+	//------------------------------公有方法start--------------------------------------------
+
+
+	/**
+	 * @description 发起HTTP / HTTPS 请求
+	 *
+	 * @param reqType
+	 * 			{@link EsignRequestType} 请求类型  GET、 POST 、 DELETE 、 PUT
+	 * @param httpUrl
+	 * 			{@link String} 请求目标地址
+	 * @param headers
+	 * 			{@link Map} 请求头
+	 * @param param
+	 * 			{@link Object} 参数
+	 * @return
+	 * @throws EsignDemoException
+	 * @author 澄泓
+	 */
+	public static EsignHttpResponse sendHttp(EsignRequestType reqType, String httpUrl, Map<String, String> headers, Object param, boolean debug)
+			throws EsignDemoException {
+		HttpRequestBase reqBase=null;
+		if(httpUrl.startsWith("http")){
+			reqBase=reqType.getHttpType(httpUrl);
+		}else{
+			throw new EsignDemoException("请求url地址格式错误");
+		}
+		if(debug){
+			LOGGER.info("请求头:{}",headers+"\n");
+			LOGGER.info("请求参数\n{}", param+"\n");
+			LOGGER.info("请求地址\n:{}\n请求方式\n:{}",reqBase.getURI(),reqType+"\n");
+		}
+		//请求方法不是GET或者DELETE时传入body体,否则不传入。
+		String[] methods = {"DELETE", "GET"};
+		if(param instanceof String&&Arrays.binarySearch(methods, reqType.name())<0){//POST或者PUT请求
+			((HttpEntityEnclosingRequest) reqBase).setEntity(
+					new StringEntity(String.valueOf(param), ContentType.create("application/json", "UTF-8")));
+		}
+		//参数时字节流数组
+		else if(param instanceof byte[]) {
+			reqBase=reqType.getHttpType(httpUrl);
+			byte[] paramBytes = (byte[])param;
+			((HttpEntityEnclosingRequest) reqBase).setEntity(new ByteArrayEntity(paramBytes));
+		}
+		//参数是form表单时
+		else if(param instanceof List){
+			((HttpEntityEnclosingRequest) reqBase).setEntity(new UrlEncodedFormEntity((Iterable<? extends NameValuePair>) param));
+		}
+		httpClient = getHttpClient();
+		config(reqBase);
+
+		//设置请求头
+		if(headers != null &&headers.size()>0) {
+			for(Map.Entry<String, String> entry :headers.entrySet()) {
+				reqBase.setHeader(entry.getKey(), entry.getValue());
+			}
+		}
+		//响应对象
+		CloseableHttpResponse res = null;
+		//响应内容
+		String resCtx = null;
+		int status;
+		EsignHttpResponse esignHttpResponse = new EsignHttpResponse();
+		try {
+			//执行请求
+			res = httpClient.execute(reqBase);
+			status=res.getStatusLine().getStatusCode();
+
+			//获取请求响应对象和响应entity
+			HttpEntity httpEntity = res.getEntity();
+			if(httpEntity != null) {
+				resCtx = EntityUtils.toString(httpEntity,"utf-8");
+			}
+			if(debug) {
+				LOGGER.info("响应\n{}", resCtx + "\n");
+				LOGGER.info("----------------------------end------------------------");
+			}
+		} catch (NoHttpResponseException e) {
+			throw new EsignDemoException("服务器丢失了",e);
+		} catch (SSLHandshakeException e){
+			String msg = MessageFormat.format("SSL握手异常", e);
+			EsignDemoException ex = new EsignDemoException(msg, e);
+			throw ex;
+		} catch (UnknownHostException e){
+			EsignDemoException ex = new EsignDemoException("服务器找不到", e);
+			ex.initCause(e);
+			throw ex;
+		} catch(ConnectTimeoutException e){
+			EsignDemoException ex = new EsignDemoException("连接超时", e);
+			ex.initCause(e);
+			throw ex;
+		} catch(SSLException e){
+			EsignDemoException ex = new EsignDemoException("SSL异常",e);
+			ex.initCause(e);
+			throw ex;
+		} catch (ClientProtocolException e) {
+			EsignDemoException ex = new EsignDemoException("请求头异常",e);
+			ex.initCause(e);
+			throw ex;
+		} catch (IOException e) {
+			EsignDemoException ex = new EsignDemoException("网络请求失败",e);
+			ex.initCause(e);
+			throw ex;
+		} finally {
+			if(res != null) {
+				try {
+					res.close();
+				} catch (IOException e) {
+					EsignDemoException ex = new EsignDemoException("--->>关闭请求响应失败",e);
+					ex.initCause(e);
+					throw ex;
+				}
+			}
+		}
+		esignHttpResponse.setStatus(status);
+		esignHttpResponse.setBody(resCtx);
+		return esignHttpResponse;
+	}
+	//------------------------------公有方法end----------------------------------------------
+
+	//------------------------------私有方法start--------------------------------------------
+
+	/**
+	 * @description 请求头和超时时间配置
+	 *
+	 * @param httpReqBase
+	 * @author 澄泓
+	 */
+	private static void config(HttpRequestBase httpReqBase) {
+		// 配置请求的超时设置
+		RequestConfig.Builder builder = RequestConfig.custom()
+				.setConnectionRequestTimeout(MAX_TIMEOUT)
+				.setConnectTimeout(MAX_TIMEOUT)
+				.setSocketTimeout(MAX_TIMEOUT);
+		if(OPEN_PROXY){
+			HttpHost proxy=new HttpHost(PROXY_IP,PROXY_PORT,PROXY_AGREEMENT);
+			builder.setProxy(proxy);
+		}
+		RequestConfig requestConfig = builder.build();
+		httpReqBase.setConfig(requestConfig);
+	}
+
+	/**
+	 * @description 连接池配置
+	 *
+	 * @return
+	 * @author 澄泓
+	 */
+	private static void cfgPoolMgr() throws EsignDemoException {
+		ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
+		LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
+		if(!SSL_VERIFY){
+            sslsf=sslConnectionSocketFactory();
+        }
+
+		Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+				.register("http", plainsf)
+				.register("https", sslsf)
+				.build();
+
+		//连接池管理器
+		connMgr = new PoolingHttpClientConnectionManager(registry);
+		//请求池最大连接数
+		connMgr.setMaxTotal(MAX_TOTAL);
+		//但域名最大的连接数
+		connMgr.setDefaultMaxPerRoute(ROUTE_MAX_TOTAL);
+	}
+
+
+
+
+	/**
+	 * @description 设置重试机制
+	 *
+	 * @author 澄泓
+	 */
+	private static void cfgRetryHandler() {
+		retryHandler = new HttpRequestRetryHandler() {
+
+			@Override
+			public boolean retryRequest(IOException e, int excCount, HttpContext ctx) {
+				//超过最大重试次数,就放弃
+				if(excCount > MAX_RETRY) {
+					return false;
+				}
+				//服务器丢掉了链接,就重试
+				if(e instanceof NoHttpResponseException) {
+					return true;
+				}
+				//不重试SSL握手异常
+				if(e instanceof SSLHandshakeException) {
+					return false;
+				}
+				//中断
+				if(e instanceof InterruptedIOException) {
+					return false;
+				}
+				//目标服务器不可达
+				if(e instanceof UnknownHostException) {
+					return false;
+				}
+				//连接超时
+				//SSL异常
+				if(e instanceof SSLException) {
+					return false;
+				}
+
+				HttpClientContext clientCtx = HttpClientContext.adapt(ctx);
+				HttpRequest req = clientCtx.getRequest();
+				//如果是幂等请求,就再次尝试
+				if(!(req instanceof HttpEntityEnclosingRequest)) {
+					return true;
+				}
+				return false;
+			}
+		};
+	}
+
+    /**
+     * 忽略域名校验
+     */
+    private static SSLConnectionSocketFactory sslConnectionSocketFactory() throws EsignDemoException {
+        try {
+            SSLContext ctx = SSLContext.getInstance("TLS");    // 创建一个上下文(此处指定的协议类型似乎不是重点)
+            X509TrustManager tm = new X509TrustManager() {     // 创建一个跳过SSL证书的策略
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+                }
+
+                public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+                }
+            };
+            ctx.init(null, new TrustManager[] { tm }, null);    // 使用上面的策略初始化上下文
+            return new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
+        }catch (Exception e){
+            EsignDemoException ex = new EsignDemoException("忽略域名校验失败",e);
+            ex.initCause(e);
+            throw ex;
+        }
+
+    }
+
+	/**
+	 * @description 获取单例HttpClient
+	 *
+	 * @return
+	 * @author 澄泓
+	 */
+	private static synchronized CloseableHttpClient getHttpClient() throws EsignDemoException {
+		if(httpClient==null) {
+			CredentialsProvider credsProvider = new BasicCredentialsProvider();
+			credsProvider.setCredentials(new AuthScope(PROXY_IP,PROXY_PORT),new UsernamePasswordCredentials(PROXY_USERNAME, PROXY_PASSWORD));
+			cfgPoolMgr();
+			cfgRetryHandler();
+            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
+            httpClient =  httpClientBuilder.setDefaultCredentialsProvider(credsProvider).setConnectionManager(connMgr).setRetryHandler(retryHandler).build();
+		}
+		return httpClient;
+
+	}
+	//------------------------------私有方法end----------------------------------------------
+
+
+}

+ 171 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpHelper.java

@@ -0,0 +1,171 @@
+package org.jeecg.modules.app.esign.comm;
+
+import org.jeecg.modules.app.esign.enums.EsignHeaderConstant;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @description Http 请求 辅助类
+ * @author 澄泓
+ * @since JDK1.7
+ */
+public class EsignHttpHelper {
+	private static final Logger LOGGER = LoggerFactory.getLogger(EsignHttpHelper.class);
+
+	/**
+	 * 不允许外部创建实例
+	 */
+	private EsignHttpHelper() {
+
+	}
+
+	/**
+	 * @description 发送常规HTTP 请求
+	 *
+	 * @param reqType 请求方式
+	 * @param url 请求路径
+	 * @param paramStr 请求参数
+	 * @return
+	 * @throws EsignDemoException
+	 * @author 澄泓
+	 */
+	public static EsignHttpResponse doCommHttp(String host, String url, EsignRequestType reqType, Object paramStr , Map<String,String> httpHeader, boolean debug) throws EsignDemoException {
+		return EsignHttpCfgHelper.sendHttp(reqType, host+url,httpHeader, paramStr, debug);
+	}
+
+
+	/**
+	 * @description 发送文件流上传 HTTP 请求
+	 *
+	 * @param reqType 请求方式
+	 * @param uploadUrl 请求路径
+	 * @param param 请求参数
+	 * @param fileContentMd5 文件fileContentMd5
+	 * @param contentType 文件MIME类型
+	 * @return
+	 * @throws EsignDemoException
+	 * @author 澄泓
+	 */
+	public static EsignHttpResponse doUploadHttp( String uploadUrl,EsignRequestType reqType,byte[] param, String fileContentMd5,
+												 String contentType, boolean debug) throws EsignDemoException {
+		Map<String, String> uploadHeader = buildUploadHeader(fileContentMd5, contentType);
+		if(debug){
+			LOGGER.info("----------------------------start------------------------");
+			LOGGER.info("fileContentMd5:{}",fileContentMd5);
+			LOGGER.info("contentType:{}",contentType);
+		}
+		return EsignHttpCfgHelper.sendHttp(reqType,uploadUrl, uploadHeader, param,debug);
+	}
+
+
+
+	/**
+	 * @description 构建一个签名鉴权+json数据的esign请求头
+	 * @return
+	 * @author 澄泓
+	 */
+	public static Map<String, String> buildSignAndJsonHeader(String projectId,String contentMD5,String accept,String contentType,String authMode) {
+
+		Map<String, String> header = new HashMap<>();
+		header.put("X-Tsign-Open-App-Id", projectId);
+		header.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
+		header.put("X-Tsign-Open-Ca-Timestamp", EsignEncryption.timeStamp());
+		header.put("Accept",accept);
+		header.put("Content-MD5",contentMD5);
+		header.put("Content-Type", contentType);
+		header.put("X-Tsign-Open-Auth-Mode", authMode);
+		return header;
+	}
+
+	/**
+	 * 签名计算并且构建一个签名鉴权+json数据的esign请求头
+	 * @param  httpMethod
+	 *      *         The name of a supported {@linkplain java.nio.charset.Charset
+	 *      *         charset}
+	 * @return
+	 */
+	public static Map<String,String> signAndBuildSignAndJsonHeader(String projectId, String secret,String paramStr,String httpMethod,String url,boolean debug) throws EsignDemoException {
+		String contentMD5="";
+		//统一转大写处理
+		httpMethod = httpMethod.toUpperCase();
+		if("GET".equals(httpMethod)||"DELETE".equals(httpMethod)){
+			paramStr=null;
+			contentMD5="";
+		} else if("PUT".equals(httpMethod)||"POST".equals(httpMethod)){
+			//对body体做md5摘要
+			contentMD5=EsignEncryption.doContentMD5(paramStr);
+		}else{
+			throw new EsignDemoException(String.format("不支持的请求方法%s",httpMethod));
+		}
+		//构造一个初步的请求头
+		Map<String, String> esignHeaderMap = buildSignAndJsonHeader(projectId, contentMD5, EsignHeaderConstant.ACCEPT.VALUE(), EsignHeaderConstant.CONTENTTYPE_JSON.VALUE(), EsignHeaderConstant.AUTHMODE.VALUE());
+		//排序
+		url=EsignEncryption.sortApiUrl(url);
+		//传入生成的bodyMd5,加上其他请求头部信息拼接成字符串
+		String message = EsignEncryption.appendSignDataString(httpMethod, esignHeaderMap.get("Content-MD5"),esignHeaderMap.get("Accept"),esignHeaderMap.get("Content-Type"),esignHeaderMap.get("Headers"),esignHeaderMap.get("Date"), url);
+		//整体做sha256签名
+		String reqSignature = EsignEncryption.doSignatureBase64(message, secret);
+		//请求头添加签名值
+		esignHeaderMap.put("X-Tsign-Open-Ca-Signature",reqSignature);
+		if(debug){
+			LOGGER.info("----------------------------start------------------------");
+			LOGGER.info("待计算body值:{}", paramStr+"\n");
+			LOGGER.info("MD5值:{}",contentMD5+"\n");
+			LOGGER.info("待签名字符串:{}",message+"\n");
+			LOGGER.info("签名值:{}",reqSignature+"\n");
+		}
+		return esignHeaderMap;
+	}
+
+
+	/**
+	 * @description 构建一个Token鉴权+jsons数据的esign请求头
+	 * @return
+	 * @author 澄泓
+	 */
+	public static Map<String, String> buildTokenAndJsonHeader(String appid,String token) {
+		Map<String, String> esignHeader = new HashMap<>();
+		esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
+		esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_JSON.VALUE());
+		esignHeader.put("X-Tsign-Open-App-Id", appid);
+		esignHeader.put("X-Tsign-Open-Token", token);
+		return esignHeader;
+	}
+
+	/**
+	 * @description 构建一个form表单数据的esign请求头
+	 * @return
+	 * @author 澄泓
+	 */
+	public static Map<String, String> buildFormDataHeader(String appid) {
+		Map<String, String> esignHeader = new HashMap<>();
+		esignHeader.put("X-Tsign-Open-Version-Sdk",EsignCoreSdkInfo.getSdkVersion());
+		esignHeader.put("X-Tsign-Open-Authorization-Version","v2");
+		esignHeader.put("Content-Type", EsignHeaderConstant.CONTENTTYPE_FORMDATA.VALUE());
+		esignHeader.put("X-Tsign-Open-App-Id", appid);
+		return esignHeader;
+	}
+
+	/**
+	 * @description 创建文件流上传 请求头
+	 *
+	 * @param fileContentMd5
+	 * @param contentType
+	 * @return
+	 * @author 澄泓
+	 */
+	public static Map<String, String> buildUploadHeader(String fileContentMd5, String contentType) {
+		Map<String, String> header = new HashMap<>();
+		header.put("Content-MD5", fileContentMd5);
+		header.put("Content-Type", contentType);
+
+		return header;
+	}
+
+	// ------------------------------私有方法end----------------------------------------------
+}

+ 27 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/EsignHttpResponse.java

@@ -0,0 +1,27 @@
+package org.jeecg.modules.app.esign.comm;
+/**
+ * 网络请求的response类
+ * @author  澄泓
+ * @date  2022/2/21 17:28
+ * @version
+ */
+public class EsignHttpResponse {
+    private int status;
+    private String body;
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public String getBody() {
+        return body;
+    }
+
+    public void setBody(String body) {
+        this.body = body;
+    }
+}

+ 284 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/comm/FileTransformation.java

@@ -0,0 +1,284 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
+ */
+package org.jeecg.modules.app.esign.comm;
+
+import org.apache.commons.codec.binary.Base64;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author 澄泓
+ * @version JDK1.7
+ * @description 文件转换类
+ * @date 2020/10/26 10:47
+ */
+public class FileTransformation {
+
+    /**
+     * 传入本地文件路径转二进制byte
+     *
+     * @param srcFilePath 本地文件路径
+     * @return
+     * @throws EsignDemoException
+     */
+    public static byte[] fileToBytes(String srcFilePath) throws EsignDemoException {
+        return getBytes(srcFilePath);
+    }
+
+    /**
+     * 图片转base64
+     *
+     * @param filePath 本地文件路径
+     * @return
+     * @throws EsignDemoException
+     */
+    public static String fileToBase64(String filePath) throws EsignDemoException {
+        byte[] bytes;
+        String base64 = null;
+        bytes = fileToBytes(filePath);
+        base64 = Base64.encodeBase64String(bytes);
+        base64 = base64.replaceAll("\r\n", "");
+        return base64;
+    }
+
+    public static void main(String[] args) throws EsignDemoException {
+        System.out.println(getFileContentMD5("D:\\文档\\PLT2022-02124CT.pdf"));
+    }
+
+    /***
+     * 计算文件内容的Content-MD5
+     * @param filePath 文件路径
+     * @return
+     */
+    public static String getFileContentMD5(String filePath) throws EsignDemoException {
+        // 获取文件MD5的二进制数组(128位)
+        byte[] bytes = getFileMD5Bytes128(filePath);
+        // 对文件MD5的二进制数组进行base64编码
+        return new String(Base64.encodeBase64String(bytes));
+    }
+
+    /**
+     * 下载文件
+     *
+     * @param httpUrl 网络文件地址url
+     * @return
+     */
+    public static boolean downLoadFileByUrl(String httpUrl, String dir) throws EsignDemoException {
+        InputStream fis = null;
+        FileOutputStream fileOutputStream = null;
+        try {
+            URL url = new URL(httpUrl);
+            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
+            httpConn.connect();
+            fis = httpConn.getInputStream();
+            fileOutputStream = new FileOutputStream(new File(dir));
+            byte[] md5Bytes = null;
+
+            byte[] buffer = new byte[1024];
+            int length = -1;
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
+                fileOutputStream.write(buffer, 0, length);
+            }
+        } catch (IOException e) {
+            EsignDemoException ex = new EsignDemoException("获取文件流异常", e);
+            ex.initCause(e);
+            throw ex;
+        } finally {
+            try {
+                if (fis != null) {
+                    fis.close();
+                }
+                if (fileOutputStream != null) {
+                    fileOutputStream.close();
+                }
+            } catch (IOException e) {
+                EsignDemoException ex = new EsignDemoException("关闭文件流异常", e);
+                ex.initCause(e);
+                throw ex;
+            }
+        }
+        return true;
+    }
+
+
+    /**
+     * 网络文件转二进制MD5数组并获取文件大小
+     *
+     * @param fileUrl 网络文件地址url
+     * @return
+     */
+    public static Map fileUrlToBytes(String fileUrl) throws EsignDemoException {
+        HashMap<String, Object> map = new HashMap<String, Object>();
+        try {
+            URL url = new URL(fileUrl);
+            HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
+            httpConn.connect();
+            InputStream fis = httpConn.getInputStream();
+            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+            outStream.close();
+            map.put("fileSize", fis.available());
+            byte[] md5Bytes = null;
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            byte[] buffer = new byte[1024];
+            int length = -1;
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
+                md5.update(buffer, 0, length);
+                outStream.write(buffer, 0, length);
+            }
+            md5Bytes = md5.digest();
+            byte[] fileData = outStream.toByteArray();
+            map.put("fileData", fileData);
+            outStream.close();
+            fis.close();
+            map.put("md5Bytes", md5Bytes);
+        } catch (IOException e) {
+            EsignDemoException ex = new EsignDemoException("获取文件流异常", e);
+            ex.initCause(e);
+            throw ex;
+        } catch (NoSuchAlgorithmException e) {
+            EsignDemoException ex = new EsignDemoException("文件计算异常", e);
+            ex.initCause(e);
+            throw ex;
+        }
+        return map;
+    }
+
+    /***
+     * 获取文件MD5的二进制数组(128位)
+     * @param filePath
+     * @return
+     * @throws EsignDemoException
+     */
+    public static byte[] getFileMD5Bytes128(String filePath) throws EsignDemoException {
+        FileInputStream fis = null;
+        byte[] md5Bytes = null;
+        try {
+            File file = new File(filePath);
+            fis = new FileInputStream(file);
+            MessageDigest md5 = MessageDigest.getInstance("MD5");
+            byte[] buffer = new byte[1024];
+            int length = -1;
+            while ((length = fis.read(buffer, 0, 1024)) != -1) {
+                md5.update(buffer, 0, length);
+            }
+            md5Bytes = md5.digest();
+            fis.close();
+        } catch (FileNotFoundException e) {
+            EsignDemoException ex = new EsignDemoException("文件找不到", e);
+            ex.initCause(e);
+            throw ex;
+        } catch (NoSuchAlgorithmException e) {
+            EsignDemoException ex = new EsignDemoException("不支持此算法", e);
+            ex.initCause(e);
+            throw ex;
+        } catch (IOException e) {
+            EsignDemoException ex = new EsignDemoException("输入流或输出流异常", e);
+            ex.initCause(e);
+            throw ex;
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e);
+                    ex.initCause(e);
+                    throw ex;
+                }
+            }
+        }
+        return md5Bytes;
+    }
+
+    /**
+     * @param path
+     * @return
+     * @throws EsignDemoException
+     * @description 根据文件路径,获取文件base64
+     * @author 宫清
+     * @date 2019年7月21日 下午4:22:08
+     */
+    public static String getBase64Str(String path) throws EsignDemoException {
+        InputStream is = null;
+        try {
+            is = new FileInputStream(new File(path));
+            byte[] bytes = new byte[is.available()];
+            is.read(bytes);
+            return Base64.encodeBase64String(bytes);
+        } catch (Exception e) {
+            EsignDemoException ex = new EsignDemoException("获取文件输入流失败", e);
+            ex.initCause(e);
+            throw ex;
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    EsignDemoException ex = new EsignDemoException("关闭文件输入流失败", e);
+                    ex.initCause(e);
+                    throw ex;
+                }
+            }
+        }
+    }
+
+    /**
+     * @param path 文件路径
+     * @return
+     * @description 获取文件名称
+     * @author 宫清
+     * @date 2019年7月21日 下午8:21:16
+     */
+    public static String getFileName(String path) {
+        return new File(path).getName();
+    }
+
+    /**
+     * @param filePath {@link String} 文件地址
+     * @return
+     * @throws EsignDemoException
+     * @description 获取文件字节流
+     * @date 2019年7月10日 上午9:17:00
+     * @author 宫清
+     */
+    public static byte[] getBytes(String filePath) throws EsignDemoException {
+        File file = new File(filePath);
+        FileInputStream fis = null;
+        byte[] buffer = null;
+        try {
+            fis = new FileInputStream(file);
+            buffer = new byte[(int) file.length()];
+            fis.read(buffer);
+        } catch (Exception e) {
+            EsignDemoException ex = new EsignDemoException("获取文件字节流失败", e);
+            ex.initCause(e);
+            throw ex;
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    EsignDemoException ex = new EsignDemoException("关闭文件字节流失败", e);
+                    ex.initCause(e);
+                    throw ex;
+                }
+            }
+        }
+        return buffer;
+    }
+}

+ 13 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/constant/EsignDemoConfig.java

@@ -0,0 +1,13 @@
+package org.jeecg.modules.app.esign.constant;
+
+public class EsignDemoConfig {
+
+    // 应用ID
+    public static final String EsignAppId = "7439072990";
+    // 应用密钥
+    public static final String EsignAppSecret = "ce891a865bdd94d0081cae50f13739e4";
+    // e签宝接口调用域名(模拟环境)
+    public static final String EsignHost = "https://smlopenapi.esign.cn";
+    // e签宝接口调用域名(正式环境)
+    // public static final String EsignHost = "https://openapi.esign.cn";
+}

+ 26 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/enums/EsignHeaderConstant.java

@@ -0,0 +1,26 @@
+package org.jeecg.modules.app.esign.enums;
+/**
+ * @description  头部信息常量
+ * @author  澄泓
+ * @date  2020/10/22 15:05
+ * @version JDK1.7
+ */
+public enum EsignHeaderConstant {
+    ACCEPT("*/*"),
+    DATE(""),
+    HEADERS( ""),
+    CONTENTTYPE_FORMDATA("application/x-www-form-urlencoded"),
+    CONTENTTYPE_JSON("application/json; charset=UTF-8"),
+    CONTENTTYPE_PDF("application/pdf"),
+    CONTENTTYPE_STREAM("application/octet-stream"),
+    AUTHMODE("Signature");
+
+    private String value;
+    private EsignHeaderConstant(String value) {
+        this.value=value;
+    }
+
+    public String VALUE(){
+        return this.value;
+    }
+}

+ 39 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/enums/EsignRequestType.java

@@ -0,0 +1,39 @@
+package org.jeecg.modules.app.esign.enums;
+
+import org.apache.http.client.methods.*;
+
+/**
+ * @description 请求类型
+ * @author 澄泓
+ * @since JDK1.7
+ */
+public enum EsignRequestType {
+
+	POST{
+		@Override
+		public HttpRequestBase getHttpType(String url) {
+			return new HttpPost(url);
+		}
+	},
+	GET{
+		@Override
+		public HttpRequestBase getHttpType(String url) {
+			return new HttpGet(url);
+		}
+	},
+	DELETE{
+		@Override
+		public HttpRequestBase getHttpType(String url) {
+			return new HttpDelete(url);
+		}
+	},
+	PUT{
+		@Override
+		public HttpRequestBase getHttpType(String url) {
+			return new HttpPut(url);
+		}
+	},
+	;
+
+   public abstract HttpRequestBase getHttpType(String url);
+}

+ 107 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/ep/epDemo.java

@@ -0,0 +1,107 @@
+package org.jeecg.modules.app.esign.ep;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignCoreSdkInfo;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+
+/**
+ *
+ * @author  古柯
+ * @date  2022/8/20 10:42
+ * @version
+ */
+public class epDemo {
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret= EsignDemoConfig.EsignAppSecret;
+
+
+    //注意:使用之前需要调用认证授权口授予企业资源管理权限(manage_org_resource)
+    public static void main(String[] args) throws EsignDemoException, InterruptedException {
+        System.out.println(EsignCoreSdkInfo.getInfo());
+        Gson gson = new Gson();
+        //获取购买e签宝套餐链接
+        EsignHttpResponse orgPlaceOrderUrl = orgPlaceOrderUrl();
+        JsonObject orgPlaceOrderUrlObject = gson.fromJson(orgPlaceOrderUrl.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orgPlaceOrderUrlObject);
+
+        //查询e签宝套餐余量
+        EsignHttpResponse remainingQuantity = remainingQuantity();
+        JsonObject remainingQuantityObject = gson.fromJson(remainingQuantity.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+remainingQuantityObject);
+        //查询套餐订单列表
+        EsignHttpResponse orderList = orderList();
+        JsonObject orderListObject = gson.fromJson(orderList.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orderListObject);
+    }
+
+    /**
+     *获取购买e签宝套餐链接
+     * @return
+     */
+    public static EsignHttpResponse orgPlaceOrderUrl() throws EsignDemoException {
+        String orgId="97fb1647202xxxxxx8c58428c7";
+        String transactorPsnId="217c64929xxxxxxx3eadd00cdd";
+        String apiaddr="/v3/orders/org-place-order-url";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+
+        String jsonParm="{\n" +
+                "    \"orgId\": \""+orgId+"\",\n" +
+                "    \"transactorPsnId\": \""+transactorPsnId+"\",    \n" +
+                "    \"redirectUrl\": \"https://www.xxx.com\",\n" +
+                "    \"notifyUrl\": \"http://xx.xx.xx.172:8081/CSTNotify/asyn/notify\",\n" +
+                "    \"customBizNum\": \"123\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询e签宝套餐余量
+     */
+
+    public static EsignHttpResponse remainingQuantity() throws EsignDemoException {
+        String orgId="97fb1647xxxxxx28c58428c7";
+
+        String apiaddr="/v3/orders/remaining-quantity?orgId="+orgId;
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+    /**
+     * 查询套餐订单列表
+     */
+
+    public static EsignHttpResponse orderList() throws EsignDemoException {
+        String orgId="97fb1647xxxxxxb405a28c58428c7";
+
+        String apiaddr="/v3/orders/order-list?orgId="+orgId;
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+}

+ 36 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/exception/EsignDemoException.java

@@ -0,0 +1,36 @@
+package org.jeecg.modules.app.esign.exception;
+
+/**
+ * description 自定义全局异常
+ * @author 澄泓
+ * datetime 2019年7月1日上午10:43:24
+ */
+public class EsignDemoException extends Exception {
+
+	private static final long serialVersionUID = 4359180081622082792L;
+	private Exception e;
+
+	public EsignDemoException(String msg) {
+		super(msg);
+	}
+
+	public EsignDemoException(String msg, Throwable cause) {
+		super(msg,cause);
+	}
+
+	public EsignDemoException(){
+
+	}
+
+	public Exception getE() {
+		return e;
+	}
+
+	public void setE(Exception e) {
+		this.e = e;
+	}
+
+
+
+
+}

+ 117 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/fileAndTemplate/FileDemo.java

@@ -0,0 +1,117 @@
+package org.jeecg.modules.app.esign.fileAndTemplate;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignFileBean;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignHeaderConstant;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.io.File;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * description 文件服务
+ * @author 语冰
+ * datetime 2022年8月10日上午09:43:24
+ */
+public class FileDemo extends Exception {
+
+	private static String eSignHost= EsignDemoConfig.EsignHost;
+	private static String eSignAppId=EsignDemoConfig.EsignAppId;
+	private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+	public static void main(String[] args) throws EsignDemoException, InterruptedException {
+
+		String rootFolder = new File("").getAbsolutePath();
+		//获取文件id以及文件上传地址
+		String filePath=rootFolder + File.separator + "pdf" + File.separator + "合同模板.pdf";
+		EsignHttpResponse getUploadUrl = getUploadUrl(filePath);
+		Gson gson = new Gson();
+		JsonObject getUploadUrlJsonObject = gson.fromJson(getUploadUrl.getBody(), JsonObject.class);
+		JsonObject data = getUploadUrlJsonObject.getAsJsonObject("data");
+		//文件id后续发起签署使用
+		String fileId =data.get("fileId").getAsString();
+		String fileUploadUrl =data.get("fileUploadUrl").getAsString();
+		System.out.println("获取文件id以及文件上传地址成功,文件id:"+fileId);
+		System.out.println("上传链接"+fileUploadUrl);
+
+		//文件上传
+		EsignHttpResponse uploadFileResponse = uploadFile(fileUploadUrl,filePath);
+		JsonObject uploadFileResponseJsonObject = gson.fromJson(uploadFileResponse.getBody(), JsonObject.class);
+		String code = uploadFileResponseJsonObject.get("errCode").getAsString();
+		System.out.println("文件上传成功,状态码:"+code);
+
+		//文件上传成功后文件会有一个异步处理过程,建议轮询文件状态,正常后发起签署
+		//查询文件上传状态
+		int i=0;
+		while(i<3) {
+			EsignHttpResponse fileStatus = getFileStatus(fileId);
+			JsonObject fileStatusJsonObject = gson.fromJson(fileStatus.getBody(), JsonObject.class);
+			String status = fileStatusJsonObject.getAsJsonObject("data").get("fileStatus").getAsString();
+			System.out.println(String.format("查询文件状态执行第%s次",i+1));
+			if("2".equalsIgnoreCase(status)||"5".equalsIgnoreCase(status)){//查询状态为2或者5代表文件准备完成
+				System.out.println("文件准备完成");
+				break;
+			}
+			System.out.println("文件未准备完成,等待两秒重新查询");
+			TimeUnit.SECONDS.sleep(2);
+			i++;
+		}
+	}
+
+	/**
+	 * 获取文件上传地址
+	 * @return
+	 */
+	public static EsignHttpResponse getUploadUrl(String filePath) throws EsignDemoException {
+		//自定义的文件封装类,传入文件地址可以获取文件的名称大小,文件流等数据
+		EsignFileBean esignFileBean = new EsignFileBean(filePath);
+		String apiaddr="/v3/files/file-upload-url";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\n" +
+				"    \"contentMd5\": \""+esignFileBean.getFileContentMD5()+"\",\n" +
+				"    \"fileName\":\""+esignFileBean.getFileName()+"\"," +
+				"    \"fileSize\": "+esignFileBean.getFileSize()+",\n" +
+				"    \"convertToPDF\": false,\n" +
+				"    \"contentType\": \""+ EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE()+"\"\n" +
+				"}";
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+	/**
+	 * 文件流上传
+	 * @return
+	 */
+	public static EsignHttpResponse uploadFile(String uploadUrl,String filePath) throws EsignDemoException {
+		//根据文件地址获取文件contentMd5
+		EsignFileBean esignFileBean = new EsignFileBean(filePath);
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.PUT;
+		return EsignHttpHelper.doUploadHttp(uploadUrl,requestType,esignFileBean.getFileBytes(),esignFileBean.getFileContentMD5(), EsignHeaderConstant.CONTENTTYPE_STREAM.VALUE(),true);
+	}
+
+	/**
+	 * 获取文件上传状态
+	 */
+	public static EsignHttpResponse getFileStatus(String fileId) throws EsignDemoException {
+		String apiaddr="/v3/files/"+fileId;
+
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm=null;
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.GET;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+}

+ 160 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/fileAndTemplate/TemplateDemo.java

@@ -0,0 +1,160 @@
+package org.jeecg.modules.app.esign.fileAndTemplate;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+/**
+ * description 模板服务
+ * @author 语冰
+ * datetime 2022年8月10日上午09:43:24
+ */
+public class TemplateDemo extends Exception {
+
+	private static String eSignHost= EsignDemoConfig.EsignHost;
+	private static String eSignAppId=EsignDemoConfig.EsignAppId;
+	private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+	public static void main(String[] args) throws EsignDemoException {
+		/* 获取制作合同模板页面*/
+		EsignHttpResponse getTemplateCreateUrl = getTemplateCreateUrl();
+		Gson gson = new Gson();
+		JsonObject getTemplateCreateUrlObject = gson.fromJson(getTemplateCreateUrl.getBody(), JsonObject.class);
+
+		String docTemplateCreateUrl = getTemplateCreateUrlObject.getAsJsonObject("data").get("docTemplateCreateUrl").getAsString();
+		String docTemplateId = getTemplateCreateUrlObject.getAsJsonObject("data").get("docTemplateId").getAsString();
+		System.err.println("制作合同模板的页面链接:"+docTemplateCreateUrl);
+		System.err.println("合同模板id:"+docTemplateId);
+
+		/* 获取编辑合同模板页面*/
+		EsignHttpResponse getTemplateEditUrl = getTemplateEditUrl();
+		JsonObject getTemplateEditUrlObject = gson.fromJson(getTemplateEditUrl.getBody(), JsonObject.class);
+		String docTemplateEditUrl = getTemplateEditUrlObject.getAsJsonObject("data").get("docTemplateEditUrl").getAsString();
+		System.err.println("编辑合同模板的页面链接:"+docTemplateEditUrl);
+
+		/* 查询合同模板中控件详情*/
+		EsignHttpResponse getComponentsInfo = getComponentsInfo();
+		JsonObject getComponentsInfoObject = gson.fromJson(getComponentsInfo.getBody(), JsonObject.class);
+		System.err.println("查询模板详情返回:"+getComponentsInfoObject);
+
+
+		/* 填写模板生成文件*/
+		EsignHttpResponse createByDocTemplate = createByDocTemplate();
+		JsonObject createByDocTemplateObject = gson.fromJson(createByDocTemplate.getBody(), JsonObject.class);
+		String fileId = createByDocTemplateObject.getAsJsonObject("data").get("fileId").getAsString();
+		String fileDownloadUrl = createByDocTemplateObject.getAsJsonObject("data").get("fileDownloadUrl").getAsString();
+		System.err.println("填充后文件id:"+fileId);
+		System.err.println("文件下载链接:"+fileDownloadUrl);
+
+		//删除合同模板
+		EsignHttpResponse deleteDocTemplate = deleteDocTemplate();
+		JsonObject deleteDocTemplateObject = gson.fromJson(deleteDocTemplate.getBody(), JsonObject.class);
+		System.err.println("删除模板文件返回:"+deleteDocTemplateObject);
+	}
+	/**
+	 * 获取制作合同模板页面
+	 * @return
+	 * @throws EsignDemoException
+	 */
+	private static EsignHttpResponse getTemplateCreateUrl() throws EsignDemoException {
+		String apiaddr="/v3/doc-templates/doc-template-create-url";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\"docTemplateName\":\"测试模板\",\"docTemplateType\":0,\"fileId\":\"b3f01axxxxxx05d320da35\",\"redirectUrl\":\"https://www.esign.cn\"}";
+
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+	/**
+	 * 获取编辑合同模板页面
+	 * @return
+	 * @throws EsignDemoException
+	 */
+	private static EsignHttpResponse getTemplateEditUrl() throws EsignDemoException {
+		String docTemplateId="a6f7e3b4e7xxxxxxxedc6fc89";
+		String apiaddr="/v3/doc-templates/"+docTemplateId+"/doc-template-edit-url";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\"redirectUrl\":\"https://www.esign.cn\"}";
+
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+	/**
+	 * 查询合同模板中控件详情
+	 */
+	private static EsignHttpResponse getComponentsInfo() throws EsignDemoException {
+		String docTemplateId="a6f7e3b4xxxxxxxxfdedc6fc89";
+		String apiaddr="/v3/doc-templates/"+docTemplateId;
+
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm=null;
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.GET;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+
+	/**
+	 * 填写模板生成文件
+	 * @return
+	 * @throws EsignDemoException
+	 */
+	private static EsignHttpResponse createByDocTemplate() throws EsignDemoException {
+		String apiaddr="/v3/files/create-by-doc-template";
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{\n" +
+				"    \"docTemplateId\": \"a6f7e3b4xxxxxxxxedc6fc89\",\n" +
+				"    \"fileName\": \"测试模板.doc\",\n" +
+				"    \"components\":[\n" +
+				"        {\n" +
+				"            \"componentId\":\"\",\n" +
+				"            \"componentKey\":\"danhangwenben\",\n" +
+				"            \"componentValue\":\"这里是填充的文本\"\n" +
+				"        },\n" +
+				"        {\n" +
+				"            \"componentId\":\"\",\n" +
+				"            \"componentKey\":\"shuzi\",\n" +
+				"            \"componentValue\":\"1234567890\"\n" +
+				"        }\n" +
+				"    ]\n" +
+				"}";
+
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.POST;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+	/**
+	 * 删除模板
+	 */
+	private static EsignHttpResponse deleteDocTemplate() throws EsignDemoException {
+		String docTemplateId="a6f7e3b4xxxxxxxxfc89";
+		String apiaddr="/v3/doc-templates/"+docTemplateId;
+
+		//请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+		String jsonParm="{}";
+		//请求方法
+		EsignRequestType requestType= EsignRequestType.DELETE;
+		//生成签名鉴权方式的的header
+		Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+		//发起接口请求
+		return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+	}
+
+}

+ 144 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/members/MembersDemo.java

@@ -0,0 +1,144 @@
+package org.jeecg.modules.app.esign.members;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+
+/**
+ * description 企业机构成员服务
+ * @author  古柯
+ * @date  2022/8/20 10:42
+ * @version
+ */
+public class MembersDemo {
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+    //注意:使用企业成员管理服务之前需要调用认证授权口授予企业资源管理权限(manage_org_resource)
+    public static void main(String[] args) throws EsignDemoException, InterruptedException {
+        Gson gson = new Gson();
+        //添加企业机构成员
+        EsignHttpResponse createMembers = createMembers();
+        JsonObject createMembersObject = gson.fromJson(createMembers.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+createMembersObject);
+
+        //查询企业成员列表
+        EsignHttpResponse memberList = memberList();
+        JsonObject memberListObject = gson.fromJson(memberList.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+memberListObject);
+        //查询企业管理员
+        EsignHttpResponse administrators = administrators();
+        JsonObject administratorsObject = gson.fromJson(administrators.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+administratorsObject);
+
+        //删除企业成员
+        EsignHttpResponse deleteMembers = deleteMembers();
+        JsonObject deleteMembersObject = gson.fromJson(deleteMembers.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+deleteMembersObject);
+    }
+
+
+
+    /**
+     *添加企业机构成员
+     * @return
+     */
+    public static EsignHttpResponse createMembers() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";//调用认证服务查询企业认证授权状态接口获取orgId
+        String psnId="319f513178f242e590c04b2fc2bb8ca5";//调用认证服务查询个人认证授权状态接口获取psnId
+        String apiaddr="/v3/organizations/"+orgId+"/members";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+
+        String jsonParm="{\n" +
+                "  \"members\":[\n" +
+                "    {\n" +
+                "      \"psnId\":\""+psnId+"\",\n" +
+                "      \"memberName\":\"黄阳\",\n" +
+                "      \"employeeNum\":\"100\"\n" +
+                "    }\n" +
+                "  ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询企业成员列表
+     */
+
+    public static EsignHttpResponse memberList() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+        int pageNum=1;
+        int pageSize=10;
+
+        String apiaddr="/v3/organizations/"+orgId+"/member-list?pageNum="+pageNum+"&pageSize="+pageSize;
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+    /**
+     * 查询企业管理员
+     */
+
+    public static EsignHttpResponse administrators() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+
+        String apiaddr="/v3/organizations/"+orgId+"/administrators";
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 移除企业成员
+     */
+
+    public static EsignHttpResponse deleteMembers() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+        String memberPsnIds="319f513178f242e590c04b2fc2bb8ca5";
+
+        String apiaddr="/v3/organizations/"+orgId+"/members";
+        System.out.println(apiaddr);
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+
+        String jsonParm="{\n" +
+                "    \"memberPsnIds\":[\""+memberPsnIds+"\"]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        System.out.println("2464654646456465");
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+
+
+
+
+
+}

+ 182 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/scenedemo/PlatformSignToB.java

@@ -0,0 +1,182 @@
+package org.jeecg.modules.app.esign.scenedemo;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+import org.jeecg.modules.app.esign.fileAndTemplate.FileDemo;
+
+import java.util.Map;
+
+/**
+ * description 平台方自动签署企业手动签署场景
+ * @author 舞乐
+ */
+public class PlatformSignToB {
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+    public static void main(String[] args) throws EsignDemoException, InterruptedException {
+        Gson gson = new Gson();
+        //无前置实名,客户需要到签署流程中实名
+        //获取文件id以及文件上传地址
+        String filePath="E:/合同模板/test-template1.pdf";
+        EsignHttpResponse getUploadUrl = FileDemo.getUploadUrl(filePath);
+        JsonObject getUploadUrlJsonObject = gson.fromJson(getUploadUrl.getBody(), JsonObject.class);
+        JsonObject data = getUploadUrlJsonObject.getAsJsonObject("data");
+        //文件id后续发起签署使用
+        String fileId =data.get("fileId").getAsString();
+        String fileUploadUrl =data.get("fileUploadUrl").getAsString();
+        System.out.println("获取文件id以及文件上传地址成功,文件id:"+fileId);
+        System.out.println("上传链接:"+fileUploadUrl);
+
+        //文件上传
+        EsignHttpResponse uploadFileResponse = FileDemo.uploadFile(fileUploadUrl,filePath);
+        JsonObject uploadFileResponseJsonObject = gson.fromJson(uploadFileResponse.getBody(), JsonObject.class);
+        int errCode = uploadFileResponseJsonObject.get("errCode").getAsInt();
+        System.out.println("文件上传成功,状态码:"+errCode);
+
+
+        //文件上传成功后文件会有一个异步处理过程,建议轮询文件状态,正常后发起签署
+        //查询文件上传状态
+        int i=0;
+//        while(i<3) {
+//            EsignHttpResponse fileStatus = FileDemo.getFileStatus(fileId);
+//            JSONObject fileStatusJsonObject = JSONObject.parseObject(fileStatus.getBody());
+//            String status = fileStatusJsonObject.getJSONObject("data").getString("fileStatus");
+//            System.out.println(String.format("查询文件状态执行第%s次",i+1));
+//            if("2".equalsIgnoreCase(status)||"5".equalsIgnoreCase(status)){//查询状态为2或者5代表文件准备完成
+//                System.out.println("文件准备完成");
+//                break;
+//            }
+//            System.out.println("文件未准备完成,等待两秒重新查询");
+//            TimeUnit.SECONDS.sleep(2);
+//            i++;
+//        }
+        //发起签署
+//        EsignHttpResponse createByFile = createByFile();
+//        JSONObject createByFileJsonObject = JSONObject.parseObject(createByFile.getBody());
+//        String signFlowId = createByFileJsonObject.getJSONObject("data").getString("signFlowId");
+//        System.out.println("signFlowId:" + signFlowId);
+
+        //获取合同文件签署链接
+        // SignDemo.signUrl(signFlowId);
+
+        //下载已签署文件及附属材料
+        //SignDemo.fileDownloadUrl(signFlowId);
+
+    }
+
+    /**
+     * 发起签署
+     *
+     * @return
+     * @throws EsignDemoException
+     */
+    public static EsignHttpResponse createByFile() throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/create-by-file";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"docs\": [\n" +
+                "        {\n" +
+                "            \"fileId\": \"7ccce6f0e7b54f06b2e1df8f0ca84b87\",\n" +
+                "            \"fileName\": \"1234.pdf\"\n" +
+                "        }\n" +
+                "    ],\n" +
+                "    \"signFlowConfig\": {\n" +
+                "        \"signFlowTitle\": \"横山供用水合同\",\n" +
+                "        \"autoFinish\": true,\n" +
+                "        \"chargeConfig\": {\n" +
+                "            \"chargeMode\": 0\n" +
+                "        }\n" +
+                "    },\n" +
+                "    \"signers\": [\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"orgSignerInfo\": {\n" +
+                "                \"orgId\": \"215453190bxxxxxx181668e1c\"\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"signOrder\": 1\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"62453252523\",\n" +
+                "                    \"fileId\": \"7ccce6f0exxxxxxxe1df8f0ca84b87\",\n" +
+                "                    \"normalSignFieldConfig\": {\n" +
+                "                        \"assignedSealId\": \"\",\n" +
+                "                        \"autoSign\": true,\n" +//自动盖章参数:true - 后台自动落章(无感知),false - 签署页手动签章
+                "                        \"freeMode\": false,\n" +
+                "                        \"movableSignField\": false,\n" +
+                "                        \"orgSealBizTypes\": \"\",\n" +
+                "                        \"psnSealStyles\": \"\",\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 120,\n" +
+                "                            \"positionY\": 460\n" +
+                "                        },\n" +
+                "                        \"signFieldStyle\": 1\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 0\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 1\n" +
+                "        },\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"orgSignerInfo\": {\n" +
+                "                \"orgName\": \"xxx科技公司 \",\n" +
+                "                \"orgInfo\":{\n" +
+                "                    \"legalRepName\":\"孙x宏\",\n" +
+                "                    \"legalRepIDCardNum\":\"34102xxxxxxx19533\",\n" +
+                "                    \"legalRepIDCardType\":\"CRED_PSN_CH_IDCARD\"\n" +
+                "                },\n" +
+                "                \"transactorInfo\":{\n" +
+                "                    \"psnAccount\":\"181xxxxx34\"\n" +
+                "                }\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"signOrder\": 1\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"62453252523\",\n" +
+                "                    \"fileId\": \"7ccce6f0xxxxxxe1df8f0ca84b87\",\n" +
+                "                    \"normalSignFieldConfig\": {\n" +
+                "                        \"assignedSealId\": \"\",\n" +
+                "                        \"autoSign\": false,\n" +
+                "                        \"freeMode\": false,\n" +
+                "                        \"movableSignField\": false,\n" +
+                "                        \"orgSealBizTypes\": \"\",\n" +
+                "                        \"psnSealStyles\": \"\",\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 320,\n" +
+                "                            \"positionY\": 460\n" +
+                "                        },\n" +
+                "                        \"signFieldStyle\": 1\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 0\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 1\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成请求签名鉴权方式的Header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
+    }
+}

+ 176 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/scenedemo/PlatformSignToC.java

@@ -0,0 +1,176 @@
+package org.jeecg.modules.app.esign.scenedemo;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+import org.jeecg.modules.app.esign.fileAndTemplate.FileDemo;
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * description 平台方自动签署个人手动签署场景
+ * @author 舞乐
+ */
+public class PlatformSignToC {
+
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+    public static void main(String[] args) throws EsignDemoException, InterruptedException {
+        Gson gson = new Gson();
+        //无前置实名,客户需要到签署流程中实名
+        //获取文件id以及文件上传地址
+        String filePath="E:/合同模板/test-template1.pdf";
+        EsignHttpResponse getUploadUrl = FileDemo.getUploadUrl(filePath);
+        JsonObject getUploadUrlJsonObject = gson.fromJson(getUploadUrl.getBody(), JsonObject.class);
+        JsonObject data = getUploadUrlJsonObject.getAsJsonObject("data");
+        //文件id后续发起签署使用
+        String fileId =data.get("fileId").getAsString();
+        String fileUploadUrl =data.get("fileUploadUrl").getAsString();
+        System.out.println("获取文件id以及文件上传地址成功,文件id:"+fileId);
+        System.out.println("上传链接:"+fileUploadUrl);
+
+        //文件上传
+        EsignHttpResponse uploadFileResponse = FileDemo.uploadFile(fileUploadUrl,filePath);
+        JsonObject uploadFileResponseJsonObject = gson.fromJson(uploadFileResponse.getBody(), JsonObject.class);
+        int errCode = uploadFileResponseJsonObject.get("errCode").getAsInt();
+        System.out.println("文件上传成功,状态码:"+errCode);
+
+
+        //文件上传成功后文件会有一个异步处理过程,建议轮询文件状态,正常后发起签署
+        //查询文件上传状态
+        int i=0;
+        while(i<3) {
+            EsignHttpResponse fileStatus = FileDemo.getFileStatus(fileId);
+            JsonObject fileStatusJsonObject = gson.fromJson(fileStatus.getBody(), JsonObject.class);
+            String status = fileStatusJsonObject.getAsJsonObject("data").get("fileStatus").getAsString();
+            System.out.println(String.format("查询文件状态执行第%s次",i+1));
+            if("2".equalsIgnoreCase(status)||"5".equalsIgnoreCase(status)){//查询状态为2或者5代表文件准备完成
+                System.out.println("文件准备完成");
+                break;
+            }
+            System.out.println("文件未准备完成,等待两秒重新查询");
+            TimeUnit.SECONDS.sleep(2);
+            i++;
+        }
+        //发起签署
+//        EsignHttpResponse createByFile = createByFile();
+//        JSONObject createByFileJsonObject = JSONObject.parseObject(createByFile.getBody());
+//        String signFlowId = createByFileJsonObject.getJSONObject("data").getString("signFlowId");
+//        System.out.println(signFlowId);
+
+        //获取合同文件签署链接
+        //SignDemo.signUrl(signFlowId);
+
+        //下载已签署文件及附属材料
+        //SignDemo.fileDownloadUrl(signFlowId);
+
+    }
+
+    /**
+     * 发起签署
+     *
+     * @return
+     * @throws EsignDemoException
+     */
+    public static EsignHttpResponse createByFile() throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/create-by-file";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"docs\": [\n" +
+                "        {\n" +
+                "            \"fileId\": \"64125cc6121xxxxxx37525e7a0890\",\n" +
+                "            \"fileName\": \"1234.pdf\"\n" +
+                "        }\n" +
+                "    ],\n" +
+                "    \"signFlowConfig\": {\n" +
+                "        \"signFlowTitle\": \"测试合同\",\n" +
+                "        \"autoFinish\": true,\n" +
+                "        \"chargeConfig\": {\n" +
+                "            \"chargeMode\": 0\n" +
+                "        }\n" +
+                "    },\n" +
+                "    \"signers\": [\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"orgSignerInfo\": {\n" +
+                "                \"orgId\": \"21545xxxxxxx4bd6b6d9694181668e1c\"\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"signOrder\": 1\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"62453252523\",\n" +
+                "                    \"fileId\": \"64125cxxxxxx3537525e7a0890\",\n" +
+                "                    \"normalSignFieldConfig\": {\n" +
+                "                        \"assignedSealId\": \"\",\n" +
+                "                        \"autoSign\": true,\n" +
+                "                        \"freeMode\": false,\n" +
+                "                        \"movableSignField\": false,\n" +
+                "                        \"orgSealBizTypes\": \"\",\n" +
+                "                        \"psnSealStyles\": \"\",\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 120,\n" +
+                "                            \"positionY\": 460\n" +
+                "                        },\n" +
+                "                        \"signFieldStyle\": 1\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 0\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 1\n" +
+                "        },\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"psnSignerInfo\":{\n" +
+                "                    \"psnAccount\":181xxxxx234\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"signOrder\": 1\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"62453252523\",\n" +
+                "                    \"fileId\": \"64125cc6xxxxxx37525e7a0890\",\n" +
+                "                    \"normalSignFieldConfig\": {\n" +
+                "                        \"assignedSealId\": \"\",\n" +
+                "                        \"autoSign\": false,\n" +
+                "                        \"freeMode\": false,\n" +
+                "                        \"movableSignField\": false,\n" +
+                "                        \"orgSealBizTypes\": \"\",\n" +
+                "                        \"psnSealStyles\": \"\",\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 320,\n" +
+                "                            \"positionY\": 460\n" +
+                "                        },\n" +
+                "                        \"signFieldStyle\": 1\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 0\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 0\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成请求签名鉴权方式的Header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
+    }
+}

+ 314 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/seal/SealDemo.java

@@ -0,0 +1,314 @@
+package org.jeecg.modules.app.esign.seal;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+
+/**
+ * description 印章服务
+ * @author  古柯
+ * @date  2022/8/20 10:42
+ * @version
+ */
+public class SealDemo {
+
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+
+    //注意:使用印章服务之前需要调用认证授权口授予资源管理权限(manage_org_resource)
+    public static void main(String[] args) throws EsignDemoException, InterruptedException {
+        Gson gson = new Gson();
+     /*   //创建个人模板印章
+        EsignHttpResponse createByTemplate = createByTemplate();
+        JsonObject createByTemplateObject = gson.fromJson(createByTemplate.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+createByTemplateObject);
+
+
+        //查询个人印章列表
+        EsignHttpResponse psnSealList = psnSealList();
+        JsonObject psnSealListObject = gson.fromJson(psnSealList.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+psnSealListObject);
+
+        //删除个人印章
+        EsignHttpResponse deletePsnSeal = deletePsnSeal();
+        JsonObject deletePsnSealObject = gson.fromJson(deletePsnSeal.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+deletePsnSealObject);
+   */
+
+
+    //企业印章场景
+        //创建机构模板印章
+        EsignHttpResponse createOrgByTemplate = createOrgByTemplate();
+        JsonObject createOrgByTemplateObject = gson.fromJson(createOrgByTemplate.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+createOrgByTemplateObject);
+        //查询企业内部印章
+        EsignHttpResponse orgOwnSealList = orgOwnSealList();
+        JsonObject orgOwnSealListObject = gson.fromJson(orgOwnSealList.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orgOwnSealListObject);
+        //查询被外部企业授权印章
+        EsignHttpResponse orgAuthorizedSealList = orgAuthorizedSealList();
+        JsonObject orgAuthorizedSealListObject = gson.fromJson(orgAuthorizedSealList.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orgAuthorizedSealListObject);
+        //跨企业印章授权
+        EsignHttpResponse orgSealsExternalAuth = orgSealsExternalAuth();
+        JsonObject orgSealsExternalAuthObject = gson.fromJson(orgSealsExternalAuth.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orgSealsExternalAuthObject);
+        //解除印章授权
+        EsignHttpResponse orgSealsauthDelete = orgSealsauthDelete();
+        JsonObject orgSealsauthDeleteObject = gson.fromJson(orgSealsauthDelete.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+orgSealsauthDeleteObject);
+        //删除企业印章
+        EsignHttpResponse deleteOrgSeal = deleteOrgSeal();
+        JsonObject deleteOrgSealObject = gson.fromJson(deleteOrgSeal.getBody(), JsonObject.class);
+        System.out.println("请求返回:"+deleteOrgSealObject);
+
+
+    }
+    /**
+     *创建个人模板印章
+     * @return
+     */
+    public static EsignHttpResponse createByTemplate() throws EsignDemoException {
+        String psnId="319f513178f242e590c04b2fc2bb8ca5";
+        String apiaddr="/v3/seals/psn-seals/create-by-template";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm="{\n" +
+                "  \"psnId\": \""+psnId+"\",\n" +
+                "  \"sealName\": \"这是一个自定义的名称2\",\n" +
+                "  \"sealTemplateStyle\": \"RECTANGLE_NO_BORDER\",\n" +
+                "  \"sealSize\":\"20_10\",\n" +
+                "  \"sealColor\": \"RED\",\n" +
+                "  \"sealSuffix\": \"2\",\n" +
+                "  \"sealOldStyle\": \"OLD_1\",\n" +
+                "  \"sealOpacity\": \"100\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询个人印章列表
+     */
+
+    public static EsignHttpResponse psnSealList() throws EsignDemoException {
+        String psnId="319f513178f242e590c04b2fc2bb8ca5";
+        String apiaddr="/v3/seals/psn-seal-list?psnId="+psnId+"&pageNum=1&pageSize=20";
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+
+    /**
+     * 删除个人印章
+     */
+
+    public static EsignHttpResponse deletePsnSeal() throws EsignDemoException {
+        String psnId="319f513178f242e590c04b2fc2bb8ca5";
+        String sealId="a7b4ca07-ee51-446e-a3c5-3a7e85d117c4";
+        String apiaddr="/v3/seals/psn-seal?psnId="+psnId+"&sealId="+sealId;
+        System.out.println(apiaddr);
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+    /**
+     *创建机构模板印章
+     * @return
+     */
+    public static EsignHttpResponse createOrgByTemplate() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+
+        String apiaddr="/v3/seals/org-seals/create-by-template";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm="{\n" +
+                "  \"orgId\": \""+orgId+"\",\n" +
+                "  \"sealName\": \"企业公章1\",\n" +
+                "  \"sealTemplateStyle\": \"PERSONNEL_ROUND_NO_STAR\",\n" +
+                "  \"sealOpacity\": \"100\",\n" +
+                "  \"sealColor\": \"RED\",\n" +
+                "  \"sealOldStyle\": \"OLD_12\",\n" +
+                "  \"sealSize\":\"38_38\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询企业内部印章
+     */
+
+    public static EsignHttpResponse orgOwnSealList() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+        int pageNum=1;
+        int pageSize=10;
+
+        String apiaddr="/v3/seals/org-own-seal-list?orgId="+orgId+"&pageNum="+pageNum+"&pageSize="+pageSize;
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+    /**
+     * 查询被外部企业授权印章
+     */
+
+    public static EsignHttpResponse orgAuthorizedSealList() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+        int pageNum=1;
+        int pageSize=10;
+        String apiaddr="/v3/seals/org-authorized-seal-list?orgId="+orgId+"&pageNum="+pageNum+"&pageSize="+pageSize;
+
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 删除机构印章
+     */
+
+    public static EsignHttpResponse deleteOrgSeal() throws EsignDemoException {
+        String orgId="89621ebc8fe64239b61001c46caa8de6";
+        String sealId="";
+        String apiaddr="/v3/seals/org-seal?orgId="+orgId+"&sealId="+sealId;
+        System.out.println(apiaddr);
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 跨企业授权
+     */
+
+    public static EsignHttpResponse orgSealsExternalAuth() throws EsignDemoException {
+
+        String orgId="89621ebc8fe64239b61001c46caa8de6";//授权企业账号id
+        String transactorPsnId="319f513178f242e590c04b2fc2bb8ca5 ";//操作人的账号id
+        String orgName="esigntest-guke";//被授权的企业名称
+        String orgIDCardNum="913301087458302417";//被授权企业证件号
+        String sealId="475f2ebc-dc17-xxxx-8xx5-714ded5cbb0a";
+
+        String apiaddr="/v3/seals/org-seals/external-auth";
+        System.out.println(apiaddr);
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+
+
+
+        String jsonParm="{\n" +
+                "    \"orgId\": \""+orgId+"\",\n" +
+                "    \"effectiveTime\": 1636525541000,\n" +
+                "    \"expireTime\": 1668061541000,\n" +
+                "    \"transactorPsnId\":\""+transactorPsnId+"\",\n" +
+                "    \"authorizedOrgInfo\":{\n" +
+                "        \"orgName\":\""+orgName+"\",\n" +
+                "        \"orgIDCardNum\":\""+orgIDCardNum+"\"\n" +
+                "    },\n" +
+                "    \"sealId\": \""+sealId+"\",\n" +
+                "    \"redirectUrl\": \"https://www.xx.cn/\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+
+    /**
+     * 解除印章授权
+     */
+
+    public static EsignHttpResponse orgSealsauthDelete() throws EsignDemoException {
+
+        String orgId="97fb16472026xxxx405a28c58428c7";//授权企业账号id
+        String sealId="475f2ebc-dc17-xxxx-89xxx-714ded5cbb0a";
+        String apiaddr="/v3/seals/org-seals/auth-delete";
+        System.out.println(apiaddr);
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+
+        String jsonParm="{   \n" +
+                "     \"orgId\": \""+orgId+"\",\n" +
+                "     \"deleteType\":\"sealIds\",\n" +
+                "     \"sealIds\":[\""+sealId+"\"]\n" +
+                "} ";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}

+ 724 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/esign/sign/SignDemo.java

@@ -0,0 +1,724 @@
+package org.jeecg.modules.app.esign.sign;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import org.jeecg.modules.app.esign.comm.EsignHttpHelper;
+import org.jeecg.modules.app.esign.comm.EsignHttpResponse;
+import org.jeecg.modules.app.esign.constant.EsignDemoConfig;
+import org.jeecg.modules.app.esign.enums.EsignRequestType;
+import org.jeecg.modules.app.esign.exception.EsignDemoException;
+
+import java.util.Map;
+
+public class SignDemo {
+    private static String eSignHost= EsignDemoConfig.EsignHost;
+    private static String eSignAppId=EsignDemoConfig.EsignAppId;
+    private static String eSignAppSecret=EsignDemoConfig.EsignAppSecret;
+    public static String signFlowId = "";
+    public static String fileId = "";
+
+
+    public static void main(String[] args) throws EsignDemoException {
+        Gson gson = new Gson();
+        /* 发起签署*/
+        EsignHttpResponse createByFile = createByFile();
+        //JSONObject getPsnAuthUrlObject = JSONObject.parseObject(getPsnAuthUrl.getBody());
+        JsonObject createByFileJsonObject = gson.fromJson(createByFile.getBody(), JsonObject.class);
+        JsonObject createByFileData = createByFileJsonObject.getAsJsonObject("data");
+        String authUrl = createByFileData.get("signFlowId").getAsString();
+        System.err.println("流程id:"+signFlowId);
+
+        //获取合同文件签署链接
+        EsignHttpResponse signUrl = signUrl(signFlowId);
+        JsonObject signUrlJsonObject = gson.fromJson(signUrl.getBody(), JsonObject.class);
+        JsonObject signUrlData = signUrlJsonObject.getAsJsonObject("data");
+        String shortUrl = signUrlData.get("shortUrl").getAsString();
+        String url = signUrlData.get("url").getAsString();
+        System.out.println("签署长链接:" +shortUrl);
+        System.out.println("签署短链接:"+url);
+
+        //获取批量签页面链接(多流程)
+        EsignHttpResponse batchSignUrl = batchSignUrl();
+        JsonObject batchSignUrlJsonObject = gson.fromJson(batchSignUrl.getBody(),JsonObject.class);
+        System.out.println(batchSignUrlJsonObject);
+
+        //下载已签署文件及附属材料
+        EsignHttpResponse fileDownloadUrl = fileDownloadUrl(signFlowId);
+        JsonObject fileDownloadUrlJsonObject = gson.fromJson(fileDownloadUrl.getBody(),JsonObject.class);
+        JsonObject fileDownloadUrlArray = fileDownloadUrlJsonObject.getAsJsonObject("data");
+        System.out.println(fileDownloadUrlArray);
+
+        //开启签署流程
+        EsignHttpResponse signFlowStart = signFlowStart(signFlowId);
+        JsonObject signFlowStartJsonObject = gson.fromJson(signFlowStart.getBody(),JsonObject.class);
+        System.out.println(signFlowStartJsonObject);
+
+        //完结签署流程
+        EsignHttpResponse signFlowFinish = signFlowFinish(signFlowId);
+        JsonObject signFlowFinishJsonObject = gson.fromJson(signFlowFinish.getBody(),JsonObject.class);
+        System.out.println(signFlowFinishJsonObject);
+
+        //撤销签署流程
+        EsignHttpResponse signFlowRevoke = signFlowRevoke(signFlowId);
+        JsonObject signFlowRevokeJsonObject = gson.fromJson(signFlowRevoke.getBody(),JsonObject.class);
+        System.out.println(signFlowRevokeJsonObject);
+
+        //延期签署截止时间
+        EsignHttpResponse signFlowDelay = signFlowDelay(signFlowId);
+        JsonObject signFlowDelayJsonObject = gson.fromJson(signFlowDelay.getBody(),JsonObject.class);
+        System.out.println(signFlowDelayJsonObject);
+
+        //催签流程中签署人
+        EsignHttpResponse signFlowUrge= signFlowUrge(signFlowId);
+        JsonObject signFlowUrgeJsonObject = gson.fromJson(signFlowUrge.getBody(),JsonObject.class);
+        System.out.println(signFlowUrgeJsonObject);
+
+        //查询签署流程详情
+        EsignHttpResponse signFlowDetail = signFlowDetail(signFlowId);
+        JsonObject signFlowDetailJsonObject = gson.fromJson(signFlowDetail.getBody(),JsonObject.class);
+        System.out.println(signFlowDetailJsonObject);
+
+        //查询签署流程列表
+        EsignHttpResponse signFlowList = signFlowList();
+        JsonObject signFlowListJsonObject = gson.fromJson(signFlowList.getBody(),JsonObject.class);
+        System.out.println(signFlowListJsonObject);
+
+        //追加签署区
+        EsignHttpResponse signFieldsAdd = signFieldsAdd(signFlowId);
+        JsonObject signFieldsAddJsonObject = gson.fromJson(signFieldsAdd.getBody(),JsonObject.class);
+        System.out.println(signFieldsAddJsonObject);
+
+        //删除签署区
+        EsignHttpResponse signFieldsDelete = signFieldsDelete(signFlowId);
+        JsonObject signFieldsDeleteJsonObject = gson.fromJson(signFieldsDelete.getBody(),JsonObject.class);
+        System.out.println(signFieldsDeleteJsonObject);
+
+        //追加待签文件
+        EsignHttpResponse unsignedFilesAdd = unsignedFilesAdd(signFlowId);
+        JsonObject unsignedFilesAddJsonObject = gson.fromJson(unsignedFilesAdd.getBody(),JsonObject.class);
+        System.out.println(unsignedFilesAddJsonObject);
+
+        //删除待签文件
+        EsignHttpResponse unsignedFilesDelete = unsignedFilesDelete(signFlowId);
+        JsonObject unsignedFilesDeleteJsonObject = gson.fromJson(unsignedFilesDelete.getBody(),JsonObject.class);
+        System.out.println(unsignedFilesDeleteJsonObject);
+
+        //追加附属材料
+        EsignHttpResponse attachmentsAdd = attachmentsAdd(signFlowId);
+        JsonObject attachmentsAddJsonObject = gson.fromJson(attachmentsAdd.getBody(),JsonObject.class);
+        System.out.println(attachmentsAddJsonObject);
+
+        //删除附属材料
+        EsignHttpResponse attachmentsDelete = attachmentsDelete(signFlowId);
+        JsonObject attachmentsDeleteJsonObject = gson.fromJson(attachmentsDelete.getBody(),JsonObject.class);
+        System.out.println(attachmentsDeleteJsonObject);
+
+        //添加抄送方
+        EsignHttpResponse copiersAdd = copiersAdd(signFlowId);
+        JsonObject copiersAddJsonObject = gson.fromJson(copiersAdd.getBody(),JsonObject.class);
+        System.out.println(copiersAddJsonObject);
+
+        //添加抄送方
+        EsignHttpResponse copiersDelete = copiersDelete(signFlowId);
+        JsonObject copiersDeleteJsonObject = gson.fromJson(copiersDelete.getBody(),JsonObject.class);
+        System.out.println(copiersDeleteJsonObject);
+
+        //核验合同文件签名有效性
+        EsignHttpResponse filesVerify = filesVerify(fileId);
+        JsonObject filesVerifyJsonObject = gson.fromJson(filesVerify.getBody(),JsonObject.class);
+        System.out.println(filesVerifyJsonObject);
+
+        //获取区块链存证信息
+        EsignHttpResponse antchainFileInfo = antchainFileInfo(fileId);
+        JsonObject antchainFileInfoJsonObject = gson.fromJson(antchainFileInfo.getBody(),JsonObject.class);
+        System.out.println(antchainFileInfoJsonObject);
+
+        //核验区块链存证文件
+        EsignHttpResponse antchainFileInfoVerify = antchainFileInfoVerify();
+        JsonObject antchainFileInfoVerifyJsonObject = gson.fromJson(antchainFileInfoVerify.getBody(),JsonObject.class);
+        System.out.println(antchainFileInfoVerifyJsonObject);
+
+        //获取合同解约链接
+        EsignHttpResponse signflowRescissionUrl = signflowRescissionUrl(signFlowId);
+        JsonObject signflowRescissionUrlJsonObject = gson.fromJson(signflowRescissionUrl.getBody(),JsonObject.class);
+        System.out.println(signflowRescissionUrlJsonObject);
+
+    }
+
+    /**
+     * 获取合同解约链接
+     * @return
+     */
+    public static EsignHttpResponse signflowRescissionUrl(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/rescission-url";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"rescissionInitiator\": {\n" +
+                "        \"orgInitiator\": {\n" +
+                "            \"orgId\": \"0c5bd49248***5648bfbf\",\n" +
+                "            \"transactor\": {\n" +
+                "                \"psnId\": \"c7e002947***310541e7\"\n" +
+                "            }\n" +
+                "        }\n" +
+                "    },\n" +
+                "    \"signFlowConfig\": {\n" +
+                "        \"chargeConfig\": {\n" +
+                "            \"chargeMode\": 0\n" +
+                "        },\n" +
+                "        \"noticeConfig\": {\n" +
+                "            \"noticeTypes\": \"1,2\"\n" +
+                "        },\n" +
+                "        \"notifyUrl\": \"https://xx.xx.xx/callback\"\n" +
+                "    }\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 核验区块链存证文件
+     * @return
+     */
+    public static EsignHttpResponse antchainFileInfoVerify() throws EsignDemoException {
+        String apiaddr= "/v3/antchain-file-info/verify";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"fileHash\": \"bcdc3c***0477\",\n" +
+                "    \"antTxHash\": \"11111111222222226c***fd1ed2f4\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 获取区块链存证信息
+     * @return
+     */
+    public static EsignHttpResponse antchainFileInfo(String fileId) throws EsignDemoException {
+        String apiaddr= "/v3/antchain-file-info";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"signFlowId\": \"\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 核验合同文件签名有效性
+     * @return
+     */
+    public static EsignHttpResponse filesVerify(String fileId) throws EsignDemoException {
+        String apiaddr= "/v3/files/"+ fileId + "verify";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"signFlowId\": \"\"\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 删除抄送方
+     * @return
+     */
+    public static EsignHttpResponse copiersDelete(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/copiers/delete";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"copiers\": [\n" +
+                "        {\n" +
+                "            \"copierPsnInfo\": {\n" +
+                "                \"psnId\": \"\",\n" +
+                "                \"psnAccount\": \"151****0101\"\n" +
+                "            },\n" +
+                "            \"copierOrgInfo\": {\n" +
+                "                \"orgId\": \"\",\n" +
+                "                \"orgName\": \"这是个抄送方的企业名称\"\n" +
+                "            }\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 添加抄送方
+     * @return
+     */
+    public static EsignHttpResponse copiersAdd(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/copiers";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"copiers\": [\n" +
+                "        {\n" +
+                "            \"copierOrgInfo\": {\n" +
+                "                \"orgName\": \"这是个抄送通知企业的名称\",\n" +
+                "                \"orgId\": \"\"\n" +
+                "            },\n" +
+                "            \"copierPsnInfo\": {\n" +
+                "                \"psnAccount\": \"153****7650\",\n" +
+                "                \"psnId\": \"\"\n" +
+                "            }\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 删除附属材料
+     * @return
+     */
+    public static EsignHttpResponse attachmentsDelete(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/attachments?fileIds=xxx1,xxx2";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = null;
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 追加附属材料
+     * @return
+     */
+    public static EsignHttpResponse attachmentsAdd(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/attachments";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"attachmentList\": [\n" +
+                "        {\n" +
+                "            \"fileId\": \"ea3151***a53d3f4c\",\n" +
+                "            \"fileName\": \"入职手册.pdf\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 删除待签文件
+     * @return
+     */
+    public static EsignHttpResponse unsignedFilesDelete(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/unsigned-files?fileIds=xxx1,xxx2";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = null;
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 追加待签文件
+     * @return
+     */
+    public static EsignHttpResponse unsignedFilesAdd(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/unsigned-files";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"unsignedFiles\": [\n" +
+                "        {\n" +
+                "            \"fileId\": \"ea3151a8d***a53d3f4c\",\n" +
+                "            \"fileName\": \"入职证明.pdf\"\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 删除签署区
+     * @return
+     */
+    public static EsignHttpResponse signFieldsDelete(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/signers/sign-fields?signFieldIds=xxx1,xxx2";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = null;
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.DELETE;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 追加签署区
+     * @return
+     */
+    public static EsignHttpResponse signFieldsAdd(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/signers/sign-fields";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"signers\": [\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"psnSignerInfo\": {\n" +
+                "                \"psnAccount\": \"153****0000\"\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"forcedReadingTime\": 10,\n" +
+                "                \"signOrder\": 2\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"202201010001\",\n" +
+                "                    \"fileId\": \"0e99de7c***09db2cd69\",\n" +
+                "                    \"remarkSignFieldConfig\": {\n" +
+                "                        \"aiCheck\": 0,\n" +
+                "                        \"freeMode\": true,\n" +
+                "                        \"movableSignField\": true,\n" +
+                "                        \"remarkContent\": \"我已阅读并知悉\",\n" +
+                "                        \"remarkFontSize\": 20,\n" +
+                "                        \"signFieldHeight\": 100,\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"acrossPageMode\": \"\",\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 100,\n" +
+                "                            \"positionY\": 100\n" +
+                "                        },\n" +
+                "                        \"signFieldWidth\": 100\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 1\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 0\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询签署流程列表
+     * @return
+     */
+    public static EsignHttpResponse signFlowList() throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/sign-flow-list";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"operator\": {\n" +
+                "        \"psnAccount\": \"18******34\",\n" +
+                "        \"psnId\": \"\"\n" +
+                "    },\n" +
+                "    \"pageNum\": 1,\n" +
+                "    \"pageSize\": 20,\n" +
+                "    \"signFlowStartTimeFrom\": 1648801671000,\n" +
+                "    \"signFlowStartTimeTo\": 1651393671000,\n" +
+                "    \"signFlowStatus\": [\n" +
+                "        1,\n" +
+                "        2\n" +
+                "    ]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 查询签署流程详情
+     * @return
+     */
+    public static EsignHttpResponse signFlowDetail(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/detail";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = null;
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 催签流程中签署人
+     * @return
+     */
+    public  static EsignHttpResponse signFlowUrge(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/urge";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm="{\n" +
+                "    \"noticeTypes\": \"1\",\n" +
+                "    \"urgedOperator\": {\n" +
+                "        \"psnAccount\": \"183****0101\"\n" +
+                "    }\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 延期签署截止时间
+     * @return
+     */
+    public static EsignHttpResponse signFlowDelay(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/delay";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 撤销签署流程
+     * @return
+     */
+    public static EsignHttpResponse signFlowRevoke(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ signFlowId + "/revoke";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm="{}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 完结签署流程
+     * @return
+     * @param signFlowId
+     */
+    public static EsignHttpResponse signFlowFinish(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ SignDemo.signFlowId + "/finish";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm="{}";
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 开启签署流程     *
+     * @return
+     * @param signFlowId
+     */
+    public static EsignHttpResponse signFlowStart(String signFlowId) throws EsignDemoException {
+        String apiaddr= "/v3/sign-flow/"+ SignDemo.signFlowId +"/start";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm= null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.POST;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+    /**
+     * 下载已签署文件及附属材料     *
+     * @return
+     * @throws EsignDemoException
+     */
+    public static EsignHttpResponse fileDownloadUrl(String signFlowId) throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/"+ signFlowId +"/file-download-url";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm=null;
+        //请求方法
+        EsignRequestType requestType= EsignRequestType.GET;
+        //生成签名鉴权方式的的header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId,eSignAppSecret,jsonParm,requestType.name(),apiaddr,true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr,requestType , jsonParm, header,true);
+    }
+
+
+
+    /**
+     * 获取批量签页面链接(多流程)
+     * @return
+     */
+    public static EsignHttpResponse batchSignUrl() throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/batch-sign-url";
+        String jsonParm = "{\n" +
+                "    \"operatorId\":\"0f375***********5738d976\",\n" +
+                "    \"redirectUrl\":\"https://www.esign.cn\",\n" +
+                "    \"signFlowIds\":[\"1fc79b***********1f2d5fd\"]\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成请求签名鉴权方式的Header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
+    }
+
+    /**
+     * 获取合同文件签署链接
+     * @return
+     * @throws EsignDemoException
+     */
+    public static EsignHttpResponse signUrl(String signFlowId) throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/" + signFlowId + "/sign-url";
+        String jsonParm = "{\n" +
+                "    \"clientType\": \"ALL\",\n" +
+                "    \"needLogin\": true,\n" +
+                "    \"operator\": {\n" +
+                "        \"psnAccount\":\"181xxxxxx\"\n" +
+                "    },\n" +
+                "    \"organization\": {\n" +
+                "        \"orgName\": \"**科技信息有限公司\"\n" +
+                "    },\n" +
+                "    \"urlType\": 1\n" +
+                "}";
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成请求签名鉴权方式的Header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
+    }
+
+    /**
+     * 发起签署
+     * @return
+     * @throws EsignDemoException
+     */
+    public static EsignHttpResponse createByFile() throws EsignDemoException {
+        String apiaddr = "/v3/sign-flow/create-by-file";
+        //请求参数body体,json格式。get或者delete请求时jsonString传空json:"{}"或者null
+        String jsonParm = "{\n" +
+                "    \"docs\": [\n" +
+                "        {\n" +
+                "            \"fileId\": \"c3c22a9***********fa9c482\",\n" +
+                "            \"fileName\": \"1234.pdf\"\n" +
+                "        }\n" +
+                "    ],\n" +
+                "    \"signFlowConfig\": {\n" +
+                "        \"signFlowTitle\": \"测试合同\",\n" +
+                "        \"chargeConfig\": {\n" +
+                "            \"chargeMode\": 0\n" +
+                "        }\n" +
+                "    },\n" +
+                "    \"signers\": [\n" +
+                "        {\n" +
+                "            \"noticeConfig\": {\n" +
+                "                \"noticeTypes\": \"1\"\n" +
+                "            },\n" +
+                "            \"orgSignerInfo\": {\n" +
+                "                \"orgId\": \"\",\n" +
+                "                \"orgInfo\": {\n" +
+                "                    \"legalRepIDCardNum\": \"\",\n" +
+                "                    \"legalRepIDCardType\": \"\",\n" +
+                "                    \"legalRepName\": \"孙xx\",\n" +
+                "                    \"orgIDCardNum\": \"915******52355\",\n" +
+                "                    \"orgIDCardType\": \"CRED_ORG_USCC\"\n" +
+                "                },\n" +
+                "                \"orgName\": \"**科技信息有限公司\",\n" +
+                "                \"transactorInfo\": {\n" +
+                "                    \"psnAccount\": \"18********79\",\n" +
+                "                    \"psnId\": \"\",\n" +
+                "                    \"psnInfo\": {\n" +
+                "                        \"bankCardNum\": \"\",\n" +
+                "                        \"psnIDCardNum\": \"\",\n" +
+                "                        \"psnIDCardType\": \"\",\n" +
+                "                        \"psnName\": \"\"\n" +
+                "                    }\n" +
+                "                }\n" +
+                "            },\n" +
+                "            \"signConfig\": {\n" +
+                "                \"signOrder\": 1\n" +
+                "            },\n" +
+                "            \"signFields\": [\n" +
+                "                {\n" +
+                "                    \"customBizNum\": \"62453252523\",\n" +
+                "                    \"fileId\": \"c3c22a9***********87cfa9c482\",\n" +
+                "                    \"normalSignFieldConfig\": {\n" +
+                "                        \"assignedSealId\": \"\",\n" +
+                "                        \"autoSign\": false,\n" +
+                "                        \"freeMode\": true,\n" +
+                "                        \"movableSignField\": true,\n" +
+                "                        \"orgSealBizTypes\": \"\",\n" +
+                "                        \"psnSealStyles\": \"\",\n" +
+                "                        \"signFieldPosition\": {\n" +
+                "                            \"positionPage\": \"1\",\n" +
+                "                            \"positionX\": 120,\n" +
+                "                            \"positionY\": 460\n" +
+                "                        },\n" +
+                "                        \"signFieldStyle\": 1\n" +
+                "                    },\n" +
+                "                    \"signFieldType\": 0\n" +
+                "                }\n" +
+                "            ],\n" +
+                "            \"signerType\": 1\n" +
+                "        }\n" +
+                "    ]\n" +
+                "}";
+
+        //请求方法
+        EsignRequestType requestType = EsignRequestType.POST;
+        //生成请求签名鉴权方式的Header
+        Map<String, String> header = EsignHttpHelper.signAndBuildSignAndJsonHeader(eSignAppId, eSignAppSecret, jsonParm, requestType.name(), apiaddr, true);
+        //发起接口请求
+        return EsignHttpHelper.doCommHttp(eSignHost, apiaddr, requestType, jsonParm, header, true);
+    }
+
+
+}

+ 10 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/IOrderService.java

@@ -3,6 +3,7 @@ package org.jeecg.modules.app.service;
 import org.jeecg.modules.app.vo.OrderVO;
 
 import java.util.Date;
+import java.util.List;
 
 public interface IOrderService {
 
@@ -50,4 +51,13 @@ public interface IOrderService {
      * @return OrderVO.PreviewOrderPlaceGymnasiumChartered {@link OrderVO.PreviewOrderPlaceGymnasiumChartered}
      **/
     OrderVO.PreviewOrderPlaceGymnasiumChartered previewOrderPlaceGymnasiumChartered(String rulesId);
+
+    /**
+     * @Author SheepHy
+     * @Description 学校包场-预览时间选择
+     * @Date 14:45 2025/7/17
+     * @Param placeId
+     * @return OrderVO.PreviewOrderPlaceSchoolTime {@link OrderVO.PreviewOrderPlaceSchoolTime}
+     **/
+    List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTime(String placeId);
 }

+ 1 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/AppHomeServiceImpl.java

@@ -150,6 +150,7 @@ public class AppHomeServiceImpl implements IAppHomeService {
                 .map(courses -> new CourseVO()
                         .setId(courses.getId()).setCover(courses.getCover())
                         .setPriceType(courses.getPriceType())
+                        .setCover(courses.getBackgroundImage())
                         .setSellingPrice(courses.getSellingPrice()))
                 .collect(Collectors.toList());
     }

+ 7 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/service/impl/OrderServiceImpl.java

@@ -46,6 +46,8 @@ public class OrderServiceImpl implements IOrderService {
     private AppIsinMapper appIsinMapper;
     @Resource
     private FamilyMembersMapper familyMembersMapper;
+    @Resource
+    private AppTeachingTimeMapper appTeachingTimeMapper;
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -167,6 +169,11 @@ public class OrderServiceImpl implements IOrderService {
                 .setStoreName(depart != null ? depart.getDepartName() : "未知门店");
     }
 
+    @Override
+    public List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTime(String placeId) {
+        return appTeachingTimeMapper.previewOrderPlaceSchoolTime(appSitePlaceMapper.selectById(placeId).getOrgCode());
+    }
+
     /**
      * @Author SheepHy
      * @Description 查询用户对该类型课程是否有试听资格

+ 14 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/app/vo/OrderVO.java

@@ -171,5 +171,18 @@ public class OrderVO {
         @Schema(description = "到期时间")
         private Date expireTime;
     }
-
+    @Data
+    @Accessors(chain = true)
+    @EqualsAndHashCode(callSuper = false)
+    @Schema(description="学校包场-预览时间选择")
+    public static class PreviewOrderPlaceSchoolTime{
+        @JsonFormat(timezone = "GMT+8", pattern = "MM-dd")
+        @DateTimeFormat(pattern = "MM-dd")
+        @Schema(description = "日期")
+        private Date day;
+        @Schema(description = "当前剩余库存")
+        private int inventory;
+        @Schema(description = "简称")
+        private String namedDay;
+    }
 }

+ 12 - 5
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/AppTeachingTimeMapper.java

@@ -1,10 +1,10 @@
 package org.jeecg.modules.system.app.mapper;
 
-import java.util.List;
-
-import org.apache.ibatis.annotations.Param;
-import org.jeecg.modules.system.app.entity.AppTeachingTime;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.jeecg.modules.app.vo.OrderVO;
+import org.jeecg.modules.system.app.entity.AppTeachingTime;
+
+import java.util.List;
 
 /**
  * @Description: 教学/非教学维护表
@@ -13,5 +13,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * @Version: V1.0
  */
 public interface AppTeachingTimeMapper extends BaseMapper<AppTeachingTime> {
-
+    /**
+     * @Author SheepHy
+     * @Description 学校包场-预览时间选择
+     * @Date 14:45 2025/7/17
+     * @Param placeId
+     * @return OrderVO.PreviewOrderPlaceSchoolTime {@link OrderVO.PreviewOrderPlaceSchoolTime}
+     **/
+    List<OrderVO.PreviewOrderPlaceSchoolTime> previewOrderPlaceSchoolTime(String orgCode);
 }

+ 1 - 1
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppCoursesMapper.xml

@@ -65,7 +65,7 @@
         WHERE
             a.STATUS = 0
           AND a.del_flag = 0
-          AND a.address_site_id = #{id}
+          AND a.id = #{id}
         GROUP BY
             a.id,
             a.NAME,

+ 21 - 0
national-motion-module-system/national-motion-system-biz/src/main/java/org/jeecg/modules/system/app/mapper/xml/AppTeachingTimeMapper.xml

@@ -1,5 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="org.jeecg.modules.system.app.mapper.AppTeachingTimeMapper">
+    <select id="previewOrderPlaceSchoolTime" resultType="org.jeecg.modules.app.vo.OrderVO$PreviewOrderPlaceSchoolTime">
+        SELECT
+            a.day,
+            COALESCE ( b.inventory, 0 ) AS inventory,
+            CASE
 
+                WHEN a.DAY = CURDATE() THEN
+                    '今天'
+                WHEN a.DAY = CURDATE() + INTERVAL 1 DAY THEN
+                '明天'
+                WHEN a.DAY = CURDATE() + INTERVAL 2 DAY THEN
+                '后天' ELSE ELT( WEEKDAY( a.DAY ) + 1, '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日' )
+        END AS named_day
+        FROM
+	        nm_teaching_time a
+	    LEFT JOIN ( SELECT date_of_sale, org_code, SUM( inventory ) AS inventory FROM nm_site_price_rules WHERE org_code = #{orgCode} GROUP BY date_of_sale, org_code ) b ON a.DAY = b.date_of_sale
+    	AND a.org_code = b.org_code
+        WHERE
+	    a.DAY BETWEEN CURDATE()
+	    AND CURDATE() + INTERVAL 6 DAY
+	    AND a.org_code = #{orgCode};
+    </select>
 </mapper>