package com.ynxbd.common.service; import com.alibaba.fastjson.JSONObject; import com.ynxbd.ali.enums.AliEnergyEnum; import com.ynxbd.ali.enums.AliMsgEnum; import com.ynxbd.ali.helper.*; import com.ynxbd.common.action.pay.PEnum; import com.ynxbd.common.bean.sms.SmsRegTem; import com.ynxbd.common.bean.enums.HospEnum; 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.bean.sms.SmsTemplate; 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.common.JsonHelper; import com.ynxbd.common.helper.common.SmsHelper; 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.config.WeChatConfig; 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.Date; import java.util.HashMap; import java.util.Map; /** * 挂号业务层 * * @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"); 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); } if(HospEnum.isHosp(HospEnum.红河州人民医院)&&"0503".equals(reg.getDeptCode())){ MessagePushConfig.regObsDocument(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); refundResult = order.isOk() ? WxPayHelper.OK : order.getMessage(); if (!regDao.updateRefundByTradeNo(payOrdId, refundResult)) { 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 tel = reg.getTel(); String date = reg.getRegDate(); String begTime = reg.getBegTime(); String endTime = reg.getEndTime(); String openid = reg.getOpenid(); if (ObjectUtils.isEmpty(tel) || tel.length() != 11) { log.info("[挂号]短信通知:tel为空或长度异常"); return false; } if (ObjectUtils.isEmpty(openid)) { // 关注过,并且填写过电话号码 log.info("[挂号]短信通知:openid为空"); } SmsRegTem sms = new SmsRegTem(); sms.setTime(date + " " + begTime + "-" + endTime); sms.setAddress(reg.getAddress()); sms.setDeptName(reg.getDeptName()); sms.setDoctorName(reg.getDoctName()); sms.setSeq(reg.getQueueNum()); boolean isResult = false; if (HospEnum.isHosp(HospEnum.德宏州中医医院)) { sms.setHosp_tel("0692-2991794"); sms.setHosp_tip("提前15分钟到医院门诊各导医服务台签到后排队候诊"); log.info("[挂号]发送预约短信通知 sms={}, appId={}, tel-{}", JsonHelper.toJsonString(sms), WeChatConfig.APP_ID, tel); isResult = SmsHelper.send("SMS_262510249", tel, sms); } return isResult; } /** * 取消预约 * * @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.getMerchantEnumByOutTradeNo(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()); // 短信通知 if (HospEnum.isHosp(HospEnum.德宏州中医医院)) { String tel = reg.getTel(); if (tel != null && tel.length() == 11) { String template = "SMS_184121392"; SmsRegTem sms = new SmsRegTem(); sms.setTime(reg.getRegDate() + " " + reg.getBegTime() + "-" + reg.getEndTime()); sms.setDeptName(reg.getDeptName()); sms.setDoctorName(reg.getDoctName()); sms.setAddress(reg.getAddress()); sms.setSeq(reg.getQueueNum()); SmsHelper.send(template, tel, sms); } } MessagePushConfig.regCancelPush(merchantEnum, reg); if (result.isSuccess()) { 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.DATA_NOT_FOUND); } String tradeNo = reg.getTradeNo(); String outTradeNo = reg.getOutTradeNo(); MerchantEnum merchantEnum = MerchantEnum.getMerchantEnumByOutTradeNo(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); } 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()); // 短信通知 if (HospEnum.isHosp(HospEnum.德宏州中医医院)) { String tel = reg.getTel(); if (tel != null && tel.length() == 11) { String template = "SMS_184121392"; SmsRegTem sms = new SmsRegTem(); sms.setTime(reg.getRegDate() + " " + reg.getBegTime() + "-" + reg.getEndTime()); sms.setDeptName(reg.getDeptName()); sms.setDoctorName(reg.getDoctName()); sms.setAddress(reg.getAddress()); sms.setSeq(reg.getQueueNum()); SmsHelper.send(template, tel, sms); } } MessagePushConfig.regCancelPush(merchantEnum, reg); if (result.isSuccess()) { 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.isNoPay(); if (noPayTime != null) { return noPayTime; } MerchantEnum merchantEnum = MerchantEnum.getMerchantEnumByCode(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); } }