ExecService.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. package thyyxxk.webserver.service.medicalinsurance;
  2. import cn.hutool.core.util.StrUtil;
  3. import com.alibaba.fastjson.JSONObject;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.commons.codec.binary.Base64;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.http.HttpEntity;
  8. import org.springframework.http.HttpHeaders;
  9. import org.springframework.stereotype.Service;
  10. import org.springframework.web.client.RestTemplate;
  11. import thyyxxk.webserver.config.envionment.MedinsurConfig;
  12. import thyyxxk.webserver.config.exception.BizException;
  13. import thyyxxk.webserver.constants.sidicts.SiFunction;
  14. import thyyxxk.webserver.dao.his.medicalinsurance.SiZyDao;
  15. import thyyxxk.webserver.entity.login.UserInfo;
  16. import thyyxxk.webserver.service.hutoolcache.UserCache;
  17. import thyyxxk.webserver.utils.DateUtil;
  18. import thyyxxk.webserver.utils.StringUtil;
  19. import thyyxxk.webserver.utils.TokenUtil;
  20. import javax.crypto.Mac;
  21. import javax.crypto.spec.SecretKeySpec;
  22. import java.text.SimpleDateFormat;
  23. import java.util.Date;
  24. import java.util.HashMap;
  25. import java.util.Map;
  26. /**
  27. * @description: 医保交易执行
  28. * @author: DingJie
  29. * @create: 2021-05-28 15:57:26
  30. **/
  31. @Slf4j
  32. @Service
  33. public class ExecService {
  34. private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  35. private static final String RESULT_CODE = "infcode";
  36. private static final String OUTPUT = "output";
  37. private static int serial = 1000;
  38. private static final int MIN_VAL = 1000;
  39. private static final int MAX_VAL = 9999;
  40. private volatile String signNo;
  41. private final SiZyDao dao;
  42. private final RestTemplate template;
  43. private final MedinsurConfig cfg;
  44. private final UserCache userCache;
  45. @Autowired
  46. public ExecService(SiZyDao dao, RestTemplate template, MedinsurConfig cfg, UserCache userCache) {
  47. this.dao = dao;
  48. this.template = template;
  49. this.cfg = cfg;
  50. this.userCache = userCache;
  51. }
  52. public synchronized String makeMsgId() {
  53. serial += 1;
  54. if (serial > MAX_VAL) {
  55. serial = MIN_VAL;
  56. }
  57. return cfg.getHospId() + sdf.format(new Date()) + serial;
  58. }
  59. private synchronized String getSignNo() {
  60. if (StringUtil.isBlank(signNo)) {
  61. signIn();
  62. }
  63. return signNo;
  64. }
  65. public synchronized void signIn() {
  66. String dbSignNo = dao.getSignInNo();
  67. if (StrUtil.isNotBlank(dbSignNo)) {
  68. signNo = dbSignNo;
  69. log.info("获取历史签到号成功:{}", dbSignNo);
  70. return;
  71. }
  72. JSONObject input = makeSignHeader(SiFunction.SIGN_IN);
  73. JSONObject signIn = new JSONObject();
  74. signIn.put("opter_no", "99999");
  75. signIn.put("mac", cfg.getMacAddress());
  76. signIn.put("ip", cfg.getIpAddress());
  77. input.getJSONObject("input").put("signIn", signIn);
  78. JSONObject result = executeTrade(input, SiFunction.SIGN_IN);
  79. if (null != result && result.getInteger(RESULT_CODE) == 0) {
  80. try {
  81. JSONObject output = result.getJSONObject(OUTPUT);
  82. signNo = output.getJSONObject("signinoutb").getString("sign_no");
  83. dao.updateSignNo(signNo);
  84. log.info("签到成功,签到号:{}", signNo);
  85. } catch (Exception e) {
  86. throw new BizException();
  87. }
  88. }
  89. }
  90. public void signOut() {
  91. if (StringUtil.notBlank(signNo)) {
  92. JSONObject input = makeSignHeader(SiFunction.SIGN_OUT);
  93. JSONObject signOut = new JSONObject();
  94. signOut.put("sign_no", signNo);
  95. signOut.put("opter_no", "99999");
  96. input.getJSONObject("input").put("signOut", signOut);
  97. JSONObject result = executeTrade(input, SiFunction.SIGN_OUT);
  98. if (null != result && result.getIntValue(RESULT_CODE) == 0) {
  99. log.info("医保签退成功。");
  100. signNo = null;
  101. dao.updateSignNo(signNo);
  102. }
  103. }
  104. }
  105. public String getInstitutionArea(String insureArea) {
  106. String hospArea = cfg.getHospArea();
  107. String prefix = hospArea.substring(0, 4);
  108. return insureArea.startsWith(prefix) ? hospArea : prefix.substring(0, 2) + "9900";
  109. }
  110. private JSONObject makeSignHeader(SiFunction function) {
  111. JSONObject header = makePublicHeader("");
  112. header.put("infno", function.getCode());
  113. header.put("opter", "99999");
  114. header.put("opter_name", "全院");
  115. return header;
  116. }
  117. public JSONObject makeTradeHeader(SiFunction function) {
  118. String staffId = TokenUtil.getInstance().getTokenUserId();
  119. String staffName = dao.selectStaffName(staffId);
  120. JSONObject header = makePublicHeader(cfg.getHospArea());
  121. header.put("infno", function.getCode());
  122. header.put("opter", staffId);
  123. header.put("opter_name", staffName);
  124. header.replace("sign_no", getSignNo());
  125. return header;
  126. }
  127. public JSONObject makeTradeHeaderWithInsureArea(SiFunction function, String insureArea) {
  128. String staffId = TokenUtil.getInstance().getTokenUserId();
  129. String staffName = dao.selectStaffName(staffId);
  130. JSONObject header = makePublicHeader(insureArea);
  131. header.put("infno", function.getCode());
  132. header.put("opter", staffId);
  133. header.put("opter_name", staffName);
  134. header.replace("sign_no", getSignNo());
  135. return header;
  136. }
  137. private JSONObject makePublicHeader(String insureArea) {
  138. if (null == insureArea) {
  139. insureArea = "";
  140. }
  141. UserInfo user = userCache.getUserInfoByToken();
  142. JSONObject header = new JSONObject();
  143. JSONObject input = new JSONObject();
  144. header.put("msgid", makeMsgId());
  145. header.put("mdtrtarea_admvs", getInstitutionArea(insureArea));
  146. header.put("insuplc_admdvs", insureArea);
  147. header.put("recer_sys_code", "医院");
  148. header.put("dev_no", "");
  149. header.put("dev_safe_info", "");
  150. header.put("cainfo", "");
  151. header.put("signtype", "");
  152. header.put("infver", cfg.getApiVersion());
  153. header.put("opter_type", "1");
  154. header.put("opter", user.getCode());
  155. header.put("opter_name", user.getName());
  156. header.put("inf_time", DateUtil.now());
  157. header.put("fixmedins_code", cfg.getHospId());
  158. header.put("fixmedins_name", cfg.getHospName());
  159. header.put("sign_no", "");
  160. if (StrUtil.isNotBlank(cfg.getSoftDeveloper())) {
  161. header.put("fixmedins_soft_fcty", cfg.getSoftDeveloper());
  162. }
  163. header.put("input", input);
  164. return header;
  165. }
  166. public Map<String, String> getSiHeaderMap(SiFunction function) {
  167. Map<String, String> headers = new HashMap<>();
  168. String timestamp = String.valueOf(System.currentTimeMillis());
  169. String signature = getSignature(timestamp, function.getCode());
  170. // 医保原始地址添加header
  171. // headers.put("_api_access_key", apiAccessKey);
  172. // headers.put("_api_secreKey", apiSecretKey);
  173. // headers.put("_api_name", function.getCode());
  174. // headers.put("_api_version", API_VERSION);
  175. // headers.put("_api_timestamp", timestamp);
  176. // headers.put("_api_signature", signature);
  177. // webhis.thyy.cn代理地址添加header
  178. headers.put("apiAccessKey", cfg.getAccessKey());
  179. headers.put("apiSecreKey", cfg.getSecretKey());
  180. headers.put("apiName", StrUtil.isBlank(cfg.getApiName()) ? function.getCode() : cfg.getApiName());
  181. headers.put("apiVersion", cfg.getApiVersion());
  182. headers.put("apiTimestamp", timestamp);
  183. headers.put("apiSignature", signature);
  184. return headers;
  185. }
  186. public HttpHeaders getHttpHeaders(SiFunction function) {
  187. String timestamp = String.valueOf(System.currentTimeMillis());
  188. String signature = getSignature(timestamp, function.getCode());
  189. HttpHeaders headers = new HttpHeaders();
  190. headers.add("apiAccessKey", cfg.getAccessKey());
  191. headers.add("apiSecreKey", cfg.getSecretKey());
  192. headers.add("apiName", StrUtil.isBlank(cfg.getApiName()) ? function.getCode() : cfg.getApiName());
  193. headers.add("apiVersion", cfg.getApiVersion());
  194. headers.add("apiTimestamp", timestamp);
  195. headers.add("apiSignature", signature);
  196. return headers;
  197. }
  198. public String getSignature(String timestamp, String function) {
  199. String source =
  200. "_api_access_key=" + cfg.getAccessKey() +
  201. "&_api_name=" + function +
  202. "&_api_timestamp=" + timestamp +
  203. "&_api_version=" + cfg.getApiVersion();
  204. return hmacSha1(source);
  205. }
  206. private String hmacSha1(String src) {
  207. byte[] result = null;
  208. try {
  209. SecretKeySpec signInKey = new SecretKeySpec(cfg.getSecretKey().getBytes(), "HmacSHA1");
  210. Mac mac = Mac.getInstance("HmacSHA1");
  211. mac.init(signInKey);
  212. byte[] rawHmac = mac.doFinal(src.getBytes());
  213. result = Base64.encodeBase64(rawHmac);
  214. } catch (Exception e) {
  215. log.error("HmacSHA1加密出错", e);
  216. }
  217. return null == result ? null : new String(result);
  218. }
  219. public JSONObject executeTrade(JSONObject input, SiFunction function) {
  220. try {
  221. String result = template.postForObject(cfg.getApiUrl(),
  222. new HttpEntity<>(input, getHttpHeaders(function)), String.class);
  223. log.info("【接口号:" + function.getCode() + "】医保接口调用:\r\n参数:" + input + "\r\n返回:" + result);
  224. return JSONObject.parseObject(result);
  225. } catch (Exception e) {
  226. log.error("医保网络出错", e);
  227. JSONObject object = new JSONObject();
  228. object.put("infcode", -1);
  229. if (e.getMessage().contains("Connection timed out")) {
  230. object.put("err_msg", "医保中心网络故障,连接超时。");
  231. } else {
  232. object.put("err_msg", e.getMessage());
  233. }
  234. return object;
  235. }
  236. }
  237. }