package com.ynxbd.common.service; import com.alibaba.fastjson.JSONObject; import com.ynxbd.ali.enums.AliMsgEnum; import com.ynxbd.ali.helper.AliHelper; import com.ynxbd.ali.helper.AliMessageHelper; import com.ynxbd.common.action.pay.PEnum; import com.ynxbd.common.bean.RegSign; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.Order; import com.ynxbd.common.bean.pay.Register; import com.ynxbd.common.dao.RefundDao; import com.ynxbd.common.dao.RegisterDao; import com.ynxbd.common.dao.his.HisAccountDao; import com.ynxbd.common.dao.his.HisRegisterDao; import com.ynxbd.common.helper.common.CodeHelper; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.his.HisHelper; import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; import com.ynxbd.wx.config.MessagePushConfig; import com.ynxbd.wx.utils.DateGenerate; import com.ynxbd.wx.wxfactory.WxMedicalHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.bean.MedicalOrder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import java.math.BigDecimal; import java.util.*; import java.util.stream.Collectors; /** * 挂号业务层 * * @Author wsq * @Date 2021/3/4 11:36 * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. */ @Slf4j public class RegService { /** * 挂号类型设置 * * @param regDate 挂号日期 * @param isSplitTime 是否分时段 * @return 是否成功 */ public static String setRegType(String regDate, boolean isSplitTime) { if (ObjectUtils.isEmpty(regDate)) { log.info("[挂号]挂号日期异常 regDate={}", regDate); return null; } // 挂号类型:1:预约挂号,2:现场挂号,3:分时段预约挂号,4:分时段现场挂号 if (isSplitTime) { return DateHelper.isToday(regDate) ? "4" : "3"; // 判断是否是今天 } return DateHelper.isToday(regDate) ? "2" : "1"; // 判断是否是今天 } /** * 挂号预付款信息存储 * * @param reg 挂号信息 * @return 是否成功 */ public boolean isSaveRegPrepay(Register reg) { if (reg == null) { log.info("reg is null"); return false; } reg.setHisStatus(-1); reg.setPayStatus(-1); boolean isResult = new RegisterDao().insert(reg); log.info("[挂号预存信息{}", (isResult ? "成功" : "失败")); return isResult; } /** * 支付完成-->挂号回调 * * @param merchantEnum 商户类型 * @param totalFee 订单金额 * @param openid openid * @param bankTransNo 商户返回流水号 * @param outTradeNo 订单号 * @param payDate 支付日期 * @param payTime 支付时间 * @param payInfo 商户返回支付信息 * @return 是否完成 */ public boolean regPaidNotify(MerchantEnum merchantEnum, BigDecimal totalFee, String openid, String bankTransNo, String outTradeNo, String bankMerchantNo, String payDate, String payTime, String payInfo, Date tradeDate) throws ServiceException { RegisterDao registerDao = new RegisterDao(); Register reg; String regType, patientId; String tradeNo = HisHelper.getHisTradeNo(bankTransNo, PEnum.REG); try { reg = registerDao.selectByOutTradeNo(outTradeNo); if (reg == null) { throw new ServiceException(ResultEnum.DATA_NOT_FOUND, String.format("{%s} [挂号]数据库中未找到订单 outTradeNo={%s}, bankTransNo={%s}, tradeNo={%s}", merchantEnum.NAME, outTradeNo, bankTransNo, tradeNo)); } Integer hisStatus = reg.getHisStatus(); Integer payStatus = reg.getPayStatus(); if (payStatus == null || hisStatus == null || payStatus == 0 || hisStatus == 0) { // 状态不明确 log.info(String.format("{%s} [挂号]订单已支付,停止向下执行 outTradeNo={%s}, bankTransNo={%s}, tradeNo={%s}", merchantEnum.NAME, outTradeNo, bankTransNo, tradeNo)); return false; } // 更新商户支付状态 if (!registerDao.updateMerPaidByOutTradeNo(outTradeNo, payDate, payTime, bankTransNo, tradeNo, bankMerchantNo)) { log.info(String.format("{%s} [挂号]更新订单失败,停止向下执行 outTradeNo={%s}, bankTransNo={%s}, tradeNo={%s}", merchantEnum.NAME, outTradeNo, bankTransNo, tradeNo)); return false; } reg.setPayDate(payDate); reg.setPayTime(payTime); reg.setBankTransNo(bankTransNo); reg.setTradeNo(tradeNo); // 挂号类型:1:预约挂号,2:现场挂号;3:分时段预约挂号,4:分时段现场挂号 regType = reg.getRegType(); patientId = reg.getPatientId(); if (ObjectUtils.isEmpty(patientId) || ObjectUtils.isEmpty(regType) || ObjectUtils.isEmpty(reg.getRegDate())) { throw new ServiceException(ResultEnum.PARAM_IS_BLANK, String.format("{%s} [挂号]参数缺失 outTradeNo={%s}, bankTransNo={%s}, tradeNo={%s}", merchantEnum.NAME, outTradeNo, bankTransNo, tradeNo)); } } catch (ServiceException e) { log.error(e.getMessage()); ResultEnum resultEnum = e.getResultEnum(); String message = resultEnum == null ? "系统繁忙" : resultEnum.message; String pushMessage = "挂号失败已申请退款,原因:" + message + ",订单号:" + outTradeNo; // 推送消息 regAutoRefund(merchantEnum, HisHelper.createErrorResult(message), openid, totalFee, outTradeNo, tradeNo, message, pushMessage, tradeDate); throw new ServiceException(message); } log.info("{} 开始调用HIS挂号:patientId={}, bankTransNo={}", merchantEnum.NAME, patientId, bankTransNo); String hisTransNo = null, treatNum = null, hisQueueNo, callNum = null, invoiceTransNo = null; // 挂号类型:1:预约挂号,2:现场挂号;3:分时段预约挂号,4:分时段现场挂号 JsonResult jsonResult; if ("1".equals(regType) || "2".equals(regType)) { // 挂号 log.info("[挂号]开始执行"); jsonResult = new HisRegisterDao().handleReg(reg, merchantEnum); if (jsonResult.success()) { hisTransNo = jsonResult.getDataMapString("HISTransNo"); treatNum = jsonResult.getDataMapString("MZNum"); // 门诊号 callNum = jsonResult.getDataMapString("CallNum"); // 现场叫号号 invoiceTransNo = jsonResult.getDataMapString("InvoiceTransNo"); // 发票流水号 log.info("[挂号]HIS返回 hisTransNo={}, treatNum={}", hisTransNo, treatNum); if (hisTransNo == null) { log.info("[挂号]读取HIS信息失败"); } if ("2".equals(regType) && ObjectUtils.isEmpty(treatNum)) { log.info("[今日挂号]HIS返回门诊号为空"); } } } else if ("3".equals(regType) || "4".equals(regType)) { log.info("[分时段挂号]开始执行"); jsonResult = new HisRegisterDao().handleTimeReg(reg, merchantEnum); if (jsonResult.success()) { hisTransNo = jsonResult.getDataMapString("HISTransNo"); treatNum = jsonResult.getDataMapString("MZNum"); // 门诊号 hisQueueNo = jsonResult.getDataMapString("QueueNo"); // 排队号 invoiceTransNo = jsonResult.getDataMapString("InvoiceTransNo"); // 发票流水号 log.info("[分时段挂号]HIS返回 hisTransNo={}, hisQueueNo={}", hisTransNo, hisQueueNo); if (hisTransNo == null || hisQueueNo == null) { log.info("[分时段挂号]读取HIS信息失败"); } } } else { // 不执行挂号-->退费 String message = "挂号类型异常:{" + regType + "}"; log.info("{} [挂号] patientId={}, message={}", merchantEnum.NAME, patientId, message); jsonResult = HisHelper.createErrorResult(message); } String message = jsonResult.getMessage(); if (!jsonResult.success()) { // 调用HIS失败-->自动退款 log.info("{} [挂号]调用HIS挂号失败:patientId={}", merchantEnum.NAME, patientId); String pushMessage = "挂号失败已申请退款,原因:" + message + ",订单号:" + outTradeNo; // 推送消息 // 自动退款 regAutoRefund(merchantEnum, jsonResult, openid, totalFee, outTradeNo, tradeNo, message, pushMessage, tradeDate); throw new ServiceException(message); } // 挂号成功-->更新挂号信息 log.info("{} [挂号]更新HIS挂号信息[after] outTradeNo={}, tradeNo={}, patientId={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, tradeNo, patientId, bankTransNo); if (registerDao.updateHisRegInfo(outTradeNo, bankTransNo, hisTransNo, treatNum, invoiceTransNo, callNum)) { log.info("{} [挂号]更新HIS挂号信息成功 patientId={}", merchantEnum.NAME, patientId); } new MsgPushService().regMsgPush(merchantEnum, reg); // 短信通知 smsNotice(reg); if (MerchantEnum.WX.equals(merchantEnum)) { MessagePushConfig.regPush(merchantEnum, reg); MessagePushConfig.regAI(merchantEnum, reg); // 挂号导航推送 MessagePushConfig.regNavigatePush(merchantEnum, reg); // 电子健康卡上报数据 HCodeService.regPayReportHISData(openid, patientId, reg.getDeptName(), reg.getRegDate()); } if (MerchantEnum.ALI.equals(merchantEnum)) { String link = DateHelper.isToday(reg.getRegDate()) ? "pages/center/components/remordList/index" : "pages/center/components/remordList/reserve"; String title = "挂号 " + reg.getDeptName(); AliMessageHelper.hospitalOrder(openid, title, AliMsgEnum.MERCHANT_PREORDER_SUCCESS, reg.getUpdateTime(), true, totalFee, outTradeNo, reg.getRegDate(), reg.getBegTime(), reg.getDeptCode(), reg.getDeptName(), reg.getDoctName(), AliHelper.getLink(link, null)); } return true; } /** * His系统处方手动退费 * * @param reason 退费原因 * @return 是否成功 */ public Result mdCashRefund(String payOrdId, String reason) { RegisterDao regDao = new RegisterDao(); Register regInfo = regDao.selectStatusErrOrder(payOrdId); if (regInfo == null) { return Result.error(ResultEnum.DATA_NOT_FOUND); } String refundResult = regInfo.getRefundResult(); if (WxPayHelper.OK.equals(refundResult)) { return Result.error(ResultEnum.REFUND_IS_REPEAT); // 退费重复申请 } String outTradeNo = regInfo.getOutTradeNo(); BigDecimal cashFee = regInfo.getPayMoney(); if (cashFee == null) { return Result.error(ResultEnum.REFUND_CASH_IS_NULL); } if (cashFee.compareTo(BigDecimal.ZERO) == 0) { if (!regDao.updateRefundByTradeNo(payOrdId, WxPayHelper.OK)) { log.error("[医保]挂号现金0修改数据库状态失败 payOrderId={}", payOrdId); return Result.error(ResultEnum.DATA_UPDATE_ERROR); } Map map = new HashMap<>(); map.put("transNo", regInfo.getTradeNo()); map.put("payWay", regInfo.getPayWay()); map.put("bankTransNo", regInfo.getBankTransNo()); map.put("payMoney", cashFee); return Result.success(map); } MedicalOrder order = WxMedicalHelper.refund(outTradeNo, ("R" + payOrdId), payOrdId, cashFee, reason); log.info("[医保]挂号现金退费order={}", order); String refundReason = "线下现金退费"; if (!ObjectUtils.isEmpty(reason)) { refundReason = ":" + reason; } refundResult = order.isOk() ? WxPayHelper.OK : order.getMessage(); if (!regDao.updateRefundByTradeNo(payOrdId, refundResult, refundReason)) { log.error("[医保]挂号现金退费修改数据库状态失败 payOrderId={}, refundResult={}", payOrdId, refundResult); } if (order.isOk()) { Map map = new HashMap<>(); map.put("transNo", regInfo.getTradeNo()); map.put("payWay", regInfo.getPayWay()); map.put("bankTransNo", regInfo.getBankTransNo()); map.put("payMoney", cashFee); return Result.success(map); } return Result.error(refundResult); } // /** // * 消息推送 // * // * @param reg 挂号信息 // */ // private void messagePush(Register reg) { // try { // if (!MessagePushConfig.isRegIsEnable()) { // return; // } // // String openid = reg.getOpenid(); // String patientId = reg.getPatientId(); // String regDate = reg.getRegDate(); // 挂号日期 // String begTime = reg.getBegTime(); // 开始时间 // String endTime = reg.getEndTime(); // 结束时间 // String doctName = reg.getDoctName(); // String deptName = reg.getDeptName(); // String deptCode = reg.getDeptCode(); // if (openid == null || patientId == null) { // return; // } // // Patient patient = new PatientDao().selectByOpenidAndPatientId(openid, patientId); // // log.info("[挂号导航]开始推送 openid={}, patientId={}", openid, patientId); // // HashMap params = new HashMap<>(); // params.put("templateId", MessagePushConfig.getRegTemplateId()); // // params.put("patientName", patient == null ? null : patient.getName() + " ID:" + patientId); // params.put("content", "就诊时间:" + regDate + " " + begTime + "-" + endTime); // params.put("openId", DesEncryptHelper.enCode(openid)); // params.put("deptName", deptName); // params.put("deptCode", deptCode); // // Result result = RequestHelper.get(MessagePushConfig.getRegUrl(), params, String.class); // if (result.getCode() != 200) { // log.info("[挂号导航]推送失败 {}", JSON.toJSONString(result)); // } // } catch (Exception e) { // e.printStackTrace(); // } // } /** * 预约短信通知 * * @param reg 预约信息 */ private boolean smsNotice(Register reg) { String openid = reg.getOpenid(); if (ObjectUtils.isEmpty(openid)) { // 关注过,并且填写过电话号码 log.info("[挂号]短信通知:openid为空"); } return new SmsService().sms_reg_001(reg); } /** * 取消预约 * * @param patientId 患者id * @param tradeNo HIS交易流水号 * @param hisTransNo HIS流水号 * @return 是否成功 */ public Result cancelRegReserve(String patientId, String tradeNo, String hisTransNo) { log.info("[挂号][取消预约]申请 patientId={}, tradeNo={}, hisTransNo={}", patientId, tradeNo, hisTransNo); if (patientId == null || ObjectUtils.isEmpty(tradeNo) || hisTransNo == null) { log.info("[挂号][取消预约]参数缺失 patientId={}, bankTransNo={}, hisTransNo={}", patientId, tradeNo, hisTransNo); return Result.error(ResultEnum.PARAM_IS_DEFECT); } Register reg = new RegisterDao().selectRegByHisTransNo(hisTransNo); if (reg == null) { log.info("[挂号][取消预约]失败, 未查询到挂号支付信息"); return Result.error(ResultEnum.DATA_NOT_FOUND); } String outTradeNo = reg.getOutTradeNo(); MerchantEnum merchantEnum = MerchantEnum.findEnumByOutTradeNo(outTradeNo); JsonResult JsonResult = new HisRegisterDao().cancelReserve(patientId, tradeNo, merchantEnum); if (!JsonResult.success()) { String message = JsonResult.getMessage(); log.info("[挂号][取消预约]失败 HIS返回:{}", message); return Result.error(message); } String dbTradeNo = reg.getTradeNo(); BigDecimal payMoney = reg.getPayMoney(); if (dbTradeNo == null || outTradeNo == null || payMoney == null) { log.info("[挂号][取消预约]失败, 支付信息的参数为空,patientId={}, tradeNo={}, payMoney={}", patientId, tradeNo, payMoney); return Result.error("支付信息的参数为空"); } if (merchantEnum == null) { return Result.error("支付方式未匹配 outTradeNo=" + outTradeNo); } log.info("{}[挂号][取消预约]开始退款:outTradeNo={}, dbTradeNo={}, payMoney={}", merchantEnum.NAME, outTradeNo, dbTradeNo, payMoney); String pushInfo = "取消预约 科室:" + reg.getDeptName(); Result result = regAutoRefund(merchantEnum, JsonResult, reg.getOpenid(), payMoney, outTradeNo, dbTradeNo, "取消预约", pushInfo, reg.getUpdateTime()); new SmsService().sms_reg_002(reg); MessagePushConfig.regCancelPush(merchantEnum, reg); if (result.isOK()) { result.setMessage(merchantEnum.NAME + "取消成功,挂号费用将在24小时内退回!"); // 修改返回提示的信息 } if (MerchantEnum.ALI.equals(merchantEnum)) { String link = "pages/center/components/remordList/reserve"; String title = "预约挂号取消 " + reg.getDeptName(); AliMessageHelper.hospitalOrder(reg.getOpenid(), title, AliMsgEnum.MERCHANT_CLOSED, reg.getUpdateTime(), false, reg.getTotalFee(), outTradeNo, reg.getRegDate(), reg.getBegTime(), reg.getDeptCode(), reg.getDeptName(), reg.getDoctName(), AliHelper.getLink(link, null)); } return result; } public Result refundRegister(String hisTransNo) { log.info("[今日挂号][取消预约]hisTransNo={}", hisTransNo); if (hisTransNo == null) { log.info("[今日挂号][取消预约]参数缺失 hisTransNo=null"); return Result.error(ResultEnum.PARAM_IS_DEFECT); } Register reg = new RegisterDao().selectRegByHisTransNo(hisTransNo); if (reg == null) { log.info("[今日挂号][取消预约]失败, 未查询到挂号支付信息;若是医保支付则不允许线上退号,请到窗口进行退费"); return Result.error(ResultEnum.REG_NOT_FIND); } String tradeNo = reg.getTradeNo(); String outTradeNo = reg.getOutTradeNo(); MerchantEnum merchantEnum = MerchantEnum.findEnumByOutTradeNo(outTradeNo); JsonResult JsonResult = new HisRegisterDao().refundRegister(tradeNo, merchantEnum); if (!JsonResult.success()) { String message = JsonResult.getMessage(); log.info("[今日挂号][取消预约]失败 HIS返回:{}", message); return Result.error(message); } String dbTradeNo = reg.getTradeNo(); BigDecimal payMoney = reg.getPayMoney(); if (dbTradeNo == null || outTradeNo == null || payMoney == null) { log.info("[今日挂号][取消预约]失败, 支付信息的参数为空, tradeNo={}, payMoney={}", tradeNo, payMoney); return Result.error("今日挂号支付信息的参数为空"); } if ("OK".equals(reg.getRefundResult())) { return Result.error("已退费,请不要重复退费"); } if (merchantEnum == null) { return Result.error("支付方式未匹配 outTradeNo=" + outTradeNo); } new MiddleOfficeService().reg_JH0105(reg.getTreatNum()); log.info("{}[今日挂号][取消预约]开始退款:outTradeNo={}, dbTradeNo={}, payMoney={}", merchantEnum.NAME, outTradeNo, dbTradeNo, payMoney); String pushInfo = "取消预约 科室:" + reg.getDeptName(); Result result = refundTodayRegister(merchantEnum, JsonResult, reg.getOpenid(), payMoney, outTradeNo, dbTradeNo, "取消预约", pushInfo, reg.getUpdateTime()); new SmsService().sms_reg_002(reg); // 短信通知 MessagePushConfig.regCancelPush(merchantEnum, reg); if (result.isOK()) { result.setMessage(merchantEnum.NAME + "取消成功,挂号费用将在24小时内退回!"); // 修改返回提示的信息 } if (MerchantEnum.ALI.equals(merchantEnum)) { String link = "pages/center/components/remordList/reserve"; String title = "预约挂号取消 " + reg.getDeptName(); AliMessageHelper.hospitalOrder(reg.getOpenid(), title, AliMsgEnum.MERCHANT_CLOSED, reg.getUpdateTime(), false, reg.getTotalFee(), outTradeNo, reg.getRegDate(), reg.getBegTime(), reg.getDeptCode(), reg.getDeptName(), reg.getDoctName(), AliHelper.getLink(link, null)); } return result; } /** * 挂号手动退费 * * @param invoiceTransNo 发票流水号 * @param refundUser 退费操作人 * @param refundDesc 退费说明 * @param refundMoney 退款金额 * @return 是否成功 */ public synchronized boolean hisRefund(String invoiceTransNo, String patientId, String refundUser, String refundDesc, BigDecimal refundMoney, PEnum pEnum) throws ServiceException { RegisterDao registerDao = new RegisterDao(); Register reg = registerDao.selectByInvoiceTransNo(invoiceTransNo, patientId); if (reg == null) { log.info("[HIS挂号退费] 没有查询到可退款的记录 invoiceTransNo={}", invoiceTransNo); throw new ServiceException(ResultEnum.DATA_NOT_FOUND); } String authCode = reg.getAuthCode(); if (ObjectUtils.isEmpty(authCode)) { log.info("[HIS挂号退费] 条码为空 authCode={}", authCode); throw new ServiceException("条码为空"); } MerchantEnum merchantEnum = MerchantEnum.getMerchantEnumByAuthCode(authCode); if (merchantEnum == null) { log.info("[HIS挂号退费] 支付方式异常 authCode={}", authCode); throw new ServiceException(ResultEnum.PAY_TYPE_ERROR); } if (ObjectUtils.isEmpty(refundDesc)) { refundDesc = "HIS手动退费"; } String outTradeNo = reg.getOutTradeNo(); BigDecimal dbPayMoney = reg.getPayMoney(); if (refundMoney.compareTo(dbPayMoney) != 0) { log.info("[HIS挂号退费] 退款金额错误禁止退费, invoiceTransNo={}", invoiceTransNo); throw new ServiceException(ResultEnum.REFUND_MONEY_ERROR); } String outRefundNo = HisHelper.getHisTradeNo(reg.getBankTransNo(), pEnum); Order refundInfo = PayService.refund(merchantEnum, outTradeNo, outRefundNo, refundMoney, dbPayMoney, refundDesc, reg.getUpdateTime(), reg.getOpenid(), reg.getPatientId(), null); boolean isResult = refundInfo.isSuccess(); log.info("{} [HIS挂号退费] 申请{} outTradeNo={}, outRefundNo={}, invoiceTransNo={},refundMoney={}, payMoney={}", merchantEnum.NAME, (isResult ? "成功" : "失败"), outTradeNo, outRefundNo, invoiceTransNo, refundMoney, dbPayMoney ); if (!isResult) { throw new ServiceException(ResultEnum.PAY_ERROR_REFUND); } // 退款成功 String refundResult = refundInfo.getRefundResult(); if (!registerDao.updateRefundByInvoiceTransNo(outTradeNo, outRefundNo, invoiceTransNo, refundResult)) { log.info("{} [HIS挂号退费]信息更新失败 outTradeNo={}, outRefundNo={}, invoiceTransNo={}", merchantEnum.NAME, outTradeNo, outRefundNo, invoiceTransNo); } reg.setTotalFee(dbPayMoney); reg.setRefundUser(refundUser); reg.setRefundMoney(refundMoney); reg.setRefundTable(pEnum.CODE); reg.setRefundResult(refundResult); reg.setTradeNo(outRefundNo); if (!new RefundDao().insert(reg, refundDesc, "HIS")) { log.info("{} [HIS挂号退费]退费信息存储失败:outTradeNo={}", merchantEnum.NAME, outTradeNo); } return true; } /** * 挂号手动退费 * * @param refundUser 退费操作人 * @param refundDesc 退费说明 * @return 是否成功 */ public synchronized boolean isHandRefund(String tradeNo, String refundUser, String refundDesc, PEnum orderType, String sys) throws ServiceException { RegisterDao regDao = new RegisterDao(); Register reg = regDao.selectStatusErrOrder(tradeNo); if (reg == null) { throw new ServiceException(ResultEnum.DATA_NOT_FOUND); } // String regType = reg.getRegType(); // if ("1".equals(regType) || "3".equals(regType)) { // throw new ServiceException(ResultEnum.REFUND_RES_REG_NOT_ALLOW); // } if (!PEnum.isNewOrderNo(reg.getBankTransNo(), reg.getTradeNo())) { // 旧版本订单号禁止退费 throw new ServiceException(ResultEnum.REFUND_IS_OLD_ORDER_NUM); } String regDate = reg.getRegDate(); Date verifyDate = DateHelper.strToDate(regDate, DateHelper.DateEnum.yyyy_MM_dd); if (verifyDate == null) { throw new ServiceException(ResultEnum.DATE_FORMAT_ERROR); } Order refundInfo = PayService.handRefund(verifyDate, reg.getUpdateTime(), reg, reg.getPayMoney(), refundUser, refundDesc, orderType.CODE, 1, sys, () -> regDao.updateRefund(reg.getOutTradeNo(), reg.getTradeNo())); // 退款成功 if (!regDao.updateRefundByTradeNo(tradeNo, refundInfo.getRefundResult())) { log.info("[挂号]退费成功,更新状态失败:{}", refundInfo); } else { if ("0".equals(reg.getRefundResult())) { throw new ServiceException(ResultEnum.REFUND_STATUS_ERROR_UPDATE_STATUS_SUCCESS); } } return true; } /** * 挂号失败自动退款 * * @param merchantEnum 退费方式 * @param JsonResult 响应结果 * @param openid openid * @param totalFee 订单总金额 * @param outTradeNo 订单号 * @param tradeNo HIS交易流水号 * @param hisResult 记录信息 */ public Result regAutoRefund(MerchantEnum merchantEnum, JsonResult JsonResult, String openid, BigDecimal totalFee, String outTradeNo, String tradeNo, String hisResult, String pushInfo, Date tradeDate) { log.info("[预约挂号/挂号失败自动退费][开始退费]---merchantEnum-{},JsonResult-{},openid-{},totalFee-{},outTradeNo-{},tradeNo-{},hisResult-{},pushInfo-{},tradeDate-{}", merchantEnum, JsonResult, openid, totalFee, outTradeNo, tradeNo, hisResult, pushInfo, tradeDate); return regRefund(merchantEnum, JsonResult, openid, totalFee, outTradeNo, tradeNo, hisResult, pushInfo, tradeDate, false); } public Result refundTodayRegister(MerchantEnum merchantEnum, JsonResult JsonResult, String openid, BigDecimal totalFee, String outTradeNo, String tradeNo, String hisResult, String pushInfo, Date tradeDate) { log.info("[今日挂号][开始退费]---merchantEnum-{},JsonResult-{},openid-{},totalFee-{},outTradeNo-{},tradeNo-{},hisResult-{},pushInfo-{},tradeDate-{}", merchantEnum, JsonResult, openid, totalFee, outTradeNo, tradeNo, hisResult, pushInfo, tradeDate); return regRefund(merchantEnum, JsonResult, openid, totalFee, outTradeNo, tradeNo, hisResult, pushInfo, tradeDate, true); } public Result regRefund(MerchantEnum merchantEnum, JsonResult JsonResult, String openid, BigDecimal totalFee, String outTradeNo, String tradeNo, String hisResult, String pushInfo, Date tradeDate, boolean isToday) { RegisterDao regDao = new RegisterDao(); String code = JsonResult.getCode(); // 挂号记录更新HIS返回的错误信息 if (!regDao.updateHisPaidFailByOutTradeNo(outTradeNo, code, hisResult)) { log.info("[挂号][退费错误]更新HIS返回的错误信息失败 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo); } if (JsonResult.isTimeout()) { // 超时不退费 log.info("[挂号][退费错误]HIS请求超时 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo); return Result.error("[挂号不退费]HIS请求超时"); } if (!isToday) { // 如果HIS交过费返回true-->就不向下执行(自动退款) String dateShort = DateGenerate.getStringDateShort(); String paidTip = new HisAccountDao().isPaid(DateGenerate.getNextDay(dateShort, "-7"), DateGenerate.getNextDay(dateShort, "7"), tradeNo); if (paidTip != null) { log.info("[挂号][退费错误] paidTip={}, outTradeNo={}, tradeNo={}", paidTip, outTradeNo, tradeNo); return Result.error(paidTip); } } String refundResult; if (totalFee.compareTo(BigDecimal.ZERO) != 0) { // 金为0 log.info("[挂号][退款]开始申请 outTradeNo={}, pushInfo={}", outTradeNo, pushInfo); Order orderRefund = PayService.refund(merchantEnum, outTradeNo, tradeNo, totalFee, totalFee, pushInfo, tradeDate, openid, null, pushInfo); if (!orderRefund.isSuccess()) { log.info("{} [挂号][退费错误] outTradeNo={}, tradeNo={}, totalFee={}", merchantEnum.NAME, outTradeNo, tradeNo, totalFee); } refundResult = orderRefund.getRefundResult(); } else { refundResult = "OK"; } boolean isUpdate = regDao.updateRefundResult(outTradeNo, tradeNo, refundResult); if (!isUpdate) { log.info("{} [挂号][退费错误]信息更新失败 tradeNo={}", merchantEnum.NAME, tradeNo); return Result.error(); } return Result.success(); } /** * 挂号下单 */ public Result regPlaceOrder(String payCode, String ip, Boolean isOccupySource, Boolean isZeroPay, Register reg) { Result noPayTime = PayService.isPaymentPermittedByTime(); if (noPayTime != null) { return noPayTime; } MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); if (merchantEnum == null) { return Result.error(ResultEnum.PAY_TYPE_ERROR); // 支付方式异常 } String openid = reg.getOpenid(); String patientId = reg.getPatientId(); if (reg.getIsSplitTime()) { // 分时段挂号 String sourceId = reg.getSourceId(); // 占用查询开关被开启 if (isOccupySource != null && isOccupySource) { JsonResult result = HisRegisterDao.isOccupySource(patientId, sourceId, merchantEnum); if (!result.success()) { return Result.error(result.getMessage()); } } } JSONObject mdRespJson = PayService.goMedical(merchantEnum, PEnum.REG); if (mdRespJson != null) { return Result.success(mdRespJson); } String deptName = reg.getDeptName(); String regDate = reg.getRegDate(); BigDecimal totalFee = reg.getPayMoney(); String body = deptName + " 挂号(" + regDate + ")"; String outTradeNo = CodeHelper.getOutTradeNo(merchantEnum); log.info("{} [挂号]生成 outTradeNo={}", merchantEnum.NAME, outTradeNo); reg.setPayDeviceId("mobile"); reg.setOutTradeNo(outTradeNo); reg.setPayWay(merchantEnum.PAY_WAY_IN); if (!isSaveRegPrepay(reg)) { log.info("{} [挂号]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); } if (totalFee.compareTo(BigDecimal.ZERO) == 0) { if (isZeroPay == null || !isZeroPay) { return Result.error(ResultEnum.PAY_MONEY_IS_ZERO); } String payDate = DateHelper.getCurDate(); String payTime = DateHelper.getCurTime(); String bankTransNo = outTradeNo.substring(merchantEnum.CODE.length()); try { new RegService().regPaidNotify(merchantEnum, totalFee, openid, bankTransNo, outTradeNo, null, payDate, payTime, null, new Date()); Map map = new HashMap<>(); map.put("totalFee", 0); return Result.success(map); } catch (ServiceException e) { return Result.error(e); } } JSONObject respJson = PayService.createOrder(merchantEnum, openid, patientId, totalFee.toString(), outTradeNo, PEnum.REG.CODE, ip, body); if (respJson == null) { return Result.error(ResultEnum.PAY_ERROR); // 支付异常 } respJson.put("outTradeNo", outTradeNo); return Result.success(respJson); } public boolean updateMicroOrderState(String outTradeNo, String bankTransNo, String openid) { return new RegisterDao().updateMicroOrderState(outTradeNo, bankTransNo, openid); } // 查询挂号预约记录 public List getHisRegReserveRecords(String patientId, String regDate) { return new HisRegisterDao().getRegReserveRecords(patientId, regDate); } // 查询挂号历史记录 public List getHisRegRecordsByRegDate(String patientId, String begDate, String endDate) throws ServiceException { if (begDate == null || endDate == null) { throw new ServiceException("查询日期异常"); } List hisRegList = new HisRegisterDao().getHisRegHistoryRecords(patientId, begDate.equals(endDate) ? begDate : null); // 起止日期相同时,传递挂号日期 List dataList = new ArrayList<>(); String regDate; for (Register reg : hisRegList) { regDate = reg.getRegDate(); if (regDate != null) { regDate = DateHelper.dateFormatShort(regDate); if (regDate != null && DateHelper.inDateRange(begDate, endDate, regDate, DateHelper.DateEnum.yyyy_MM_dd)) { dataList.add(reg); } } } return dataList; } /** * 根据HIS流水号查询订单 * * @param hisTransNo HIS流水号 * @return bean */ public Register queryRegByHisTransNo(String hisTransNo) { return new RegisterDao().selectRegByHisTransNo(hisTransNo); } /** * 根据HIS流水号查询订单 * * @param hisTransNo HIS流水号 * @return bean */ public Register queryRegByPatientIdAndHisTransNo(String patientId, String hisTransNo) throws ServiceException { List dataList = new RegisterDao().selectListByPatientIdAndHisTransNo(patientId, hisTransNo); if (dataList.isEmpty()) { return null; } if (dataList.size() > 1) { throw new ServiceException("错误:查询到多条订单信息"); } return dataList.get(0); } /** * 查询订单 * * @param tradeNo HIS订单号 * @return bean */ public Register queryRegByTradeNoAndPatientId(String patientId, String tradeNo) { return new RegisterDao().selectRegByPatientIdAndTradeNo(patientId, tradeNo); } /** * 根据HIS挂号订单信息查询 * * @param hisTransNo HIS流水号 * @return bean */ public Register queryRegByHisInfo(String patientId, String tradeNo, String hisTransNo) throws ServiceException { Register register; log.info("[挂号订单]根据信息查询订单 patientId={}, hisTransNo={} tradeNo={}", patientId, hisTransNo, tradeNo); if (ObjectUtils.isEmpty(patientId)) { return null; } if (ObjectUtils.isEmpty(tradeNo) && ObjectUtils.isEmpty(hisTransNo)) { return null; } if (ObjectUtils.isEmpty(tradeNo)) { register = queryRegByPatientIdAndHisTransNo(patientId, hisTransNo); } else { register = queryRegByTradeNoAndPatientId(patientId, tradeNo); } return register; } /** * 查询HIS待就诊记录(今日挂号和预约挂号记录) * * @param patientId 患者id */ public List getHisWaitRegRecords(String patientId) throws ServiceException { if (ObjectUtils.isEmpty(patientId)) { throw new ServiceException(ResultEnum.PARAM_IS_BLANK); } String curDate = DateHelper.getCurDate(); // 挂号历史记录(今日) List hisRegRecords = getHisRegRecordsByRegDate(patientId, curDate, curDate); if (hisRegRecords == null) { hisRegRecords = new ArrayList<>(); } // 预约挂号 List hisRegReserveRecords = getHisRegReserveRecords(patientId, null); if (hisRegReserveRecords != null && !hisRegReserveRecords.isEmpty()) { hisRegRecords.addAll(hisRegReserveRecords); } return hisRegRecords; } /** * 根据挂号日期查询挂号记录 * * @param patientId 患者id * @param regDate 挂号日期 */ public List getHisRegRecordsByRegDate(String patientId, String regDate) throws ServiceException { if (ObjectUtils.isEmpty(patientId) || ObjectUtils.isEmpty(regDate)) { throw new ServiceException(ResultEnum.PARAM_IS_BLANK); } String curDate = DateHelper.getCurDate(); List hisRegRecords; if (curDate.equals(regDate)) { // 今日挂号 hisRegRecords = getHisRegRecordsByRegDate(patientId, regDate, regDate); } else { // 预约挂号 hisRegRecords = getHisRegReserveRecords(patientId, regDate); } return hisRegRecords; } public Register findHisRegRecordByHisTransNo(String patientId, String regDate, String hisTransNo) throws ServiceException { if (ObjectUtils.isEmpty(regDate) || ObjectUtils.isEmpty(hisTransNo)) { throw new ServiceException(ResultEnum.PARAM_IS_BLANK); } String tip; List hisRegRecords = getHisRegRecordsByRegDate(patientId, regDate); if (hisRegRecords.isEmpty()) { tip = "HIS中未查询到挂号记录"; log.info("[挂号]{} patientId={}, regDate={}, hisTransNo={}", tip, patientId, regDate, hisTransNo); throw new ServiceException("错误:" + tip + " 日期:" + regDate); } List filterList = hisRegRecords.stream().filter(o -> hisTransNo.equals(o.getHisTransNo())).collect(Collectors.toList()); if (filterList.size() == 1) { return filterList.get(0); } tip = filterList.isEmpty() ? "HIS中未匹配到挂号记录" : "HIS中同一科室查询到多条挂号记录"; log.info("[挂号]{} patientId={}, regDate={}, hisTransNo={}", tip, patientId, regDate, hisTransNo); throw new ServiceException("错误:" + tip + " 日期:" + regDate); } public Register findHisRegRecordByTreatNum(String patientId, String regDate, String treatNum) throws ServiceException { if (ObjectUtils.isEmpty(regDate) || ObjectUtils.isEmpty(treatNum)) { throw new ServiceException(ResultEnum.PARAM_IS_BLANK); } List hisRegRecords = getHisRegRecordsByRegDate(patientId, regDate, regDate); String tip; if (hisRegRecords.isEmpty()) { tip = "HIS中未查询到挂号记录"; log.info("[挂号]{} patientId={}, regDate={}, treatNum={}", tip, patientId, regDate, treatNum); throw new ServiceException("错误:" + tip + " 日期:" + regDate); } List filterList = hisRegRecords.stream().filter(o -> treatNum.equals(o.getTreatNum())).collect(Collectors.toList()); if (filterList.size() == 1) { return filterList.get(0); } tip = filterList.isEmpty() ? "HIS中未匹配到挂号记录" : "HIS中同一科室查询到多条挂号记录"; log.info("[挂号]{} patientId={}, regDate={}, treatNum={}", tip, patientId, regDate, treatNum); throw new ServiceException("错误:" + tip + " 日期:" + regDate); } /** * 查询数据库挂号记录 * * @param patientId 患者id * @param regDate 挂号日期 * @param treatNum 门诊号 * @return bean */ public Register findDBRegRecordByTreatNum(String patientId, String regDate, String treatNum) { try { Register hisRegRecord = findHisRegRecordByTreatNum(patientId, regDate, treatNum); if (hisRegRecord == null) { log.info("[挂号]根据门诊号查询失败,未找到HIS挂号记录 patientId={}, regDate={} treatNum={}", patientId, regDate, treatNum); return null; } String hisTransNo = hisRegRecord.getHisTransNo(); if (ObjectUtils.isEmpty(hisTransNo)) { log.info("[挂号]根据门诊号查询失败 HisTransNo为空 patientId={}, regDate={} treatNum={}", patientId, regDate, treatNum); return null; } return queryRegByHisTransNo(hisTransNo); } catch (Exception e) { return null; } } /** * 补充挂号门诊号 * * @param treatNum 门诊号 * @param openId openId */ public boolean completeRegTreatNum(String treatNum, String openId, String patientId, String tradeNo, String hisTransNo, String orderFromOwner) throws ServiceException { if (!ObjectUtils.isEmpty(orderFromOwner) && !"蓝旗".equals(orderFromOwner)) { return true; } RegisterDao regDao = new RegisterDao(); Register findInfo = queryRegByHisInfo(patientId, tradeNo, hisTransNo); if (findInfo == null) { throw new ServiceException("未找到挂号信息"); } Long id = findInfo.getId(); String curDate = DateHelper.getCurDate(); if (!curDate.equals(findInfo.getRegDate())) { throw new ServiceException("不是今日就诊"); } if (!ObjectUtils.isEmpty(findInfo.getTreatNum())) { //就诊号不为空=>无需补充门诊号 return true; } return regDao.updateTreatNum(id, treatNum) > 0; } // public boolean updateRegMedToolMarkByTreatNum(String treatNum, String patientId, String addMedToolMark) throws ServiceException { // RegisterDao regDao = new RegisterDao(); // String curDate = DateHelper.getCurDate(); // // Register findInfo = findDBRegRecordByTreatNum(patientId, curDate, treatNum); // if (findInfo == null) { // throw new ServiceException("未找到挂号信息"); // } // if (!curDate.equals(findInfo.getRegDate())) { // throw new ServiceException("不是今日就诊"); // } // Long id = findInfo.getId(); // if (!ObjectUtils.isEmpty(findInfo.getTreatNum())) { // 就诊号不为空=>无需补充门诊号 // treatNum = null; // } // // String dbMedToolMark = findInfo.getMedToolMark(); // String updateMedToolMark = addMedToolMark; // if (!ObjectUtils.isEmpty(dbMedToolMark)) { // if (dbMedToolMark.contains(addMedToolMark)) { // 已存在 // throw new ServiceException("状态已存在"); // } else { // updateMedToolMark = dbMedToolMark + "," + addMedToolMark; // } // } // return regDao.updateTreatNum(String.valueOf(id), treatNum) > 0; // } public List getRegLineSignInRecords(String begDate, String endDate) { if (begDate == null || endDate == null) { // 只查询今日 begDate = DateHelper.getCurDate() + " 06:00:00"; endDate = DateHelper.getCurDate() + " 23:59:59"; } return new HisRegisterDao().getRegLineSignInRecords(begDate, endDate); } /** * 根据患者id,查询预约待签到记录 * * @param patientId patientId * @return list */ public List getRegLineSignInRecordsByPatientId(String patientId, String begDate, String endDate) { List records = getRegLineSignInRecords(null, null); if (records.isEmpty()) { return new ArrayList<>(); } return records.stream().filter(o -> patientId.equals(o.getPatientId())).collect(Collectors.toList()); } /** * 根据treatNum,查询预约待签到记录 * * @param treatNum 门诊号 * @return bean */ public RegSign getRegLineSignInRecordByTreatNum(String treatNum) { List records = getRegLineSignInRecords(null, null); if (records.isEmpty()) { return null; } return records.stream().filter(o -> treatNum.equals(o.getTreatNum())).findFirst().orElse(null); } }