PowersiMiPayPlugin.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. package thyyxxk.wxservice_server.controller.api;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.http.HttpEntity;
  8. import org.springframework.http.HttpHeaders;
  9. import org.springframework.http.MediaType;
  10. import org.springframework.web.bind.annotation.*;
  11. import org.springframework.web.client.RestTemplate;
  12. import thyyxxk.wxservice_server.config.auth.PassToken;
  13. import thyyxxk.wxservice_server.config.exception.ExceptionEnum;
  14. import thyyxxk.wxservice_server.config.properties.ApiAddr;
  15. import thyyxxk.wxservice_server.dao.api.PowersiPluginDao;
  16. import thyyxxk.wxservice_server.entity.ResultVo;
  17. import thyyxxk.wxservice_server.entity.assessment.PushQuestionnaireVisit;
  18. import thyyxxk.wxservice_server.entity.medinsmobilepay.InsuinfoRequest;
  19. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.OrdState;
  20. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.request.CommonRequest;
  21. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.request.PowersiMipSetlinfo;
  22. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.request.RevokeSettleRequest;
  23. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.response.BillInfo;
  24. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.response.CommonResponse;
  25. import thyyxxk.wxservice_server.entity.medinsmobilepay.frompowersiplugin.response.Upload6201;
  26. import thyyxxk.wxservice_server.factory.thmz.ThmzService;
  27. import thyyxxk.wxservice_server.factory.thmz.model.QueryReceiptRequest;
  28. import thyyxxk.wxservice_server.factory.thmz.model.SaveMzPayRequest;
  29. import thyyxxk.wxservice_server.service.IdCardAnalyzeService;
  30. import thyyxxk.wxservice_server.service.PushWxMessageService;
  31. import thyyxxk.wxservice_server.utils.*;
  32. import thyyxxk.wxservice_server.utils.mip.DataHandler;
  33. import java.io.IOException;
  34. import java.math.BigDecimal;
  35. import java.util.*;
  36. @Slf4j
  37. @RestController
  38. @RequestMapping("/api/mobilePayPlugin")
  39. public class PowersiMiPayPlugin {
  40. private final PowersiPluginDao dao;
  41. private final IdCardAnalyzeService idCardAnalyzeService;
  42. private final ThmzService thmzService;
  43. private final PushWxMessageService messageService;
  44. private final String hisMipApi;
  45. private final DataHandler dataHandler = DataHandler.newInstance();
  46. @Autowired
  47. public PowersiMiPayPlugin(PowersiPluginDao dao, IdCardAnalyzeService idCardAnalyzeService, ThmzService thmzService, PushWxMessageService messageService, ApiAddr apiAddr) throws IOException {
  48. this.dao = dao;
  49. this.idCardAnalyzeService = idCardAnalyzeService;
  50. this.thmzService = thmzService;
  51. this.messageService = messageService;
  52. this.hisMipApi = apiAddr.getHisMipApi();
  53. }
  54. @PostMapping("/lockOrder")
  55. public ResultVo<String> lockOrder(@RequestBody InsuinfoRequest request) {
  56. String openid = TokenUtil.getInstance().getUserOpenid();
  57. dao.lockOrder(request.getHisOrdNum(), openid,1);
  58. return ResultVoUtil.success(openid);
  59. }
  60. @PostMapping("/unlockOrder")
  61. public ResultVo<String> unlockOrder(@RequestBody InsuinfoRequest request) {
  62. dao.lockOrder(request.getHisOrdNum(), null, 0);
  63. return ResultVoUtil.success("操作成功。");
  64. }
  65. private JSONObject decryptRequest(JSONObject body) throws Exception {
  66. body.put("code", 0);
  67. JSONObject decrypt = dataHandler.processRspData(body.toJSONString());
  68. return decrypt.getJSONObject("data");
  69. }
  70. @PassToken
  71. @PostMapping("/patientInquiry")
  72. public CommonResponse patientInquiry(@RequestBody JSONObject body) throws Exception {
  73. JSONObject request = decryptRequest(body);
  74. List<String> patNos = dao.selectPatientCount(request.getString("idNo"));
  75. if (patNos.isEmpty()) {
  76. return new CommonResponse("未查询到建档信息。");
  77. }
  78. return new CommonResponse();
  79. }
  80. @PassToken
  81. @PostMapping("/patientCreate")
  82. public CommonResponse patientCreate(@RequestBody JSONObject body) throws Exception {
  83. JSONObject request = decryptRequest(body);
  84. return idCardAnalyzeService.createCardFromPowersiPlugin(request);
  85. }
  86. @PassToken
  87. @PostMapping("/billListInquiry")
  88. public JSONObject billListInquiry(@RequestBody JSONObject body) throws Exception {
  89. JSONObject request = decryptRequest(body);
  90. List<String> patNos = dao.selectPatientCount(request.getString("idNo"));
  91. if (patNos.isEmpty()) {
  92. JSONObject res = new JSONObject();
  93. res.put("code", -1);
  94. res.put("success", false);
  95. res.put("message", "没有患者的建档信息。");
  96. return res;
  97. }
  98. List<BillInfo> list = new ArrayList<>();
  99. for (String patNo : patNos) {
  100. QueryReceiptRequest receiptRequest = new QueryReceiptRequest.Builder()
  101. .patCardNo(patNo).build();
  102. ResultVo<List<Map<String, Object>>> vo =
  103. thmzService.getMzChargeDetailForUnPaid(receiptRequest);
  104. if (vo.getCode() != ExceptionEnum.SUCCESS.getCode()) {
  105. continue;
  106. }
  107. List<Map<String, Object>> feeList = vo.getData();
  108. for (Map<String, Object> map : feeList) {
  109. BillInfo billInfo = new BillInfo(map);
  110. if (billInfo.getVipFlag() != 0) {
  111. continue;
  112. }
  113. String url = hisMipApi + "/writeMtReceipt?hisOrdNum=" + billInfo.getBizId();
  114. String writeMtReceipt = new RestTemplate().getForObject(url, String.class);
  115. if (Objects.equals(writeMtReceipt, "SUCCESS")) {
  116. billInfo.setIdNo(request.getString("idNo"));
  117. billInfo.setIdType(request.getString("idType"));
  118. billInfo.setDeptId(dao.selectDeptId(billInfo.getDeptName()));
  119. list.add(billInfo);
  120. }
  121. }
  122. }
  123. if (list.isEmpty()) {
  124. JSONObject res = new JSONObject();
  125. res.put("code", -1);
  126. res.put("success", false);
  127. res.put("message", "没有患者的待缴费信息。");
  128. return res;
  129. }
  130. String listRef = JSONArray.toJSONString(list);
  131. JSONObject temp = new JSONObject();
  132. temp.put("billInfo", JSONArray.parseArray(listRef));
  133. String raw = dataHandler.buildReqData(temp);
  134. JSONObject response = JSONObject.parseObject(raw);
  135. response.put("code", 0);
  136. response.put("success", true);
  137. response.put("message", "OK");
  138. return response;
  139. }
  140. @PassToken
  141. @PostMapping("/billDetailInquiry")
  142. public JSONObject billDetailInquiry(@RequestBody JSONObject body) throws Exception {
  143. JSONObject request = decryptRequest(body);
  144. String bizId = request.getString("bizId");
  145. bizId = null == bizId ? "" : bizId;
  146. String[] arr = bizId.split("_");
  147. if (arr.length != 3) {
  148. JSONObject res = new JSONObject();
  149. res.put("code", -1);
  150. res.put("success", false);
  151. res.put("message", "bizId[" + bizId + "]不正确!");
  152. return res;
  153. }
  154. request.put("patNo", arr[0]);
  155. request.put("times", Integer.parseInt(arr[1]));
  156. Upload6201 upload6201 = new RestTemplate().postForObject(hisMipApi + "/getUpload6201", request, Upload6201.class);
  157. if (null == upload6201) {
  158. JSONObject res = new JSONObject();
  159. res.put("code", -1);
  160. res.put("success", false);
  161. res.put("message", "网络异常,请稍后再试。");
  162. return res;
  163. }
  164. upload6201.setIdNo(request.getString("idNo"));
  165. upload6201.setIdType(request.getString("idType"));
  166. upload6201.setUserName(request.getString("userName"));
  167. String raw = dataHandler.buildReqData(JSONObject.toJSONString(upload6201));
  168. JSONObject response = JSONObject.parseObject(raw);
  169. response.put("code", 0);
  170. response.put("success", true);
  171. response.put("message", "OK");
  172. return response;
  173. }
  174. @PassToken
  175. @PostMapping("/settleNotify")
  176. public CommonResponse settleNotify(@RequestBody JSONObject body) throws Exception {
  177. JSONObject request = decryptRequest(body);
  178. PowersiMipSetlinfo setlinfo = dao.selectById(request.getString("platformOrderId"));
  179. if (null == setlinfo) {
  180. setlinfo = JSONObject.parseObject(request.toJSONString(), PowersiMipSetlinfo.class);
  181. JSONObject hiExtData = request.getJSONObject("hiExtData");
  182. if (null != hiExtData) {
  183. JSONObject clrObj = hiExtData.getJSONObject("setlinfo");
  184. if (null != clrObj) {
  185. String clrOptins = clrObj.getString("clrOptins");
  186. String clrType = clrObj.getString("clrType");
  187. setlinfo.setClrOptins(clrOptins);
  188. setlinfo.setClrType(clrType);
  189. }
  190. }
  191. int insert = dao.insert(setlinfo);
  192. if (insert == 1) {
  193. saveMzOrder(setlinfo);
  194. return new CommonResponse();
  195. }
  196. return new CommonResponse("HIS业务处理失败。");
  197. }
  198. if (setlinfo.getMzSaved() == 0) {
  199. saveMzOrder(setlinfo);
  200. return new CommonResponse();
  201. }
  202. return new CommonResponse();
  203. }
  204. private void saveMzOrder(PowersiMipSetlinfo setlinfo) {
  205. SaveMzPayRequest saveMzPayRequest = new SaveMzPayRequest.Builder()
  206. .payTime(DateUtil.formatDatetime(setlinfo.getTraceTime()))
  207. .patCardNo(setlinfo.getMedOrgOrd().split("_")[0])
  208. .agtOrdNum(setlinfo.getThirdOrderId())
  209. .payAmt(setlinfo.getFeeSumamt())
  210. .fundpayAmt(setlinfo.getFundPay())
  211. .acctpayAmt(setlinfo.getPsnAcctPay())
  212. .couponAmt(BigDecimal.ZERO)
  213. .cashpayAmt(setlinfo.getOwnpayAmt())
  214. .hisOrdNum(setlinfo.getMedOrgOrd())
  215. .psOrdNum(setlinfo.getPlatformOrderId())
  216. .isNormalClinic(true).build();
  217. ResultVo<String> res = thmzService.saveMzPay(saveMzPayRequest);
  218. if (res.getCode() == ExceptionEnum.SUCCESS.getCode()) {
  219. dao.updateMzSaved(setlinfo.getPlatformOrderId());
  220. }
  221. pushMessage(setlinfo.getMedOrgOrd(), setlinfo.getUserName());
  222. }
  223. private void pushMessage(String hisOrdNum, String userName) {
  224. String[] arr = hisOrdNum.split("_");
  225. int times = Integer.parseInt(arr[1]);
  226. PushQuestionnaireVisit visit = dao.getVisit(arr[0], times, hisOrdNum);
  227. String visitId = hisOrdNum.replaceAll("_", "AND") + "AND" + visit.getDoctorCode() + "AND" + visit.getDeptCode();
  228. String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxbde6b16acad84204&redirect_uri=" +
  229. "https://staticweb.hnthyy.cn/wxserver/redirect/page2?to=doctorGradeByPush_" + visitId +
  230. "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
  231. String msgContent = "{\"touser\":\"" + visit.getOpenid() + "\",\"data\":" +
  232. "{\"keyword1\":{\"color\":\"#173177\",\"value\":\"" + userName + "\"}," +
  233. "\"keyword2\":{\"color\":\"#173177\",\"value\":\"长沙泰和医院\"}," +
  234. "\"keyword3\":{\"color\":\"#173177\",\"value\":\"" + visit.getDeptName() + "\"}," +
  235. "\"keyword4\":{\"color\":\"#173177\",\"value\":\"" + visit.getDoctorName() + "\"}," +
  236. "\"keyword5\":{\"color\":\"#173177\",\"value\":\"" + visit.getVisitDate() + "\"}," +
  237. "\"remark\":{\"color\":\"#FF0000\",\"value\":\"特邀请您对医生服务作出评价。\"}," +
  238. "\"first\":{\"color\":\"#FF0000\",\"value\":\"您曾在我院进行诊疗。\"}}," +
  239. "\"template_id\":\"G4YAN56RmDjEPpNyP5fpCdr5TghyqspDeWlWaD5Eg2o\"," +
  240. "\"url\":\"" + url + "\"}";
  241. JSONObject message = JSONObject.parseObject(msgContent);
  242. messageService.pushMessage2(message);
  243. }
  244. @PassToken
  245. @GetMapping("/isMipOrder")
  246. public ResultVo<String> isMipOrder(@RequestParam("hisOrdNum") String hisOrdNum) throws Exception {
  247. PowersiMipSetlinfo setlinfo = getSetlinfo(hisOrdNum, null);
  248. if (null == setlinfo) {
  249. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  250. }
  251. return ResultVoUtil.success(setlinfo.getPlatformOrderId());
  252. }
  253. @PassToken
  254. @PostMapping("/revokeMipSettle")
  255. public ResultVo<String> revokeMipSettle(@RequestBody CommonRequest request) throws Exception {
  256. PowersiMipSetlinfo setlinfo = getRefundableSetl(request.getHisOrdNum());
  257. if (null == setlinfo) {
  258. setlinfo = getSetlinfo(request.getHisOrdNum(), OrdState.REFUND_SUCCEED);
  259. if (null != setlinfo) {
  260. return ResultVoUtil.success("医保移动支付退款成功");
  261. }
  262. return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有可以退款的结算交易。");
  263. }
  264. Date now = new Date();
  265. RevokeSettleRequest refd = new RevokeSettleRequest();
  266. if (StringUtil.notBlank(request.getRefdType())) {
  267. refd.setRefdType(request.getRefdType());
  268. }
  269. refd.setMedOrgOrd(request.getHisOrdNum());
  270. refd.setMedRefdId(SnowFlakeId.instance().nextId());
  271. refd.setRefdTime(DateUtil.formatDatetime(now));
  272. refd.setTotlRefdAmt(setlinfo.getFeeSumamt());
  273. refd.setPsnAcctRefdAmt(setlinfo.getPsnAcctPay());
  274. refd.setFundRefdAmt(setlinfo.getFundPay());
  275. refd.setCashRefdAmt(setlinfo.getOwnpayAmt());
  276. refd.setRefdReason(request.getRefundReason());
  277. refd.setEcToken(request.getEcToken());
  278. refd.setPlatformOrderId(setlinfo.getPlatformOrderId());
  279. JSONObject raw = JSONObject.parseObject(JSONObject.toJSONString(refd));
  280. String body = dataHandler.buildReqData(raw);
  281. String url = "http://webhis.thyy.cn:8077/powersiMipRefund";
  282. HttpHeaders headers = new HttpHeaders();
  283. headers.setContentType(MediaType.APPLICATION_JSON);
  284. HttpEntity<String> entity = new HttpEntity<>(body, headers);
  285. RestTemplate restTemplate = new RestTemplate();
  286. String encRes = restTemplate.postForObject(url, entity, String.class);
  287. JSONObject decRes = dataHandler.processRspData(encRes);
  288. Integer code = decRes.getInteger("code");
  289. if (null != code && code == 0) {
  290. JSONObject data = decRes.getJSONObject("data");
  291. OrdState state = OrdState.get(data.getString("refStatus"));
  292. if (null == state) {
  293. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  294. }
  295. String refId = data.getString("platformRefdId");
  296. dao.updateRevokeInfo(request.getStaffId(), now, refId, setlinfo.getMedOrgOrd(), state);
  297. if (state == OrdState.REFUND_SUCCEED) {
  298. return ResultVoUtil.success("医保移动支付退款成功");
  299. }
  300. if (state == OrdState.REFUND_PROCEEDING) {
  301. return ResultVoUtil.success("医保移动支付退款进行中,请稍后查询退款结果。");
  302. }
  303. if (state == OrdState.REFUND_ABNORMAL) {
  304. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保移动支付退款异常,请稍后查询退款结果。");
  305. }
  306. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, data.getString("failMsg"));
  307. }
  308. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, decRes.getString("message"));
  309. }
  310. private PowersiMipSetlinfo getRefundableSetl(String id) {
  311. PowersiMipSetlinfo setlinfo = getSetlinfo(id, OrdState.SETTLED);
  312. if (null == setlinfo) {
  313. setlinfo = getSetlinfo(id, OrdState.REFUND_FAILED);
  314. if (null == setlinfo) {
  315. setlinfo = getSetlinfo(id, OrdState.REFUND_ABNORMAL);
  316. }
  317. }
  318. return setlinfo;
  319. }
  320. private PowersiMipSetlinfo getSetlinfo(String id, OrdState state) {
  321. QueryWrapper<PowersiMipSetlinfo> wrapper = new QueryWrapper<>();
  322. wrapper.eq("med_org_ord", id);
  323. if (null == state) {
  324. List<PowersiMipSetlinfo> list = dao.selectList(wrapper);
  325. if (list == null || list.isEmpty()) {
  326. return null;
  327. }
  328. return list.get(0);
  329. }
  330. wrapper.eq("ord_state", state);
  331. return dao.selectOne(wrapper);
  332. }
  333. @PassToken
  334. @GetMapping("/queryRefundState")
  335. public ResultVo<String> queryRefundState(@RequestParam("hisOrdNum") String hisOrdNum) throws Exception {
  336. QueryWrapper<PowersiMipSetlinfo> wrapper = new QueryWrapper<>();
  337. wrapper.eq("med_org_ord", hisOrdNum);
  338. wrapper.ne("ord_state", OrdState.SETTLED);
  339. wrapper.isNotNull("platform_refd_id");
  340. PowersiMipSetlinfo setlinfo = dao.selectOne(wrapper);
  341. if (null == setlinfo) {
  342. return ResultVoUtil.fail(ExceptionEnum.NO_DATA_EXIST);
  343. }
  344. JSONObject params = new JSONObject();
  345. params.put("platformRefdId", setlinfo.getPlatformRefdId());
  346. params.put("orgCodg", "H43010500370");
  347. JSONObject raw = JSONObject.parseObject(JSONObject.toJSONString(params));
  348. String body = dataHandler.buildReqData(raw);
  349. String url = "http://webhis.thyy.cn:8077/powersiMipRefundQuery";
  350. HttpHeaders headers = new HttpHeaders();
  351. headers.setContentType(MediaType.APPLICATION_JSON);
  352. HttpEntity<String> entity = new HttpEntity<>(body, headers);
  353. RestTemplate restTemplate = new RestTemplate();
  354. String encRes = restTemplate.postForObject(url, entity, String.class);
  355. JSONObject decRes = dataHandler.processRspData(encRes);
  356. Integer code = decRes.getInteger("code");
  357. if (null != code && code == 0) {
  358. JSONObject data = decRes.getJSONObject("data");
  359. data.remove("hiExtData");
  360. OrdState state = OrdState.get(data.getString("refdStatus"));
  361. if (null == state) {
  362. return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
  363. }
  364. String refId = data.getString("platformRefdId");
  365. dao.updateRefundState(refId, state);
  366. return ResultVoUtil.success(state.toString());
  367. }
  368. return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, decRes.getString("message"));
  369. }
  370. }