123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703 |
- package thyyxxk.webserver.service.ca;
- import cn.hutool.core.codec.Base64;
- import cn.hutool.core.io.FileUtil;
- import cn.hutool.core.util.IdUtil;
- import cn.hutool.core.util.IdcardUtil;
- import cn.hutool.core.util.StrUtil;
- import cn.hutool.core.util.URLUtil;
- import cn.hutool.crypto.asymmetric.KeyType;
- import cn.hutool.crypto.asymmetric.RSA;
- import cn.hutool.json.JSONArray;
- import cn.hutool.json.JSONObject;
- import cn.hutool.json.JSONUtil;
- import com.dtflys.forest.Forest;
- import com.dtflys.forest.http.ForestRequest;
- import com.dtflys.forest.logging.LogConfiguration;
- import com.dtflys.forest.utils.ForestDataType;
- import lombok.*;
- import lombok.extern.slf4j.Slf4j;
- 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;
- import thyyxxk.webserver.dao.his.ca.EmrCaSignDao;
- import thyyxxk.webserver.dao.his.zhuyuanyisheng.emr.EmrPatientDao;
- import thyyxxk.webserver.entity.ResultVo;
- import thyyxxk.webserver.entity.ca.*;
- import thyyxxk.webserver.entity.login.UserInfo;
- import thyyxxk.webserver.entity.zhuyuanyisheng.emr.EmrPatientData;
- import thyyxxk.webserver.service.RedisServer;
- import thyyxxk.webserver.service.redislike.RedisLikeService;
- import thyyxxk.webserver.service.zhuyuanyisheng.emr.EmrServer;
- import thyyxxk.webserver.utils.ResultVoUtil;
- import java.io.UnsupportedEncodingException;
- import java.net.URLDecoder;
- import java.nio.charset.StandardCharsets;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Objects;
- @Slf4j
- @Service
- public class CaServer implements Assertion {
- private final CaData caData;
- private final String SUCCRSS = "success";
- private final RedisLikeService redisLikeService;
- private final EmrServer emrServer;
- private final EmrPatientDao dao;
- 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);
- 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, Archive archive) {
- this.caData = caData;
- this.redisLikeService = redisLikeService;
- this.emrServer = emrServer;
- this.dao = dao;
- this.redisServer = redisServer;
- this.emrCaSignDao = emrCaSignDao;
- this.emrPatientDao = emrPatientDao;
- this.archive = archive;
- }
- 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));
- }
- return returnValue;
- }
- public CaReturn.CaData sendByCode(CaSignClass.Send send) {
- UserInfo userInfoByCode = redisLikeService.getUserInfoByCode(send.getId());
- send.setBizSn(IdUtil.simpleUUID());
- String msg = CaUtils.GetSHA256FormString(send.getMsg());
- CaReturn push = push(send, msg);
- signatureAuthentication(msg, push);
- String timeStamp = generateTimestampByInData(msg);
- push.getData().setTimeStamp(timeStamp);
- push.getData().setBizSn(send.getBizSn());
- push.getData().setSignature("/doctorSignatureImage/" + send.getId() + ".png");
- push.getData().setName(userInfoByCode.getName());
- push.getData().setMsg(msg);
- push.getData().setCode(send.getId());
- return push.getData();
- }
- /**
- * 推送用户签名
- *
- * @param send
- * @return 返回值
- */
- private CaReturn push(CaSignClass.Send send, String msg) {
- CaData.MobileApp app = caData.getMobileApp();
- CaSendParams params = CaSendParams
- .builder()
- .appId(app.getAppId())
- .id(send.getId())
- .bizSn(send.getBizSn())
- .msg(msg)
- .msgWrapper("0")
- .desc(URLUtil.encode(send.getDesc()))
- .url(URLUtil.encode("http://127.0.0.1"))
- .mode("redirect")
- .sign(CaUtils.getSign(app.getPrivatekey(), msg))
- .build();
- String execute = Forest
- .post(app.getUrl() + "/v1/push/sign")
- .bodyType(ForestDataType.FORM)
- .addBody(params).execute(String.class);
- String decode = URLUtil.decode(execute);
- log.info("返回数据:{}", decode);
- CaReturn caReturn = JSONUtil.toBean(decode, CaReturn.class);
- if (!SUCCRSS.equals(caReturn.getRet())) {
- throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败。" + caReturn.getMsg());
- }
- if (Integer.valueOf(1).equals(caReturn.getData().getIsTrust())) {
- throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败,请用户打开免密签名。");
- }
- if (Integer.valueOf(2).equals(caReturn.getData().getIsTrust())) {
- return caReturn;
- }
- throw new BizException(ExceptionEnum.LOGICAL_ERROR, "签名失败。" + caReturn.getMsg());
- }
- /**
- * 认证签名
- *
- * @param msg 消息
- * @param caReturn
- */
- private void signatureAuthentication(String msg, CaReturn caReturn) {
- CaData.SignAuthentication signData = caData.getSignAuthentication();
- CaWSDL caWSDL = new CaWSDL(signData.getUrl());
- String replace = getVerifySignDataParams(msg, caReturn, signData);
- JSONObject rst = caWSDL.invoke("verifySignData", replace);
- log.info("认证签名xml:{}\n认证签名返回值:{}\n", replace, rst.toString());
- Integer code = rst.getByPath("Root.RetCode", Integer.class);
- if (!YesOrNo.YES.getCode().equals(code)) {
- String rstmsg = rst.getByPath("Root.RetMsg", String.class);
- throw new BizException(ExceptionEnum.LOGICAL_ERROR, rstmsg);
- }
- }
- private static @NotNull String getVerifySignDataParams(String msg, CaReturn caReturn, CaData.SignAuthentication signData) {
- String request = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
- "<Root>\n" +
- "\t<AppCode>${AppCode}</AppCode>\n" +
- "\t<AppPWD>${AppPWD}</AppPWD>\n" +
- "\t<Request>\n" +
- "\t\t<Cert>${Cert}</Cert>\n" +
- "\t\t<SignAlg>${SignAlg}</SignAlg>\n" +
- "\t\t<InData>${InData}</InData>\n" +
- "\t\t<SignData>${SignData}</SignData>\n" +
- "\t</Request>\n" +
- "</Root>";
- return request.replace("${AppCode}", signData.getAppCode())
- .replace("${AppPWD}", signData.getAppPwd())
- .replace("${Cert}", caReturn.getData().getCert())
- .replace("${SignAlg}", signData.getSignAig())
- .replace("${InData}", msg)
- .replace("${SignData}", caReturn.getData().getSignValue());
- }
- /**
- * 认证时间戳并返回
- *
- * @param msg 数据
- * @return
- */
- private String generateTimestampByInData(String msg) {
- String data = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
- "<Root>\n" +
- "\t<AppCode>${AppCode}</AppCode>\n" +
- "\t<AppPWD>${AppPWD}</AppPWD>\n" +
- "\t<Request>\n" +
- "\t\t<InData>${InData}</InData>\n" +
- "<HashAlg>${HashAlg}</HashAlg>\n" +
- "<CertReq>${CertReq}</CertReq>\n" +
- "\t</Request>\n" +
- "</Root>";
- CaData.TimestampAuthentication timeData = caData.getTimestampAuthentication();
- String request = data.replace("${AppCode}", timeData.getAppCode())
- .replace("${AppPWD}", timeData.getAppPwd())
- .replace("${InData}", msg)
- .replace("${HashAlg}", "SHA256")
- .replace("${CertReq}", "true");
- CaWSDL caWSDL = new CaWSDL(timeData.getUrl());
- JSONObject ret = caWSDL.invoke("generateTimestampByInData", request);
- Integer code = ret.getByPath("Root.RetCode", Integer.class);
- log.info("认证时间戳xml:{}\n认证时间戳返回值:{}\n", request, ret);
- if (code != 1) {
- String retmsg = ret.getByPath("Root.RetMsg", String.class);
- throw new BizException(ExceptionEnum.LOGICAL_ERROR, retmsg);
- }
- return ret.getByPath("Root.Response.TimeStamp", String.class);
- }
- public ResultVo<CaSingBizSnReturnData> getSignInfoByBizSn(String bizSn) {
- CaData.MobileApp app = caData.getMobileApp();
- ForestRequest<?> post = Forest
- .post(app.getUrl() + "/v1/sign/info/" + bizSn)
- .setLogConfiguration(new LogConfiguration() {{
- setLogEnabled(false);
- }})
- .bodyType(ForestDataType.JSON);
- CaSendParams send = new CaSendParams();
- send.setAppId(app.getAppId());
- String indata = "appId=" + app.getAppId() + "&bizSn=" + bizSn;
- String sign = CaUtils.getSign(app.getPrivatekey(), indata);
- send.setSign(sign);
- String ret = post.addBody(send).execute(String.class);
- CaSingBizSnReturnData execute = JSONUtil.toBean(ret, CaSingBizSnReturnData.class);
- if (SUCCRSS.equals(execute.getRet())) {
- CaSingBizSnReturnData.SingData data = execute.getData();
- try {
- data.setSignData(URLDecoder.decode(data.getSignData(), "UTF-8"));
- data.setCert(URLDecoder.decode(data.getCert(), "UTF-8"));
- data.setSeal(URLDecoder.decode(data.getSeal(), "UTF-8"));
- } catch (UnsupportedEncodingException e) {
- log.error(e.getMessage());
- return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, "解码失败请联系管理员" + bizSn);
- }
- return ResultVoUtil.success(execute);
- }
- return ResultVoUtil.success(ExceptionEnum.LOGICAL_ERROR, execute.getMsg());
- }
- private void verifyMedicalRecordStatus(String documentId, EmrSignType type) {
- EmrPatientData emrData = emrPatientDao.selectById(documentId);
- // 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流程中途不得修改。");
- } else {
- emrPatientDao.updateById(EmrPatientData.builder()
- .emrDocumentId(documentId)
- .signType(type.getCode())
- .build());
- }
- }
- /**
- * 发送签名到移动平板
- *
- * @param moreEventSign 数据
- * @return 暂无
- */
- public ResultVo<JSONObject> sendMoreEventSign(CaSignClass.MoreEventSign moreEventSign) {
- verifyMedicalRecordStatus(moreEventSign.getDocumentId(), EmrSignType.MOVE);
- moreEventSign.getData().forEach(item -> {
- isBlank(item.getIdCard(), "身份证不能为空。");
- isBlank(item.getSignName(), "签名人名字不能为空。");
- isBlank(item.getSignType(), "与患者的关系不能为空。");
- item.setIdCard(idCardRsa.decryptStr(item.getIdCard(), KeyType.PrivateKey));
- });
- String redisKey = getRedisKey(moreEventSign.getDocumentId());
- String redisData = redisServer.getData(redisKey, () -> null);
- if (redisData != null) {
- cancelSignature(redisData);
- }
- 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);
- 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) {
- redisServer.setData(redisKey, uuid, 30);
- return ResultVoUtil.success(ExceptionEnum.SUCCESS_AND_EL_MESSAGE, "发送成功。");
- } else {
- return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "请联系管理员" + decode);
- }
- }
- private JSONObject getMoreEventSignData(CaSignClass.MoreEventSign moreEventSign, String uuid) {
- JSONObject ret = new JSONObject();
- CaData.HBoardSign app = caData.getHBoardSign();
- ret.set("api_key", app.getApiKey());
- ret.set("api_secret", app.getApiSecret());
- 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()));
- JSONArray signature = new JSONArray();
- for (int i = 0; i < moreEventSign.getData().size(); i++) {
- CaSignClass.MoreEventSignData item = moreEventSign.getData().get(i);
- JSONObject entries = new JSONObject();
- entries.set("type", "keyword");
- entries.set("sign_type", URLUtil.encode(item.getSignTypeName()));
- entries.set("keyword", new JSONObject() {{
- set("page", "0");
- set("content", URLUtil.encode(item.getContent()));
- }});
- JSONObject user_info = new JSONObject() {{
- set("name", item.getSignName());
- set("idno", item.getIdCard());
- set("age", IdcardUtil.getAgeByIdCard(item.getIdCard()));
- }};
- user_info.set("relation", item.getSignType());
- if (StrUtil.isNotBlank(item.getSignOpinion())) {
- JSONObject informed_keyword = JSONUtil.createObj()
- .set("informed_page", 0)
- .set("informed _content", URLUtil.encode(item.getSignOpinion()));
- JSONObject informed_stamp = JSONUtil.createObj()
- .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() {{
- set("doctor_no", moreEventSign.getSendCode());
- }});
- data.set("pic_size", new JSONObject() {{
- set("width", "60");
- set("height", "10");
- }});
- ret.set("data", data);
- return ret;
- }
- /**
- * h5 签名返回一个http连接
- *
- * @param value
- * @return
- * @deprecated 没啥用
- */
- public ResultVo<CaSignClass.H5Return> h5EventSign(CaSignClass.H5EventSign value) {
- JSONObject ret = new JSONObject();
- String uuid = IdUtil.simpleUUID();
- CaData.HBoardSign app = caData.getHBoardSign();
- ret.set("api_key", app.getApiKey());
- ret.set("api_secret", app.getApiSecret());
- ret.set("data", new JSONObject() {{
- set("document_no", uuid);
- set("pdf", emrServer.getPdfBase(value.getDocumentId()));
- set("type", "keyword");
- set("keyword", new JSONObject() {{
- set("page", "0");
- set("content", URLUtil.encode(value.getContent()));
- }});
- }});
- String execute = Forest
- .post(caData.getHBoardSign().getUrl() + "/seal/h5EventSign")
- .addBody(ret)
- .bodyType(ForestDataType.JSON)
- .execute(String.class);
- return getStringResultVo(execute, uuid, "");
- }
- @Getter
- public enum EmrSignType {
- QR(1, "扫码"),
- MOVE(2, "移动平板"),
- HANDWRITING_BOARD(3, "有线手写板");
- private final Integer code;
- private final String name;
- EmrSignType(int code, String name) {
- this.code = code;
- this.name = name;
- }
- }
- /**
- * CA 扫码签名
- *
- * @param value
- * @return
- */
- public ResultVo<CaSignClass.H5Return> hBoardSignV2(CaSignClass.H5EventSign value) {
- isNoll(value.getSignType(), "请选择和患者的关系");
- isBlank(value.getIdCard(), "身份证不能为空。");
- isBlank(value.getName(), "姓名不能为空。");
- JSONObject ret = new JSONObject();
- String caDocumentId = IdUtil.simpleUUID();
- verifyMedicalRecordStatus(value.getDocumentId(), EmrSignType.QR);
- 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", caDocumentId);
- set("pdf", redisData.getPdf());
- set("sign_way", "face,hand_sign");
- set("keyword", new JSONObject() {{
- set("page", "0");
- set("content", URLUtil.encode(value.getContent()));
- }});
- set("user_info", new JSONObject() {{
- set("name", URLUtil.encode(value.getName()));
- set("idno", idCard);
- }});
- set("collection_source", "face_photos,hand_sign");
- if (StrUtil.isNotBlank(value.getSignOpinion())) {
- set("informed_stamp", new JSONObject() {{
- set("informed_type", "informed_keyword");
- set("informed_keyword", new JSONObject() {{
- set("informed_page", "0");
- set("informed_content", URLUtil.encode(value.getSignOpinion()));
- }});
- }});
- }
- }});
- String execute = Forest
- .post(caData.getHBoardSign().getUrl() + "/v2/seal/hBoardSign")
- .addBody(ret)
- .bodyType(ForestDataType.JSON)
- .execute(String.class);
- 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<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)) {
- CaSignClass.H5Return build = CaSignClass.H5Return.builder()
- .result(rst.getByPath("sign_url", String.class))
- .caDocumentId(caDocumentId)
- .uuid(uuid)
- .build();
- return ResultVoUtil.success(build);
- }
- return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, "签名失败" + msg);
- }
- public ResultVo<JSONObject> downloadSealV2(String id, String documentId) {
- JSONObject ret = new JSONObject();
- ret.set("api_key", caData.getHBoardSign().getApiKey());
- ret.set("api_secret", caData.getHBoardSign().getApiSecret());
- ret.set("data", new JSONObject() {{
- set("document_no", id);
- }});
- String execute = Forest
- .post(caData.getHBoardSign().getUrl() + "/v2/seal/download")
- .addBody(ret)
- .bodyType(ForestDataType.JSON)
- .execute(String.class);
- JSONObject rst = JSONUtil.parseObj(execute);
- String msg = URLUtil.decode(rst.getByPath("ret_msg", String.class));
- if (0 == rst.getByPath("ret_code", Integer.class)) {
- return ResultVoUtil.success(rst);
- }
- return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST, msg);
- }
- /**
- * 判断扫码是否完成以及回写扫码的数据
- *
- * @return 提示
- */
- 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();
- 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);
- if (null == redisData.getData()) {
- redisData.setData(new ArrayList<>());
- }
- redisData.getData().add(saveData);
- redisServer.setData(key, redisData, 30);
- return ResultVoUtil.success(true);
- }
- public static void main(String[] args) {
- System.out.println(EmrServer.getPdfBase("927936636556216320"));
- }
- /**
- * 扫码流程完成
- */
- public void completeQrCode(String documentId) {
- EmrPatientData data = emrPatientDao.selectById(documentId);
- String redisKey = getRedisKey(documentId);
- CaSignClass.H5EventSignRedis redisServerData = redisServer.getData(redisKey);
- 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);
- redisServer.delData(redisKey);
- }
- public void cancelSignature(String id) {
- JSONObject ret = new JSONObject();
- CaData.HBoardSign app = caData.getHBoardSign();
- ret.set("api_key", app.getApiKey());
- ret.set("api_secret", app.getApiSecret());
- ret.set("data", new JSONObject() {{
- set("document_no", id);
- }});
- Forest.post(caData.getHBoardSign().getUrl() + "/v2/seal/cancelSigne")
- .addBody(ret)
- .bodyType(ForestDataType.JSON)
- .execute(JSONObject.class);
- }
- /**
- * 签名回调
- *
- * @param document 文档id
- * @param data 签名数据
- * @return
- */
- public JSONObject hBoardSignReturnUrl(String document, JSONObject data) {
- // TODO 完成一定手写板签名的时候,需要保存一下PDF
- 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", code);
- set("res_msg", msg);
- }};
- }
- public JSONObject appDownload(String bizSn) {
- JSONObject data = new JSONObject() {{
- set("api_key", caData.getHBoardSign().getApiKey());
- set("api_secret", caData.getHBoardSign().getApiSecret());
- set("data", new JSONObject() {{
- set("document_no", bizSn);
- }});
- }};
- JSONObject execute = Forest
- .post(caData.getHBoardSign().getUrl() + "/app/download")
- .bodyType(ForestDataType.JSON)
- .addBody(data.toJSONString(0))
- .execute(JSONObject.class);
- execute.set("ret_msg", URLUtil.decode(execute.getStr("ret_msg")));
- log.info("返回:{}", execute);
- 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 = "/emr" + "/" + upload.getPatNo()
- + "/" + upload.getTimes()
- + "/" + upload.getFileName();
- String pdfPath = tmpPath + ".pdf";
- String caPath = "/emr" + "/" + 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" + pdfPath;
- }
- }
|