diff --git a/src/main/java/com/ynxbd/common/action/RecipeAction.java b/src/main/java/com/ynxbd/common/action/RecipeAction.java index a530b28..b48edc7 100644 --- a/src/main/java/com/ynxbd/common/action/RecipeAction.java +++ b/src/main/java/com/ynxbd/common/action/RecipeAction.java @@ -17,7 +17,7 @@ import com.ynxbd.common.his.HisFactory; import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.wx.config.WeChatConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -73,7 +73,7 @@ public class RecipeAction extends BaseAction { for (HisRecipe item : hisRxList) { item.filterSetEnBillNo(); } - return Result.success(new RecipeService().filterPaidList(hisRxList)); + return Result.success(new RxService().filterPaidList(hisRxList)); } /** @@ -240,7 +240,7 @@ public class RecipeAction extends BaseAction { */ @Action("getStandardPrice") public Result getStandardPrice(Integer pageNum, Integer pageSize, String pyCode, String type, String groupFlag) { - return new RecipeService().getStandardPrice(pageNum, pageSize, pyCode, type, groupFlag); + return new RxService().getStandardPrice(pageNum, pageSize, pyCode, type, groupFlag); } diff --git a/src/main/java/com/ynxbd/common/action/pay/AliPayAction.java b/src/main/java/com/ynxbd/common/action/pay/AliPayAction.java index 8414d03..fc4ac66 100644 --- a/src/main/java/com/ynxbd/common/action/pay/AliPayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/AliPayAction.java @@ -14,7 +14,7 @@ import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.InHospService; import com.ynxbd.common.service.MedicalService; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.common.service.RegService; import lombok.extern.slf4j.Slf4j; import org.apache.struts2.convention.annotation.Action; @@ -60,7 +60,7 @@ public class AliPayAction extends BaseAction { switch (PEnum.toEnum(notifyType)) { case RECIPE: - new RecipeService().recipeListPay(MerchantEnum.ALI, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); + new RxService().recipeListPay(MerchantEnum.ALI, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); break; case REG: // 挂号 diff --git a/src/main/java/com/ynxbd/common/action/pay/BcmPayAction.java b/src/main/java/com/ynxbd/common/action/pay/BcmPayAction.java index 8bc531a..841b838 100644 --- a/src/main/java/com/ynxbd/common/action/pay/BcmPayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/BcmPayAction.java @@ -6,10 +6,9 @@ import com.ynxbd.common.action.base.BaseAction; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.PayResult; import com.ynxbd.common.helper.common.DateHelper; -import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ServiceException; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.common.service.RegService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -52,8 +51,8 @@ public class BcmPayAction extends BaseAction { switch (PEnum.toEnum(notifyType)) { case RECIPE: - openid = new RecipeService().queryOpenIdByOutTradeNo(outTradeNo); - new RecipeService().recipeListPay(MerchantEnum.BCM, totalFee.toString(), openid, outTradeNo, bankTransNo, bankMerchantNo, payDate, payTime, payInfo); + openid = new RxService().queryOpenIdByOutTradeNo(outTradeNo); + new RxService().recipeListPay(MerchantEnum.BCM, totalFee.toString(), openid, outTradeNo, bankTransNo, bankMerchantNo, payDate, payTime, payInfo); break; case REG: // 挂号 diff --git a/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java b/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java index a5df09f..b64f978 100644 --- a/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java @@ -18,7 +18,7 @@ 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.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.wx.wxfactory.WxCacheHelper; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; @@ -91,7 +91,7 @@ public class MedicalTestAction extends BaseAction { } List hisRecipeList = HisMedTestDao.devPaidRecipeList(merchantEnum, patientId, begDate, endDate); - return Result.success(new RecipeService().filterPaidList(hisRecipeList)); + return Result.success(new RxService().filterPaidList(hisRecipeList)); } // diff --git a/src/main/java/com/ynxbd/common/action/pay/PayAction.java b/src/main/java/com/ynxbd/common/action/pay/PayAction.java index e26560d..aeffbd8 100644 --- a/src/main/java/com/ynxbd/common/action/pay/PayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/PayAction.java @@ -99,18 +99,18 @@ public class PayAction extends BaseAction { if (merchantEnum == null) { // 支付方式异常 return Result.error(ResultEnum.PAY_TYPE_ERROR); } - RecipeService recipeService = new RecipeService(); + RxService rxService = new RxService(); SelfHelp selfHelp = new SelfHelpDao().selectByTreatNum(treatNum); if (selfHelp != null) { // 是核酸 try { - recipeService.selfHelpPrepay(selfHelp.getCode(), treatNum); + rxService.selfHelpPrepay(selfHelp.getCode(), treatNum); } catch (ServiceException e) { return Result.error(e); } } - Result result = recipeService.recipeHand(merchantEnum, payOpenId, openid, patientId, treatNum, totalFee, recipeJson, payWay, awaitSecond, isHttpsWithProxy()); + Result result = rxService.rxHand(merchantEnum, payOpenId, openid, patientId, treatNum, totalFee, recipeJson, payWay, awaitSecond, isHttpsWithProxy()); if (!result.isOK() || result.getData() != null) { // 业务错误 || 存在返回数据-需提前返回 return result; } @@ -122,14 +122,14 @@ public class PayAction extends BaseAction { log.info("{} [处方]预结算开始... patientId={}", merchantEnum.NAME, patientId); // 调用预结算!!!!注意如果HIS不支持开启改功能后,会存在直接入库的风险 - List respList = recipeService.hisRxPrepay(recipeJson, patientId, treatNum); + List respList = rxService.hisRxPrepay(recipeJson, patientId, treatNum); return Result.success(respList); } String outTradeNo = merchantEnum.createOutTradeNo(); // 订单信息预存 - if (!recipeService.saveRecipeInfo(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, outTradeNo, totalFee)) { + if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, outTradeNo, totalFee)) { log.info("{} [处方支付]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); } @@ -298,7 +298,7 @@ public class PayAction extends BaseAction { switch (PEnum.toEnum(callNo)) { case RECIPE: - return new RecipeService().mdCashRefund(payOrdId, refundDesc); + return new RxService().mdCashRefund(payOrdId, refundDesc); case REG: // 挂号 return new RegService().mdCashRefund(payOrdId, refundDesc); @@ -349,7 +349,7 @@ public class PayAction extends BaseAction { try { switch (pEnum) { case RECIPE: // 处方 - new RecipeService().hisRefund(invoiceTransNo, patientId, refundUser, refundDesc, refundMoney, pEnum); + new RxService().hisRefund(invoiceTransNo, patientId, refundUser, refundDesc, refundMoney, pEnum); break; case REG: // 挂号 @@ -519,7 +519,7 @@ public class PayAction extends BaseAction { } switch (orderType) { case RECIPE: // 处方 - isResult = new RecipeService().isHandRefund(tradeNo, refundUser, refundDesc, orderType, callNo); + isResult = new RxService().isHandRefund(tradeNo, refundUser, refundDesc, orderType, callNo); break; case REG: // 挂号 @@ -589,7 +589,7 @@ public class PayAction extends BaseAction { } switch (orderType) { case RECIPE: // 处方 - isResult = new RecipeService().isHandRefund(tradeNo, username, refundDesc, orderType, "MICRO"); + isResult = new RxService().isHandRefund(tradeNo, username, refundDesc, orderType, "MICRO"); break; case REG: // 挂号 @@ -709,7 +709,7 @@ public class PayAction extends BaseAction { } try { - new RecipeService().selfHelpMaxNum(code); + new RxService().selfHelpMaxNum(code); } catch (ServiceException e) { return Result.error(e); } diff --git a/src/main/java/com/ynxbd/common/bean/pay/PrepayResp.java b/src/main/java/com/ynxbd/common/bean/pay/PrepayResp.java new file mode 100644 index 0000000..1a6efb3 --- /dev/null +++ b/src/main/java/com/ynxbd/common/bean/pay/PrepayResp.java @@ -0,0 +1,39 @@ +package com.ynxbd.common.bean.pay; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString +@NoArgsConstructor +public class PrepayResp { + // 时间戳 10位字符串 "1790063260" + private String timeStamp; + + // 预支付数据包 prepay_id=xxx + private String packageVal; + + // 支付签名 paySign + private String paySign; + + // 公众号appId + private String appId; + + // 签名类型 MD5 + private String signType; + + // 随机字符串 nonceStr + private String nonceStr; + + // 商户订单号 + private String outTradeNo; + // 订单流水号 + private String transId; + // 订单流水号 + private String tradeNo; + // 混合订单号 + private String mixTradeNo; +} diff --git a/src/main/java/com/ynxbd/common/healthcard/HealthCardHelper.java b/src/main/java/com/ynxbd/common/healthcard/HealthCardHelper.java index d7cde4d..02a91eb 100644 --- a/src/main/java/com/ynxbd/common/healthcard/HealthCardHelper.java +++ b/src/main/java/com/ynxbd/common/healthcard/HealthCardHelper.java @@ -595,7 +595,7 @@ public class HealthCardHelper { log.info("[电子健康卡]用卡数据监测接口-[scene:{}]", scene); if (ObjectUtils.isEmpty(openid) || ObjectUtils.isEmpty(healthCardId) || ObjectUtils.isEmpty(idCardNo) || ObjectUtils.isEmpty(scene)) { - log.warn("[电子健康卡]用卡数据监测,参数为空"); + System.out.println("[电子健康卡]用卡数据监测,参数为空"); return null; } @@ -605,7 +605,7 @@ public class HealthCardHelper { } if (ObjectUtils.isEmpty(qrCodeText)) { - log.error("[电子健康卡]用卡数据监测,qrCodeText为空"); + log.warn("[电子健康卡]用卡数据监测,qrCodeText为空"); return null; } diff --git a/src/main/java/com/ynxbd/common/service/MedicalService.java b/src/main/java/com/ynxbd/common/service/MedicalService.java index b3b5b1c..e39b3ea 100644 --- a/src/main/java/com/ynxbd/common/service/MedicalService.java +++ b/src/main/java/com/ynxbd/common/service/MedicalService.java @@ -416,7 +416,7 @@ public class MedicalService { // 0:公众号内支付,1:扫码支付 payWay = payWay == null ? "0" : payWay; - Recipe rxInfo = new RecipeService().recipeJsonToInfo(treatNum, recipeJson); + Recipe rxInfo = new RxService().recipeJsonToInfo(treatNum, recipeJson); log.info("[医保][处方]JSON解析 RxInfo={}", rxInfo); if (rxInfo == null) { return Result.error(ResultEnum.PAY_PREPAY_SAVE_ERROR); @@ -1072,7 +1072,7 @@ public class MedicalService { break; case RECIPE: - order = new RecipeService().queryRxByOrderNo(outTradeNo, tradeNo); + order = new RxService().queryRxByOrderNo(outTradeNo, tradeNo); break; default: diff --git a/src/main/java/com/ynxbd/common/service/PayService.java b/src/main/java/com/ynxbd/common/service/PayService.java index e1cb187..804c5ff 100644 --- a/src/main/java/com/ynxbd/common/service/PayService.java +++ b/src/main/java/com/ynxbd/common/service/PayService.java @@ -65,7 +65,7 @@ public class PayService { switch (PEnum.toEnum(notifyType)) { case RECIPE: - new RecipeService().recipeListPay(mchEnum, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); + new RxService().recipeListPay(mchEnum, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); break; case REG: // 挂号 @@ -589,7 +589,7 @@ public class PayService { } switch (pEnum) { case RECIPE: // 处方 - return new RecipeService().updateMicroOrderState(outTradeNo, bankTransNo, openid); + return new RxService().updateMicroOrderState(outTradeNo, bankTransNo, openid); case REG: // 挂号 return new RegService().updateMicroOrderState(outTradeNo, bankTransNo, openid); diff --git a/src/main/java/com/ynxbd/common/service/RecipeService.java b/src/main/java/com/ynxbd/common/service/RxService.java similarity index 95% rename from src/main/java/com/ynxbd/common/service/RecipeService.java rename to src/main/java/com/ynxbd/common/service/RxService.java index 3605342..dcb0bda 100644 --- a/src/main/java/com/ynxbd/common/service/RecipeService.java +++ b/src/main/java/com/ynxbd/common/service/RxService.java @@ -1,1096 +1,1096 @@ -package com.ynxbd.common.service; - -import com.alibaba.fastjson.JSONObject; -import com.ynxbd.common.action.pay.PEnum; -import com.ynxbd.common.bean.ConfigSelfHelp; -import com.ynxbd.common.bean.HisRecipe; -import com.ynxbd.common.bean.SelfHelpCount; -import com.ynxbd.common.bean.StandardPrice; -import com.ynxbd.common.bean.enums.MerchantEnum; -import com.ynxbd.common.bean.pay.Order; -import com.ynxbd.common.bean.pay.Recipe; -import com.ynxbd.common.dao.RecipeDao; -import com.ynxbd.common.dao.RefundDao; -import com.ynxbd.common.dao.SelfHelpDao; -import com.ynxbd.common.dao.his.HisAccountDao; -import com.ynxbd.common.dao.his.HisRecipeDao; -import com.ynxbd.common.helper.common.DateHelper; -import com.ynxbd.common.helper.common.ErrorHelper; -import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.helper.common.QuickDrugDispenseHelper; -import com.ynxbd.common.his.HisFactory; -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.common.service.cache.PayCache; -import com.ynxbd.wx.config.HospConfigEnum; -import com.ynxbd.wx.config.TZReserveConfig; -import com.ynxbd.wx.config.WeChatConfig; -import com.ynxbd.wx.utils.DateGenerate; -import com.ynxbd.wx.wxfactory.WxMedHelper; -import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; - -import java.math.BigDecimal; -import java.util.*; - -/** - * 支付业务层 - * - * @Author wsq - * @Date 2021/3/4 10:41 - * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. - */ -@Slf4j -public class RecipeService { - - /** - * 是否在指定时间内重复支付 - * - * @return 是否完成操作 - */ - public Long isRepeatPay(String treatNum, Integer second) { - log.info("[处方]是否重复支付 treatNum={}, second={}", treatNum, second); - if (treatNum == null || second == null) { - return null; - } - - try { - List orderList = new RecipeDao().selectByTreatNum(treatNum); - int size = orderList.size(); - if (size == 0) { - return null; - } - - second += size; - Order order = orderList.get(0); - log.info("[处方]在指定时间内重复支付 recipe={}", order); - - Date updateTime = order.getUpdateTime(); - if (updateTime == null) { - return null; - } - long curTime = new Date().getTime(); - long time = ((curTime - updateTime.getTime()) / 1000); - - if (time < second) { - return second - time; - } - return null; - } catch (Exception e) { - ErrorHelper.println(e); - } - return null; - } - - - /** - * 处方订单信息预存 - * - * @param recipeJson 处方单json数据 - * @param patientId 患者id - * @param treatNum 门诊号 - * @return 是否完成操作 - */ - public Result recipeHand(MerchantEnum merchantEnum, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer awaitSecond, boolean isHttps) { - Result result = PayService.isPaymentPermittedByTime(); - if (result != null) { - return result; - } - if (merchantEnum == null) { // 支付方式异常 - return Result.error(ResultEnum.PAY_TYPE_ERROR); - } - - log.info("{}[处方预支付]参数 isHttps={}, openid={}, patientId={}, treatNum={}, totalFee={}, awaitSecond={}, payWay={}", merchantEnum.NAME, isHttps, openid, patientId, treatNum, totalFee, awaitSecond, payWay); - if (openid == null || patientId == null || treatNum == null || totalFee == null || recipeJson == null) { - return Result.error(ResultEnum.PARAM_IS_DEFECT); - } - - RecipeService recipeService = new RecipeService(); - if (awaitSecond == null) { - awaitSecond = 0; - } - - if (awaitSecond != 0) { - Long second = recipeService.isRepeatPay(treatNum, awaitSecond); - if (second != null) { - // 是否 awaitSecond s内重复支付 - log.info("[处方] 下单等待 {} s 确定", second); - return Result.error(ResultEnum.PAY_AWAIT, second); - } - } - - // 金额为0的处方不进行回调通知 - if ("0".equals(totalFee)) { - String outTradeNo = merchantEnum.createOutTradeNo(); - // 订单信息预存 - if (!recipeService.saveRecipeInfo(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, outTradeNo, totalFee)) { - log.info("{} [处方支付]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); - return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); - } - - String payDate = DateHelper.getCurDate(); - String payTime = DateHelper.getCurTime(); - String bankTransNo = outTradeNo.substring(merchantEnum.CODE.length()); - recipeService.recipeListPay(merchantEnum, totalFee, openid, outTradeNo, bankTransNo, null, payDate, payTime, null); - - Map map = new HashMap<>(); - map.put("totalFee", 0); - return Result.success(map); - } - - // 医保支付 - JSONObject respMedJson = PayService.getMedAuthUrl(merchantEnum, PEnum.RECIPE, isHttps); - if (respMedJson != null) { - return Result.success(respMedJson); - } - return Result.success(); - } - - - /** - * 处方订单信息预存 - * - * @param recipeJson 处方单json数据 - * @param patientId 患者id - * @param treatNum 门诊号 - * @return 是否完成操作 - */ - public List hisRxPrepay(String recipeJson, String patientId, String treatNum) { - log.info("[处方]预结算 patientId={}, treatNum={}, recipeJson={}", patientId, treatNum, recipeJson); - List respList = new ArrayList<>(); - List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); - if (recipeList == null || recipeList.isEmpty()) { - log.info("[处方]预结算勾选处方数量为0 或 数据转换失败"); - return respList; - } - - List recipeIds; - String curDate = DateHelper.getCurDate(); - String curTime = DateHelper.getCurTime(); - String recipeId, feeId, feeInfo; - JsonResult response; - Recipe addInfo; - for (Recipe recipe : recipeList) { - recipeId = recipe.getRecipeId(); - if (ObjectUtils.isEmpty(recipeId) || ObjectUtils.isEmpty(recipe.getRecipeFee())) { - continue; - } - recipeIds = new ArrayList<>(); - recipeIds.add(recipe.getRecipeId()); - - response = HisRecipeDao.prepay( - patientId, - treatNum, - recipeIds, - recipe.getRecipeFee().toString(), - curDate, - curTime, - "app", - MerchantEnum.WX); - - log.info("[处方]预结算 resp={}", response); - if (response.success()) { - feeId = response.getDataMapString("FeeID"); - feeInfo = response.getDataMapString("FeeInfo"); - log.info("[处方]预结算成功 treatNum={}, recipeId={}, feeId={}, feeInfo={}", treatNum, recipeId, feeId, feeInfo); - if (feeId != null && feeInfo != null) { - addInfo = new Recipe(); - - addInfo.setTreatNum(treatNum); - addInfo.setRecipeId(recipeId); - addInfo.setFeeId(feeId); - addInfo.setFeeInfo(feeInfo); - respList.add(addInfo); - } - } - } - return respList; - - } - - - /** - * 处方订单信息预存 - * - * @param recipeJson 处方单json数据 - * @param payWay 支付方式 0:公众号内;1:扫码支付 - * @param openid openid - * @param patientId 患者id - * @param treatNum 门诊号 - * @param outTradeNo 订单号 - * @return 是否完成操作 - */ - public boolean saveRecipeInfo(MerchantEnum merchantEnum, String payOpenId, String openid, String recipeJson, String payWay, String patientId, String treatNum, String outTradeNo, String totalFee) { - log.info("{}[处方支付]预存信息 patientId={}, treatNum={}, recipeJson={}", merchantEnum.NAME, patientId, treatNum, recipeJson); - List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); - if (recipeList == null || recipeList.isEmpty()) { - log.info("[处方支付]勾选处方数量为0 或 数据转换失败"); - return false; - } - - RecipeDao recipeDao = new RecipeDao(); - // 0:公众号内支付,1:扫码支付 - payWay = payWay == null ? "0" : payWay; - - for (Recipe recipe : recipeList) { - if (ObjectUtils.isEmpty(recipe.getRecipeId()) || ObjectUtils.isEmpty(recipe.getRecipeFee())) { - return false; - } - recipe.setPayMchCode(merchantEnum.CODE); - recipe.setOpenid(openid); - recipe.setPayOpenId(payOpenId); - recipe.setPatientId(patientId); - recipe.setTreatNum(treatNum); - recipe.setOutTradeNo(outTradeNo); - recipe.setPayWay(payWay); -// recipe.setTradeNo(CodeHelper.getHisTradeNo()); // 本次his交易流水号 - recipe.setTradeNo(null); // 本次his交易流水号 - recipe.setTotalFee(new BigDecimal(totalFee)); - recipe.setPayMoney(recipe.getRecipeFee()); - recipe.setHisStatus(-1); - recipe.setPayStatus(-1); - if (treatNum.contains("P-")) { - recipe.setOrderType("PEIS"); - } - } - - boolean isResult = recipeDao.insertBatch(recipeList) == recipeList.size(); - log.info("[处方]信息预存{}, patientId={}, treatNum={}", (isResult ? "成功" : "失败"), patientId, treatNum); - return isResult; - } - - - /** - * 处方多张支付 - * - * @param totalFee 总金额 - * @param openid openid - * @param outTradeNo 订单号 - * @param bankTransNo 交易流水号 - * @param payDate 支付日期 - * @param payTime 支付时间 - * @return 是否完成操作 - */ - public boolean recipeListPay(MerchantEnum merchantEnum, String totalFee, String openid, String outTradeNo, String bankTransNo, String bankMerchantNo, String payDate, String payTime, String payInfo) { - RecipeDao recipeDao = new RecipeDao(); - - // 此处判断是否已经发起缴费,只要已存在数据库记录,说明已经发起了缴费请求,不能根据已经缴费成功,才取消本次缴费请求,因为请求可能已经延时,本次请求可能是重复提交的请求 - if (PayService.hasUserOrderNo(outTradeNo, openid)) { - log.info("{} [处方]已发起缴费 outTradeNo={}", merchantEnum.NAME, outTradeNo); - return false; - } - - if (recipeDao.isHisPaidByOutTradeNo(outTradeNo)) { - log.info("{} [处方]已交过费, 退出本次缴费成功通知处理流程:outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); - return false; - } - - if (payInfo != null) { - PayService.saveOrderNo(PEnum.RECIPE, outTradeNo, openid, payInfo, null); - } - - List recipeList = recipeDao.selectListByOutTradeNo(outTradeNo); - if (!recipeDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { - log.info("{} [处方]更新商户信息失败(1) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); - if (!recipeDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { - log.info("{} [处方]更新商户信息失败(2) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); - return false; - } - } - - // 订单金额验证 - BigDecimal rxTotalFee = BigDecimal.ZERO; - for (Recipe recipe : recipeList) { - rxTotalFee = rxTotalFee.add(recipe.getPayMoney()); - } - - log.info("{} [处方]金额计算{} outTradeNo={}, bankTransNo={}, rxTotalFee={}, totalFee={}", merchantEnum.NAME, (rxTotalFee.compareTo(new BigDecimal(totalFee)) == 0 ? "" : "异常"), outTradeNo, bankTransNo, rxTotalFee, totalFee); - if (rxTotalFee.compareTo(new BigDecimal(totalFee)) > 0) { // 支付的金额不足 - log.info("{} [处方]缴费金额异常 outTradeNo={}, bankTransNo={}, rxTotalFee={}, totalFee={}", merchantEnum.NAME, outTradeNo, bankTransNo, rxTotalFee, totalFee); - return false; - } - - List failedList = new ArrayList<>(); // HIS缴费失败的处方单 - - long begTime = System.currentTimeMillis(); // 开始时间 - // HIS缴费 - String patientId = null; - Recipe recipeInfo; - for (Recipe recipeItem : recipeList) { - patientId = recipeItem.getPatientId(); - recipeItem.setBankTransNo(bankTransNo); - // HIS处方缴费 - recipeInfo = recipeSinglePay(recipeItem, payDate, payTime, merchantEnum); - - // 调用失败的处方 - if (recipeInfo.isRefund()) { - failedList.add(recipeInfo); - } - - // 如果是体检支付就只调用一次his结算 - if (recipeItem.getTreatNum().contains("P-")) { - // 体检缴费失败的所有费用进行退回 - if (recipeInfo.isRefund()) { - failedList = recipeList; - for (Recipe failed : failedList) { - failed.setErrorCode(recipeInfo.getErrorCode()); - failed.setErrorMsg(recipeInfo.getErrorMsg()); - } - } - break; - } - } - long endTime = System.currentTimeMillis(); // 结束时间 - log.info("{} [处方]请求HIS结束 耗时:{} outTradeNo={}, bankTransNo={}", merchantEnum.NAME, ((endTime - begTime) / 1000) + "s(" + (endTime - begTime) + "ms)", outTradeNo, bankTransNo); - - if ("0".equals(totalFee)) { // 总金额为0不进行退费处理 - return true; - } - - // 处理his缴费失败的处方 - String failedRecipeId, errorCode, errorMsg, refundDesc; - // 调用超时处方 - List outTimeList = new ArrayList<>(); - for (Recipe failed : failedList) { - failedRecipeId = failed.getRecipeId(); - errorCode = failed.getErrorCode(); - errorMsg = failed.getErrorMsg(); - if ("500".equals(errorCode)) { // 500 - log.info("[处方]HIS请求超时,不退费 outTradeNo={}, tradeNo={}", outTradeNo, failed.getTradeNo()); - outTimeList.add(failed); - PayCache.putRecipeCache(failed.getTradeNo(), failed); - - } else { - refundDesc = "缴费失败 处方号:" + failedRecipeId + "\n原因:[" + errorCode + "]" + errorMsg; - try { - // 自动退费 - rxAutoRefund(merchantEnum, openid, patientId, outTradeNo, failed.getTradeNo(), failedRecipeId, failed.getPayMoney(), new BigDecimal(totalFee), failed.getUpdateTime(), errorCode, errorMsg, refundDesc); - } catch (Exception e) { - ErrorHelper.println(e); - } - } - } - - String tip = String.format("共计缴费处方单数:%s,失败数:%s,超时数:%s", recipeList.size(), (failedList.size() - outTimeList.size()), outTimeList.size()); - log.info("{} [处方]{}", merchantEnum.NAME, tip); - - if (WeChatConfig.APP_ID.equals(HospConfigEnum.红河州第一人民医院.WX_APP_ID)) { - TZReserveConfig.reserveRun(patientId); // 天助医技预约 - } - - new HealthUploadService().rxReportHISData(merchantEnum, openid, patientId); - return true; - } - - - /** - * 单张处方支付 - * - * @param recipe 支付信息 - * @param payDate 支付日期 - * @param payTime 支付时间 - * @return order - */ - public Recipe recipeSinglePay(Recipe recipe, String payDate, String payTime, MerchantEnum merchantEnum) { - Recipe order = new Recipe(); - String openid = recipe.getOpenid(); - String patientId = recipe.getPatientId(); - String bankTransNo = recipe.getBankTransNo(); - BigDecimal recipeFee = recipe.getPayMoney(); - BigDecimal totalFee = recipe.getTotalFee(); - - order.setUpdateTime(recipe.getUpdateTime()); - String tradeNo = recipe.getTradeNo(); - String recipeId = recipe.getRecipeId(); - order.setBankTransNo(bankTransNo); - if (recipeFee == null) { - order.setErrorMsg(String.format("[处方]金额为异常 recipeId=%s, tradeNo=%s", recipeId, tradeNo)); - return order; - } - - List recipeIds = new ArrayList<>(); - recipeIds.add(recipeId); - - RecipeDao recipeDao = new RecipeDao(); - - String outTradeNo = recipe.getOutTradeNo(); - - String treatNum = recipe.getTreatNum(); - JsonResult response = HisRecipeDao.payInvoice( - openid, - patientId, - treatNum, - recipeIds, - recipeFee.toString(), - totalFee.toString(), - payDate, - payTime, - tradeNo, - "app", - bankTransNo, - merchantEnum, - recipe.getFeeId(), - recipe.getFeeInfo()); - - log.info("[处方]结算返回 resp={}", JsonHelper.toJsonString(response)); - String respCode = response.getCode(); - String respMessage = response.getMessage(); - - if (!response.success()) { - order.setErrorMsg(response.getMessage()); - order.setErrorCode(response.getCode()); - - String errorMsg = recipe.getErrorMsg(); - if (!ObjectUtils.isEmpty(errorMsg)) { - respMessage = respMessage + "|" + errorMsg; - } - - if (!recipeDao.updateHisPaidFailByTradeNo(tradeNo, respCode, respMessage)) { - log.info("[处方]更新HIS缴费失败信息失败 tradeNo={}, code={}, message={}", tradeNo, respCode, respMessage); - } - - if (recipeFee.compareTo(BigDecimal.ZERO) == 0) { - log.info("[处方]HIS缴费失败,0元处方不退费,HIS返回:[{}] [{}]", respCode, respMessage); - return order; - } - - order.setRefund(true); // 需要退费 - order.setTradeNo(tradeNo); - order.setOutTradeNo(outTradeNo); - order.setRecipeId(recipeId); - order.setPayMoney(recipeFee); - return order; - } - - String drugInfo = response.getDataMapString("DrugInfo"); - String hisTransNo = response.getDataMapString("HISTransNo"); - String invoiceTransNo = response.getDataMapString("InvoiceTransNo"); - - log.info("[处方]HIS缴费成功, 更新支付信息:hisTransNo={}, invoiceTransNo={}, drugInfo={}", hisTransNo, invoiceTransNo, drugInfo); - if (!ObjectUtils.isEmpty(drugInfo) && !ObjectUtils.isEmpty(invoiceTransNo)) { - log.info("[处方]调用快速发药 invoiceTransNo={}, drugInfo={}", invoiceTransNo, drugInfo); - QuickDrugDispenseHelper.quickDrug(drugInfo, invoiceTransNo); - } - - // 更新支付信息 - if (!recipeDao.updateHisPaidByTradeNo(tradeNo, hisTransNo, invoiceTransNo)) { - log.info("[处方]更新HIS返回数据失败 outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); - } - - // 如果是体检支付就更新所有处方 - if (treatNum.contains("P-")) { - // 更新支付信息 - if (!recipeDao.updateHisPaidByBankTransNo(bankTransNo, hisTransNo, invoiceTransNo)) { - log.info("[处方]更新体检缴费HIS返回数据失败 outTradeNo={}, bankTransNo={}, recipeId={}", outTradeNo, bankTransNo, recipeId); - } - } - - if (new SelfHelpDao().updateNotice(treatNum)) { - log.info("[自助开单]通知状态修改成功 treatNum={}", treatNum); - } - return order; - } - - - /** - * 处方自动退费 - * - * @param openid openid - * @param patientId 患者id - * @param outTradeNo 商户单号 - * @param tradeNo HIS交易流水号 - * @param recipeId 退款处方id - * @param recipeFee 退款处方金额 - * @param totalFee 退款总金额 - * @param refundDesc 退费说明 - * @return 是否成功 - */ - public boolean rxAutoRefund(MerchantEnum merchantEnum, String openid, String patientId, String outTradeNo, String tradeNo, String recipeId, BigDecimal recipeFee, BigDecimal totalFee, Date tradeDate, String respCode, String respMessage, String refundDesc) { - if (recipeFee == null || totalFee == null || ObjectUtils.isEmpty(outTradeNo) || ObjectUtils.isEmpty(recipeId) || ObjectUtils.isEmpty(tradeNo)) { - log.info("[处方自动退款]参数缺失:outTradeNo={}, recipeId={}, tradeNo={}, fee={}, payMoney={}", outTradeNo, recipeId, tradeNo, recipeFee, totalFee); - return false; - } - - if ("500".equals(respCode)) { // 超时or异常不退费 - log.info("[处方]HIS请求超时,不退费 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo); - return false; - } - - RecipeDao recipeDao = new RecipeDao(); - HisAccountDao hisAccountDao = new HisAccountDao(); - - if (recipeDao.isHisPaidByRecipeId(outTradeNo, recipeId)) { - log.info("[处方自动退款]数据库中已缴费成功,不退费:outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); - return false; - } - - String begDate = DateGenerate.getNextDay(DateGenerate.getStringDateShort(), "-7"); - String endDate = DateGenerate.getNextDay(DateGenerate.getStringDateShort(), "7"); - - String paidTip = hisAccountDao.isPaid(begDate, endDate, tradeNo); - if (paidTip != null) { - log.info("[处方自动退款]{}-不退费:outTradeNo={}, tradeNo={}, recipeId={}", paidTip, outTradeNo, tradeNo, recipeId); - return false; - } - - try { - log.info("[处方退款]第1次等待8s"); - Thread.sleep(8000); - if (recipeDao.isHisPaidByRecipeId(outTradeNo, recipeId)) { - log.info("[处方自动退款]数据库中已缴费成功 outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); - return false; - } - - paidTip = hisAccountDao.isPaid(begDate, endDate, tradeNo); - if (paidTip != null) { - log.info("[处方自动退款]{}-不退费:outTradeNo={}, tradeNo={}, recipeId={}", paidTip, outTradeNo, tradeNo, recipeId); - return false; - } - } catch (Exception e) { - ErrorHelper.println(e); - } - - // 更新退款状态失败,不退费!!! - if (!recipeDao.updateRefundByRecipeId(outTradeNo, recipeId)) { - log.info("{} [处方自动退款]更新退款状态失败-不退费", merchantEnum.NAME); - return false; - } - Order refundInfo = PayService.refund(merchantEnum, outTradeNo, tradeNo, recipeFee, totalFee, refundDesc, tradeDate, openid, patientId, null); - - boolean isResult = refundInfo.isSuccess(); - log.info("{} [处方自动退款]申请{} outTradeNo={}, recipeId={}, recipeFee={}, HIS返回:{}", merchantEnum.NAME, - (isResult ? "成功" : "失败"), - outTradeNo, recipeId, recipeFee, refundDesc - ); - - if (!recipeDao.updateRefundByTradeNo(tradeNo, refundInfo.getRefundResult())) { - log.info("{} [处方自动退款]更新退款返回结果失败:outTradeNo={}, recipeId={}", merchantEnum.NAME, outTradeNo, recipeId); - } - return true; - } - - - /** - * His系统处方手动退费 - * - * @param invoiceTransNo 发票流水号 - * @param refundUser 退款人 - * @param refundDesc 退款描述 - * @return 是否成功 - */ - public synchronized boolean hisRefund(String invoiceTransNo, String patientId, String refundUser, String refundDesc, BigDecimal refundMoney, PEnum pEnum) throws ServiceException { - RecipeDao recipeDao = new RecipeDao(); - Recipe recipe = recipeDao.selectRefundByInvoiceTransNo(invoiceTransNo, patientId); - - if (recipe == null) { - log.info("[HIS处方退费]没有查询到可退款的记录, 不退费 invoiceTransNo={}", invoiceTransNo); - throw new ServiceException(ResultEnum.DATA_NOT_FOUND); - } - - String authCode = recipe.getAuthCode(); - if (ObjectUtils.isEmpty(authCode)) { - log.info("[HIS处方退费]失败,条码为空 authCode={}", authCode); - throw new ServiceException("条码为空"); - } - - MerchantEnum merchantEnum = MerchantEnum.findEnumByAuthCode(authCode); - if (merchantEnum == null) { - log.info("[HIS处方退费]失败,支付方式异常 authCode={}", authCode); - throw new ServiceException(ResultEnum.PAY_TYPE_ERROR); - } - - if (ObjectUtils.isEmpty(refundDesc)) { - refundDesc = "HIS手动退费"; - } - - String bankTransNo = recipe.getBankTransNo(); - String outTradeNo = recipe.getOutTradeNo(); - BigDecimal dbPayMoney = recipe.getPayMoney(); - if (refundMoney.compareTo(dbPayMoney) != 0) { - log.info("[HIS挂号退费]金额符合禁止退费 invoiceTransNo={}, payMoney={}", invoiceTransNo, dbPayMoney); - throw new ServiceException(ResultEnum.REFUND_MONEY_ERROR); - } - - String outRefundNo = HisFactory.getHisTradeNo(bankTransNo, pEnum); - Order orderRefund = PayService.refund(merchantEnum, outTradeNo, outRefundNo, refundMoney, recipe.getTotalFee(), refundDesc, recipe.getUpdateTime(), recipe.getOpenid(), recipe.getPatientId(), null); - - boolean isResult = orderRefund.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 = orderRefund.getRefundResult(); - if (!recipeDao.updateRefundByInvoiceTransNo(outTradeNo, outRefundNo, invoiceTransNo, refundResult)) { - log.info("{} [HIS处方退费]更新退款结果失败 outTradeNo={}, outRefundNo={}, invoiceTransNo={}, refundResult={}", merchantEnum.NAME, outTradeNo, outRefundNo, invoiceTransNo, refundResult); - } - - recipe.setRefundUser(refundUser); - recipe.setRefundMoney(refundMoney); - recipe.setRefundResult(refundResult); - recipe.setRefundTable(pEnum.CODE); - recipe.setTradeNo(outRefundNo); - if (!new RefundDao().insert(recipe, refundDesc, "HIS")) { - log.info("{} [HIS处方退费]退费信息新增失败 outTradeNo={}, outRefundNo={}, invoiceTransNo={}, refundResult={}", merchantEnum.NAME, outTradeNo, outRefundNo, invoiceTransNo, refundResult); - } - return true; - } - - - /** - * His系统处方线下退费 - * - * @param reason 退费原因 - * @return 是否成功 - */ - public Result mdCashRefund(String payOrdId, String reason) { - RecipeDao recipeDao = new RecipeDao(); - Recipe recipe = recipeDao.selectByTradeNo(payOrdId); - if (recipe == null) { - return Result.error(ResultEnum.DATA_NOT_FOUND); - } - if (!recipe.hasPayStatusPaid()) { - log.info("[医保]订单未支付 payOrdId={}, payStatus={}", payOrdId, recipe.getPayStatus()); - return Result.error(ResultEnum.PAY_ORDER_PARAMS_IS_DEFECT); - } - - if (recipe.hasRefundByRefundResult()) { - return Result.error(ResultEnum.REFUND_IS_REPEAT); // 退费重复申请 - } - - Boolean hasDateRange = DateHelper.inDateRangeByDay(-30, DateHelper.dateToStr(recipe.getUpdateTime(), DateHelper.DateEnum.yyyy_MM_dd_HH_mm_ss)); - if (hasDateRange == null || !hasDateRange) { - return Result.error("订单支付日期已经超过30天,请从商户平台退费"); - } - - String outTradeNo = recipe.getOutTradeNo(); - BigDecimal cashFee = recipe.getPayMoney(); - if (cashFee == null) { - return Result.error(ResultEnum.REFUND_CASH_IS_NULL); - } - - if (cashFee.compareTo(BigDecimal.ZERO) == 0) { - if (!recipeDao.updateRefundByTradeNo(payOrdId, WxPayHelper.OK)) { - log.error("[医保]现金为0修改数据库状态失败 payOrderId={}", payOrdId); - return Result.error(ResultEnum.DATA_UPDATE_ERROR); - } - - Map map = new HashMap<>(); - map.put("transNo", recipe.getTradeNo()); - map.put("payWay", recipe.getPayWay()); - map.put("bankTransNo", recipe.getBankTransNo()); - map.put("payMoney", cashFee); - return Result.success(map); - } - - WxMedOrder order = WxMedHelper.refundCash(outTradeNo, ("R" + payOrdId), payOrdId, cashFee, reason); - log.info("[医保]现金退费order={}", order); - String refundReason = "线下HIS医保现金部分退费"; - if (!ObjectUtils.isEmpty(reason)) { - refundReason = ":" + reason; - } - - String refundResult = order.isOk() ? WxPayHelper.OK : order.getMessage(); - if (!recipeDao.updateRefundByTradeNo(payOrdId, refundResult, refundReason)) { - log.error("[医保]现金退费修改数据库状态失败 payOrderId={}, refundResult={}", payOrdId, refundResult); - } - if (order.isOk()) { - Map map = new HashMap<>(); - map.put("transNo", recipe.getTradeNo()); - map.put("payWay", recipe.getPayWay()); - map.put("bankTransNo", recipe.getBankTransNo()); - map.put("payMoney", cashFee); - return Result.success(map); - } - return Result.error(refundResult); - } - - - /** - * 处方手动退费 - * - * @param refundUser 退款人 - * @param refundDesc 退款描述 - * @return 是否成功 - */ - public synchronized boolean isHandRefund(String tradeNo, String refundUser, String refundDesc, PEnum orderType, String sys) throws ServiceException { - RecipeDao recipeDao = new RecipeDao(); - Recipe recipe = recipeDao.selectRefundByTradeNo(tradeNo); - if (recipe == null) { - throw new ServiceException(ResultEnum.DATA_NOT_FOUND); - } - - String outTradeNo = recipe.getOutTradeNo(); - if (outTradeNo == null) { - throw new ServiceException(ResultEnum.DATA_IS_WRONG); - } - List recipeList = recipeDao.selectListByOutTradeNo(outTradeNo); - - String recipeId = recipe.getRecipeId(); - Order refundInfo = PayService.handRefund(recipe.getUpdateTime(), recipe.getUpdateTime(), recipe, recipe.getTotalFee(), refundUser, refundDesc, orderType.CODE, recipeList.size(), sys, - () -> recipeDao.updateRefundByRecipeId(outTradeNo, recipeId)); - - if (!recipeDao.updateRefundByTradeNo(tradeNo, refundInfo.getRefundResult())) { - log.info("[处方]退费成功,更新状态失败:outTradeNo={}, {}", outTradeNo, refundInfo); - } else { - if ("0".equals(recipe.getRefundResult())) { - throw new ServiceException(ResultEnum.REFUND_STATUS_ERROR_UPDATE_STATUS_SUCCESS); - } - } - return true; - } - - - /** - * 处方手动退费 - * - * @return 是否成功 - */ - public Recipe recipeJsonToInfo(String treatNum, String recipeJson) { - log.info("[处方支付]预存信息 treatNum={} recipeJson={}", treatNum, recipeJson); - List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); - if (recipeList == null || recipeList.size() == 0) { - log.info("[处方支付]勾选处方数量为0 或 数据转换失败"); - return null; - } - Recipe recipeInfo = new Recipe(); - - List> objects = new ArrayList<>(); - Map recipeItem; - - boolean isFlag = false; - for (Recipe recipe : recipeList) { - if (!isFlag) { - recipeInfo.setDeptCode(recipe.getDeptCode()); - recipeInfo.setDeptName(recipe.getDeptName()); - recipeInfo.setReqDeptCode(recipe.getReqDeptCode()); - recipeInfo.setReqDeptName(recipe.getReqDeptName()); - } - recipeItem = new HashMap<>(); - recipeItem.put("id", recipe.getRecipeId()); - recipeItem.put("fee", recipe.getRecipeFee()); - objects.add(recipeItem); - isFlag = true; - } - recipeInfo.setRecipeJson(JsonHelper.toJsonString(objects)); - return recipeInfo; - } - - - /** - * 自助申请单预交费判断 - */ - public synchronized void selfHelpPrepay(String code, String treatNum) throws ServiceException { - SelfHelpDao selfHelpDao = new SelfHelpDao(); - ConfigSelfHelp config = selfHelpDao.selectConfigByCode(code); - if (config != null && config.getEveryDayNum() != null) { - SelfHelpCount countBean = selfHelpDao.selectTodayCountBean(code); - int endTotal = countBean.getEndTotal(); // 已确认支付完成的数量 - int payTotal = countBean.getPayTotal(); // 5分钟内点了支付按钮的用户数量 - Integer everyDayNum = config.getEveryDayNum(); // 每日限制数量 - if (endTotal >= everyDayNum) { // 超过数量限制 - throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); - } - // 600 - 597 - 3 = 2 - if ((everyDayNum - endTotal - payTotal) > 0) { - log.info("[1]endTotal={}, payTotal={}", endTotal, payTotal); - if (!selfHelpDao.updatePrepay(treatNum)) { // 修改失败 | 或没有找到数据 - throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); - } - } else { - log.info("[2]endTotal={}, payTotal={}", endTotal, payTotal); - if (selfHelpDao.selectPrepayByTreatNum(treatNum) == null) { // 不在五分钟范围内 - throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); - } - } - } - } - - -// public static void main(String[] args) throws InterruptedException { -// RecipeService recipeService = new RecipeService(); -// Thread thread = new Thread(() -> { -// Pay one = recipeService.handRefund(PayTypeEnum.WX, "test", "test", "WX4596f62262eb4e2fa535d9c6d59d", "10552830", "recipe"); -// System.out.println(one); -// }); -// thread.start(); -// -// Pay two = recipeService.handRefund(PayTypeEnum.WX, "test", "test", "WX4596f62262eb4e2fa535d9c6d59d", "10552830", "recipe"); -// thread.join(); -// System.out.println(two); -// } - -// /** -// * 扫码获取二维码中的信息 -// * -// * @param request 请求 -// * @return 支付信息 -// */ -// public Pay getQRPayInfo(HttpServletRequest request) { -// Pay pay = new Pay(); -// InputStream in = null; -// BufferedReader reader = null; -// try { -// StringBuilder sb = new StringBuilder(); -// in = request.getInputStream(); -// reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); -// String len; -// while ((len = reader.readLine()) != null) { -// sb.append(len); -// } -// -// // 解析xml成map -// Map map = XMLConverUtil.convertToMap(sb.toString()); -// -// // 验证请求签名 -// if (!map.get("sign").equals(SignatureUtil.generateSign(map, WeChatConfig.getMchKey()))) { -// log.info("收到扫码支付请求:签名无效!"); -// return null; -// } -// -// String product_id = map.get("product_id"); -// log.info("收到扫码支付请求:product_id=" + product_id + ", open_id=" + map.get("openid")); -// if (!product_id.contains("XBD")) { -// log.info("扫码支付:不合规则的字符串,不允许支付!product_id=" + product_id); -// return null; -// } -// -// String[] array = product_id.split("XBD"); -// if (array.length < 5) { -// log.info("扫码支付:参数少于5个,不允许支付!product_id=" + product_id); -// return null; -// } -// -// String patientId = array[0]; -// String mzNum = array[1]; // 门诊号 -// String recipeId = array[2]; -// String payMoney = array[3]; -// String recipeType = array[4]; // 1:处方单,2:申请单 -// -// log.info("多处方扫码支付:patientId=" + patientId); -// if (patientId.equals("") || mzNum.equals("") || payMoney.equals("")) { -// log.info("扫码支付:参数中有空值,不允许支付!product_id=" + product_id); -// return null; -// } -// -// Map recipeMap = new HashMap<>(); -// recipeMap.put("id", recipeId); -// String recipeJson = JSON.toJSONString(recipeMap); -// -// pay.setPatientId(patientId); -// pay.setTreatNum(mzNum); -// pay.setRecipeId(recipeId); -//// pay.setPayMoney(payMoney); -// pay.setRecipeType(recipeType); -// pay.setRecipeJson(recipeJson); -// -// } catch (Exception e) { -// e.printStackTrace(); -// ErrorHelper.println(e); -// } finally { -// try { -// if (reader != null) reader.close(); -// -// if (in != null) in.close(); -// -// } catch (Exception e) { -// e.printStackTrace(); -// ErrorHelper.println(e); -// } -// } -// return pay; -// } -// -// -// /** -// * 退款 -// * -// * @param tradeNo tradeNo -// * @param fee 单次金额 -// * @return 是否退款成功 -// */ -// public boolean old_recipe_refund(String tradeNo, String recipeId, int totalFee, int fee, String desc) { -// String clazzPath = Objects.requireNonNull(RecipeService.class.getClassLoader().getResource("")).getPath(); -// if (clazzPath == null) { -// log.error("【微信】证书路径为空"); -// return false; -// -// } -// -// String filePath = clazzPath + "apiclient_cert.p12"; -// LocalHttpClient.initMchKeyStore(WeChatConfig.getMchId(), filePath); -// SecapiPayRefund refund = new SecapiPayRefund(); -// refund.setAppid(WeChatConfig.getAppId()); -// refund.setMch_id(WeChatConfig.getMchId()); -// refund.setNonce_str(UUID.randomUUID().toString().replace("-", "")); -// refund.setSign_type("MD5"); -// refund.setOut_trade_no(tradeNo); -// refund.setOut_refund_no(UUID.randomUUID().toString().replace("-", "")); -// refund.setTotal_fee(totalFee); -// refund.setRefund_fee(fee); -// refund.setRefund_fee_type("CNY"); -// refund.setRefund_account("REFUND_SOURCE_UNSETTLED_FUNDS"); -// if (desc.length() > 80) -// desc = desc.substring(0, 80); -// refund.setRefund_desc(desc); -// SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(refund, WeChatConfig.getMchKey()); -// -// if (!"SUCCESS".equals(refundResult.getReturn_code())) { -// log.info("【微信】退款失败"); -// return false; -// } -// String refundMsg = refundResult.getReturn_msg(); -// log.info("退款申请结果:tradeNo={}, refundMsg={}", tradeNo, refundMsg); -// -// return new RecipeDao().updateRefundResult(refundMsg, tradeNo, recipeId); -// } - - - /** - * 标准物价查询 - * - * @param pageNum 页码 - * @param pageSize 每页数量 - * @param pyCode 拼音码 - * @param type 类型 {1:检查治疗; 2:药品材料; 99:全部} - * @param groupFlag 检查治疗是否包含组套项目 [0:否;1:是(不传时默认值)] - * @return 结果 - */ - public Result getStandardPrice(Integer pageNum, Integer pageSize, String pyCode, String type, String groupFlag) { - if (pageNum == null || pageSize == null) { - return Result.error(ResultEnum.PARAM_IS_DEFECT); - } - - if (type == null) { - type = "99"; - } - - if (ObjectUtils.isEmpty(groupFlag)) { - groupFlag = "1"; - } - - JsonResult result = HisRecipeDao.getStandardPrice(pageNum, pageSize, pyCode, type, groupFlag); - if (!result.success()) { - return Result.error(result.getMessage()); - } - - int pageCount; - try { - JSONObject jsonObj = result.getJsonObject("Items"); - pageCount = jsonObj.getInteger("PageCount"); - } catch (Exception e) { - ErrorHelper.println(e); - return Result.error(e.getMessage()); - } - - List dataList = result.getDataMapList(StandardPrice.class, "Items", "Item"); - return Result.success(dataList, (pageCount * pageSize)); - } - - - public void selfHelpMaxNum(String code) throws ServiceException { - SelfHelpDao selfHelpDao = new SelfHelpDao(); - ConfigSelfHelp config = selfHelpDao.selectConfigByCode(code); - if (config != null && config.getEveryDayNum() != null) { - int count = selfHelpDao.selectTodayCount(code); // 当前数量 - Integer everyDayNum = config.getEveryDayNum(); // 每日限制数量 - log.warn("[申请单]数量限制 everyDayNum={}, count={}", everyDayNum, count); - if (count >= everyDayNum) { // 超过数量限制 - throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); - } - } - } - - public boolean updateMicroOrderState(String outTradeNo, String bankTransNo, String openid) { - return new RecipeDao().updateMicroOrderState(outTradeNo, bankTransNo, openid); - } - - - public List filterPaidList(List hisRecipeList) { - List dataList = new ArrayList<>(); - HisRecipe treatItem; - List groupList; - for (HisRecipe item : hisRecipeList) { - String treatNum = item.getMzNum(); - if (ObjectUtils.isEmpty(treatNum)) { - continue; - } - String execDate = item.getExecDate(); - item.setTreatNum(treatNum); - - HisRecipe findTreat = dataList.stream().filter(o -> o.getTreatNum().equals(treatNum)).findFirst().orElse(null); - if (findTreat == null) { - treatItem = new HisRecipe(); - treatItem.setTreatNum(treatNum); - treatItem.setDate(execDate); - groupList = new ArrayList<>(); - groupList.add(item); - treatItem.setGroupList(groupList); - dataList.add(treatItem); - } else { - if (findTreat.getGroupList() == null) { - findTreat.setGroupList(new ArrayList<>()); - } - Boolean isGreaterThan = DateHelper.leftGreaterThanRight(execDate, findTreat.getDate(), null); - if (isGreaterThan != null && isGreaterThan) { - findTreat.setDate(execDate); - } - findTreat.getGroupList().add(item); - } - } - return dataList; - } - - // 添加旧版体检订单 - public boolean addOldPEISOrder(String outTradeNo, String payMoney, String openid, String patientId, String treatNum, String rxId) { - Recipe recipe = new Recipe(); - recipe.setOpenid(openid); - recipe.setPatientId(patientId); - recipe.setTreatNum(treatNum); - recipe.setOutTradeNo(outTradeNo); - recipe.setPayWay("1"); - recipe.setPayMoney(new BigDecimal(payMoney)); - recipe.setTotalFee(new BigDecimal(payMoney)); - recipe.setRecipeId(rxId); - recipe.setHisStatus(-1); - recipe.setPayStatus(-1); - return new RecipeDao().insert(recipe); - } - - // 查询唯一订单-不支持查询多张发票的处方 - public Order queryRxByOrderNo(String outTradeNo, String tradeNo) { - if (!ObjectUtils.isEmpty(outTradeNo)) { - return new RecipeDao().selectOneByOutTradeNo(outTradeNo); - } - if (ObjectUtils.isEmpty(tradeNo)) { - return null; - } - return new RecipeDao().selectByTradeNo(tradeNo); - } - - // 查询处方订单集 - public List queryRxListByOrderNo(String outTradeNo) { - if (ObjectUtils.isEmpty(outTradeNo)) { - return new ArrayList<>(); - } - return new RecipeDao().selectListByOutTradeNo(outTradeNo); - } - - // 查询订单openid - public String queryOpenIdByOutTradeNo(String outTradeNo) { - List rxList = queryRxListByOrderNo(outTradeNo); - if (rxList.isEmpty()) { - return null; - } - Recipe order = rxList.get(0); - return order.getOpenid(); - } -} +package com.ynxbd.common.service; + +import com.alibaba.fastjson.JSONObject; +import com.ynxbd.common.action.pay.PEnum; +import com.ynxbd.common.bean.ConfigSelfHelp; +import com.ynxbd.common.bean.HisRecipe; +import com.ynxbd.common.bean.SelfHelpCount; +import com.ynxbd.common.bean.StandardPrice; +import com.ynxbd.common.bean.enums.MerchantEnum; +import com.ynxbd.common.bean.pay.Order; +import com.ynxbd.common.bean.pay.Recipe; +import com.ynxbd.common.dao.RecipeDao; +import com.ynxbd.common.dao.RefundDao; +import com.ynxbd.common.dao.SelfHelpDao; +import com.ynxbd.common.dao.his.HisAccountDao; +import com.ynxbd.common.dao.his.HisRecipeDao; +import com.ynxbd.common.helper.common.DateHelper; +import com.ynxbd.common.helper.common.ErrorHelper; +import com.ynxbd.common.helper.common.JsonHelper; +import com.ynxbd.common.helper.common.QuickDrugDispenseHelper; +import com.ynxbd.common.his.HisFactory; +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.common.service.cache.PayCache; +import com.ynxbd.wx.config.HospConfigEnum; +import com.ynxbd.wx.config.TZReserveConfig; +import com.ynxbd.wx.config.WeChatConfig; +import com.ynxbd.wx.utils.DateGenerate; +import com.ynxbd.wx.wxfactory.WxMedHelper; +import com.ynxbd.wx.wxfactory.WxPayHelper; +import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; + +import java.math.BigDecimal; +import java.util.*; + +/** + * 支付业务层 + * + * @Author wsq + * @Date 2021/3/4 10:41 + * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. + */ +@Slf4j +public class RxService { + + /** + * 是否在指定时间内重复支付 + * + * @return 是否完成操作 + */ + public Long isRepeatPay(String treatNum, Integer second) { + log.info("[处方]是否重复支付 treatNum={}, second={}", treatNum, second); + if (treatNum == null || second == null) { + return null; + } + + try { + List orderList = new RecipeDao().selectByTreatNum(treatNum); + int size = orderList.size(); + if (size == 0) { + return null; + } + + second += size; + Order order = orderList.get(0); + log.info("[处方]在指定时间内重复支付 recipe={}", order); + + Date updateTime = order.getUpdateTime(); + if (updateTime == null) { + return null; + } + long curTime = new Date().getTime(); + long time = ((curTime - updateTime.getTime()) / 1000); + + if (time < second) { + return second - time; + } + return null; + } catch (Exception e) { + ErrorHelper.println(e); + } + return null; + } + + + /** + * 处方订单信息预存 + * + * @param recipeJson 处方单json数据 + * @param patientId 患者id + * @param treatNum 门诊号 + * @return 是否完成操作 + */ + public Result rxHand(MerchantEnum merchantEnum, String payOpenId, String openid, String patientId, String treatNum, String totalFee, String recipeJson, String payWay, Integer awaitSecond, boolean isHttps) { + Result result = PayService.isPaymentPermittedByTime(); + if (result != null) { + return result; + } + if (merchantEnum == null) { // 支付方式异常 + return Result.error(ResultEnum.PAY_TYPE_ERROR); + } + + log.info("{}[处方预支付]参数 isHttps={}, openid={}, patientId={}, treatNum={}, totalFee={}, awaitSecond={}, payWay={}", merchantEnum.NAME, isHttps, openid, patientId, treatNum, totalFee, awaitSecond, payWay); + if (openid == null || patientId == null || treatNum == null || totalFee == null || recipeJson == null) { + return Result.error(ResultEnum.PARAM_IS_DEFECT); + } + + RxService rxService = new RxService(); + if (awaitSecond == null) { + awaitSecond = 0; + } + + if (awaitSecond != 0) { + Long second = rxService.isRepeatPay(treatNum, awaitSecond); + if (second != null) { + // 是否 awaitSecond s内重复支付 + log.info("[处方] 下单等待 {} s 确定", second); + return Result.error(ResultEnum.PAY_AWAIT, second); + } + } + + // 金额为0的处方不进行回调通知 + if ("0".equals(totalFee)) { + String outTradeNo = merchantEnum.createOutTradeNo(); + // 订单信息预存 + if (!rxService.saveRxData(merchantEnum, payOpenId, openid, recipeJson, payWay, patientId, treatNum, outTradeNo, totalFee)) { + log.info("{} [处方支付]预存支付信息失败 patientId={}", merchantEnum.NAME, patientId); + return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); + } + + String payDate = DateHelper.getCurDate(); + String payTime = DateHelper.getCurTime(); + String bankTransNo = outTradeNo.substring(merchantEnum.CODE.length()); + rxService.recipeListPay(merchantEnum, totalFee, openid, outTradeNo, bankTransNo, null, payDate, payTime, null); + + Map map = new HashMap<>(); + map.put("totalFee", 0); + return Result.success(map); + } + + // 医保支付 + JSONObject respMedJson = PayService.getMedAuthUrl(merchantEnum, PEnum.RECIPE, isHttps); + if (respMedJson != null) { + return Result.success(respMedJson); + } + return Result.success(); + } + + + /** + * 处方订单信息预存 + * + * @param recipeJson 处方单json数据 + * @param patientId 患者id + * @param treatNum 门诊号 + * @return 是否完成操作 + */ + public List hisRxPrepay(String recipeJson, String patientId, String treatNum) { + log.info("[处方]预结算 patientId={}, treatNum={}, recipeJson={}", patientId, treatNum, recipeJson); + List respList = new ArrayList<>(); + List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); + if (recipeList == null || recipeList.isEmpty()) { + log.info("[处方]预结算勾选处方数量为0 或 数据转换失败"); + return respList; + } + + List recipeIds; + String curDate = DateHelper.getCurDate(); + String curTime = DateHelper.getCurTime(); + String recipeId, feeId, feeInfo; + JsonResult response; + Recipe addInfo; + for (Recipe recipe : recipeList) { + recipeId = recipe.getRecipeId(); + if (ObjectUtils.isEmpty(recipeId) || ObjectUtils.isEmpty(recipe.getRecipeFee())) { + continue; + } + recipeIds = new ArrayList<>(); + recipeIds.add(recipe.getRecipeId()); + + response = HisRecipeDao.prepay( + patientId, + treatNum, + recipeIds, + recipe.getRecipeFee().toString(), + curDate, + curTime, + "app", + MerchantEnum.WX); + + log.info("[处方]预结算 resp={}", response); + if (response.success()) { + feeId = response.getDataMapString("FeeID"); + feeInfo = response.getDataMapString("FeeInfo"); + log.info("[处方]预结算成功 treatNum={}, recipeId={}, feeId={}, feeInfo={}", treatNum, recipeId, feeId, feeInfo); + if (feeId != null && feeInfo != null) { + addInfo = new Recipe(); + + addInfo.setTreatNum(treatNum); + addInfo.setRecipeId(recipeId); + addInfo.setFeeId(feeId); + addInfo.setFeeInfo(feeInfo); + respList.add(addInfo); + } + } + } + return respList; + + } + + + /** + * 处方订单信息预存 + * + * @param recipeJson 处方单json数据 + * @param payWay 支付方式 0:公众号内;1:扫码支付 + * @param openid openid + * @param patientId 患者id + * @param treatNum 门诊号 + * @param outTradeNo 订单号 + * @return 是否完成操作 + */ + public boolean saveRxData(MerchantEnum merchantEnum, String payOpenId, String openid, String recipeJson, String payWay, String patientId, String treatNum, String outTradeNo, String totalFee) { + log.info("{}[处方支付]预存信息 patientId={}, treatNum={}, recipeJson={}", merchantEnum.NAME, patientId, treatNum, recipeJson); + List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); + if (recipeList == null || recipeList.isEmpty()) { + log.info("[处方支付]勾选处方数量为0 或 数据转换失败"); + return false; + } + + RecipeDao recipeDao = new RecipeDao(); + // 0:公众号内支付,1:扫码支付 + payWay = payWay == null ? "0" : payWay; + + for (Recipe recipe : recipeList) { + if (ObjectUtils.isEmpty(recipe.getRecipeId()) || ObjectUtils.isEmpty(recipe.getRecipeFee())) { + return false; + } + recipe.setPayMchCode(merchantEnum.CODE); + recipe.setOpenid(openid); + recipe.setPayOpenId(payOpenId); + recipe.setPatientId(patientId); + recipe.setTreatNum(treatNum); + recipe.setOutTradeNo(outTradeNo); + recipe.setPayWay(payWay); +// recipe.setTradeNo(CodeHelper.getHisTradeNo()); // 本次his交易流水号 + recipe.setTradeNo(null); // 本次his交易流水号 + recipe.setTotalFee(new BigDecimal(totalFee)); + recipe.setPayMoney(recipe.getRecipeFee()); + recipe.setHisStatus(-1); + recipe.setPayStatus(-1); + if (treatNum.contains("P-")) { + recipe.setOrderType("PEIS"); + } + } + + boolean isResult = recipeDao.insertBatch(recipeList) == recipeList.size(); + log.info("[处方]信息预存{}, patientId={}, treatNum={}", (isResult ? "成功" : "失败"), patientId, treatNum); + return isResult; + } + + + /** + * 处方多张支付 + * + * @param totalFee 总金额 + * @param openid openid + * @param outTradeNo 订单号 + * @param bankTransNo 交易流水号 + * @param payDate 支付日期 + * @param payTime 支付时间 + * @return 是否完成操作 + */ + public boolean recipeListPay(MerchantEnum merchantEnum, String totalFee, String openid, String outTradeNo, String bankTransNo, String bankMerchantNo, String payDate, String payTime, String payInfo) { + RecipeDao recipeDao = new RecipeDao(); + + // 此处判断是否已经发起缴费,只要已存在数据库记录,说明已经发起了缴费请求,不能根据已经缴费成功,才取消本次缴费请求,因为请求可能已经延时,本次请求可能是重复提交的请求 + if (PayService.hasUserOrderNo(outTradeNo, openid)) { + log.info("{} [处方]已发起缴费 outTradeNo={}", merchantEnum.NAME, outTradeNo); + return false; + } + + if (recipeDao.isHisPaidByOutTradeNo(outTradeNo)) { + log.info("{} [处方]已交过费, 退出本次缴费成功通知处理流程:outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); + return false; + } + + if (payInfo != null) { + PayService.saveOrderNo(PEnum.RECIPE, outTradeNo, openid, payInfo, null); + } + + List recipeList = recipeDao.selectListByOutTradeNo(outTradeNo); + if (!recipeDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { + log.info("{} [处方]更新商户信息失败(1) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); + if (!recipeDao.updateNotifyPaid(outTradeNo, bankTransNo, bankMerchantNo, recipeList)) { + log.info("{} [处方]更新商户信息失败(2) outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); + return false; + } + } + + // 订单金额验证 + BigDecimal rxTotalFee = BigDecimal.ZERO; + for (Recipe recipe : recipeList) { + rxTotalFee = rxTotalFee.add(recipe.getPayMoney()); + } + + log.info("{} [处方]金额计算{} outTradeNo={}, bankTransNo={}, rxTotalFee={}, totalFee={}", merchantEnum.NAME, (rxTotalFee.compareTo(new BigDecimal(totalFee)) == 0 ? "" : "异常"), outTradeNo, bankTransNo, rxTotalFee, totalFee); + if (rxTotalFee.compareTo(new BigDecimal(totalFee)) > 0) { // 支付的金额不足 + log.info("{} [处方]缴费金额异常 outTradeNo={}, bankTransNo={}, rxTotalFee={}, totalFee={}", merchantEnum.NAME, outTradeNo, bankTransNo, rxTotalFee, totalFee); + return false; + } + + List failedList = new ArrayList<>(); // HIS缴费失败的处方单 + + long begTime = System.currentTimeMillis(); // 开始时间 + // HIS缴费 + String patientId = null; + Recipe recipeInfo; + for (Recipe recipeItem : recipeList) { + patientId = recipeItem.getPatientId(); + recipeItem.setBankTransNo(bankTransNo); + // HIS处方缴费 + recipeInfo = recipeSinglePay(recipeItem, payDate, payTime, merchantEnum); + + // 调用失败的处方 + if (recipeInfo.isRefund()) { + failedList.add(recipeInfo); + } + + // 如果是体检支付就只调用一次his结算 + if (recipeItem.getTreatNum().contains("P-")) { + // 体检缴费失败的所有费用进行退回 + if (recipeInfo.isRefund()) { + failedList = recipeList; + for (Recipe failed : failedList) { + failed.setErrorCode(recipeInfo.getErrorCode()); + failed.setErrorMsg(recipeInfo.getErrorMsg()); + } + } + break; + } + } + long endTime = System.currentTimeMillis(); // 结束时间 + log.info("{} [处方]请求HIS结束 耗时:{} outTradeNo={}, bankTransNo={}", merchantEnum.NAME, ((endTime - begTime) / 1000) + "s(" + (endTime - begTime) + "ms)", outTradeNo, bankTransNo); + + if ("0".equals(totalFee)) { // 总金额为0不进行退费处理 + return true; + } + + // 处理his缴费失败的处方 + String failedRecipeId, errorCode, errorMsg, refundDesc; + // 调用超时处方 + List outTimeList = new ArrayList<>(); + for (Recipe failed : failedList) { + failedRecipeId = failed.getRecipeId(); + errorCode = failed.getErrorCode(); + errorMsg = failed.getErrorMsg(); + if ("500".equals(errorCode)) { // 500 + log.info("[处方]HIS请求超时,不退费 outTradeNo={}, tradeNo={}", outTradeNo, failed.getTradeNo()); + outTimeList.add(failed); + PayCache.putRecipeCache(failed.getTradeNo(), failed); + + } else { + refundDesc = "缴费失败 处方号:" + failedRecipeId + "\n原因:[" + errorCode + "]" + errorMsg; + try { + // 自动退费 + rxAutoRefund(merchantEnum, openid, patientId, outTradeNo, failed.getTradeNo(), failedRecipeId, failed.getPayMoney(), new BigDecimal(totalFee), failed.getUpdateTime(), errorCode, errorMsg, refundDesc); + } catch (Exception e) { + ErrorHelper.println(e); + } + } + } + + String tip = String.format("共计缴费处方单数:%s,失败数:%s,超时数:%s", recipeList.size(), (failedList.size() - outTimeList.size()), outTimeList.size()); + log.info("{} [处方]{}", merchantEnum.NAME, tip); + + if (WeChatConfig.APP_ID.equals(HospConfigEnum.红河州第一人民医院.WX_APP_ID)) { + TZReserveConfig.reserveRun(patientId); // 天助医技预约 + } + + new HealthUploadService().rxReportHISData(merchantEnum, openid, patientId); + return true; + } + + + /** + * 单张处方支付 + * + * @param recipe 支付信息 + * @param payDate 支付日期 + * @param payTime 支付时间 + * @return order + */ + public Recipe recipeSinglePay(Recipe recipe, String payDate, String payTime, MerchantEnum merchantEnum) { + Recipe order = new Recipe(); + String openid = recipe.getOpenid(); + String patientId = recipe.getPatientId(); + String bankTransNo = recipe.getBankTransNo(); + BigDecimal recipeFee = recipe.getPayMoney(); + BigDecimal totalFee = recipe.getTotalFee(); + + order.setUpdateTime(recipe.getUpdateTime()); + String tradeNo = recipe.getTradeNo(); + String recipeId = recipe.getRecipeId(); + order.setBankTransNo(bankTransNo); + if (recipeFee == null) { + order.setErrorMsg(String.format("[处方]金额为异常 recipeId=%s, tradeNo=%s", recipeId, tradeNo)); + return order; + } + + List recipeIds = new ArrayList<>(); + recipeIds.add(recipeId); + + RecipeDao recipeDao = new RecipeDao(); + + String outTradeNo = recipe.getOutTradeNo(); + + String treatNum = recipe.getTreatNum(); + JsonResult response = HisRecipeDao.payInvoice( + openid, + patientId, + treatNum, + recipeIds, + recipeFee.toString(), + totalFee.toString(), + payDate, + payTime, + tradeNo, + "app", + bankTransNo, + merchantEnum, + recipe.getFeeId(), + recipe.getFeeInfo()); + + log.info("[处方]结算返回 resp={}", JsonHelper.toJsonString(response)); + String respCode = response.getCode(); + String respMessage = response.getMessage(); + + if (!response.success()) { + order.setErrorMsg(response.getMessage()); + order.setErrorCode(response.getCode()); + + String errorMsg = recipe.getErrorMsg(); + if (!ObjectUtils.isEmpty(errorMsg)) { + respMessage = respMessage + "|" + errorMsg; + } + + if (!recipeDao.updateHisPaidFailByTradeNo(tradeNo, respCode, respMessage)) { + log.info("[处方]更新HIS缴费失败信息失败 tradeNo={}, code={}, message={}", tradeNo, respCode, respMessage); + } + + if (recipeFee.compareTo(BigDecimal.ZERO) == 0) { + log.info("[处方]HIS缴费失败,0元处方不退费,HIS返回:[{}] [{}]", respCode, respMessage); + return order; + } + + order.setRefund(true); // 需要退费 + order.setTradeNo(tradeNo); + order.setOutTradeNo(outTradeNo); + order.setRecipeId(recipeId); + order.setPayMoney(recipeFee); + return order; + } + + String drugInfo = response.getDataMapString("DrugInfo"); + String hisTransNo = response.getDataMapString("HISTransNo"); + String invoiceTransNo = response.getDataMapString("InvoiceTransNo"); + + log.info("[处方]HIS缴费成功, 更新支付信息:hisTransNo={}, invoiceTransNo={}, drugInfo={}", hisTransNo, invoiceTransNo, drugInfo); + if (!ObjectUtils.isEmpty(drugInfo) && !ObjectUtils.isEmpty(invoiceTransNo)) { + log.info("[处方]调用快速发药 invoiceTransNo={}, drugInfo={}", invoiceTransNo, drugInfo); + QuickDrugDispenseHelper.quickDrug(drugInfo, invoiceTransNo); + } + + // 更新支付信息 + if (!recipeDao.updateHisPaidByTradeNo(tradeNo, hisTransNo, invoiceTransNo)) { + log.info("[处方]更新HIS返回数据失败 outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); + } + + // 如果是体检支付就更新所有处方 + if (treatNum.contains("P-")) { + // 更新支付信息 + if (!recipeDao.updateHisPaidByBankTransNo(bankTransNo, hisTransNo, invoiceTransNo)) { + log.info("[处方]更新体检缴费HIS返回数据失败 outTradeNo={}, bankTransNo={}, recipeId={}", outTradeNo, bankTransNo, recipeId); + } + } + + if (new SelfHelpDao().updateNotice(treatNum)) { + log.info("[自助开单]通知状态修改成功 treatNum={}", treatNum); + } + return order; + } + + + /** + * 处方自动退费 + * + * @param openid openid + * @param patientId 患者id + * @param outTradeNo 商户单号 + * @param tradeNo HIS交易流水号 + * @param recipeId 退款处方id + * @param recipeFee 退款处方金额 + * @param totalFee 退款总金额 + * @param refundDesc 退费说明 + * @return 是否成功 + */ + public boolean rxAutoRefund(MerchantEnum merchantEnum, String openid, String patientId, String outTradeNo, String tradeNo, String recipeId, BigDecimal recipeFee, BigDecimal totalFee, Date tradeDate, String respCode, String respMessage, String refundDesc) { + if (recipeFee == null || totalFee == null || ObjectUtils.isEmpty(outTradeNo) || ObjectUtils.isEmpty(recipeId) || ObjectUtils.isEmpty(tradeNo)) { + log.info("[处方自动退款]参数缺失:outTradeNo={}, recipeId={}, tradeNo={}, fee={}, payMoney={}", outTradeNo, recipeId, tradeNo, recipeFee, totalFee); + return false; + } + + if ("500".equals(respCode)) { // 超时or异常不退费 + log.info("[处方]HIS请求超时,不退费 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo); + return false; + } + + RecipeDao recipeDao = new RecipeDao(); + HisAccountDao hisAccountDao = new HisAccountDao(); + + if (recipeDao.isHisPaidByRecipeId(outTradeNo, recipeId)) { + log.info("[处方自动退款]数据库中已缴费成功,不退费:outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); + return false; + } + + String begDate = DateGenerate.getNextDay(DateGenerate.getStringDateShort(), "-7"); + String endDate = DateGenerate.getNextDay(DateGenerate.getStringDateShort(), "7"); + + String paidTip = hisAccountDao.isPaid(begDate, endDate, tradeNo); + if (paidTip != null) { + log.info("[处方自动退款]{}-不退费:outTradeNo={}, tradeNo={}, recipeId={}", paidTip, outTradeNo, tradeNo, recipeId); + return false; + } + + try { + log.info("[处方退款]第1次等待8s"); + Thread.sleep(8000); + if (recipeDao.isHisPaidByRecipeId(outTradeNo, recipeId)) { + log.info("[处方自动退款]数据库中已缴费成功 outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); + return false; + } + + paidTip = hisAccountDao.isPaid(begDate, endDate, tradeNo); + if (paidTip != null) { + log.info("[处方自动退款]{}-不退费:outTradeNo={}, tradeNo={}, recipeId={}", paidTip, outTradeNo, tradeNo, recipeId); + return false; + } + } catch (Exception e) { + ErrorHelper.println(e); + } + + // 更新退款状态失败,不退费!!! + if (!recipeDao.updateRefundByRecipeId(outTradeNo, recipeId)) { + log.info("{} [处方自动退款]更新退款状态失败-不退费", merchantEnum.NAME); + return false; + } + Order refundInfo = PayService.refund(merchantEnum, outTradeNo, tradeNo, recipeFee, totalFee, refundDesc, tradeDate, openid, patientId, null); + + boolean isResult = refundInfo.isSuccess(); + log.info("{} [处方自动退款]申请{} outTradeNo={}, recipeId={}, recipeFee={}, HIS返回:{}", merchantEnum.NAME, + (isResult ? "成功" : "失败"), + outTradeNo, recipeId, recipeFee, refundDesc + ); + + if (!recipeDao.updateRefundByTradeNo(tradeNo, refundInfo.getRefundResult())) { + log.info("{} [处方自动退款]更新退款返回结果失败:outTradeNo={}, recipeId={}", merchantEnum.NAME, outTradeNo, recipeId); + } + return true; + } + + + /** + * His系统处方手动退费 + * + * @param invoiceTransNo 发票流水号 + * @param refundUser 退款人 + * @param refundDesc 退款描述 + * @return 是否成功 + */ + public synchronized boolean hisRefund(String invoiceTransNo, String patientId, String refundUser, String refundDesc, BigDecimal refundMoney, PEnum pEnum) throws ServiceException { + RecipeDao recipeDao = new RecipeDao(); + Recipe recipe = recipeDao.selectRefundByInvoiceTransNo(invoiceTransNo, patientId); + + if (recipe == null) { + log.info("[HIS处方退费]没有查询到可退款的记录, 不退费 invoiceTransNo={}", invoiceTransNo); + throw new ServiceException(ResultEnum.DATA_NOT_FOUND); + } + + String authCode = recipe.getAuthCode(); + if (ObjectUtils.isEmpty(authCode)) { + log.info("[HIS处方退费]失败,条码为空 authCode={}", authCode); + throw new ServiceException("条码为空"); + } + + MerchantEnum merchantEnum = MerchantEnum.findEnumByAuthCode(authCode); + if (merchantEnum == null) { + log.info("[HIS处方退费]失败,支付方式异常 authCode={}", authCode); + throw new ServiceException(ResultEnum.PAY_TYPE_ERROR); + } + + if (ObjectUtils.isEmpty(refundDesc)) { + refundDesc = "HIS手动退费"; + } + + String bankTransNo = recipe.getBankTransNo(); + String outTradeNo = recipe.getOutTradeNo(); + BigDecimal dbPayMoney = recipe.getPayMoney(); + if (refundMoney.compareTo(dbPayMoney) != 0) { + log.info("[HIS挂号退费]金额符合禁止退费 invoiceTransNo={}, payMoney={}", invoiceTransNo, dbPayMoney); + throw new ServiceException(ResultEnum.REFUND_MONEY_ERROR); + } + + String outRefundNo = HisFactory.getHisTradeNo(bankTransNo, pEnum); + Order orderRefund = PayService.refund(merchantEnum, outTradeNo, outRefundNo, refundMoney, recipe.getTotalFee(), refundDesc, recipe.getUpdateTime(), recipe.getOpenid(), recipe.getPatientId(), null); + + boolean isResult = orderRefund.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 = orderRefund.getRefundResult(); + if (!recipeDao.updateRefundByInvoiceTransNo(outTradeNo, outRefundNo, invoiceTransNo, refundResult)) { + log.info("{} [HIS处方退费]更新退款结果失败 outTradeNo={}, outRefundNo={}, invoiceTransNo={}, refundResult={}", merchantEnum.NAME, outTradeNo, outRefundNo, invoiceTransNo, refundResult); + } + + recipe.setRefundUser(refundUser); + recipe.setRefundMoney(refundMoney); + recipe.setRefundResult(refundResult); + recipe.setRefundTable(pEnum.CODE); + recipe.setTradeNo(outRefundNo); + if (!new RefundDao().insert(recipe, refundDesc, "HIS")) { + log.info("{} [HIS处方退费]退费信息新增失败 outTradeNo={}, outRefundNo={}, invoiceTransNo={}, refundResult={}", merchantEnum.NAME, outTradeNo, outRefundNo, invoiceTransNo, refundResult); + } + return true; + } + + + /** + * His系统处方线下退费 + * + * @param reason 退费原因 + * @return 是否成功 + */ + public Result mdCashRefund(String payOrdId, String reason) { + RecipeDao recipeDao = new RecipeDao(); + Recipe recipe = recipeDao.selectByTradeNo(payOrdId); + if (recipe == null) { + return Result.error(ResultEnum.DATA_NOT_FOUND); + } + if (!recipe.hasPayStatusPaid()) { + log.info("[医保]订单未支付 payOrdId={}, payStatus={}", payOrdId, recipe.getPayStatus()); + return Result.error(ResultEnum.PAY_ORDER_PARAMS_IS_DEFECT); + } + + if (recipe.hasRefundByRefundResult()) { + return Result.error(ResultEnum.REFUND_IS_REPEAT); // 退费重复申请 + } + + Boolean hasDateRange = DateHelper.inDateRangeByDay(-30, DateHelper.dateToStr(recipe.getUpdateTime(), DateHelper.DateEnum.yyyy_MM_dd_HH_mm_ss)); + if (hasDateRange == null || !hasDateRange) { + return Result.error("订单支付日期已经超过30天,请从商户平台退费"); + } + + String outTradeNo = recipe.getOutTradeNo(); + BigDecimal cashFee = recipe.getPayMoney(); + if (cashFee == null) { + return Result.error(ResultEnum.REFUND_CASH_IS_NULL); + } + + if (cashFee.compareTo(BigDecimal.ZERO) == 0) { + if (!recipeDao.updateRefundByTradeNo(payOrdId, WxPayHelper.OK)) { + log.error("[医保]现金为0修改数据库状态失败 payOrderId={}", payOrdId); + return Result.error(ResultEnum.DATA_UPDATE_ERROR); + } + + Map map = new HashMap<>(); + map.put("transNo", recipe.getTradeNo()); + map.put("payWay", recipe.getPayWay()); + map.put("bankTransNo", recipe.getBankTransNo()); + map.put("payMoney", cashFee); + return Result.success(map); + } + + WxMedOrder order = WxMedHelper.refundCash(outTradeNo, ("R" + payOrdId), payOrdId, cashFee, reason); + log.info("[医保]现金退费order={}", order); + String refundReason = "线下HIS医保现金部分退费"; + if (!ObjectUtils.isEmpty(reason)) { + refundReason = ":" + reason; + } + + String refundResult = order.isOk() ? WxPayHelper.OK : order.getMessage(); + if (!recipeDao.updateRefundByTradeNo(payOrdId, refundResult, refundReason)) { + log.error("[医保]现金退费修改数据库状态失败 payOrderId={}, refundResult={}", payOrdId, refundResult); + } + if (order.isOk()) { + Map map = new HashMap<>(); + map.put("transNo", recipe.getTradeNo()); + map.put("payWay", recipe.getPayWay()); + map.put("bankTransNo", recipe.getBankTransNo()); + map.put("payMoney", cashFee); + return Result.success(map); + } + return Result.error(refundResult); + } + + + /** + * 处方手动退费 + * + * @param refundUser 退款人 + * @param refundDesc 退款描述 + * @return 是否成功 + */ + public synchronized boolean isHandRefund(String tradeNo, String refundUser, String refundDesc, PEnum orderType, String sys) throws ServiceException { + RecipeDao recipeDao = new RecipeDao(); + Recipe recipe = recipeDao.selectRefundByTradeNo(tradeNo); + if (recipe == null) { + throw new ServiceException(ResultEnum.DATA_NOT_FOUND); + } + + String outTradeNo = recipe.getOutTradeNo(); + if (outTradeNo == null) { + throw new ServiceException(ResultEnum.DATA_IS_WRONG); + } + List recipeList = recipeDao.selectListByOutTradeNo(outTradeNo); + + String recipeId = recipe.getRecipeId(); + Order refundInfo = PayService.handRefund(recipe.getUpdateTime(), recipe.getUpdateTime(), recipe, recipe.getTotalFee(), refundUser, refundDesc, orderType.CODE, recipeList.size(), sys, + () -> recipeDao.updateRefundByRecipeId(outTradeNo, recipeId)); + + if (!recipeDao.updateRefundByTradeNo(tradeNo, refundInfo.getRefundResult())) { + log.info("[处方]退费成功,更新状态失败:outTradeNo={}, {}", outTradeNo, refundInfo); + } else { + if ("0".equals(recipe.getRefundResult())) { + throw new ServiceException(ResultEnum.REFUND_STATUS_ERROR_UPDATE_STATUS_SUCCESS); + } + } + return true; + } + + + /** + * 处方手动退费 + * + * @return 是否成功 + */ + public Recipe recipeJsonToInfo(String treatNum, String recipeJson) { + log.info("[处方支付]预存信息 treatNum={} recipeJson={}", treatNum, recipeJson); + List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); + if (recipeList == null || recipeList.size() == 0) { + log.info("[处方支付]勾选处方数量为0 或 数据转换失败"); + return null; + } + Recipe recipeInfo = new Recipe(); + + List> objects = new ArrayList<>(); + Map recipeItem; + + boolean isFlag = false; + for (Recipe recipe : recipeList) { + if (!isFlag) { + recipeInfo.setDeptCode(recipe.getDeptCode()); + recipeInfo.setDeptName(recipe.getDeptName()); + recipeInfo.setReqDeptCode(recipe.getReqDeptCode()); + recipeInfo.setReqDeptName(recipe.getReqDeptName()); + } + recipeItem = new HashMap<>(); + recipeItem.put("id", recipe.getRecipeId()); + recipeItem.put("fee", recipe.getRecipeFee()); + objects.add(recipeItem); + isFlag = true; + } + recipeInfo.setRecipeJson(JsonHelper.toJsonString(objects)); + return recipeInfo; + } + + + /** + * 自助申请单预交费判断 + */ + public synchronized void selfHelpPrepay(String code, String treatNum) throws ServiceException { + SelfHelpDao selfHelpDao = new SelfHelpDao(); + ConfigSelfHelp config = selfHelpDao.selectConfigByCode(code); + if (config != null && config.getEveryDayNum() != null) { + SelfHelpCount countBean = selfHelpDao.selectTodayCountBean(code); + int endTotal = countBean.getEndTotal(); // 已确认支付完成的数量 + int payTotal = countBean.getPayTotal(); // 5分钟内点了支付按钮的用户数量 + Integer everyDayNum = config.getEveryDayNum(); // 每日限制数量 + if (endTotal >= everyDayNum) { // 超过数量限制 + throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); + } + // 600 - 597 - 3 = 2 + if ((everyDayNum - endTotal - payTotal) > 0) { + log.info("[1]endTotal={}, payTotal={}", endTotal, payTotal); + if (!selfHelpDao.updatePrepay(treatNum)) { // 修改失败 | 或没有找到数据 + throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); + } + } else { + log.info("[2]endTotal={}, payTotal={}", endTotal, payTotal); + if (selfHelpDao.selectPrepayByTreatNum(treatNum) == null) { // 不在五分钟范围内 + throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); + } + } + } + } + + +// public static void main(String[] args) throws InterruptedException { +// RecipeService recipeService = new RecipeService(); +// Thread thread = new Thread(() -> { +// Pay one = recipeService.handRefund(PayTypeEnum.WX, "test", "test", "WX4596f62262eb4e2fa535d9c6d59d", "10552830", "recipe"); +// System.out.println(one); +// }); +// thread.start(); +// +// Pay two = recipeService.handRefund(PayTypeEnum.WX, "test", "test", "WX4596f62262eb4e2fa535d9c6d59d", "10552830", "recipe"); +// thread.join(); +// System.out.println(two); +// } + +// /** +// * 扫码获取二维码中的信息 +// * +// * @param request 请求 +// * @return 支付信息 +// */ +// public Pay getQRPayInfo(HttpServletRequest request) { +// Pay pay = new Pay(); +// InputStream in = null; +// BufferedReader reader = null; +// try { +// StringBuilder sb = new StringBuilder(); +// in = request.getInputStream(); +// reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); +// String len; +// while ((len = reader.readLine()) != null) { +// sb.append(len); +// } +// +// // 解析xml成map +// Map map = XMLConverUtil.convertToMap(sb.toString()); +// +// // 验证请求签名 +// if (!map.get("sign").equals(SignatureUtil.generateSign(map, WeChatConfig.getMchKey()))) { +// log.info("收到扫码支付请求:签名无效!"); +// return null; +// } +// +// String product_id = map.get("product_id"); +// log.info("收到扫码支付请求:product_id=" + product_id + ", open_id=" + map.get("openid")); +// if (!product_id.contains("XBD")) { +// log.info("扫码支付:不合规则的字符串,不允许支付!product_id=" + product_id); +// return null; +// } +// +// String[] array = product_id.split("XBD"); +// if (array.length < 5) { +// log.info("扫码支付:参数少于5个,不允许支付!product_id=" + product_id); +// return null; +// } +// +// String patientId = array[0]; +// String mzNum = array[1]; // 门诊号 +// String recipeId = array[2]; +// String payMoney = array[3]; +// String recipeType = array[4]; // 1:处方单,2:申请单 +// +// log.info("多处方扫码支付:patientId=" + patientId); +// if (patientId.equals("") || mzNum.equals("") || payMoney.equals("")) { +// log.info("扫码支付:参数中有空值,不允许支付!product_id=" + product_id); +// return null; +// } +// +// Map recipeMap = new HashMap<>(); +// recipeMap.put("id", recipeId); +// String recipeJson = JSON.toJSONString(recipeMap); +// +// pay.setPatientId(patientId); +// pay.setTreatNum(mzNum); +// pay.setRecipeId(recipeId); +//// pay.setPayMoney(payMoney); +// pay.setRecipeType(recipeType); +// pay.setRecipeJson(recipeJson); +// +// } catch (Exception e) { +// e.printStackTrace(); +// ErrorHelper.println(e); +// } finally { +// try { +// if (reader != null) reader.close(); +// +// if (in != null) in.close(); +// +// } catch (Exception e) { +// e.printStackTrace(); +// ErrorHelper.println(e); +// } +// } +// return pay; +// } +// +// +// /** +// * 退款 +// * +// * @param tradeNo tradeNo +// * @param fee 单次金额 +// * @return 是否退款成功 +// */ +// public boolean old_recipe_refund(String tradeNo, String recipeId, int totalFee, int fee, String desc) { +// String clazzPath = Objects.requireNonNull(RecipeService.class.getClassLoader().getResource("")).getPath(); +// if (clazzPath == null) { +// log.error("【微信】证书路径为空"); +// return false; +// +// } +// +// String filePath = clazzPath + "apiclient_cert.p12"; +// LocalHttpClient.initMchKeyStore(WeChatConfig.getMchId(), filePath); +// SecapiPayRefund refund = new SecapiPayRefund(); +// refund.setAppid(WeChatConfig.getAppId()); +// refund.setMch_id(WeChatConfig.getMchId()); +// refund.setNonce_str(UUID.randomUUID().toString().replace("-", "")); +// refund.setSign_type("MD5"); +// refund.setOut_trade_no(tradeNo); +// refund.setOut_refund_no(UUID.randomUUID().toString().replace("-", "")); +// refund.setTotal_fee(totalFee); +// refund.setRefund_fee(fee); +// refund.setRefund_fee_type("CNY"); +// refund.setRefund_account("REFUND_SOURCE_UNSETTLED_FUNDS"); +// if (desc.length() > 80) +// desc = desc.substring(0, 80); +// refund.setRefund_desc(desc); +// SecapiPayRefundResult refundResult = PayMchAPI.secapiPayRefund(refund, WeChatConfig.getMchKey()); +// +// if (!"SUCCESS".equals(refundResult.getReturn_code())) { +// log.info("【微信】退款失败"); +// return false; +// } +// String refundMsg = refundResult.getReturn_msg(); +// log.info("退款申请结果:tradeNo={}, refundMsg={}", tradeNo, refundMsg); +// +// return new RecipeDao().updateRefundResult(refundMsg, tradeNo, recipeId); +// } + + + /** + * 标准物价查询 + * + * @param pageNum 页码 + * @param pageSize 每页数量 + * @param pyCode 拼音码 + * @param type 类型 {1:检查治疗; 2:药品材料; 99:全部} + * @param groupFlag 检查治疗是否包含组套项目 [0:否;1:是(不传时默认值)] + * @return 结果 + */ + public Result getStandardPrice(Integer pageNum, Integer pageSize, String pyCode, String type, String groupFlag) { + if (pageNum == null || pageSize == null) { + return Result.error(ResultEnum.PARAM_IS_DEFECT); + } + + if (type == null) { + type = "99"; + } + + if (ObjectUtils.isEmpty(groupFlag)) { + groupFlag = "1"; + } + + JsonResult result = HisRecipeDao.getStandardPrice(pageNum, pageSize, pyCode, type, groupFlag); + if (!result.success()) { + return Result.error(result.getMessage()); + } + + int pageCount; + try { + JSONObject jsonObj = result.getJsonObject("Items"); + pageCount = jsonObj.getInteger("PageCount"); + } catch (Exception e) { + ErrorHelper.println(e); + return Result.error(e.getMessage()); + } + + List dataList = result.getDataMapList(StandardPrice.class, "Items", "Item"); + return Result.success(dataList, (pageCount * pageSize)); + } + + + public void selfHelpMaxNum(String code) throws ServiceException { + SelfHelpDao selfHelpDao = new SelfHelpDao(); + ConfigSelfHelp config = selfHelpDao.selectConfigByCode(code); + if (config != null && config.getEveryDayNum() != null) { + int count = selfHelpDao.selectTodayCount(code); // 当前数量 + Integer everyDayNum = config.getEveryDayNum(); // 每日限制数量 + log.warn("[申请单]数量限制 everyDayNum={}, count={}", everyDayNum, count); + if (count >= everyDayNum) { // 超过数量限制 + throw new ServiceException(ResultEnum.SELF_HELP_EXCEED_MAX); + } + } + } + + public boolean updateMicroOrderState(String outTradeNo, String bankTransNo, String openid) { + return new RecipeDao().updateMicroOrderState(outTradeNo, bankTransNo, openid); + } + + + public List filterPaidList(List hisRecipeList) { + List dataList = new ArrayList<>(); + HisRecipe treatItem; + List groupList; + for (HisRecipe item : hisRecipeList) { + String treatNum = item.getMzNum(); + if (ObjectUtils.isEmpty(treatNum)) { + continue; + } + String execDate = item.getExecDate(); + item.setTreatNum(treatNum); + + HisRecipe findTreat = dataList.stream().filter(o -> o.getTreatNum().equals(treatNum)).findFirst().orElse(null); + if (findTreat == null) { + treatItem = new HisRecipe(); + treatItem.setTreatNum(treatNum); + treatItem.setDate(execDate); + groupList = new ArrayList<>(); + groupList.add(item); + treatItem.setGroupList(groupList); + dataList.add(treatItem); + } else { + if (findTreat.getGroupList() == null) { + findTreat.setGroupList(new ArrayList<>()); + } + Boolean isGreaterThan = DateHelper.leftGreaterThanRight(execDate, findTreat.getDate(), null); + if (isGreaterThan != null && isGreaterThan) { + findTreat.setDate(execDate); + } + findTreat.getGroupList().add(item); + } + } + return dataList; + } + + // 添加旧版体检订单 + public boolean addOldPEISOrder(String outTradeNo, String payMoney, String openid, String patientId, String treatNum, String rxId) { + Recipe recipe = new Recipe(); + recipe.setOpenid(openid); + recipe.setPatientId(patientId); + recipe.setTreatNum(treatNum); + recipe.setOutTradeNo(outTradeNo); + recipe.setPayWay("1"); + recipe.setPayMoney(new BigDecimal(payMoney)); + recipe.setTotalFee(new BigDecimal(payMoney)); + recipe.setRecipeId(rxId); + recipe.setHisStatus(-1); + recipe.setPayStatus(-1); + return new RecipeDao().insert(recipe); + } + + // 查询唯一订单-不支持查询多张发票的处方 + public Order queryRxByOrderNo(String outTradeNo, String tradeNo) { + if (!ObjectUtils.isEmpty(outTradeNo)) { + return new RecipeDao().selectOneByOutTradeNo(outTradeNo); + } + if (ObjectUtils.isEmpty(tradeNo)) { + return null; + } + return new RecipeDao().selectByTradeNo(tradeNo); + } + + // 查询处方订单集 + public List queryRxListByOrderNo(String outTradeNo) { + if (ObjectUtils.isEmpty(outTradeNo)) { + return new ArrayList<>(); + } + return new RecipeDao().selectListByOutTradeNo(outTradeNo); + } + + // 查询订单openid + public String queryOpenIdByOutTradeNo(String outTradeNo) { + List rxList = queryRxListByOrderNo(outTradeNo); + if (rxList.isEmpty()) { + return null; + } + Recipe order = rxList.get(0); + return order.getOpenid(); + } +} diff --git a/src/main/java/com/ynxbd/common/service/cache/PayCache.java b/src/main/java/com/ynxbd/common/service/cache/PayCache.java index 68057dd..a6c957c 100644 --- a/src/main/java/com/ynxbd/common/service/cache/PayCache.java +++ b/src/main/java/com/ynxbd/common/service/cache/PayCache.java @@ -7,7 +7,7 @@ import com.ynxbd.common.config.EhCacheConfig; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.timer.TimerManager; import com.ynxbd.common.service.PayService; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.ehcache.Cache; @@ -76,7 +76,7 @@ public class PayCache { RECIPE_ORDER_CACHE.clear(); } - RecipeService recipeService = new RecipeService(); + RxService rxService = new RxService(); Recipe errorRecipe; String outTradeNo, tradeNo; Recipe resp; @@ -113,7 +113,7 @@ public class PayCache { } log.info("[处方][定时器]HIS请求开始 outTradeNo={}, tradeNo={}", outTradeNo, tradeNo); - resp = recipeService.recipeSinglePay(errorRecipe, + resp = rxService.recipeSinglePay(errorRecipe, DateHelper.getCurDate(), DateHelper.getCurTime(), merchantEnum); if (resp.isSuccess()) { diff --git a/src/main/java/com/ynxbd/jy/bean/JYResult.java b/src/main/java/com/ynxbd/jy/bean/JYResult.java index b36abe4..ccecf48 100644 --- a/src/main/java/com/ynxbd/jy/bean/JYResult.java +++ b/src/main/java/com/ynxbd/jy/bean/JYResult.java @@ -39,7 +39,7 @@ public class JYResult { return null; } - public JSONObject toWxPrepay() { + public JSONObject toWxPrepayJson() { if (this.data == null) { return null; } diff --git a/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java b/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java index 67d7309..15e62a4 100644 --- a/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java +++ b/src/main/java/com/ynxbd/jy/helper/JYPayHelper.java @@ -3,10 +3,8 @@ package com.ynxbd.jy.helper; import com.alibaba.fastjson.JSONObject; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.ReqOrder; -import com.ynxbd.common.helper.common.Base64Helper; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.helper.common.URLHelper; import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.common.helper.rsa.RSAHelper; import com.ynxbd.jy.bean.JYOrder; @@ -132,7 +130,7 @@ public class JYPayHelper { log.error("【京硕】预下单-失败:{}", result.getMessage()); return null; } - return result.toWxPrepay(); + return result.toWxPrepayJson(); } catch (Exception e) { log.error("【京硕】预下单-异常:", e); } diff --git a/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java b/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java index c68b4e6..5e243db 100644 --- a/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java @@ -4,7 +4,7 @@ import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.helper.common.HttpHelper; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ServiceException; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; import com.ynxbd.wx.wxfactory.utils.WxRespHelper; @@ -51,7 +51,7 @@ public class PayNotifyServlet extends HttpServlet { String payTime = notifyInfo.getPayTime(); // 和HIS交互 - new RecipeService().recipeListPay(MerchantEnum.WX, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); + new RxService().recipeListPay(MerchantEnum.WX, totalFee.toString(), openid, outTradeNo, bankTransNo, null, payDate, payTime, payInfo); } catch (ServiceException e) { Result.respXml(response, WxRespHelper.resp(e)); // 收到请求-解析成功 diff --git a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java b/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java index 9599d84..4840e8a 100644 --- a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java @@ -2,10 +2,9 @@ package com.ynxbd.wx.servlet.oldpay; import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.dao.RecipeDao; -import com.ynxbd.common.helper.common.CodeHelper; import com.ynxbd.common.helper.common.HttpHelper; import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.service.RecipeService; +import com.ynxbd.common.service.RxService; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxNativePayResult; @@ -130,7 +129,7 @@ public class QRPayServlet extends HttpServlet { HttpHelper.outRespAlert(response, "已缴费成功,无需支付!"); return; } - boolean isOk = new RecipeService().addOldPEISOrder(outTradeNo, payMoney, openid, patientId, treatNum, recipeId); + boolean isOk = new RxService().addOldPEISOrder(outTradeNo, payMoney, openid, patientId, treatNum, recipeId); if (!isOk) { log.info("[Native]扫码支付 存储数据失败 product_id={}", productId); }