微信后端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1056 lines
46 KiB

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.WxMedHelper;
import com.ynxbd.wx.wxfactory.WxPayHelper;
import com.ynxbd.wx.wxfactory.bean.WxMedOrder;
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;
}
// 查询订单
public Register queryRegByOrderNo(String outTradeNo, String tradeNo) {
if (!ObjectUtils.isEmpty(outTradeNo)) {
return new RegisterDao().selectByOutTradeNo(outTradeNo);
}
if (ObjectUtils.isEmpty(tradeNo)) {
return null;
}
return new RegisterDao().selectByTradeNo(tradeNo);
}
/**
* 支付完成-->挂号回调
*
* @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 = queryRegByOrderNo(outTradeNo, null);
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);
// 电子健康卡上报数据
new 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<String, Object> 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);
}
WxMedOrder order = WxMedHelper.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<String, Object> 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<String, Object> 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, boolean isHttps) {
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.hasOccupySource(patientId, sourceId, merchantEnum);
if (!result.success()) {
return Result.error(result.getMessage());
}
}
}
JSONObject mdRespJson = PayService.getMedAuthUrl(merchantEnum, PEnum.REG, isHttps);
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<String, Object> 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<Register> getHisRegReserveRecords(String patientId, String regDate) {
return new HisRegisterDao().getRegReserveRecords(patientId, regDate);
}
// 查询挂号历史记录
public List<Register> getHisRegRecordsByRegDate(String patientId, String begDate, String endDate) throws ServiceException {
if (begDate == null || endDate == null) {
throw new ServiceException("查询日期异常");
}
List<Register> hisRegList = new HisRegisterDao().getHisRegHistoryRecords(patientId, begDate.equals(endDate) ? begDate : null); // 起止日期相同时,传递挂号日期
List<Register> 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<Register> 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<Register> getHisWaitRegRecords(String patientId) throws ServiceException {
if (ObjectUtils.isEmpty(patientId)) {
throw new ServiceException(ResultEnum.PARAM_IS_BLANK);
}
String curDate = DateHelper.getCurDate();
// 挂号历史记录(今日)
List<Register> hisRegRecords = getHisRegRecordsByRegDate(patientId, curDate, curDate);
if (hisRegRecords == null) {
hisRegRecords = new ArrayList<>();
}
// 预约挂号
List<Register> hisRegReserveRecords = getHisRegReserveRecords(patientId, null);
if (hisRegReserveRecords != null && !hisRegReserveRecords.isEmpty()) {
hisRegRecords.addAll(hisRegReserveRecords);
}
return hisRegRecords;
}
/**
* 根据挂号日期查询挂号记录
*
* @param patientId 患者id
* @param regDate 挂号日期
*/
public List<Register> 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<Register> 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<Register> hisRegRecords = getHisRegRecordsByRegDate(patientId, regDate);
if (hisRegRecords.isEmpty()) {
tip = "HIS中未查询到挂号记录";
log.info("[挂号]{} patientId={}, regDate={}, hisTransNo={}", tip, patientId, regDate, hisTransNo);
throw new ServiceException("错误:" + tip + " 日期:" + regDate);
}
List<Register> 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<Register> 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<Register> 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<RegSign> 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<RegSign> getRegLineSignInRecordsByPatientId(String patientId, String begDate, String endDate) {
List<RegSign> 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<RegSign> records = getRegLineSignInRecords(null, null);
if (records.isEmpty()) {
return null;
}
return records.stream().filter(o -> treatNum.equals(o.getTreatNum())).findFirst().orElse(null);
}
}