SavePayResultService.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package thyyxxk.wxservice_server.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.wechat.pay.java.service.payments.model.Transaction;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.beans.factory.annotation.Value;
  8. import org.springframework.stereotype.Service;
  9. import org.springframework.web.client.RestTemplate;
  10. import thyyxxk.wxservice_server.config.exception.ExceptionEnum;
  11. import thyyxxk.wxservice_server.constant.CardCostTypes;
  12. import thyyxxk.wxservice_server.dao.InpatientDao;
  13. import thyyxxk.wxservice_server.dao.WxApiDao;
  14. import thyyxxk.wxservice_server.entity.PureCodeName;
  15. import thyyxxk.wxservice_server.entity.ResultVo;
  16. import thyyxxk.wxservice_server.entity.electronichealthcard.HisRegister;
  17. import thyyxxk.wxservice_server.entity.inpatient.GetZyFeeParam;
  18. import thyyxxk.wxservice_server.entity.paymzfee.MedinsPresettle;
  19. import thyyxxk.wxservice_server.entity.wxapi.PushMessageParam;
  20. import thyyxxk.wxservice_server.entity.wxapi.WxPayOrder;
  21. import thyyxxk.wxservice_server.factory.thmz.ThmzService;
  22. import thyyxxk.wxservice_server.factory.thmz.model.SaveAppointmentRequest;
  23. import thyyxxk.wxservice_server.factory.thmz.model.SaveClinicRegisterRequest;
  24. import thyyxxk.wxservice_server.factory.thmz.model.SaveMzPayRequest;
  25. import thyyxxk.wxservice_server.utils.*;
  26. import java.math.BigDecimal;
  27. import java.util.Date;
  28. import java.util.concurrent.TimeUnit;
  29. /**
  30. * @description: 保存付费结果
  31. * @author: DingJie
  32. * @create: 2021/7/518:02
  33. */
  34. @Slf4j
  35. @Service
  36. public class SavePayResultService {
  37. private final WxApiDao dao;
  38. private final InpatientDao yjjDao;
  39. private final ThmzService thmzService;
  40. private final WxRefundService refundService;
  41. private final PushWxMessageService pushWxMessageService;
  42. private final ElectronicHealthCardService healthCardService;
  43. @Value("${siMzApiUrl}")
  44. private String siMzApiUrl;
  45. @Autowired
  46. public SavePayResultService(WxApiDao dao, InpatientDao yjjDao, ThmzService thmzService, WxRefundService refundService,
  47. PushWxMessageService pushWxMessageService, ElectronicHealthCardService healthCardService) {
  48. this.dao = dao;
  49. this.yjjDao = yjjDao;
  50. this.thmzService = thmzService;
  51. this.refundService = refundService;
  52. this.pushWxMessageService = pushWxMessageService;
  53. this.healthCardService = healthCardService;
  54. }
  55. public String saveClinicRegister(WxPayOrder order, String payTime) {
  56. if (dao.alreadyPaidRegisterFee(order.getTradeNo()) == 1) {
  57. dao.updateSuccessHisStatus(order.getTradeNo());
  58. log.info("订单号:{} 的挂号信息已保存,无需再次保存。", order.getTradeNo());
  59. return payTime;
  60. }
  61. SaveClinicRegisterRequest request = new SaveClinicRegisterRequest.Builder()
  62. .patientId(order.getPatientId()).times(order.getMzyRequestId())
  63. .psordnum(order.getTradeNo()).agtordnum(order.getSerialNo())
  64. .amount(order.getTotalFee()).fundpayAmt(order.getFundpayAmt())
  65. .acctpayAmt(order.getAcctpayAmt()).couponAmt(order.getCouponAmt())
  66. .cashpayAmt(order.getCashpayAmt()).build();
  67. String saveClinicRegisterResponse = thmzService.saveClinicRegister(request);
  68. return afterSaveAllAppointment(saveClinicRegisterResponse, order, payTime);
  69. }
  70. public String saveAppointment(WxPayOrder order, String payTime) {
  71. if (dao.alreadyPaidRegisterFee(order.getTradeNo()) == 1) {
  72. dao.updateSuccessHisStatus(order.getTradeNo());
  73. log.info("订单号:{} 的挂号信息已保存,无需再次保存。", order.getTradeNo());
  74. return payTime;
  75. }
  76. SaveAppointmentRequest request = new SaveAppointmentRequest.Builder()
  77. .mzyRequestId(order.getMzyRequestId()).patientId(order.getPatientId())
  78. .totalFee(order.getTotalFee()).fundpayAmt(order.getFundpayAmt())
  79. .acctpayAmt(order.getAcctpayAmt()).couponAmt(order.getCouponAmt())
  80. .cashpayAmt(order.getCashpayAmt()).psordnum(order.getTradeNo())
  81. .agtordnum(order.getSerialNo()).apTime(order.getApTime()).build();
  82. String saveAppointmentResponse = thmzService.saveAppointment(request);
  83. return afterSaveAllAppointment(saveAppointmentResponse, order, payTime);
  84. }
  85. private String afterSaveAllAppointment(String response, WxPayOrder order, String payTime) {
  86. if (!response.startsWith("ERROR:")) {
  87. dao.updateSuccessHisStatus(order.getTradeNo());
  88. dao.couponUsed(order.getCouponId());
  89. HisRegister hisRegister = dao.selectRegisterDateDiff(order.getTradeNo());
  90. if (null != hisRegister) {
  91. String scene = hisRegister.getDateDiff() > 0 ? "0101011" : "0101012";
  92. healthCardService.reportHisData(order.getPatientId(), scene, hisRegister.getUnitCode(), CardCostTypes.SELF_PAY);
  93. }
  94. return payTime;
  95. }
  96. if (dao.alreadyPaidRegisterFee(order.getTradeNo()) == 1) {
  97. dao.updateSuccessHisStatus(order.getTradeNo());
  98. dao.couponUsed(order.getCouponId());
  99. return payTime;
  100. }
  101. String refund = refundService.autoRefund(order.getTradeNo(), response);
  102. if (!refund.startsWith("ERROR:")) {
  103. dao.refundOrder(order.getTradeNo(), response);
  104. return response;
  105. }
  106. return "ERROR:保存挂号信息失败,自动退款失败,请联系服务中心进行退款。";
  107. }
  108. public String saveMzChargeInfo(WxPayOrder order, String payTime) throws Exception {
  109. String hisOrdNum = order.getHisOrdNum();
  110. String tradeNo = order.getTradeNo();
  111. while (TradeVectorUtil.tradeNoBeingRefund(tradeNo)) {
  112. TimeUnit.SECONDS.sleep(3);
  113. }
  114. if (dao.alreadyPayed(tradeNo) > 0) {
  115. log.info("订单号:{} 的门诊缴费信息已保存,无需再次保存。", tradeNo);
  116. updateAppletHisChargeplStatus(hisOrdNum, tradeNo, order.getCouponId(), order.getCashpayAmt());
  117. return payTime;
  118. }
  119. PureCodeName status = dao.selectPayStatus(tradeNo);
  120. log.info("【订单号:{}】查询订单是否已退款结果:{}", tradeNo, status);
  121. if (null != status && (StringUtil.notBlank(status.getName()) ||
  122. status.getTradeState() == Transaction.TradeStateEnum.REFUND)) {
  123. if (status.getTradeState() != Transaction.TradeStateEnum.REFUND) {
  124. dao.updateRefundStatus(tradeNo);
  125. }
  126. TradeVectorUtil.removeRefunded(tradeNo);
  127. return "ERROR:因系统原因,订单已退款。请稍后重新缴费或前往一楼收费窗口缴费。";
  128. }
  129. if (TradeVectorUtil.tradeNoRefunded(tradeNo)) {
  130. dao.updateRefundStatus(tradeNo);
  131. return "ERROR:因系统原因,订单已退款。请稍后重新缴费或前往一楼收费窗口缴费。";
  132. }
  133. SaveMzPayRequest request = new SaveMzPayRequest.Builder().payTime(payTime)
  134. .patCardNo(order.getPatientId()).agtOrdNum(order.getSerialNo())
  135. .payAmt(order.getTotalFee()).fundpayAmt(order.getFundpayAmt())
  136. .acctpayAmt(order.getAcctpayAmt()).couponAmt(order.getCouponAmt())
  137. .cashpayAmt(order.getCashpayAmt()).hisOrdNum(hisOrdNum)
  138. .psOrdNum(tradeNo).build();
  139. ResultVo<String> saveMzPayResponse = thmzService.saveMzPay(request);
  140. if (saveMzPayResponse.getCode() == ExceptionEnum.SUCCESS.getCode()) {
  141. updateAppletHisChargeplStatus(hisOrdNum, tradeNo, order.getCouponId(), order.getCashpayAmt());
  142. int fundpayCount = dao.selectFundPayCount(tradeNo);
  143. String cardCostTypes = fundpayCount > 0 ? CardCostTypes.MED_INS : CardCostTypes.SELF_PAY;
  144. healthCardService.reportHisData(order.getPatientId(), "0101051", null, cardCostTypes);
  145. return payTime;
  146. }
  147. if (dao.alreadyPayed(tradeNo) > 0) {
  148. updateAppletHisChargeplStatus(hisOrdNum, tradeNo, order.getCouponId(), order.getCashpayAmt());
  149. return payTime;
  150. }
  151. String refund = refundService.autoRefund(tradeNo, saveMzPayResponse.getMessage());
  152. if (!refund.startsWith("ERROR:")) {
  153. dao.refundOrder(tradeNo, saveMzPayResponse.getMessage());
  154. return "ERROR:【" + saveMzPayResponse.getMessage() + "】已为您自动退款,请留意到账信息。";
  155. }
  156. return "ERROR:【" + saveMzPayResponse.getMessage() + "】自动退款失败,请联系服务中心进行退款。";
  157. }
  158. private void updateAppletHisChargeplStatus(String hisOrdNum, String tradeNo, String couponId, BigDecimal cashpayAmt) {
  159. String[] patinfo = hisOrdNum.split("_");
  160. medinsSettle(hisOrdNum, cashpayAmt);
  161. dao.updateMzSavedFlag(patinfo[0], patinfo[1]);
  162. dao.updateSuccessHisStatus(tradeNo);
  163. dao.couponUsed(couponId);
  164. }
  165. private void medinsSettle(String hisOrdNum, BigDecimal cashpayAmt) {
  166. String[] arr = hisOrdNum.split("_");
  167. MedinsPresettle presettle = dao.selectPreSetlinfo(arr[0], arr[1]);
  168. if (null != presettle) {
  169. BigDecimal medinsPayAmt = presettle.getFundPaySumamt().add(presettle.getAcctPay());
  170. JSONObject params = new JSONObject();
  171. params.put("patNo", arr[0]);
  172. params.put("times", arr[1]);
  173. params.put("staffId", "99999");
  174. if (presettle.getAcctPay().compareTo(BigDecimal.ZERO) > 0) {
  175. params.put("acctUsedFlag", "1");
  176. }
  177. if (medinsPayAmt.compareTo(BigDecimal.ZERO) > 0) {
  178. if (presettle.getMedfeeSumamt().compareTo(cashpayAmt) <= 0) {
  179. String url = siMzApiUrl + "/revokeOutpatientSettlement";
  180. String response = new RestTemplate().postForObject(url, params, String.class);
  181. log.info("患者全自费缴费,自动撤销医保业务:\n参数:{}\n:结果:{}", params, JSON.toJSON(response));
  182. return;
  183. }
  184. }
  185. String url = siMzApiUrl + "/outpatientSettlement";
  186. String response = new RestTemplate().postForObject(url, params, String.class);
  187. log.info("患者自助医保结算:\n参数:{}\n结果:{}", params, JSON.toJSON(response));
  188. }
  189. }
  190. public String saveZyYjjInfo(WxPayOrder order, String payTime) {
  191. int savedCount = yjjDao.selectSavedCount(order.getTradeNo(), order.getSerialNo());
  192. if (savedCount > 0) {
  193. log.info("订单号:{} 的住院预交金信息已保存,无需再次保存。", order.getTradeNo());
  194. dao.couponUsed(order.getCouponId());
  195. return payTime;
  196. }
  197. String datetime = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd HH:mm:ss");
  198. yjjDao.payZyYjjSuccessful(order.getInpatientNo(), order.getAdmissTimes(), order.getTotalFee(),
  199. datetime, order.getTradeNo(), order.getSerialNo(), "");
  200. GetZyFeeParam getZyFeeParam = new GetZyFeeParam();
  201. String date = DateUtil.formatDatetime(new Date(), "yyyy-MM-dd");
  202. getZyFeeParam.setInpatientNo(order.getInpatientNo());
  203. getZyFeeParam.setAdmissTimes(order.getAdmissTimes());
  204. getZyFeeParam.setStart(date);
  205. getZyFeeParam.setEnd(date);
  206. yjjDao.selectZyFees(getZyFeeParam);
  207. dao.updateSuccessHisStatus(order.getTradeNo());
  208. dao.couponUsed(order.getCouponId());
  209. if (StringUtil.isBlank(order.getPatientId())) {
  210. return payTime;
  211. }
  212. healthCardService.reportHisData(order.getPatientId(), "0101056", null, CardCostTypes.SELF_PAY);
  213. log.info("缴纳住院预交金成功:{}", JSON.toJSONStringWithDateFormat(order, "yyyy-MM-dd HH:mm:ss"));
  214. String msgContent = "{\"touser\":\"\",\"data\":" +
  215. "{\"keyword3\":{\"color\":\"#173177\",\"value\":\"" + order.getTotalFee() + "\"}," +
  216. "\"keyword1\":{\"color\":\"#173177\",\"value\":\"" + order.getPatientName() + "\"}," +
  217. "\"keyword2\":{\"color\":\"#173177\",\"value\":\"" + order.getInpatientNo() + "\"}," +
  218. "\"remark\":{\"color\":\"#FF0000\",\"value\":\"感谢您的使用,祝您健康!\"}," +
  219. "\"first\":{\"color\":\"#FF0000\",\"value\":\"您好,您已成功支付住院预交金,详情如下:\"}}," +
  220. "\"template_id\":\"6qWVpQopIe4a_fYYnZg_yaInPoMFduDDJ4hotv3Mtxo\"," +
  221. "\"url\":\"\"}";
  222. PushMessageParam pojo = new PushMessageParam();
  223. pojo.setCardNo(yjjDao.selectCardNoByPatientId(order.getPatientId()));
  224. pojo.setMsgContext(JSONObject.parseObject(msgContent));
  225. pushWxMessageService.pushMessage2(pojo);
  226. return payTime;
  227. }
  228. }