Переглянути джерело

完成电子病历ca签名

xiaochan 9 місяців тому
батько
коміт
e3372bf7a0

+ 3 - 1
src/main/java/thyyxxk/webserver/WebServerApplication.java

@@ -9,6 +9,7 @@ import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 import org.springframework.core.env.Environment;
+import thyyxxk.webserver.service.ca.CaServer;
 import thyyxxk.webserver.utils.ZipUtil;
 
 import java.net.InetAddress;
@@ -27,7 +28,8 @@ public class WebServerApplication {
     public static void main(String[] args) {
         ConfigurableApplicationContext application = SpringApplication.run(WebServerApplication.class, args);
         String OS = System.getProperty("os.name");
-        ZipUtil.setDirectory(OS.startsWith("Windows") ? "D:\\" : "/home/web-server/temp/");
+        boolean isWindow = OS.startsWith("Windows");
+        ZipUtil.setDirectory(isWindow ? "D:\\" : "/home/web-server/temp/");
         try {
             log.info("Done-CY");
             Environment env = application.getEnvironment();

+ 26 - 0
src/main/java/thyyxxk/webserver/config/envionment/Archive.java

@@ -0,0 +1,26 @@
+package thyyxxk.webserver.config.envionment;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 归档配置
+ */
+@Component
+@Data
+@ConfigurationProperties(prefix = "thyy.archive")
+@NoArgsConstructor
+public class Archive {
+
+    /**
+     * 生成的pdf在什么路径
+     */
+    private String path = System.getProperty("user.dir");
+
+    /**
+     * 生成的pdf前缀
+     */
+    private String urlPrefix;
+}

+ 1 - 2
src/main/java/thyyxxk/webserver/entity/ca/CaData.java → src/main/java/thyyxxk/webserver/config/envionment/CaData.java

@@ -1,4 +1,4 @@
-package thyyxxk.webserver.entity.ca;
+package thyyxxk.webserver.config.envionment;
 
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -79,5 +79,4 @@ public class CaData {
     private MobileApp mobileApp;
     private SignAuthentication signAuthentication;
     private TimestampAuthentication timestampAuthentication;
-
 }

+ 14 - 18
src/main/java/thyyxxk/webserver/controller/ca/CaController.java

@@ -7,6 +7,7 @@ import springfox.documentation.spring.web.json.Json;
 import thyyxxk.webserver.config.auth.PassToken;
 import thyyxxk.webserver.entity.ResultVo;
 import thyyxxk.webserver.entity.ca.CaReturn;
+import thyyxxk.webserver.entity.ca.CaSignClass;
 import thyyxxk.webserver.entity.ca.CaSingBizSnReturnData;
 import thyyxxk.webserver.service.ca.CaServer;
 import thyyxxk.webserver.utils.ResultVoUtil;
@@ -25,12 +26,12 @@ public class CaController {
     }
 
     @PostMapping("/sendBatchByCode")
-    public ResultVo<List<CaReturn.CaData>> sendBatchByCode(@RequestBody CaServer.Send send) {
+    public ResultVo<List<CaReturn.CaData>> sendBatchByCode(@RequestBody CaSignClass.Send send) {
         return ResultVoUtil.success(server.sendBatchByCode(send));
     }
 
     @PostMapping("/sendByCode")
-    public ResultVo<CaReturn.CaData> sendByCode(@RequestBody CaServer.Send send) {
+    public ResultVo<CaReturn.CaData> sendByCode(@RequestBody CaSignClass.Send send) {
         return ResultVoUtil.success(server.sendByCode(send));
     }
 
@@ -40,22 +41,22 @@ public class CaController {
     }
 
     @PostMapping("/sendMoreEventSign")
-    public ResultVo<JSONObject> sendMoreEventSign(@RequestBody CaServer.MoreEventSign moreEventSign) {
+    public ResultVo<JSONObject> sendMoreEventSign(@RequestBody CaSignClass.MoreEventSign moreEventSign) {
         return server.sendMoreEventSign(moreEventSign);
     }
 
     @PostMapping("/h5EventSign")
-    public ResultVo<CaServer.H5Return> h5EventSign(@RequestBody CaServer.H5EventSign value) {
+    public ResultVo<CaSignClass.H5Return> h5EventSign(@RequestBody CaSignClass.H5EventSign value) {
         return server.h5EventSign(value);
     }
 
     @PostMapping("/emrH5EventSign")
-    public ResultVo<CaServer.H5Return> emrH5EventSign(@RequestBody CaServer.H5EventSign value) {
+    public ResultVo<CaSignClass.H5Return> emrH5EventSign(@RequestBody CaSignClass.H5EventSign value) {
         return server.h5EventSign(value);
     }
 
     @PostMapping("/hBoardSignV2")
-    public ResultVo<CaServer.H5Return> hBoardSignV2(@RequestBody CaServer.H5EventSign value) {
+    public ResultVo<CaSignClass.H5Return> hBoardSignV2(@RequestBody CaSignClass.H5EventSign value) {
         return server.hBoardSignV2(value);
     }
 
@@ -65,29 +66,24 @@ public class CaController {
     }
 
     @GetMapping("/scanCodeVerification")
-    public ResultVo<Boolean> scanCodeVerification(@RequestParam("id") String id, @RequestParam("documentId") String documentId) {
-        return server.scanCodeVerification(id, documentId);
+    public ResultVo<Boolean> scanCodeVerification(@RequestParam("id") String id,
+                                                  @RequestParam("documentId") String documentId,
+                                                  @RequestParam("uuid") String uuid) {
+        return server.scanCodeVerification(id, documentId, uuid);
     }
 
     @GetMapping("/completeQrCode")
+    @PassToken
     public ResultVo<String> completeQrCode(@RequestParam("documentId") String documentId) {
         server.completeQrCode(documentId);
         return ResultVoUtil.success();
     }
 
-    @RequestMapping("/hBoardSignReturnUrl/{document}/{bizSn}")
+    @RequestMapping("/hBoardSignReturnUrl/{document}")
     @PassToken
     public JSONObject hBoardSignReturnUrl(@PathVariable("document") String document,
-                                          @PathVariable("bizSn") String bizSn,
                                           @RequestBody(required = false) JSONObject data) {
-        return server.hBoardSignReturnUrl(document, bizSn, data);
-    }
-
-    @GetMapping("/appDownload")
-    @PassToken
-    public ResultVo<String> appDownload(@RequestParam(value = "documentId", required = false) String documentId,
-                                        @RequestParam(value = "bizSn", required = false) String bizSn) {
-        return server.appDownload(documentId, bizSn);
+        return server.hBoardSignReturnUrl(document, data);
     }
 
 }

+ 0 - 2
src/main/java/thyyxxk/webserver/entity/ca/CaReturn.java

@@ -28,6 +28,4 @@ public class CaReturn {
         private String signature;
         private String name;
     }
-    // 2191 THyy3456
-
 }

+ 0 - 41
src/main/java/thyyxxk/webserver/entity/ca/CaSendBatchParams.java

@@ -1,41 +0,0 @@
-package thyyxxk.webserver.entity.ca;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class CaSendBatchParams {
-
-    @Data
-    @Builder
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class CaSendBatchData {
-        private String bizSn;
-        private String msg;
-        private String msgWrapper;
-        private String desc;
-    }
-
-    /**
-     * 移动安全认证系统分配的应用Id
-     */
-    private String appId;
-    /**
-     * 用户标识,用于关联应用系统的用户身份,对应用户注册信息中的uuid
-     */
-    private String id;
-
-    /**
-     * 用应用私钥对msg值(URLEncode编码之前,摘要处理之后的数据)进行参数签名,
-     * 得到Base64 编码格式签名值后进行URLEncode(UTF-8)传
-     * 输。当后台开启鉴权时,此参数必填。
-     * 应用私钥由Mkey后台分配,示例代码参考8.2参
-     */
-    private String sign;
-}

+ 99 - 0
src/main/java/thyyxxk/webserver/entity/ca/CaSignClass.java

@@ -0,0 +1,99 @@
+package thyyxxk.webserver.entity.ca;
+
+import cn.hutool.json.JSONObject;
+import lombok.*;
+
+import javax.sound.sampled.Port;
+import java.util.List;
+
+public class CaSignClass {
+
+    /**
+     * 发送医生签名的类
+     */
+    @EqualsAndHashCode(callSuper = true)
+    @Data
+    public static class Send extends CaSendParams {
+        private String id;
+        private String msg;
+        private String desc;
+        private Integer count = 1;
+    }
+
+    @Data
+    public static class MoreEventSignData {
+        private String content;
+
+        /**
+         * 签署人身份类型。例如患者本人、亲属、朋友
+         * 、伴侣。进行 URLEncode 编码的数据,并且中
+         * 文长度不得大于 8
+         */
+        private String signType;
+        private String signTypeName;
+        private String signName;
+        private String idCard;
+        private String name;
+        private String signOpinion;
+    }
+
+    /**
+     * 移动平板实体类
+     */
+    @Data
+    public static class MoreEventSign {
+        private String documentId;
+        private String sendCode;
+        private String sendCodeName;
+        private List<MoreEventSignData> data;
+    }
+
+    /**
+     * 页面扫码的类
+     */
+    @Data
+    public static class H5EventSign {
+        private String uuid;
+        private String documentId;
+        private String content;
+        private String idCard;
+        private Integer signType;
+        private Boolean clear = true;
+        private String name;
+        private String signOpinion;
+    }
+
+    @Data
+    @Builder
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class H5Return {
+        private String caDocumentId;
+        private String result;
+        private String uuid;
+    }
+
+    @Data
+    @Builder
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class H5EventSignRedis {
+        private String uuid;
+        private String pdf;
+
+        private List<JSONObject> data;
+    }
+
+    @Data
+    @Builder
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class Upload {
+        private String file;
+        private String fileName;
+        private String patNo;
+        private Integer times;
+        private String caData;
+    }
+
+}

+ 2 - 0
src/main/java/thyyxxk/webserver/entity/zhuyuanyisheng/emr/EmrPatientData.java

@@ -188,6 +188,8 @@ public class EmrPatientData implements Serializable {
      */
     private Boolean signComplete;
 
+    private String archivePath;
+
     public String getEmrDataElementStr() {
         if (emrDataElement != null) {
             return emrDataElement.toString();

+ 171 - 152
src/main/java/thyyxxk/webserver/service/ca/CaServer.java

@@ -1,8 +1,8 @@
 package thyyxxk.webserver.service.ca;
 
 import cn.hutool.core.codec.Base64;
-import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.FileNameUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.IdcardUtil;
 import cn.hutool.core.util.StrUtil;
@@ -16,12 +16,14 @@ import com.dtflys.forest.Forest;
 import com.dtflys.forest.http.ForestRequest;
 import com.dtflys.forest.logging.LogConfiguration;
 import com.dtflys.forest.utils.ForestDataType;
-import com.sun.org.apache.bcel.internal.generic.NEW;
 import lombok.*;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.annotations.Update;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Service;
 import thyyxxk.webserver.config.Assertion;
+import thyyxxk.webserver.config.envionment.Archive;
+import thyyxxk.webserver.config.envionment.CaData;
 import thyyxxk.webserver.config.exception.BizException;
 import thyyxxk.webserver.config.exception.ExceptionEnum;
 import thyyxxk.webserver.constants.YesOrNo;
@@ -36,9 +38,9 @@ import thyyxxk.webserver.service.redislike.RedisLikeService;
 import thyyxxk.webserver.service.zhuyuanyisheng.emr.EmrServer;
 import thyyxxk.webserver.utils.ResultVoUtil;
 
-import javax.swing.text.EditorKit;
 import java.io.UnsupportedEncodingException;
 import java.net.URLDecoder;
+import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
@@ -48,7 +50,6 @@ import java.util.concurrent.TimeUnit;
 @Slf4j
 @Service
 public class CaServer implements Assertion {
-
     private final CaData caData;
     private final String SUCCRSS = "success";
     private final RedisLikeService redisLikeService;
@@ -57,26 +58,17 @@ public class CaServer implements Assertion {
     private final RedisServer redisServer;
     private final EmrCaSignDao emrCaSignDao;
     private final EmrPatientDao emrPatientDao;
+    private final Archive archive;
 
     private final static String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKAc+jzqVKHsjNdyuDGL7u6zZR55j87l+0GGT4/yEV+K8ZtL1GoIgOD6vv6eEg2iOwl6Wh6hq8XR4cIyzVyvMZ35dIw3oGN89ObtuCha7gLOmWYUIGVnkUBkLFeIdwe4F8bq1q15o7azsTVekSyNJf/wnxWMp8ibtvO41T8DIzZPAgMBAAECgYAeeLVVD4Gw2VyKij4sy8Var1CQxrDMPu+c7ktJCVguFzrZA8r2rQyeBIqB2aJ07smOibcJ+lm/Ca0N8O4tc/gcm4g/JsjBALFUmqyCkLQpRyIbz8V9uAmrLcchT74GS727Uv4KVTmQNDZTPIDdSZWSJ8S+WKmj8q3wUF1HLF1eXQJBAOC7D6xIB2XNS6Voa7C7m8aeg53lfcDUVJ6m0YFdvMbsU2cnlxnCSX1OsghFuVQLKcGeN+aXiTEileb3pAl2RC0CQQC2ZDtDb+1OmLmRNugp29Pmm8MM8KpktfqiBFi92Q747XwEeMgLi3qetq1wDT4dgvyURs2McsbF7diVtFv7DMXrAkAoYzXj3mYF86k+ps+DyZOrVF2PCOlauE4k3RIVz8TXcy1iAolzRalzbastNWqjIgZ1F3wwYtdzDyYlhifi03BZAkEArkgidPMbwDGhiAf+WhkrZz1JaTECsM9PGcergGVLsENFcQR0qstxtPz7x4lv5EVI0urA+Man93OptIsuJTr0VwJAd86EbHyOn5Lah7ptPGsmsqkrdMZcJ3chRj6pDtvb0A2lhaJfDRxmAiWCnviPhTApH6/1WRzBqc1ZTymyRTF9kA==";
     private final static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCgHPo86lSh7IzXcrgxi+7us2UeeY/O5ftBhk+P8hFfivGbS9RqCIDg+r7+nhINojsJeloeoavF0eHCMs1crzGd+XSMN6BjfPTm7bgoWu4CzplmFCBlZ5FAZCxXiHcHuBfG6tateaO2s7E1XpEsjSX/8J8VjKfIm7bzuNU/AyM2TwIDAQAB";
     RSA idCardRsa = new RSA(privateKey, publicKey);
 
-    public static void main(String[] args) {
-        test();
-    }
-
-    public static void test() {
-        String url = "D:\\.a1.world\\1.txt";
-        String s = FileUtil.readString(url, StandardCharsets.UTF_8);
-        JSONObject entries = JSONUtil.parseObj(s);
-        String handSign = entries.getStr("pdf");
-        byte[] decode = Base64.decode(handSign);
-        FileUtil.writeBytes(decode, "D:\\.a1.world\\1.pdf");
-        log.info("数据:{}\ndecode:{}", s, decode);
+    private String getRedisKey(String documentId) {
+        return "ca-emr-" + documentId;
     }
 
-    public CaServer(CaData caData, RedisLikeService redisLikeService, EmrServer emrServer, EmrPatientDao dao, RedisServer redisServer, EmrCaSignDao emrCaSignDao, EmrPatientDao emrPatientDao) {
+    public CaServer(CaData caData, RedisLikeService redisLikeService, EmrServer emrServer, EmrPatientDao dao, RedisServer redisServer, EmrCaSignDao emrCaSignDao, EmrPatientDao emrPatientDao, Archive archive) {
         this.caData = caData;
         this.redisLikeService = redisLikeService;
         this.emrServer = emrServer;
@@ -84,18 +76,10 @@ public class CaServer implements Assertion {
         this.redisServer = redisServer;
         this.emrCaSignDao = emrCaSignDao;
         this.emrPatientDao = emrPatientDao;
+        this.archive = archive;
     }
 
-    @EqualsAndHashCode(callSuper = true)
-    @Data
-    public static class Send extends CaSendParams {
-        private String id;
-        private String msg;
-        private String desc;
-        private Integer count = 1;
-    }
-
-    public List<CaReturn.CaData> sendBatchByCode(Send send) {
+    public List<CaReturn.CaData> sendBatchByCode(CaSignClass.Send send) {
         List<CaReturn.CaData> returnValue = new ArrayList<>();
         for (int i = 0; i < send.getCount(); i++) {
             returnValue.add(sendByCode(send));
@@ -103,7 +87,7 @@ public class CaServer implements Assertion {
         return returnValue;
     }
 
-    public CaReturn.CaData sendByCode(Send send) {
+    public CaReturn.CaData sendByCode(CaSignClass.Send send) {
         UserInfo userInfoByCode = redisLikeService.getUserInfoByCode(send.getId());
         send.setBizSn(IdUtil.simpleUUID());
         String msg = CaUtils.GetSHA256FormString(send.getMsg());
@@ -124,7 +108,7 @@ public class CaServer implements Assertion {
      * @param send
      * @return 返回值
      */
-    private CaReturn push(Send send, String msg) {
+    private CaReturn push(CaSignClass.Send send, String msg) {
         CaData.MobileApp app = caData.getMobileApp();
 
         CaSendParams params = CaSendParams
@@ -272,36 +256,12 @@ public class CaServer implements Assertion {
         return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, execute.getMsg());
     }
 
-    @Data
-    public static class MoreEventSignData {
-        private String content;
-
-        /**
-         * 签署人身份类型。例如患者本人、亲属、朋友
-         * 、伴侣。进行 URLEncode 编码的数据,并且中
-         * 文长度不得大于 8
-         */
-        private String signType;
-        private String signTypeName;
-        private String signName;
-        private String idCard;
-        private String name;
-        private String signOpinion;
-    }
-
-    @Data
-    public static class MoreEventSign {
-        private String documentId;
-        private String sendCode;
-        private String sendCodeName;
-        private List<MoreEventSignData> data;
-    }
 
     private void verifyMedicalRecordStatus(String documentId, EmrSignType type) {
         EmrPatientData emrData = emrPatientDao.selectById(documentId);
-        if (emrData == null || emrData.getDelFlag() == 1) {
-            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "病历已被删除。");
-        }
+//        if (emrData == null || emrData.getDelFlag() == 1) {
+//            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "病历已被删除。");
+//        }
         isTrueErr(emrData.getSignComplete(), "扫码流程已完成请勿重复点击");
         if (emrData.getSignType() != null && !Objects.equals(type.getCode(), emrData.getSignType())) {
             throw new BizException(ExceptionEnum.LOGICAL_ERROR, "请使用上次选择的方式完成CA流程中途不得修改。");
@@ -319,7 +279,7 @@ public class CaServer implements Assertion {
      * @param moreEventSign 数据
      * @return 暂无
      */
-    public ResultVo<JSONObject> sendMoreEventSign(MoreEventSign moreEventSign) {
+    public ResultVo<JSONObject> sendMoreEventSign(CaSignClass.MoreEventSign moreEventSign) {
         verifyMedicalRecordStatus(moreEventSign.getDocumentId(), EmrSignType.MOVE);
         moreEventSign.getData().forEach(item -> {
             isBlank(item.getIdCard(), "身份证不能为空。");
@@ -327,35 +287,31 @@ public class CaServer implements Assertion {
             isBlank(item.getSignType(), "与患者的关系不能为空。");
             item.setIdCard(idCardRsa.decryptStr(item.getIdCard(), KeyType.PrivateKey));
         });
-        EmrCaSign emrCaSign = emrCaSignDao.selectById(moreEventSign.getDocumentId());
-        if (emrCaSign != null) {
-            cancelSignature(emrCaSign.getData());
+        String redisKey = getRedisKey(moreEventSign.getDocumentId());
+        String redisData = redisServer.getData(redisKey, () -> null);
+        if (redisData != null) {
+            cancelSignature(redisData);
         }
-        redisServer.delData("emr-" + moreEventSign.getDocumentId());
+        redisServer.delData(redisKey);
         String uuid = IdUtil.simpleUUID();
         JSONObject data = getMoreEventSignData(moreEventSign, uuid);
-        String execute = Forest.post(caData.getHBoardSign().getUrl() + "/mobile/hBoardSign").addBody(data).bodyType(ForestDataType.JSON).execute(String.class);
+        String execute = Forest.post(caData.getHBoardSign().getUrl() + "/mobile/hBoardSign")
+                .addBody(data)
+                .bodyType(ForestDataType.JSON)
+                .execute(String.class);
         JSONObject rst = JSONUtil.parseObj(execute);
         String msg = rst.getByPath("ret_msg", String.class);
         String decode = URLUtil.decode(msg);
         log.info("返回值:{},\n错误信息:{}", execute, decode);
         if (rst.getInt("ret_code") == 0) {
-            EmrCaSign newCaSign = EmrCaSign.builder()
-                    .documentId(moreEventSign.getDocumentId())
-                    .data(uuid)
-                    .build();
-            if (emrCaSign == null) {
-                emrCaSignDao.insert(newCaSign);
-            } else {
-                emrCaSignDao.updateById(newCaSign);
-            }
+            redisServer.setData(redisKey, uuid, 30);
             return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "发送成功。");
         } else {
             return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请联系管理员" + decode);
         }
     }
 
-    private JSONObject getMoreEventSignData(MoreEventSign moreEventSign, String uuid) {
+    private JSONObject getMoreEventSignData(CaSignClass.MoreEventSign moreEventSign, String uuid) {
         JSONObject ret = new JSONObject();
         CaData.HBoardSign app = caData.getHBoardSign();
         ret.set("api_key", app.getApiKey());
@@ -363,12 +319,12 @@ public class CaServer implements Assertion {
         JSONObject data = new JSONObject();
         data.set("document_no", uuid);
         data.set("pdf", emrServer.getPdfBase(moreEventSign.getDocumentId()));
-        data.set("return_url", URLUtil.encode(app.getReturnUrl() + "/" + moreEventSign.getDocumentId() + "/" + uuid));
+        data.set("return_url", URLUtil.encode(app.getReturnUrl() + "/" + moreEventSign.getDocumentId()));
 
         JSONArray signature = new JSONArray();
 
         for (int i = 0; i < moreEventSign.getData().size(); i++) {
-            MoreEventSignData item = moreEventSign.getData().get(i);
+            CaSignClass.MoreEventSignData item = moreEventSign.getData().get(i);
             JSONObject entries = new JSONObject();
             entries.set("type", "keyword");
             entries.set("sign_type", URLUtil.encode(item.getSignTypeName()));
@@ -392,15 +348,12 @@ public class CaServer implements Assertion {
                         .set("informed_tip", URLUtil.encode("签名意见"))
                         .set("informed_num", i + 1)
                         .set("informed_keyword", informed_keyword);
-
                 entries.set("informed_stamp", informed_stamp);
             }
-
             entries.set("user_info", user_info);
             signature.put(entries);
         }
 
-
         // 签署信息
         data.set("signature", signature);
         data.set("doctor_info", new JSONObject() {{
@@ -416,33 +369,14 @@ public class CaServer implements Assertion {
         return ret;
     }
 
-    @Data
-    public static class H5EventSign {
-        private String documentId;
-        private String content;
-        private String idCard;
-        private Integer signType;
-        private Boolean clear = true;
-        private String name;
-        private String signOpinion;
-    }
-
-    @Data
-    @Builder
-    @AllArgsConstructor
-    @NoArgsConstructor
-    public static class H5Return {
-        private String id;
-        private String result;
-    }
-
     /**
      * h5 签名返回一个http连接
      *
      * @param value
      * @return
+     * @deprecated 没啥用
      */
-    public ResultVo<H5Return> h5EventSign(H5EventSign value) {
+    public ResultVo<CaSignClass.H5Return> h5EventSign(CaSignClass.H5EventSign value) {
         JSONObject ret = new JSONObject();
         String uuid = IdUtil.simpleUUID();
         CaData.HBoardSign app = caData.getHBoardSign();
@@ -463,7 +397,7 @@ public class CaServer implements Assertion {
                 .bodyType(ForestDataType.JSON)
                 .execute(String.class);
 
-        return getStringResultVo(execute, uuid);
+        return getStringResultVo(execute, uuid, "");
     }
 
     @Getter
@@ -480,7 +414,6 @@ public class CaServer implements Assertion {
             this.code = code;
             this.name = name;
         }
-
     }
 
     /**
@@ -489,25 +422,22 @@ public class CaServer implements Assertion {
      * @param value
      * @return
      */
-    public ResultVo<H5Return> hBoardSignV2(H5EventSign value) {
+    public ResultVo<CaSignClass.H5Return> hBoardSignV2(CaSignClass.H5EventSign value) {
         isNoll(value.getSignType(), "请选择和患者的关系");
         isBlank(value.getIdCard(), "身份证不能为空。");
         isBlank(value.getName(), "姓名不能为空。");
-
         JSONObject ret = new JSONObject();
-        String uuid = IdUtil.simpleUUID();
+        String caDocumentId = IdUtil.simpleUUID();
         verifyMedicalRecordStatus(value.getDocumentId(), EmrSignType.QR);
-        String idCard = idCardRsa.decryptStr(value.getIdCard(), KeyType.PrivateKey);
-        if (value.getClear()) {
-            redisServer.delData("emr-" + value.getDocumentId());
-            emrCaSignDao.deleteById(value.getDocumentId());
-        }
 
+        CaSignClass.H5EventSignRedis redisData = clearHBoardSignV2Data(value);
+
+        String idCard = idCardRsa.decryptStr(value.getIdCard(), KeyType.PrivateKey);
         ret.set("api_key", caData.getHBoardSign().getApiKey());
         ret.set("api_secret", caData.getHBoardSign().getApiSecret());
         ret.set("data", new JSONObject() {{
-            set("document_no", uuid);
-            set("pdf", emrServer.getPdfBase(value.getDocumentId()));
+            set("document_no", caDocumentId);
+            set("pdf", redisData.getPdf());
             set("sign_way", "face,hand_sign");
             set("keyword", new JSONObject() {{
                 set("page", "0");
@@ -534,17 +464,44 @@ public class CaServer implements Assertion {
                 .addBody(ret)
                 .bodyType(ForestDataType.JSON)
                 .execute(String.class);
-        return getStringResultVo(execute, uuid);
+
+        redisData.setUuid(value.getUuid());
+
+        redisServer.setData("ca-emr-" + value.getDocumentId(), redisData, 30);
+        return getStringResultVo(execute, caDocumentId, value.getUuid());
+    }
+
+    private CaSignClass.H5EventSignRedis clearHBoardSignV2Data(CaSignClass.H5EventSign value) {
+        CaSignClass.H5EventSignRedis redisData = new CaSignClass.H5EventSignRedis();
+        String redisKey = getRedisKey(value.getDocumentId());
+        // 如果 uuid 是空的就是第一次
+        if (StrUtil.isBlank(value.getUuid())) {
+            value.setUuid(IdUtil.simpleUUID());
+            redisServer.delData(redisKey);
+            redisData.setPdf(emrServer.getPdfBase(value.getDocumentId()));
+        } else {
+            redisData = redisServer.getData(redisKey);
+            if (redisData == null) {
+                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名超时请重新签名。");
+            }
+            if (!redisData.getUuid().equals(value.getUuid())) {
+                throw new BizException(ExceptionEnum.LOGICAL_ERROR, "有其他人正在签署,本次签名失效。");
+            }
+        }
+        return redisData;
     }
 
     @NotNull
-    private ResultVo<H5Return> getStringResultVo(String execute, String id) {
+    private ResultVo<CaSignClass.H5Return> getStringResultVo(String execute,
+                                                             String caDocumentId,
+                                                             String uuid) {
         JSONObject rst = JSONUtil.parseObj(execute);
         String msg = URLUtil.decode(rst.getByPath("ret_msg", String.class));
         if (0 == rst.getByPath("ret_code", Integer.class)) {
-            H5Return build = H5Return.builder()
+            CaSignClass.H5Return build = CaSignClass.H5Return.builder()
                     .result(rst.getByPath("sign_url", String.class))
-                    .id(id)
+                    .caDocumentId(caDocumentId)
+                    .uuid(uuid)
                     .build();
             return ResultVoUtil.success(build);
         }
@@ -576,40 +533,34 @@ public class CaServer implements Assertion {
      *
      * @return 提示
      */
-    public ResultVo<Boolean> scanCodeVerification(String id, String documentId) {
+    public ResultVo<Boolean> scanCodeVerification(String id, String documentId, String uuid) {
         ResultVo<JSONObject> res = downloadSealV2(id, documentId);
         if (!res.getCode().equals(ExceptionEnum.SUCCESS.getCode())) {
             return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, res.getMessage());
         }
         JSONObject rst = res.getData();
-        redisServer.setData("emr-" + documentId, rst.getByPath("pdf", String.class), 60, TimeUnit.MINUTES);
+        String key = getRedisKey(documentId);
+        CaSignClass.H5EventSignRedis redisData = redisServer.getData(key);
+        if (redisData == null) {
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名错误,文书不存在。");
+        }
 
+        if (!redisData.getUuid().equals(uuid)) {
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, "有其他人正在签署,本次签名失效。");
+        }
+
+        redisData.setPdf(rst.getByPath("pdf", String.class));
         JSONObject saveData = new JSONObject();
         saveData.set("hand_sign", rst.get("hand_sign"));
         saveData.set("fingerprint", rst.get("hand_sign"));
         saveData.set("informed_img", rst.get("hand_sign"));
         saveData.set("face_photo", rst.get("hand_sign"));
         saveData.set("biz_sn", id);
-        JSONArray js = new JSONArray();
-        boolean update = false;
-        EmrCaSign emrCaSign = emrCaSignDao.selectById(documentId);
-        if (emrCaSign != null) {
-            js = JSONUtil.parseArray(emrCaSign.getData());
-            update = true;
-        } else {
-            emrCaSign = EmrCaSign.builder()
-                    .documentId(documentId)
-                    .build();
-        }
-
-        js.put(saveData);
-        emrCaSign.setData(js.toJSONString(0));
-
-        if (update) {
-            emrCaSignDao.updateById(emrCaSign);
-        } else {
-            emrCaSignDao.insert(emrCaSign);
+        if (null == redisData.getData()) {
+            redisData.setData(new ArrayList<>());
         }
+        redisData.getData().add(saveData);
+        redisServer.setData(key, redisData, 30);
         return ResultVoUtil.success(true);
     }
 
@@ -617,8 +568,23 @@ public class CaServer implements Assertion {
      * 扫码流程完成
      */
     public void completeQrCode(String documentId) {
-        // TODO 完成H5签名的时候,需要保存一下PDF
-        EmrPatientData build = EmrPatientData.builder().emrDocumentId(documentId).signComplete(true).build();
+        EmrPatientData data = emrPatientDao.selectById(documentId);
+        CaSignClass.H5EventSignRedis redisServerData = redisServer.getData(getRedisKey(documentId));
+        CaSignClass.Upload upload = CaSignClass.Upload.builder()
+                .file(redisServerData.getPdf())
+                .fileName(documentId)
+                .patNo(data.getPatNo())
+                .times(data.getTimes())
+                .caData(JSONUtil.toJsonStr(redisServerData))
+                .build();
+
+        String path = uploadBase64(upload);
+        EmrPatientData build = EmrPatientData
+                .builder()
+                .emrDocumentId(documentId)
+                .signComplete(true)
+                .archivePath(path)
+                .build();
         emrPatientDao.updateById(build);
     }
 
@@ -637,25 +603,54 @@ public class CaServer implements Assertion {
                 .execute(JSONObject.class);
     }
 
-    public JSONObject hBoardSignReturnUrl(String document, String bizSn, JSONObject data) {
+    /**
+     * 签名回调
+     *
+     * @param document 文档id
+     * @param data     签名数据
+     * @return
+     */
+    public JSONObject hBoardSignReturnUrl(String document, JSONObject data) {
         // TODO 完成一定手写板签名的时候,需要保存一下PDF
-        log.info("回调:{},biz:{},数据:{}", document, bizSn, data);
-//
-//        String url = "D:\\.a1.world\\1.txt";
-//        String s = FileUtil.readString(url, StandardCharsets.UTF_8);
-//        JSONObject entries = JSONUtil.parseObj(s);
-//        String handSign = entries.getStr("pdf");
-//        byte[] decode = Base64.decode(handSign);
-//        FileUtil.writeBytes(decode, "D:\\.a1.world\\1.pdf");
-//        log.info("数据:{}\ndecode:{}", s, decode);
+        log.info("回调:{},数据:{}", document, data);
+        EmrPatientData emrData = emrPatientDao.selectById(document);
+        String redisKey = getRedisKey(document);
+        String redisData = redisServer.getData(redisKey, () -> null);
+        if (emrData == null || redisData == null) {
+            return R(-1, "病历文档不存在");
+        }
+
+        JSONObject signData = appDownload(redisData);
+
+        CaSignClass.Upload build = CaSignClass.Upload
+                .builder()
+                .patNo(emrData.getPatNo())
+                .times(emrData.getTimes())
+                .file(signData.getStr("pdf"))
+                .fileName(document)
+                .caData(signData.getStr("signed"))
+                .build();
+
+        String path = uploadBase64(build);
+
+        EmrPatientData update = EmrPatientData.builder()
+                .emrDocumentId(document)
+                .signComplete(true)
+                .archivePath(path)
+                .build();
+        redisServer.delData(redisKey);
+        emrPatientDao.updateById(update);
+        return R(1, "success");
+    }
 
+    private JSONObject R(Integer code, String msg) {
         return new JSONObject() {{
-            set("ret_code", 1);
-            set("res_msg", "success");
+            set("ret_code", code);
+            set("res_msg", msg);
         }};
     }
 
-    public ResultVo<String> appDownload(String documentId, String bizSn) {
+    public JSONObject appDownload(String bizSn) {
         JSONObject data = new JSONObject() {{
             set("api_key", caData.getHBoardSign().getApiKey());
             set("api_secret", caData.getHBoardSign().getApiSecret());
@@ -671,10 +666,34 @@ public class CaServer implements Assertion {
                 .execute(JSONObject.class);
 
         execute.set("ret_msg", URLUtil.decode(execute.getStr("ret_msg")));
-
         log.info("返回:{}", execute);
 
-        return ResultVoUtil.success();
+        if (execute.getInt("code") != 0) {
+            throw new BizException(ExceptionEnum.LOGICAL_ERROR, execute.getStr("ret_msg"));
+        }
+
+        return execute;
+    }
+
+    public String uploadBase64(CaSignClass.Upload upload) {
+        byte[] file = Base64.decode(upload.getFile());
+
+        String tmpPath = "/" + upload.getPatNo()
+                + "/" + upload.getTimes()
+                + "/" + upload.getFileName();
+
+        String pdfPath = tmpPath + ".pdf";
+
+        String caPath = "/" + upload.getPatNo()
+                + "/" + upload.getTimes()
+                + "/ca/" + upload.getFileName()
+                + ".txt";
+
+        // 写入CA数据
+        FileUtil.writeString(upload.getCaData(), archive.getPath() + caPath, StandardCharsets.UTF_8);
+        // 写入pdf
+        FileUtil.writeBytes(file, archive.getPath() + pdfPath);
+        return archive.getUrlPrefix() + pdfPath;
     }
 
 

+ 0 - 8
src/main/java/thyyxxk/webserver/service/ca/MoreEventSign.java

@@ -1,8 +0,0 @@
-package thyyxxk.webserver.service.ca;
-
-public class MoreEventSign {
-    private String api_key;
-    private String api_secret;
-
-
-}

+ 25 - 20
src/main/java/thyyxxk/webserver/service/zhuyuanyisheng/emr/EmrServer.java

@@ -8,9 +8,11 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.serializer.SerializerFeature;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.dtflys.forest.Forest;
 import com.dtflys.forest.http.ForestRequest;
 import com.dtflys.forest.interceptor.Interceptor;
 import com.dtflys.forest.reflection.ForestMethod;
+import com.dtflys.forest.utils.ForestDataType;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.ListUtils;
 import org.jetbrains.annotations.NotNull;
@@ -939,26 +941,29 @@ public class EmrServer {
     }
 
     public String getPdfBase(String documentId) {
-        return redisServer.getData("emr-" + documentId, () -> {
-            String url = "http://172.16.32.125:8001/emr/archive/pdf";
-            JSONObject param = new JSONObject();
-            param.put("emrToken", true);
-            param.put("stream", true);
-            param.put("arcive", false);
-            param.put("patientId", false);
-            param.put("params", new JSONObject() {{
-                put("documentId", documentId);
-            }});
-            param.put("fileName", "病历pdf");
-            param.put("type", "document");
-            String text = HttpRequest.post(url).body(param.toJSONString()).header("emr-token", emrToken).execute().body();
-            int index = text.lastIndexOf("<br/>buffer:,");
-            if (index != -1) {
-                String[] split = text.substring(text.lastIndexOf("<br/>buffer:,") + 13).split(",");
-                return Base64.encode(Convert.toPrimitiveByteArray(split));
-            }
-            return null;
-        }, 60, TimeUnit.MINUTES);
+        String url = "http://webhis.thyy.cn:8080/thyyemrpdfserver/emr/archive/pdf";
+        JSONObject param = new JSONObject();
+        param.put("emrToken", true);
+        param.put("stream", true);
+        param.put("arcive", false);
+        param.put("patientId", false);
+        param.put("params", new JSONObject() {{
+            put("documentId", documentId);
+        }});
+        param.put("fileName", "病历pdf");
+        param.put("type", "document");
+        String text = Forest.post(url)
+                .contentTypeJson()
+                .addBody(param)
+                .bodyType(ForestDataType.JSON)
+                .addHeader("emr-token", emrToken)
+                .execute(String.class);
+        int index = text.lastIndexOf("<br/>buffer:,");
+        if (index != -1) {
+            String[] split = text.substring(text.lastIndexOf("<br/>buffer:,") + 13).split(",");
+            return Base64.encode(Convert.toPrimitiveByteArray(split));
+        }
+        return null;
     }
 
 }

+ 4 - 1
src/main/resources/application-cytest.yml

@@ -84,7 +84,7 @@ spring:
       date: yyyy-MM-dd
       date-time: yyyy-MM-dd HH:mm:ss
   redis:
-    host: 172.16.32.167
+    host: 172.16.32.217
     port: 6379
     database: 0
     password: thyy@2018
@@ -195,4 +195,7 @@ thyy:
       api-secret: "00000000"
       url: http://47.100.199.230:8080/pdfsign_hw
       return-url: "https://emr.hnthyy.cn:9222/caTest/thyyca/hBoardSignReturnUrl"
+  archive:
+    path: "Z:\\"
+    url-prefix: "http://172.16.32.197:9202/archive-test"