ExecService.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package thyyxxk.sizyfeeoprnsystm.service;
  2. import com.alibaba.fastjson.JSONObject;
  3. import org.apache.commons.codec.binary.Base64;
  4. import org.springframework.http.HttpHeaders;
  5. import thyyxxk.sizyfeeoprnsystm.config.MedinsurConfig;
  6. import thyyxxk.sizyfeeoprnsystm.dao.SiZyDao;
  7. import thyyxxk.sizyfeeoprnsystm.dicts.SiFunction;
  8. import thyyxxk.sizyfeeoprnsystm.utils.DateUtil;
  9. import thyyxxk.sizyfeeoprnsystm.utils.StringUtil;
  10. import lombok.extern.slf4j.Slf4j;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.http.HttpEntity;
  13. import org.springframework.stereotype.Service;
  14. import org.springframework.web.client.RestTemplate;
  15. import javax.crypto.Mac;
  16. import javax.crypto.spec.SecretKeySpec;
  17. import java.text.SimpleDateFormat;
  18. import java.util.Date;
  19. /**
  20. * @description: 签到签退
  21. * @author: DingJie
  22. * @create: 2021-05-28 15:57:26
  23. **/
  24. @Slf4j
  25. @Service
  26. public class ExecService {
  27. private static final String RESULT_CODE = "infcode";
  28. private static final String OUTPUT = "output";
  29. private static int serial = 1000;
  30. private static final int MIN_VAL = 1000;
  31. private static final int MAX_VAL = 9999;
  32. private final SiZyDao siZyDao;
  33. private final RestTemplate template;
  34. private final MedinsurConfig cfg;
  35. private volatile String signNo;
  36. @Autowired
  37. public ExecService(SiZyDao siZyDao, RestTemplate template, MedinsurConfig cfg) {
  38. this.siZyDao = siZyDao;
  39. this.template = template;
  40. this.cfg = cfg;
  41. }
  42. private synchronized String getSignNo() {
  43. if (StringUtil.isBlank(signNo)) {
  44. signIn();
  45. }
  46. return signNo;
  47. }
  48. public synchronized void signIn() {
  49. String dbSignNo = siZyDao.getSignInNo();
  50. if (StringUtil.notBlank(dbSignNo)) {
  51. signNo = dbSignNo;
  52. log.info("获取历史签到号成功:{}", dbSignNo);
  53. return;
  54. }
  55. JSONObject input = makeSignHeader(SiFunction.SIGN_IN);
  56. JSONObject signIn = new JSONObject();
  57. signIn.put("opter_no", "99999");
  58. signIn.put("mac", cfg.getMacAddress());
  59. signIn.put("ip", cfg.getIpAddress());
  60. input.getJSONObject("input").put("signIn", signIn);
  61. JSONObject result = executeTrade(input, SiFunction.SIGN_IN);
  62. log.info("医保签到:\n参数:{},\n结果:{}", input, result);
  63. if (null != result && result.getIntValue(RESULT_CODE) == 0) {
  64. try {
  65. JSONObject output = result.getJSONObject(OUTPUT);
  66. signNo = output.getJSONObject("signinoutb").getString("sign_no");
  67. siZyDao.updateSignNo(signNo);
  68. log.info("签到成功,签到号:{}", signNo);
  69. } catch (Exception e) {
  70. log.error("签到出错", e);
  71. }
  72. }
  73. }
  74. public void signOut() {
  75. if (StringUtil.notBlank(signNo)) {
  76. JSONObject input = makeSignHeader(SiFunction.SIGN_OUT);
  77. JSONObject signOut = new JSONObject();
  78. signOut.put("sign_no", signNo);
  79. signOut.put("opter_no", "99999");
  80. input.getJSONObject("input").put("signOut", signOut);
  81. JSONObject result = executeTrade(input, SiFunction.SIGN_OUT);
  82. log.info("医保签退:\n参数:{},\n结果:{}", input, result);
  83. if (null != result && result.getIntValue(RESULT_CODE) == 0) {
  84. signNo = null;
  85. }
  86. }
  87. }
  88. public String getInstitutionArea(String insureArea) {
  89. // String hospArea = cfg.getHospArea();
  90. // String prefix = hospArea.substring(0, 4);
  91. // return insureArea.startsWith(prefix) ? hospArea : prefix.substring(0, 2) + "9900";
  92. return cfg.getHospArea();
  93. }
  94. private String timestamp() {
  95. SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
  96. return sdf.format(new Date());
  97. }
  98. public synchronized String makeMsgId() {
  99. serial += 1;
  100. if (serial > MAX_VAL) {
  101. serial = MIN_VAL;
  102. }
  103. return cfg.getHospId() + timestamp() + serial;
  104. }
  105. public HttpHeaders getHttpHeaders(SiFunction function) {
  106. String timestamp = String.valueOf(System.currentTimeMillis());
  107. String signature = getSignature(timestamp, function.getCode());
  108. HttpHeaders headers = new HttpHeaders();
  109. // headers.add("apiAccessKey", cfg.getAccessKey());
  110. // headers.add("apiSecreKey", cfg.getSecretKey());
  111. // headers.add("apiName", cfg.getApiName());
  112. // headers.add("apiVersion", cfg.getApiVersion());
  113. // headers.add("apiTimestamp", timestamp);
  114. // headers.add("apiSignature", signature);
  115. // 医保原始地址添加header
  116. headers.add("_api_access_key", cfg.getAccessKey());
  117. // headers.add("secretKey", cfg.getSecretKey());
  118. headers.add("_api_name", cfg.getApiName());
  119. headers.add("_api_version", cfg.getApiVersion());
  120. headers.add("_api_timestamp", timestamp);
  121. headers.add("_api_signature", signature);
  122. return headers;
  123. }
  124. public String getSignature(String timestamp, String function) {
  125. String source =
  126. "_api_access_key=" + cfg.getAccessKey() +
  127. "&_api_name=" + cfg.getApiName() +
  128. "&_api_timestamp=" + timestamp +
  129. "&_api_version=" + cfg.getApiVersion();
  130. return hmacSha1(source);
  131. }
  132. private String hmacSha1(String src) {
  133. byte[] result = null;
  134. try {
  135. SecretKeySpec signInKey = new SecretKeySpec(cfg.getSecretKey().getBytes(), "HmacSHA1");
  136. Mac mac = Mac.getInstance("HmacSHA1");
  137. mac.init(signInKey);
  138. byte[] rawHmac = mac.doFinal(src.getBytes());
  139. result = Base64.encodeBase64(rawHmac);
  140. } catch (Exception e) {
  141. log.error("HmacSHA1加密出错", e);
  142. }
  143. return null == result ? null : new String(result);
  144. }
  145. private JSONObject makeSignHeader(SiFunction function) {
  146. JSONObject header = makePublicHeader("");
  147. header.put("infno", function.getCode());
  148. header.put("opter", "99999");
  149. header.put("opter_name", "全院");
  150. return header;
  151. }
  152. public JSONObject makeTradeHeaderWithInsureArea(SiFunction function, String insureArea, String staffId) {
  153. String staffName = siZyDao.selectStaffName(staffId);
  154. JSONObject header = makePublicHeader(insureArea);
  155. header.put("infno", function.getCode());
  156. header.put("opter", staffId);
  157. header.put("opter_name", staffName);
  158. header.replace("sign_no", getSignNo());
  159. return header;
  160. }
  161. public JSONObject makePublicHeader(String insureArea) {
  162. if (null == insureArea) {
  163. insureArea = "";
  164. }
  165. JSONObject header = new JSONObject();
  166. JSONObject input = new JSONObject();
  167. header.put("msgid", makeMsgId());
  168. header.put("mdtrtarea_admvs", getInstitutionArea(insureArea));
  169. header.put("insuplc_admdvs", insureArea);
  170. header.put("recer_sys_code", cfg.getHospArea());
  171. header.put("dev_no", "");
  172. header.put("dev_safe_info", "");
  173. header.put("cainfo", "");
  174. header.put("signtype", "");
  175. header.put("infver", cfg.getApiVersion());
  176. header.put("opter_type", "1");
  177. header.put("inf_time", DateUtil.now());
  178. header.put("fixmedins_code", cfg.getHospId());
  179. header.put("fixmedins_name", cfg.getHospName());
  180. header.put("sign_no", "");
  181. if (StringUtil.notBlank(cfg.getSoftDeveloper())) {
  182. header.put("fixmedins_soft_fcty", cfg.getSoftDeveloper());
  183. }
  184. header.put("input", input);
  185. return header;
  186. }
  187. public JSONObject executeTrade(JSONObject input, SiFunction function) {
  188. return template.postForObject(cfg.getApiUrl(),
  189. new HttpEntity<>(input, getHttpHeaders(function)), JSONObject.class);
  190. }
  191. /**
  192. * 工伤接口URL
  193. */
  194. // 模拟接口地址(当前使用)
  195. private static final String WORK_INJURY_API_URL = "http://130.150.161.72:9206/thyy/api/public/injury/workinjury";
  196. // 真实接口地址(注释掉,需要时手动切换)
  197. // private static final String WORK_INJURY_API_URL = "http://localhost:8321/api/entry/workinjury";
  198. /**
  199. * 执行工伤接口调用(工伤接口使用不同的请求头格式)
  200. */
  201. public JSONObject executeWorkInjuryTrade(JSONObject input) {
  202. HttpHeaders headers = new HttpHeaders();
  203. headers.add("Content-Type", "application/json");
  204. // 工伤接口可能不需要医保接口的认证头,直接使用简单的JSON头
  205. return template.postForObject(WORK_INJURY_API_URL,
  206. new HttpEntity<>(input, headers), JSONObject.class);
  207. }
  208. }