From 3b61627b617d3e200cb99a07fe93e60f10ddbd98 Mon Sep 17 00:00:00 2001 From: wangsq Date: Wed, 17 Dec 2025 16:43:58 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=8C=BB=E5=85=B1=E4=BD=93=E8=AE=A4?= =?UTF-8?q?=E8=AF=81=E8=B0=83=E6=95=B4=202=E3=80=81=E4=BD=93=E6=A3=80?= =?UTF-8?q?=E9=A2=84=E7=BA=A6=E6=8E=A5=E5=8F=A3=E9=80=BB=E8=BE=91=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E9=97=AE=E9=A2=98=EF=BC=8C=E9=87=8D=E6=96=B0=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=EF=BC=8C=E6=8E=A5=E5=8F=A3=E8=AF=B7=E6=B1=82=E5=B0=81?= =?UTF-8?q?=E8=A3=85=E3=80=82=203=E3=80=81=E4=BD=93=E6=A3=80=E9=A2=84?= =?UTF-8?q?=E7=BA=A6=E6=8E=A5=E5=8F=A3=E6=96=B0=E5=A2=9E=E9=99=90=E5=88=B6?= =?UTF-8?q?=EF=BC=8C=E5=A6=82=E6=9E=9C=E6=B2=A1=E6=9C=89=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E9=93=BE=E6=8E=A5=E6=97=B6=EF=BC=8C=E7=A6=81?= =?UTF-8?q?=E6=AD=A2=E4=B8=8B=E5=8D=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/ynxbd/common/TestA.java | 56 +++- .../com/ynxbd/common/action/RecipeAction.java | 16 +- .../com/ynxbd/common/action/XBDAction.java | 4 +- .../ynxbd/common/action/pay/NotifyAction.java | 2 +- .../com/ynxbd/common/action/pay/PEnum.java | 17 +- .../ynxbd/common/action/pay/PayAction.java | 156 +++++----- .../ynxbd/common/action/pay/WxAuthAction.java | 4 +- .../ynxbd/common/action/pay/WxPayAction.java | 2 +- .../ynxbd/common/action/test/TestAction.java | 15 + .../common/action/weihu/DataWHAction.java | 25 ++ .../java/com/ynxbd/common/bean/pay/Order.java | 13 +- .../ynxbd/common/bean/pay/PEISOrderInfo.java | 47 +++ .../ynxbd/common/bean/pay/PEISReserve.java | 25 ++ .../ynxbd/common/dao/his/HisRegisterDao.java | 4 +- .../com/ynxbd/common/dao/peis/PEISDao.java | 114 +++++++ .../com/ynxbd/common/dao/peis/PeisDao.java | 116 ------- .../common/helper/common/HttpHelper.java | 16 +- .../common/helper/http/OkHttpHelper.java | 74 +++-- .../ynxbd/common/helper/xbd/XBDHelper.java | 1 + .../com/ynxbd/common/result/JsonResult.java | 24 ++ .../ynxbd/common/result/JsonResultEnum.java | 4 +- .../com/ynxbd/common/service/PEISService.java | 282 ++++++++++++++++++ .../com/ynxbd/common/service/PayService.java | 14 +- .../com/ynxbd/common/service/PeisService.java | 221 -------------- .../ynxbd/common/service/RecipeService.java | 2 +- .../com/ynxbd/common/service/RegService.java | 2 +- .../java/com/ynxbd/common/service/Test.java | 15 - .../wx/servlet/test/RefundTestServlet.java | 33 -- .../wx/servlet/test/WxIsAuthServlet.java | 27 -- .../com/ynxbd/wx/wxfactory/WxAuthHelper.java | 106 ++++--- .../com/ynxbd/wx/wxfactory/WxCacheHelper.java | 40 ++- 31 files changed, 901 insertions(+), 576 deletions(-) create mode 100644 src/main/java/com/ynxbd/common/action/weihu/DataWHAction.java create mode 100644 src/main/java/com/ynxbd/common/bean/pay/PEISOrderInfo.java create mode 100644 src/main/java/com/ynxbd/common/bean/pay/PEISReserve.java create mode 100644 src/main/java/com/ynxbd/common/dao/peis/PEISDao.java delete mode 100644 src/main/java/com/ynxbd/common/dao/peis/PeisDao.java create mode 100644 src/main/java/com/ynxbd/common/service/PEISService.java delete mode 100644 src/main/java/com/ynxbd/common/service/PeisService.java delete mode 100644 src/main/java/com/ynxbd/common/service/Test.java delete mode 100644 src/main/java/com/ynxbd/wx/servlet/test/RefundTestServlet.java diff --git a/src/main/java/com/ynxbd/common/TestA.java b/src/main/java/com/ynxbd/common/TestA.java index db75e77..599f4a0 100644 --- a/src/main/java/com/ynxbd/common/TestA.java +++ b/src/main/java/com/ynxbd/common/TestA.java @@ -1,13 +1,61 @@ package com.ynxbd.common; +import com.alibaba.fastjson.JSONObject; +import com.ynxbd.common.bean.pay.PEISOrderInfo; +import com.ynxbd.common.helper.common.Base64Helper; +import com.ynxbd.common.helper.common.JsonHelper; +import com.ynxbd.common.helper.http.OkHttpHelper; +import com.ynxbd.common.result.JsonResult; +import com.ynxbd.common.result.Result; +import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.utils.DesEncryptHelper; +import lombok.extern.slf4j.Slf4j; +import okhttp3.FormBody; +import okhttp3.RequestBody; +import org.apache.commons.lang3.ObjectUtils; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + + +@Slf4j public class TestA { + public static void main(String[] args) throws UnsupportedEncodingException { + +// String a = ""; +// String s = DesEncryptHelper.deCode(a); +// System.out.println(s); + +// RequestBody requestBody = new FormBody.Builder() +// .add("token", "") +// .add("state", "aHR0cCUzQSUyRiUyRnNseGxmd3N5LnNseHJteXkuY24lMkZ3eCUyRndlYiUyRnJlZy1yZXNlcnZlLmh0bWwlMjMlMkY=") +// .add("isUserInfo", "false") +// .add("enuId", "false") +// .add("protocolState", "0") +// .build(); +// log.info("[认证请求转发] resp:[{}]", requestBody); +// log.info("[认证请求转发] resp:[{}]", JsonHelper.toJsonString(requestBody)); + + +// String data = OkHttpHelper.postFormStr("http://slxlfwsy.slxrmyy.cn/wx/wx_auth/is_auth", map -> { +// map.put("token", null); +// map.put("state", "aHR0cCUzQSUyRiUyRnNseGxmd3N5LnNseHJteXkuY24lMkZ3eCUyRndlYiUyRnJlZy1yZXNlcnZlLmh0bWwlMjMlMkY="); +// map.put("isUserInfo", false); +// map.put("enuId", false); +// map.put("protocolState", 0); +// }, null); + +// String data = OkHttpHelper.post("http://www.slxrmyy.cn/wx/wx_auth/is_auth", requestBody); +// JSONObject jsonObject = JsonHelper.parseObject(data); +// System.out.println(JsonHelper.toJsonString(jsonObject)); + +// +// String state = "aHR0cCUzQSUyRiUyRnNseGxmd3N5LnNseHJteXkuY24lMkZ3eCUyRndlYiUyRnJlZy1yZXNlcnZlLmh0bWwlMjMlMkY="; +// String decode = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); +// System.out.println(decode); - public static void main(String[] args) { - String a = ""; - String s = DesEncryptHelper.deCode(a); - System.out.println(s); } + + } diff --git a/src/main/java/com/ynxbd/common/action/RecipeAction.java b/src/main/java/com/ynxbd/common/action/RecipeAction.java index 0d71d07..4ac863e 100644 --- a/src/main/java/com/ynxbd/common/action/RecipeAction.java +++ b/src/main/java/com/ynxbd/common/action/RecipeAction.java @@ -5,12 +5,12 @@ import com.ynxbd.common.bean.HisRecipe; import com.ynxbd.common.bean.NatRecord; import com.ynxbd.common.bean.Patient; import com.ynxbd.common.bean.enums.MerchantEnum; -import com.ynxbd.common.bean.pay.Recipe; +import com.ynxbd.common.bean.pay.PEISReserve; import com.ynxbd.common.config.interceptor.AesDecode; import com.ynxbd.common.dao.NatRecordDao; import com.ynxbd.common.dao.PatientDao; import com.ynxbd.common.dao.his.HisRecipeDao; -import com.ynxbd.common.dao.peis.PeisDao; +import com.ynxbd.common.dao.peis.PEISDao; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.his.HisEnum; import com.ynxbd.common.helper.his.HisHelper; @@ -201,12 +201,12 @@ public class RecipeAction extends BaseAction { if ("".equals(treatNum) || "".equals(outTranNo)) { return Result.error(ResultEnum.PARAM_IS_DEFECT); } - Recipe recipe = new PeisDao().selectByOutTradeNo(outTranNo); - if (recipe == null) { + PEISReserve peisReserve = new PEISDao().selectByOutTradeNo(outTranNo); + if (peisReserve == null) { return Result.error(ResultEnum.DATA_NOT_FOUND); } - if (!recipe.getBankTransNo().equals(bankTransNo)) { - log.info("[体检预约请求his计费]体检系统跟微信支付系统两笔订单不一致,体检系统:bankTransNo-{},微信系统:bankTransNo-{}", bankTransNo, recipe.getBankTransNo()); + if (!peisReserve.getBankTransNo().equals(bankTransNo)) { + log.info("[体检预约请求his计费]体检系统跟微信支付系统两笔订单不一致,体检系统:bankTransNo-{},微信系统:bankTransNo-{}", bankTransNo, peisReserve.getBankTransNo()); return Result.error(ResultEnum.DATA_IS_WRONG); } Map params = new HashMap<>(); @@ -217,11 +217,11 @@ public class RecipeAction extends BaseAction { params.put("PayMoney", payMoney); params.put("PayDate", payDate); params.put("PayTime", payTime); - params.put("TransNo", recipe.getTradeNo()); + params.put("TransNo", peisReserve.getTradeNo()); params.put("PayDeviceID", "app"); params.put("PayWay", MerchantEnum.WX.HIS_PAY_WAY); params.put("BankTransNo", bankTransNo); // 商户订单号 - params.put("OpenId", recipe.getOpenid()); + params.put("OpenId", peisReserve.getOpenid()); params.put("Token", WeChatConfig.TOKEN); JsonResult result = HisHelper.getJsonResult(HisEnum.AP_Pay_Invoice, params); return result.success() ? Result.success(result) : Result.error(result.getMessage()); diff --git a/src/main/java/com/ynxbd/common/action/XBDAction.java b/src/main/java/com/ynxbd/common/action/XBDAction.java index cc88174..1294e15 100644 --- a/src/main/java/com/ynxbd/common/action/XBDAction.java +++ b/src/main/java/com/ynxbd/common/action/XBDAction.java @@ -17,7 +17,7 @@ import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.CasebookService; -import com.ynxbd.common.service.PeisService; +import com.ynxbd.common.service.PEISService; import com.ynxbd.common.service.XBDService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -293,7 +293,7 @@ public class XBDAction extends BaseAction { return Result.error(ResultEnum.PARAM_IS_INVALID); } try { - JSONArray dataList = new PeisService().getPeisByCardNo(encode, begDate, endDate); + JSONArray dataList = new PEISService().queryPEISRecordByCardNo(encode, begDate, endDate); for (int i = 0; i < dataList.size(); i++) { JSONObject dataItem = dataList.getJSONObject(i); String eid = dataItem.getString("eid"); diff --git a/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java b/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java index b14e663..2b6faf4 100644 --- a/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java @@ -32,7 +32,7 @@ public class NotifyAction extends BaseAction { WxPayNotify notifyInfo = WxPayHelper.payNotify(request); Result.respXml(WxRespHelper.respOk()); // 收到请求-解析成功 - PayService.WxNotify(notifyInfo); + PayService.wxNotify(notifyInfo); } catch (ServiceException e) { Result.respXml(WxRespHelper.resp(e)); // 收到请求-解析失败 } diff --git a/src/main/java/com/ynxbd/common/action/pay/PEnum.java b/src/main/java/com/ynxbd/common/action/pay/PEnum.java index 96ff980..35186ee 100644 --- a/src/main/java/com/ynxbd/common/action/pay/PEnum.java +++ b/src/main/java/com/ynxbd/common/action/pay/PEnum.java @@ -22,8 +22,7 @@ public enum PEnum { TPP_QR_REG("第三方-扫码挂号", "tpp_qr_reg", "G"), - PEIS_RESERVE("体检预约", "peis_reserve", "P"), - + PEIS_RESERVE("体检预约", "peis_reserve", "PR"), ; public final String NAME; @@ -49,6 +48,20 @@ public enum PEnum { return transNo + this.ORDER_CODE; } + public static String getTradeNo(String prefix, PEnum pEnum) { + if (pEnum == null) { + return null; + } + int len = pEnum.ORDER_CODE.length(); + if (len == 1) { + return prefix + pEnum.ORDER_CODE.toUpperCase() + "001"; + } + if (len == 2) { + return prefix + pEnum.ORDER_CODE.toUpperCase() + "01"; + } + return prefix + pEnum.ORDER_CODE.toUpperCase(); + } + /** * 根据订单号获取类型 * 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 24e16e9..9d2f81d 100644 --- a/src/main/java/com/ynxbd/common/action/pay/PayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/PayAction.java @@ -9,10 +9,10 @@ import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.bean.pay.*; import com.ynxbd.common.dao.SelfHelpDao; import com.ynxbd.common.dao.his.HisRecipeDao; -import com.ynxbd.common.dao.peis.PeisDao; import com.ynxbd.common.dao.sys.SysUserDao; import com.ynxbd.common.helper.common.*; import com.ynxbd.common.helper.his.HisHelper; +import com.ynxbd.common.helper.xbd.XBDHelper; import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; @@ -57,7 +57,7 @@ public class PayAction extends BaseAction { String ip = HttpHelper.getIpAddress(request); - return new RegService().regPlaceOrder(payCode, ip, isOccupySource, isZeroPay, reg, isHttpsWithProxy()); + return new RegService().createRegOrder(payCode, ip, isOccupySource, isZeroPay, reg, isHttpsWithProxy()); } catch (ServiceException e) { return Result.error(e); } @@ -130,74 +130,6 @@ public class PayAction extends BaseAction { } - /** - * @param openid openid - * @param patientId 患者id - * @param treatNum 体检号 - * @param totalFee 总金额 - * @param recipeId 处方号 - * @param payCode 支付方式 - */ - @Action("PeisPay") - public Result PeisPay(String openid, String patientId, String treatNum, String totalFee, String recipeId, String payCode) { - if (openid == null || patientId == null || treatNum == null || totalFee == null || recipeId == null) { - return Result.error(ResultEnum.PARAM_IS_DEFECT); - } - if (new BigDecimal(totalFee).compareTo(BigDecimal.ZERO) == 0) { - return Result.error(ResultEnum.PAY_MONEY_IS_ZERO); - } - MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); - if (merchantEnum == null) { // 支付方式异常 - return Result.error(ResultEnum.PAY_TYPE_ERROR); - } - String outTradeNo = CodeHelper.getOutTradeNo(merchantEnum); - PeisService peisService = new PeisService(); - if (!peisService.Reserve(openid, patientId, treatNum, outTradeNo, totalFee, recipeId)) { - log.info("{} [体检预约]体检预约信息保存失败 patientId={},recipeId-{}", merchantEnum.NAME, patientId, recipeId); - return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); - } - - String ip = request.getRemoteAddr(); - String body = "体检预约 患者:" + patientId + "\n体检号:" + treatNum + "\n订单号:" + recipeId; - JSONObject respJson = PayService.createOrder(merchantEnum, openid, patientId, totalFee, outTradeNo, PEnum.PEIS_RESERVE.CODE, ip, body); - // 支付异常 - if (respJson == null) { - return Result.error(ResultEnum.PAY_ERROR); - } - return Result.success(respJson); - } - - - /** - * 体检退费 - * - * @param recipeId 订单号 - * @param payCode 支付方式 - * @param totalFee 订单金额 - * @param outTradeNo outTradeNo - * @param openid openid - */ - @Action("peisRefund") - public Result peisRefund(String recipeId, String payCode, String outTradeNo, String totalFee, String openid) { - log.info("[体检预约]取消预约退费,recipeId-{}.payCode-{},outTradeNo-{},totalFee-{},openid-{}", recipeId, payCode, outTradeNo, totalFee, openid); - PeisService peisService = new PeisService(); - MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); - PeisDao peisDao = new PeisDao(); - Recipe recipe = peisDao.selectByOutTradeNo(outTradeNo); - if (new BigDecimal(totalFee).compareTo(recipe.getTotalFee()) != 0) { - return Result.error(ResultEnum.REFUND_MONEY_ERROR); - } - String pushMessage = "已申请退款,原因:患者主动取消退费,订单号:" + outTradeNo + "orderNo:" + recipeId; - Result result = peisService.peisAutoRefund(recipeId, merchantEnum, outTradeNo, new BigDecimal(totalFee), pushMessage, new Date(), openid); - if (result.isOK()) { - peisService.peisRefund(recipeId, "OK", ""); - } else { - peisService.peisRefund(recipeId, "FAIL", result.getMessage()); - } - return result; - } - - /** * [住院]预交金创建订单 * * @@ -920,6 +852,90 @@ public class PayAction extends BaseAction { } + /** + * @param payCode 支付方式 + * @param openid openid + * @param patientId 患者id + * @param treatNum 体检号 + * @param totalFee 总金额 + * @param noticeOrderNo 体检订单号 + */ + @Action("createPEISOrder") + public Result createPEISOrder(String payCode, String openid, String patientId, String treatNum, String totalFee, String noticeOrderNo) { + log.info("[体检预约]下单 payCode={}, openid={}, patientId={}, treatNum={}, totalFee={}, noticeOrderNo={}", payCode, openid, patientId, treatNum, totalFee, noticeOrderNo); + MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); + if (merchantEnum == null) { // 支付方式异常 + return Result.error(ResultEnum.PAY_TYPE_ERROR); + } + + if (ObjectUtils.isEmpty(XBDHelper.XBD_PEIS)) { + return Result.error(ResultEnum.SYSTEM_CONFIG_ERROR); + } + + if (openid == null || patientId == null || treatNum == null || totalFee == null || noticeOrderNo == null) { + return Result.error(ResultEnum.PARAM_IS_DEFECT); + } + if (new BigDecimal(totalFee).compareTo(BigDecimal.ZERO) == 0) { + return Result.error(ResultEnum.PAY_MONEY_IS_ZERO); + } + + String outTradeNo = CodeHelper.getOutTradeNo(merchantEnum); + PEISService peisService = new PEISService(); + + if (peisService.hasPaidByNoticeOrderNo(noticeOrderNo)) { + log.info("[体检预约]订单已支付 noticeOrderNo={}", noticeOrderNo); + return Result.error(ResultEnum.PAY_REPEAT); + } + + if (!peisService.isSavePEISOrder(openid, patientId, treatNum, outTradeNo, totalFee, noticeOrderNo)) { + log.info("{} [体检预约]订单信息保存失败 patientId={}, noticeOrderNo={}", merchantEnum.NAME, patientId, noticeOrderNo); + return Result.error(ResultEnum.SPECIFIED_QUESTIONED_USER_NOT_EXIST); + } + + String ip = request.getRemoteAddr(); + String body = "体检预约 患者:" + patientId + "\n体检号:" + treatNum + "\n订单号:" + noticeOrderNo; + JSONObject respJson = PayService.createOrder(merchantEnum, openid, patientId, totalFee, outTradeNo, PEnum.PEIS_RESERVE.CODE, ip, body); + if (respJson == null) { + return Result.error(ResultEnum.PAY_ERROR); + } + return Result.success(respJson); + } + + + /** + * 取消体检预约 + * + * @param payCode 支付方式 + * @param noticeOrderNo 体检订单号 + * @param totalFee 订单金额 + * @param outTradeNo outTradeNo + * @param openid openid + */ + @Action("cancelPEISRes") + public Result cancelPEISRes(String payCode, String noticeOrderNo, String outTradeNo, BigDecimal totalFee, String openid) { + try { + log.info("[体检预约]取消预约 payCode={}, noticeOrderNo={}, outTradeNo={}, totalFee={}, openid={}", payCode, noticeOrderNo, outTradeNo, totalFee, openid); + MerchantEnum merchantEnum = MerchantEnum.findEnumByCode(payCode); + if (merchantEnum == null) { // 支付方式异常 + return Result.error(ResultEnum.PAY_TYPE_ERROR); + } + if (noticeOrderNo == null || outTradeNo == null || totalFee == null || openid == null) { + return Result.error(ResultEnum.PARAM_IS_DEFECT); + } + PEISService peisService = new PEISService(); + + String refundDesc = "取消预约 体检订单号:" + noticeOrderNo; + Result result = peisService.refundPEIS(merchantEnum, noticeOrderNo, outTradeNo, totalFee, refundDesc, new Date(), openid); + if (result.isOK()) { + peisService.cancelPEISReserve(noticeOrderNo, "OK", ""); + } + return result; + } catch (Exception e) { + return Result.error(e); + } + } + + // /** // * [病历]下单 // */ diff --git a/src/main/java/com/ynxbd/common/action/pay/WxAuthAction.java b/src/main/java/com/ynxbd/common/action/pay/WxAuthAction.java index 557ba48..914439d 100644 --- a/src/main/java/com/ynxbd/common/action/pay/WxAuthAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/WxAuthAction.java @@ -15,7 +15,7 @@ public class WxAuthAction extends BaseAction { @Action("is_auth") public Result is_auth() throws Exception { - return WxAuthHelper.isAuth(request, false); + return WxAuthHelper.isAuth(request, response, false); } @Action("u_auth") @@ -34,7 +34,7 @@ public class WxAuthAction extends BaseAction { @Action("is_pay_auth") public Result is_pay_auth() throws Exception { // 支付使用普通授权 - return WxAuthHelper.isAuth(request, true); + return WxAuthHelper.isAuth(request, response, true); } // @Action("pay_b_auth") diff --git a/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java b/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java index b40c58f..472ac36 100644 --- a/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java @@ -30,7 +30,7 @@ public class WxPayAction extends BaseAction { WxPayNotify notifyInfo = WxPayHelper.payNotify(request); Result.respXml(WxRespHelper.respOk()); // 收到请求-解析成功 - PayService.WxNotify(notifyInfo); + PayService.wxNotify(notifyInfo); } catch (ServiceException e) { Result.respXml(WxRespHelper.resp(e)); // 收到请求-解析失败 } diff --git a/src/main/java/com/ynxbd/common/action/test/TestAction.java b/src/main/java/com/ynxbd/common/action/test/TestAction.java index 9f384e8..c965d09 100644 --- a/src/main/java/com/ynxbd/common/action/test/TestAction.java +++ b/src/main/java/com/ynxbd/common/action/test/TestAction.java @@ -5,11 +5,15 @@ import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; +import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import lombok.extern.slf4j.Slf4j; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; import java.util.Date; /** @@ -22,6 +26,17 @@ import java.util.Date; @Namespace("/test02") public class TestAction extends BaseAction { + private static int i = 0; + + @Action("refund_test") + public Result refund_test() throws ServiceException { + if (i == 0) { + i++; +// WxPayHelper.refund("", "", new BigDecimal("0.900"), new BigDecimal("0.900"), "手动退费"); + } + return Result.success(); + } + // @Action("a") // public String a() { diff --git a/src/main/java/com/ynxbd/common/action/weihu/DataWHAction.java b/src/main/java/com/ynxbd/common/action/weihu/DataWHAction.java new file mode 100644 index 0000000..7cc1a01 --- /dev/null +++ b/src/main/java/com/ynxbd/common/action/weihu/DataWHAction.java @@ -0,0 +1,25 @@ +package com.ynxbd.common.action.weihu; + +import com.ynxbd.common.bean.pay.Order; +import com.ynxbd.common.dao.RecipeDao; +import com.ynxbd.common.result.Result; +import lombok.extern.slf4j.Slf4j; +import org.apache.struts2.convention.annotation.Action; +import org.apache.struts2.convention.annotation.Namespace; + +import java.util.List; + + +@Slf4j +@Namespace("/data_wh") +public class DataWHAction { + + + @Action("getData") + public Result getData(String callNo) { + String begTime = "2025-10-27"; + String endTime = "2025-12-08"; + return Result.success(); + } + +} diff --git a/src/main/java/com/ynxbd/common/bean/pay/Order.java b/src/main/java/com/ynxbd/common/bean/pay/Order.java index a97d58c..3a92439 100644 --- a/src/main/java/com/ynxbd/common/bean/pay/Order.java +++ b/src/main/java/com/ynxbd/common/bean/pay/Order.java @@ -71,6 +71,8 @@ public class Order implements Serializable { private BigDecimal payMoney; // 订单总金额 private BigDecimal totalFee; + // 记录支付完成状态的时间 + private Date payStatusTime; // 商户支付状态 private Integer payStatus; // HIS通知状态 @@ -136,16 +138,15 @@ public class Order implements Serializable { // 缴费订单类型 private String orderType; - // PEIS通知状态 - private Integer peisStatus; - - // PEIS返回提示 - private String peisResult; - // 第三方回调状态(-1:未调用,0:调用成功,500:调用超时,其他:调用失败) private Integer noticeStatus; // 第三方返回结果 private String noticeResult; + // 第三方订单号 + private String noticeOrderNo; + // 第三方交易流水号 + private String noticeTransNo; + // 订单额外信息 private Object orderObj; diff --git a/src/main/java/com/ynxbd/common/bean/pay/PEISOrderInfo.java b/src/main/java/com/ynxbd/common/bean/pay/PEISOrderInfo.java new file mode 100644 index 0000000..fafa896 --- /dev/null +++ b/src/main/java/com/ynxbd/common/bean/pay/PEISOrderInfo.java @@ -0,0 +1,47 @@ +package com.ynxbd.common.bean.pay; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Setter +@Getter +@ToString +@NoArgsConstructor +public class PEISOrderInfo implements Serializable { + private static final long serialVersionUID = 20251217160400001L; + + private Long id; + + private Long eid; + + private String createTime; + // 交易时间 + private String payTime; + + private String payStatus; + + // 订单金额 + private BigDecimal fee; + // 体检订单号 + private String orderNo; + // 是否删除-标识体检的订单是否已退费(true:删除;false:未删除) + private Boolean isDeleted; + // 微信是否支付(true:已支付,false:未支付) + private Boolean isWxPay; + // HIS是否记账(true:已记账,false:未记账) + private Boolean isCost; + // 退费状态 + private String refundStatus; + // 退费时间 + private String refundTime; + + // 是否已退费成功 + public boolean hasRefundOK() { + return "OK".equals(refundStatus); + } +} diff --git a/src/main/java/com/ynxbd/common/bean/pay/PEISReserve.java b/src/main/java/com/ynxbd/common/bean/pay/PEISReserve.java new file mode 100644 index 0000000..e7e87f8 --- /dev/null +++ b/src/main/java/com/ynxbd/common/bean/pay/PEISReserve.java @@ -0,0 +1,25 @@ +package com.ynxbd.common.bean.pay; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + + +/** + * 体检预约 + * + * @Author wsq + * @Date 2020/11/12 10:24 + * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. + */ +@Setter +@Getter +@ToString(callSuper = true) +@NoArgsConstructor +public class PEISReserve extends Order implements Serializable { + private static final long serialVersionUID = 202512171006000001L; + +} \ No newline at end of file diff --git a/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java b/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java index 19135fc..196bccb 100644 --- a/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java +++ b/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java @@ -1010,9 +1010,9 @@ public class HisRegisterDao { } /** - * 分时段挂号--是否占号 + * 分时段挂号--是否占号(不能作为查询号源是否占用的单独接口,容易被攻击) * - * @param patientId 患者id + * @param patientId 用于占号的患者id * @param sourceId 号源id * @return true:是; false:否 */ diff --git a/src/main/java/com/ynxbd/common/dao/peis/PEISDao.java b/src/main/java/com/ynxbd/common/dao/peis/PEISDao.java new file mode 100644 index 0000000..cfae6ee --- /dev/null +++ b/src/main/java/com/ynxbd/common/dao/peis/PEISDao.java @@ -0,0 +1,114 @@ +package com.ynxbd.common.dao.peis; + +import com.ynxbd.common.bean.pay.PEISReserve; +import com.ynxbd.common.config.db.DataBase; + +import java.util.List; + + +/** + * @author 李进才 + * @ClassName PeisDao + * @Description TODO + * @date 2023/11/16 15:43:00 + */ +public class PEISDao { + /** + * 处方支付,数据预存(单个) + * + * @param info 支付信息 + * @return 是否存储成功 + */ + public boolean insert(PEISReserve info) { + String sql = "insert into peis_reserve(updateTime, noticeStatus, payStatus, openId, patientId, payMoney, totalFee, outTradeNo, noticeOrderNo, treatNum) values (now(),?,?,?,?,?,?,?,?,?)"; + return DataBase.insert(sql, ps -> { + ps.setInt(1, info.getPayStatus()); + ps.setInt(2, info.getNoticeStatus()); + ps.setString(3, info.getOpenid()); + ps.setString(4, info.getPatientId()); + ps.setBigDecimal(5, info.getTotalFee()); + ps.setBigDecimal(6, info.getPayMoney()); + // + ps.setString(7, info.getOutTradeNo()); + ps.setString(8, info.getNoticeOrderNo()); + ps.setString(9, info.getTreatNum()); + }) > 0; + } + + /** + * 判断体检订单是否已缴费 + * + * @param noticeOrderNo 体检订单号 + */ + public boolean hasPaidByNoticeOrderNo(String noticeOrderNo) { + String sql = "select * from peis_reserve where noticeOrderNo=? and payStatus=0"; + return !DataBase.select(sql, PEISReserve.class, ps -> { + ps.setString(1, noticeOrderNo); + }).isEmpty(); + } + + public PEISReserve selectByOutTradeNo(String outTradeNo) { + String sql = "select * from peis_reserve where outTradeNo=?"; + List list = DataBase.select(sql, PEISReserve.class, ps -> { + ps.setString(1, outTradeNo); + }); + if (!list.isEmpty()) { + return list.get(0); + } + return null; + } + + public PEISReserve selectByNoticeOrderNo(String noticeOrderNo) { + String sql = "select * from peis_reserve where noticeOrderNo=? and noticeStatus = 0 and payStatus=0"; + List list = DataBase.select(sql, PEISReserve.class, ps -> { + ps.setString(1, noticeOrderNo); + }); + if (!list.isEmpty()) { + return list.get(0); + } + return null; + } + + /** + * 修改退款状态 + * + * @param outTradeNo 订单号 + * @param noticeOrderNo 体检订单号 + * @param refundResult 退款描述 + * @return 是否成功 + */ + public boolean updateRefundResult(String outTradeNo, String noticeOrderNo, String refundResult, Integer refundStatus) { + String sql = "update peis_reserve set refundTime=now(), refundResult=?, refundStatus=? where outTradeNo=? and noticeOrderNo=?"; + return DataBase.update(sql, ps -> { + ps.setString(1, refundResult); + ps.setInt(2, refundStatus); + ps.setString(3, outTradeNo); + ps.setString(4, noticeOrderNo); + }) > 0; + } + + /** + * 修改支付状态 + * + * @param outTradeNo + * @param bankTransNo + * @param tradeNo + * @return + */ + public boolean updateMerPaidByOutTradeNo(String outTradeNo, String bankTransNo, String tradeNo) { + String sql = "update peis_reserve set payStatusTime=now(), payStatus=0, bankTransNo=?, tradeNo=? where outTradeNo=? and bankTransNo is null"; + return DataBase.update(sql, ps -> { + ps.setString(1, bankTransNo); + ps.setString(2, tradeNo); + ps.setString(3, outTradeNo); + }) > 0; + } + + public boolean updateNoticeStatusOK(String outTradeNo, String bankTransNo) { + String sql = "update peis_reserve set noticeStatus=0, bankTransNo=? where outTradeNo=?"; + return DataBase.update(sql, ps -> { + ps.setString(1, bankTransNo); + ps.setString(2, outTradeNo); + }) > 0; + } +} diff --git a/src/main/java/com/ynxbd/common/dao/peis/PeisDao.java b/src/main/java/com/ynxbd/common/dao/peis/PeisDao.java deleted file mode 100644 index 0115737..0000000 --- a/src/main/java/com/ynxbd/common/dao/peis/PeisDao.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.ynxbd.common.dao.peis; - -import com.ynxbd.common.bean.pay.PayCasebook; -import com.ynxbd.common.bean.pay.Recipe; -import com.ynxbd.common.bean.record.Record; -import com.ynxbd.common.config.db.DataBase; - -import java.util.List; - - -/** - * @author 李进才 - * @ClassName PeisDao - * @Description TODO - * @date 2023/11/16 15:43:00 - */ -public class PeisDao { - /** - * 处方支付,数据预存(单个) - * - * @param recipe 支付信息 - * @return 是否存储成功 - */ - public boolean insert(Recipe recipe) { - String sql = "insert into peis_reserve(updateTime, peisStatus, payStatus, openId, patientId, payMoney, totalFee, outTradeNo, recipeId, treatNum) values (now(),?,?,?,?,?,?,?,?,?)"; - return DataBase.insert(sql, ps -> { - ps.setInt(1, recipe.getPeisStatus()); - ps.setInt(2, recipe.getPayStatus()); - ps.setString(3, recipe.getOpenid()); - ps.setString(4, recipe.getPatientId()); - ps.setBigDecimal(5, recipe.getTotalFee()); - ps.setBigDecimal(6,recipe.getPayMoney()); - // - ps.setString(7, recipe.getOutTradeNo()); - ps.setString(8, recipe.getRecipeId()); - ps.setString(9, recipe.getTreatNum()); - - }) > 0; - } - - /** - * 判断该处方是否重复计费 - * @param recipeId 处方号 - * @return - */ - public boolean isRepeat(String recipeId){ - String sql = "select * from peis_reserve where recipeId = ? and peisStatus = 0"; - return !DataBase.select(sql,Recipe.class,ps->{ - ps.setString(1,recipeId); - }).isEmpty(); - } - - public Recipe selectByOutTradeNo(String outTradeNo) { - String sql = "select * from peis_reserve where outTradeNo=? order by updateTime desc"; - List list = DataBase.select(sql, Recipe.class, ps -> { - ps.setString(1, outTradeNo); - }); - if (list.size() > 0) { - return list.get(0); - } - return null; - } - - public boolean checkRefund(String outTradeNo){ - String sql = "select * from peis_reserve where outTradeNo=? and refundResult = 'OK'"; - return !DataBase.select(sql,Recipe.class,ps->{ - ps.setString(1,outTradeNo); - }).isEmpty(); - } - - public Recipe selectByRecipeId(String recipeId) { - String sql = "select * from peis_reserve where recipeId=? and peisStatus = 0 and payStatus=0 order by updateTime desc"; - List list = DataBase.select(sql, Recipe.class, ps -> { - ps.setString(1, recipeId); - }); - if (list.size() > 0) { - return list.get(0); - } - return null; - } - - /** - * 修改退款描述 - * - * @param outTradeNo 订单号 - * @param recipeId 体检订单号 - * @param refundMsg 退款描述 - * @return 是否成功 - */ - public boolean updateRefundResult(String outTradeNo, String recipeId, String refundMsg) { - // 退款成功 - String sql = "update peis_reserve set refundResult=?, refundTime=now() where recipeId=? and outTradeNo=?"; - return DataBase.update(sql, ps -> { - ps.setString(1, refundMsg); - ps.setString(2, recipeId); - ps.setString(3, outTradeNo); - }) > 0; - } - - public boolean updatePayStateOk(String outTradeNo, String bankTransNo,String tradeNo) { - String sql = "update peis_reserve set payStatus=0, bankTransNo=?, TradeNo=? where outTradeNo=? and bankTransNo is null"; - return DataBase.update(sql, ps -> { - ps.setString(1, bankTransNo); - ps.setString(2, tradeNo); - ps.setString(3, outTradeNo); - }) > 0; - } - - public boolean updatePeisStateOk(String outTradeNo, String bankTransNo) { - String sql = "update peis_reserve set peisStatus=0, bankTransNo=? where outTradeNo=?"; - return DataBase.update(sql, ps -> { - ps.setString(1, bankTransNo); - ps.setString(2, outTradeNo); - }) > 0; - } -} diff --git a/src/main/java/com/ynxbd/common/helper/common/HttpHelper.java b/src/main/java/com/ynxbd/common/helper/common/HttpHelper.java index 303ef4d..1c63f47 100644 --- a/src/main/java/com/ynxbd/common/helper/common/HttpHelper.java +++ b/src/main/java/com/ynxbd/common/helper/common/HttpHelper.java @@ -3,6 +3,7 @@ package com.ynxbd.common.helper.common; import org.apache.commons.lang3.StringUtils; import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; @@ -267,7 +268,6 @@ public class HttpHelper { } - /** * 访问目标地址并获取返回值 * @@ -337,6 +337,20 @@ public class HttpHelper { } } + public static String getSessionIdByCookie(HttpServletRequest request) { + String sessionId = null; + Cookie[] cookies = request.getCookies(); + if (cookies != null) { + for (Cookie cookie : cookies) { + if ("JSESSIONID".equals(cookie.getName())) { // Tomcat默认Session Cookie名 + sessionId = cookie.getValue(); + break; + } + } + } + return sessionId; + } + // /** // * 响应success字符串 // * diff --git a/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java b/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java index 1881a1c..acf16ca 100644 --- a/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java +++ b/src/main/java/com/ynxbd/common/helper/http/OkHttpHelper.java @@ -10,6 +10,7 @@ import com.ynxbd.wx.utils.DesEncryptHelper; import com.ynxbd.wx.wxfactory.utils.XmlHelper; import lombok.extern.slf4j.Slf4j; import okhttp3.*; +import org.apache.commons.lang3.ObjectUtils; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; @@ -79,6 +80,9 @@ public class OkHttpHelper { return String.format("%s:%d", host, port); } + public static JsonResult get(String url, MapParams mapParams, JsonResultEnum jsonResultEnum) { + return JsonResult.jsonToBean(get(url, mapParams), jsonResultEnum); + } public static String get(String url, MapParams mapParams) { OkHttpClient client = getOkHttpClient(url); @@ -89,8 +93,11 @@ public class OkHttpHelper { if (mapParams != null) { mapParams.setParams(requestParams); } - try (Response response = client.newCall(new Request.Builder().get() - .url(mackParamsUrl(url, requestParams)).build()).execute()) { + url = mackParamsUrl(url, requestParams); + if (url == null) { + return null; + } + try (Response response = client.newCall(new Request.Builder().get().url(url).build()).execute()) { if (!response.isSuccessful()) { return null; } @@ -117,8 +124,12 @@ public class OkHttpHelper { if (mapParams != null) { mapParams.setParams(requestParams); } + url = mackParamsUrl(url, requestParams); + if (url == null) { + return; + } - client.newCall(new Request.Builder().get().url(mackParamsUrl(url, requestParams)).build()).enqueue(new Callback() { + client.newCall(new Request.Builder().get().url(url).build()).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { log.error(e.getMessage()); @@ -141,7 +152,34 @@ public class OkHttpHelper { }); } - +// public static String postCookie(String url, RequestBody requestBody, Header header) { +// OkHttpClient client = getOkHttpClient(url); +// if (client == null) { +// return null; +// } + + /// / client.cookieJar(new PersistentCookieJar()); +// Headers.Builder headersBuilder = new Headers.Builder(); +// if (header != null) { +// header.setHeaders(headersBuilder); +// } +// try (Response response = client.newCall(new Request.Builder().url(url).post(requestBody).headers(headersBuilder.build()).build()).execute()) { +// if (!response.isSuccessful()) { +// return null; +// } +// try (ResponseBody body = response.body()) { +// if (body == null) { +// return null; +// } +// String respBody = body.string(); +// log.info("接口响应数据resp={}", respBody); +// return respBody; +// } +// } catch (Exception e) { +// ErrorHelper.println(e); +// } +// return null; +// } public static String post(String url, RequestBody requestBody, Header header) { OkHttpClient client = getOkHttpClient(url); if (client == null) { @@ -216,7 +254,7 @@ public class OkHttpHelper { method.setParams(params); } FormBody.Builder builder = new FormBody.Builder(); - if (params.size() > 0) { + if (!params.isEmpty()) { Object value; for (Map.Entry item : params.entrySet()) { value = item.getValue(); @@ -286,11 +324,11 @@ public class OkHttpHelper { * @return 携带参数的链接 / null */ public static String mackParamsUrl(String url, Map params) { - if (url == null || "".equals(url)) { + if (ObjectUtils.isEmpty(url)) { return null; } - if (params == null || params.size() == 0) { + if (params == null || params.isEmpty()) { return url; } @@ -327,25 +365,19 @@ public class OkHttpHelper { * @param request 请求体 */ public static JSONObject readBody(HttpServletRequest request) { - BufferedReader br = null; - try { - br = request.getReader(); - String line; - StringBuilder sb = new StringBuilder(); - while ((line = br.readLine()) != null) { - sb.append(line); - } - return JsonHelper.parseObject(sb.toString()); - } catch (Exception e) { - log.error(e.getMessage()); - } finally { + try (BufferedReader br = request.getReader()) { try { - if (br != null) { - br.close(); + String line; + StringBuilder sb = new StringBuilder(); + while ((line = br.readLine()) != null) { + sb.append(line); } + return JsonHelper.parseObject(sb.toString()); } catch (Exception e) { log.error(e.getMessage()); } + } catch (Exception e) { + log.error(e.getMessage()); } return null; } diff --git a/src/main/java/com/ynxbd/common/helper/xbd/XBDHelper.java b/src/main/java/com/ynxbd/common/helper/xbd/XBDHelper.java index 0bf67ae..4d93cd6 100644 --- a/src/main/java/com/ynxbd/common/helper/xbd/XBDHelper.java +++ b/src/main/java/com/ynxbd/common/helper/xbd/XBDHelper.java @@ -30,4 +30,5 @@ public class XBDHelper { } + } diff --git a/src/main/java/com/ynxbd/common/result/JsonResult.java b/src/main/java/com/ynxbd/common/result/JsonResult.java index 3d01305..52b0eeb 100644 --- a/src/main/java/com/ynxbd/common/result/JsonResult.java +++ b/src/main/java/com/ynxbd/common/result/JsonResult.java @@ -396,6 +396,30 @@ public class JsonResult { return JsonHelper.decodeBean(JsonHelper.toJsonString(this.dataMap), clazz); } + /** + * 获取DataMap为bean + * + * @param clazz 类型 + * @return bean + */ + public T dataMapGetNodeToBean(Class clazz) { + return dataMapGetNodeToBean(clazz, "data"); + } + + /** + * 获取DataMap为bean + * + * @param clazz 类型 + * @return bean + */ + public T dataMapGetNodeToBean(Class clazz, String dataName) { + Object data = this.dataMap.get(dataName); + if (data == null) { + return null; + } + return JsonHelper.decodeBean(data.toString(), clazz); + } + /** * 获取DataMap为bean * diff --git a/src/main/java/com/ynxbd/common/result/JsonResultEnum.java b/src/main/java/com/ynxbd/common/result/JsonResultEnum.java index df0dab7..2d0070b 100644 --- a/src/main/java/com/ynxbd/common/result/JsonResultEnum.java +++ b/src/main/java/com/ynxbd/common/result/JsonResultEnum.java @@ -22,8 +22,10 @@ public enum JsonResultEnum { SYS_RESERVE("[天助预约]","code","msg","0","-1",String.valueOf(HttpStatus.HTTP_CLIENT_TIMEOUT)), - SYS_RM_LIS("[瑞美LIS]", "ResultCode", "ResultMessage", "1", "0", String.valueOf(HttpStatus.HTTP_CLIENT_TIMEOUT)); + SYS_RM_LIS("[瑞美LIS]", "ResultCode", "ResultMessage", "1", "0", String.valueOf(HttpStatus.HTTP_CLIENT_TIMEOUT)), + SYS_PEIS_RESERVE("[体检预约]", "code", "message", "200", "0", String.valueOf(HttpStatus.HTTP_CLIENT_TIMEOUT)) + ; // 调用系统标识 public final String SYS; diff --git a/src/main/java/com/ynxbd/common/service/PEISService.java b/src/main/java/com/ynxbd/common/service/PEISService.java new file mode 100644 index 0000000..1f58e3b --- /dev/null +++ b/src/main/java/com/ynxbd/common/service/PEISService.java @@ -0,0 +1,282 @@ +package com.ynxbd.common.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.ynxbd.common.action.pay.PEnum; +import com.ynxbd.common.bean.enums.MerchantEnum; +import com.ynxbd.common.bean.pay.Order; +import com.ynxbd.common.bean.pay.PEISOrderInfo; +import com.ynxbd.common.bean.pay.PEISReserve; +import com.ynxbd.common.dao.peis.PEISDao; +import com.ynxbd.common.helper.common.JsonHelper; +import com.ynxbd.common.helper.http.OkHttpHelper; +import com.ynxbd.common.helper.xbd.XBDHelper; +import com.ynxbd.common.result.*; +import lombok.extern.slf4j.Slf4j; +import okhttp3.FormBody; +import okhttp3.RequestBody; +import org.apache.commons.lang3.ObjectUtils; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author 王绍全 + * @ClassName PEISService + * @Description TODO + * @date 2025/12/17 15:53:00 + */ + +@Slf4j +public class PEISService { + public JsonResult get(String url, OkHttpHelper.MapParams params) { + return OkHttpHelper.get(url, params, JsonResultEnum.SYS_PEIS_RESERVE); + } + + public JsonResult postJson(String url, OkHttpHelper.MapParams params, OkHttpHelper.Header header) { + return OkHttpHelper.postJson(url, params, header, JsonResultEnum.SYS_PEIS_RESERVE); + } + + public JsonResult postForm(String url, OkHttpHelper.MapParams params, OkHttpHelper.Header header) { + return OkHttpHelper.postForm(url, params, header, JsonResultEnum.SYS_PEIS_RESERVE); + } + + /** + * 判断体检订单是否已缴费 + * + * @param noticeOrderNo 体检订单号 + */ + public boolean hasPaidByNoticeOrderNo(String noticeOrderNo) { + return new PEISDao().hasPaidByNoticeOrderNo(noticeOrderNo); + } + + /** + * 订单信息记录 + * + * @param openid openid + * @param patientId 患者id + * @param treatNum 体检号 + * @param outTradeNo 商户订单号 + * @param totalFee 金额 + * @param noticeOrderNo 体检订单号 + * @return bool + */ + public boolean isSavePEISOrder(String openid, String patientId, String treatNum, String outTradeNo, String totalFee, String noticeOrderNo) { + PEISReserve info = new PEISReserve(); + info.setOpenid(openid); + info.setPatientId(patientId); + info.setTreatNum(treatNum); + info.setOutTradeNo(outTradeNo); + info.setNoticeOrderNo(noticeOrderNo); + info.setTotalFee(new BigDecimal(totalFee)); + info.setPayMoney(new BigDecimal(totalFee)); + info.setPayStatus(-1); + info.setNoticeStatus(-1); + return new PEISDao().insert(info); + } + + public PEISReserve queryByOutTradeNo(String outTradeNo) { + return new PEISDao().selectByOutTradeNo(outTradeNo); + } + + public void payNotify(MerchantEnum merchantEnum, String openid, BigDecimal totalFee, String outTradeNo, String bankTransNo, String payDate, String payTime, String payInfo) { + PEISDao peisDao = new PEISDao(); + PEISReserve order = peisDao.selectByOutTradeNo(outTradeNo); + + if (order.hasPayStatusPaid() && order.hasNoticeStatusPaid()) { + log.info("{} [体检预约]订单已支付,停止向下执行 outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); + return; + } + + String tradeNo = PEnum.getTradeNo(bankTransNo, PEnum.PEIS_RESERVE); + String noticeOrderNo = order.getNoticeOrderNo(); + if (ObjectUtils.isEmpty(noticeOrderNo)) { + log.info("{} [体检预约]存储的体检订单号为空 outTradeNo={}, bankTransNo={}", merchantEnum.NAME, outTradeNo, bankTransNo); + return; + } + // 更新商户支付状态 + if (!peisDao.updateMerPaidByOutTradeNo(outTradeNo, bankTransNo, tradeNo)) { + log.info("{} [体检预约]更新订单失败,停止向下执行 outTradeNo={}, bankTransNo={}, tradeNo={}", merchantEnum.NAME, outTradeNo, bankTransNo, tradeNo); + return; + } + + if (order.hasNoticeStatusPaid()) { + log.info("[体检预约]订单已支付 outTradeNo={}, bankTransNo={}, noticeOrderNo={}", outTradeNo, bankTransNo, noticeOrderNo); + return; + } + + JsonResult jsonResult = postForm(XBDHelper.XBD_PEIS + "/wxUse/wxPay", params -> { + params.put("orderNo", noticeOrderNo); + params.put("payStatus", "OK"); + params.put("payFailReason", ""); + params.put("bankTransNo", bankTransNo); + params.put("outTradeNo", outTradeNo); + }, null); + + log.info("[体检预约]回调接口调用 {}", JsonHelper.toJsonString(jsonResult)); + if (jsonResult.isTimeout()) { // 调用接口超时 + log.info("[体检预约]回调接口调用超时 不进行退费处理"); + return; + } + + if (!jsonResult.success()) { // 通知失败 + String message = jsonResult.getMessage(); + if (message == null) { + message = ""; + } + String refundDesc = "体检订单号:" + noticeOrderNo + " 通知体检系统异常:" + message; + refundPEIS(merchantEnum, noticeOrderNo, outTradeNo, totalFee, refundDesc, new Date(), openid); + return; + } + + if (!peisDao.updateNoticeStatusOK(outTradeNo, bankTransNo)) { + log.info("[体检预约]修改体检系统支付状态失败 outTradeNo={}, bankTransNo={}", outTradeNo, bankTransNo); + } + } + + /** + * 根据体检订单号查询体检接口 + * + * @param noticeOrderNo 体检订单号 + * @return bean + */ + public PEISOrderInfo queryPEISOrderByNoticeOrderNo(String noticeOrderNo) throws ServiceException { + JsonResult jsonResult = get(XBDHelper.XBD_PEIS + "/wxUse/GetOrder", params -> { + params.put("orderNo", noticeOrderNo); + }); + log.info("[体检预约]订单查询 {}", JsonHelper.toJsonString(jsonResult)); + if (!jsonResult.success()) { + String message = jsonResult.getMessage(); + log.info("[体检预约]订单查询失败:{}", message); + throw new ServiceException(message); + } + return jsonResult.dataMapGetNodeToBean(PEISOrderInfo.class); + } + + /** + * 体检退费接口 + * + * @param noticeOrderNo 订单号 + * @param merchantEnum 支付方式 + * @param outTradeNo outTradeNo + * @param totalFee 总金额 + * @param refundDesc 退费描述 + * @param tradeDate 退费时间 + * @param openid openid + */ + public Result refundPEIS(MerchantEnum merchantEnum, String noticeOrderNo, String outTradeNo, BigDecimal totalFee, String refundDesc, Date tradeDate, String openid) { + try { + if (totalFee.compareTo(BigDecimal.ZERO) == 0) { + log.info("{} [体检预约]订单金额为0无需退费 outTradeNo={}, noticeOrderNo={}, totalFee={}", merchantEnum.NAME, outTradeNo, noticeOrderNo, totalFee); + return Result.error("订单金额为0无需退费"); + } + + PEISDao peisDao = new PEISDao(); + PEISReserve dbOrder = peisDao.selectByOutTradeNo(outTradeNo); + if (dbOrder.hasRefundByRefundResult()) { + log.info("{} [体检预约]订单已退费 outTradeNo={}, noticeOrderNo={}, totalFee={}", merchantEnum.NAME, outTradeNo, noticeOrderNo, totalFee); + return Result.error("订单已退费,请勿重复取消"); + } + + PEISOrderInfo findOrder = queryPEISOrderByNoticeOrderNo(noticeOrderNo); + log.info("[体检预约] findOrder={}", JsonHelper.toJsonString(findOrder)); + if (findOrder == null) { + log.info("[体检预约]未查询到订单 noticeOrderNo={}", noticeOrderNo); + return Result.error("[体检预约]未查询到订单"); + } + BigDecimal fee = findOrder.getFee(); + BigDecimal payMoney = dbOrder.getPayMoney(); + if (totalFee.compareTo(payMoney) != 0 || fee.compareTo(payMoney) != 0) { + log.info("{} [体检预约]订单金额不匹配 outTradeNo={}, noticeOrderNo={}, totalFee={}, payMoney={}, fee={}", merchantEnum.NAME, outTradeNo, noticeOrderNo, totalFee, payMoney, fee); + return Result.error(ResultEnum.REFUND_MONEY_ERROR); + } + + Boolean isHisCost = findOrder.getIsCost(); + if (isHisCost != null && isHisCost) { + log.info("{} [体检预约]HIS已计费,禁止退费 outTradeNo={}, noticeOrderNo={}, totalFee={}", merchantEnum.NAME, outTradeNo, noticeOrderNo, totalFee); + return Result.error("退费错误,体检系统his显示已计费,不允许退费"); + } + + String refundResult = "OK"; + Order orderRefund = PayService.refund(merchantEnum, outTradeNo, noticeOrderNo, totalFee, totalFee, refundDesc, tradeDate, openid, null, refundDesc); + if (!orderRefund.isSuccess()) { + refundResult = orderRefund.getRefundResult(); + log.info("{} [体检预约]退费失败 outTradeNo={}, totalFee={}, noticeOrderNo={}, refundResult={}", merchantEnum.NAME, outTradeNo, totalFee, noticeOrderNo, refundResult); + } + + Integer refundStatus = "OK".equals(refundResult) ? 1 : -1; + boolean isUpdate = peisDao.updateRefundResult(outTradeNo, noticeOrderNo, refundResult, refundStatus); + if (!isUpdate) { + log.info("{} [体检预约][退费错误]退费信息更新失败 noticeOrderNo={}", merchantEnum.NAME, noticeOrderNo); + } + if (orderRefund.isSuccess()) { // 退费成功 + return Result.success(); + } + return Result.error(refundResult); + } catch (Exception e) { + return Result.error(e); + } + } + + /** + * 取消预约 + * + * @param noticeOrderNo 体检订单号 + * @param refundStatus 退费状态 + * @param refundFailReason 退费描述 + * @return bool + */ + public boolean cancelPEISReserve(String noticeOrderNo, String refundStatus, String refundFailReason) throws ServiceException { + JsonResult jsonResult = postForm(XBDHelper.XBD_PEIS + "/wxUse/wxRefund", params -> { + params.put("orderNo", noticeOrderNo); + params.put("refundStatus", refundStatus); // 退费状态(成功:OK,失败:FAIL) + params.put("refundFailReason", refundFailReason); + }, null); + log.info("[体检预约]取消预约 {}", JsonHelper.toJsonString(jsonResult)); + if (!jsonResult.success()) { + String message = jsonResult.getMessage(); + log.info("[体检预约]取消预约失败 noticeOrderNo={}, message={}", noticeOrderNo, message); + throw new ServiceException(message); + } + return true; + } + + public JSONArray queryPEISRecordByCardNo(String cardNo, String begDate, String endDate) throws ServiceException { + RequestBody formBody = new FormBody.Builder(). + add("enIdCard", cardNo) + .add("begDate", begDate) + .add("endDate", endDate) + .build(); + String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/WxUse/GetPeisOfPacsResult", formBody); + if (ObjectUtils.isEmpty(result)) { + throw new ServiceException("请求失败"); + } + JSONObject jsonResult = JsonHelper.parseObject(result); + if (jsonResult == null) { + throw new ServiceException("请求失败"); + } + String code = jsonResult.getString("code"); + if (!"200".equals(code)) { + String message = jsonResult.getString("message"); + throw new ServiceException(ObjectUtils.isEmpty(message) ? "请求失败" : message); + } + return jsonResult.getJSONArray("data"); + } + +// public static void main(String[] args) { +// RequestBody formBody = new FormBody.Builder(). +// add("orderNo", "Fee2023112900000001") +// .add("payStatus", "OK") +// .add("payFailReason", "") +// .add("bankTransNo", "4200001809202305012522296970") +// .build(); +// String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/wxUse/wxPay", formBody); +// System.out.println(result); +//// String result = OkHttpHelper.get(XBDHelper.XBD_PEIS+"/wxUse/GetOrder",params -> { +//// params.put("orderNo","Fee2023112900000001"); +//// }); +//// JSONObject jsonResult = JsonHelper.parseObject(result); +//// System.out.println(result); +// } + +} diff --git a/src/main/java/com/ynxbd/common/service/PayService.java b/src/main/java/com/ynxbd/common/service/PayService.java index 7aa7b0f..c7820e9 100644 --- a/src/main/java/com/ynxbd/common/service/PayService.java +++ b/src/main/java/com/ynxbd/common/service/PayService.java @@ -44,7 +44,7 @@ public class PayService { * * @param notifyInfo 回调信息 */ - public static void WxNotify(WxPayNotify notifyInfo) throws ServiceException { + public static void wxNotify(WxPayNotify notifyInfo) throws ServiceException { String openid = notifyInfo.getOpenid(); String bankTransNo = notifyInfo.getTransactionId(); String outTradeNo = notifyInfo.getOutTradeNo(); @@ -79,14 +79,18 @@ public class PayService { new CasebookService().paidNotify(MerchantEnum.WX, openid, totalFee, outTradeNo, bankTransNo, payInfo); break; - case OUT_COLLECT: - new OutCollectService().ocPaidNotify(MerchantEnum.WX, openid, totalFee, outTradeNo, bankTransNo, payInfo); - break; - case OL_REG: new MicroService().OLReg(openid, totalFee, outTradeNo, bankTransNo, payDate, payTime); break; + case PEIS_RESERVE: + new PEISService().payNotify(MerchantEnum.WX, openid, totalFee, outTradeNo, bankTransNo, payDate, payTime, payInfo); + break; + + case OUT_COLLECT: + new OutCollectService().ocPaidNotify(MerchantEnum.WX, openid, totalFee, outTradeNo, bankTransNo, payInfo); + break; + case TPP_QR_REG: new ThirdPartyPayService().tppQRRegNotify(MerchantEnum.WX, openid, totalFee, outTradeNo, bankTransNo, payDate, payTime, payInfo); break; diff --git a/src/main/java/com/ynxbd/common/service/PeisService.java b/src/main/java/com/ynxbd/common/service/PeisService.java deleted file mode 100644 index 2c7e28d..0000000 --- a/src/main/java/com/ynxbd/common/service/PeisService.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.ynxbd.common.service; - -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; -import com.ynxbd.common.action.pay.PEnum; -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.peis.PeisDao; -import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.helper.his.HisHelper; -import com.ynxbd.common.helper.http.OkHttpHelper; -import com.ynxbd.common.helper.xbd.HttpHelper; -import com.ynxbd.common.helper.xbd.XBDHelper; -import com.ynxbd.common.result.JsonResult; -import com.ynxbd.common.result.JsonResultEnum; -import com.ynxbd.common.result.Result; -import com.ynxbd.common.result.ServiceException; -import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.RequestBody; -import org.apache.commons.lang3.ObjectUtils; - -import java.math.BigDecimal; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -/** - * @author 李进才 - * @ClassName PeisService - * @Description TODO - * @date 2023/11/16 15:53:00 - */ - -@Slf4j -public class PeisService { - - public Boolean Reserve(String openid, String patientId, String treatNum, String outTradeNo, String totalFee, String recipeId) { - Recipe recipe = new Recipe(); - recipe.setOpenid(openid); - recipe.setPatientId(patientId); - recipe.setTreatNum(treatNum); - recipe.setOutTradeNo(outTradeNo); - recipe.setRecipeId(recipeId); - recipe.setTotalFee(new BigDecimal(totalFee)); - recipe.setPayMoney(new BigDecimal(totalFee)); - recipe.setPeisStatus(-1); - recipe.setPayStatus(-1); - if (new PeisDao().isRepeat(recipe.getRecipeId())) { - log.info("[体检预约]该处方号已经缴费,recipeId-{}", recipe.getRecipeId()); - return false; - } - return new PeisDao().insert(recipe); - } - - public void payNotify(MerchantEnum merchantEnum, String openid, BigDecimal totalFee, String outTradeNo, String bankTransNo, String payInfo, Date tradeDate) { - PeisDao peisDao = new PeisDao(); - Recipe recipe = peisDao.selectByOutTradeNo(outTradeNo); - String tradeNo = HisHelper.getHisTradeNo(bankTransNo, PEnum.PEIS_RESERVE); - String recipeId = recipe.getRecipeId(); - Integer payStates = recipe.getPayStatus(); - if (payStates == 0) { - log.error("[体检预约] 拒绝支付-订单已支付 outTradeNo={}, bankTransNo={}, recipeId={}", outTradeNo, bankTransNo, recipeId); - return; - } - if (!peisDao.updatePayStateOk(outTradeNo, bankTransNo, tradeNo)) { - log.info("[体检预约]修改支付状态失败 outTradeNo={}, bankTransNo={},tradeNo-{}", outTradeNo, bankTransNo, tradeNo); - RequestBody formBody = new FormBody.Builder(). - add("orderNo", recipeId) - .add("payStatus", "FAIL") - .add("payFailReason", "修改支付状态失败") - .add("bankTransNo", bankTransNo) - .add("outTradeNo", outTradeNo) - .build(); - String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/wxUse/wxPay", formBody); - JSONObject jsonResult = JsonHelper.parseObject(result); - log.info("[体检预约]缴费失败回调体检系统计费 recipeId={}, bankTransNo-{}, 计费状态-{}, 计费信息-{}", recipeId, bankTransNo, jsonResult.get("code"), jsonResult.get("message")); - String pushMessage = "体检预约失败已申请退款,原因:修改支付状态失败,订单号:" + outTradeNo + "orderNo:" + recipeId; - ; - peisAutoRefund(recipeId, merchantEnum, outTradeNo, totalFee, pushMessage, tradeDate, openid); - } else { - RequestBody formBody = new FormBody.Builder(). - add("orderNo", recipeId) - .add("payStatus", "OK") - .add("payFailReason", "") - .add("bankTransNo", bankTransNo) - .add("outTradeNo", outTradeNo) - .build(); - String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/wxUse/wxPay", formBody); - if (result == null) { - log.info("[体检预约]体检服务无响应,开始退费"); - String pushMessage = "体检预约失败已申请退款,原因:体检服务无响应,订单号:" + outTradeNo + "orderNo:" + recipeId; - peisAutoRefund(recipeId, merchantEnum, outTradeNo, totalFee, pushMessage, tradeDate, openid); - } - JSONObject jsonResult = JsonHelper.parseObject(result); - log.info("[体检预约]缴费成功回调体检系统计费 recipeId={}, bankTransNo-{}, 计费状态-{}, 计费信息-{}", recipeId, bankTransNo, jsonResult.get("code"), jsonResult.get("message")); - if ("200".equals(jsonResult.get("code").toString())) { - if (!peisDao.updatePeisStateOk(outTradeNo, bankTransNo)) { - log.info("[体检预约]修改体检系统支付状态失败 outTradeNo={}, bankTransNo={}", outTradeNo, bankTransNo); - } - } else { - log.info("[体检预约]回调体检系统计费状态码异常 recipeId={}, bankTransNo-{}, 计费状态-{}, 计费信息-{}", recipeId, bankTransNo, jsonResult.get("code"), jsonResult.get("message")); - String pushMessage = "体检预约失败已申请退款,原因:体检系统计费失败,订单号:" + outTradeNo + "orderNo:" + recipeId; - peisAutoRefund(recipeId, merchantEnum, outTradeNo, totalFee, pushMessage, tradeDate, openid); - } - } - - } - - /** - * 体检退费接口 - * - * @param recipeId 订单号 - * @param merchantEnum 支付方式 - * @param outTradeNo outTradeNo - * @param totalFee 总金额 - * @param pushInfo 提示信息 - * @param tradeDate 退费时间 - * @param openid openid - */ - public Result peisAutoRefund(String recipeId, MerchantEnum merchantEnum, String outTradeNo, BigDecimal totalFee, String pushInfo, Date tradeDate, String openid) { - PeisDao peisDao = new PeisDao(); - if (peisDao.checkRefund(outTradeNo)) { - log.info("{} [体检预约][该订单已经退费,请不要重复退费] outTradeNo={}, recipeId={}, totalFee={}", merchantEnum.NAME, outTradeNo, recipeId, totalFee); - return Result.error("该订单已经退费,请不要重复退费"); - } - String result = OkHttpHelper.get(XBDHelper.XBD_PEIS + "/wxUse/GetOrder", params -> { - params.put("orderNo", recipeId); - }); - if (result == null) { - log.info("{} [体检预约][退费错误,计费信息查询失败] outTradeNo={}, recipeId={}, totalFee={}", merchantEnum.NAME, outTradeNo, recipeId, totalFee); - return Result.error("退费错误,计费信息查询失败"); - } - JSONObject jsonResult = JsonHelper.parseObject(result); - String fee = jsonResult.getJSONObject("data").get("fee").toString(); - boolean isWxPay = Boolean.parseBoolean(jsonResult.getJSONObject("data").get("isWxPay").toString()); - boolean isCost = Boolean.parseBoolean(jsonResult.getJSONObject("data").get("isCost").toString()); - if (totalFee.compareTo(BigDecimal.ZERO) == 0 || "0".equals(fee)) { - log.info("{} [体检预约][退费错误,退费金额为0] outTradeNo={}, recipeId={}, totalFee={}", merchantEnum.NAME, outTradeNo, recipeId, totalFee); - return Result.error("退费错误,退费金额为0"); - } - if (totalFee.compareTo(new BigDecimal(fee)) != 0) { - log.info("{} [体检预约][退费错误,退费金额跟订单金额不符] outTradeNo={}, recipeId={}, totalFee={}", merchantEnum.NAME, outTradeNo, recipeId, totalFee); - return Result.error("退费错误,退费金额跟订单金额不符"); - } -// if(isWxPay){ -// log.info("{} [体检预约][退费错误,体检显示已计费,不允许退费] recipeId-{}, outTradeNo={}, recipeId={}, totalFee={}", recipeId, merchantEnum.NAME, outTradeNo, recipeId, totalFee); -// return Result.error("退费错误,体检显示已计费,不允许退费"); -// } - if (isCost) { - log.info("{} [体检预约][退费错误,his显示已计费,不允许退费] outTradeNo={}, recipeId={}, totalFee={}", merchantEnum.NAME, outTradeNo, recipeId, totalFee); - return Result.error("退费错误,体检系统his显示已计费,不允许退费"); - } - String refundResult; - Order orderRefund = PayService.refund(merchantEnum, outTradeNo, recipeId, totalFee, totalFee, pushInfo, tradeDate, openid, null, pushInfo); - if (!orderRefund.isSuccess()) { - log.info("{} [体检预约][退费错误] outTradeNo={}, totalFee={},recipeId-{}", merchantEnum.NAME, outTradeNo, totalFee, recipeId); - refundResult = orderRefund.getRefundResult(); - } else { - refundResult = "OK"; - } - boolean isUpdate = peisDao.updateRefundResult(outTradeNo, recipeId, refundResult); - if (!isUpdate) { - log.info("{} [体检预约][退费错误]退费信息更新失败 recipeId={}", merchantEnum.NAME, recipeId); - } - return Result.success(); - - } - - public boolean peisRefund(String recipeId, String refundStatus, String refundFailReason) { - RequestBody formBody = new FormBody.Builder(). - add("orderNo", recipeId) - .add("refundStatus", refundStatus) - .add("refundFailReason", refundFailReason) - .build(); - String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/wxUse/wxRefund", formBody); - JSONObject jsonResult = JsonHelper.parseObject(result); - return "200".equals(jsonResult.get("code")); - } - - public JSONArray getPeisByCardNo(String cardNo, String begDate, String endDate) throws ServiceException { - RequestBody formBody = new FormBody.Builder(). - add("enIdCard", cardNo) - .add("begDate", begDate) - .add("endDate", endDate) - .build(); - String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/WxUse/GetPeisOfPacsResult", formBody); - if (ObjectUtils.isEmpty(result)) { - throw new ServiceException("请求失败"); - } - JSONObject jsonResult = JsonHelper.parseObject(result); - if (jsonResult == null) { - throw new ServiceException("请求失败"); - } - String code = jsonResult.getString("code"); - if (!"200".equals(code)) { - String message = jsonResult.getString("message"); - throw new ServiceException(ObjectUtils.isEmpty(message) ? "请求失败" : message); - } - return jsonResult.getJSONArray("data"); - } - - public static void main(String[] args) { - RequestBody formBody = new FormBody.Builder(). - add("orderNo", "Fee2023112900000001") - .add("payStatus", "OK") - .add("payFailReason", "") - .add("bankTransNo", "4200001809202305012522296970") - .build(); - String result = OkHttpHelper.post(XBDHelper.XBD_PEIS + "/wxUse/wxPay", formBody); - System.out.println(result); -// String result = OkHttpHelper.get(XBDHelper.XBD_PEIS+"/wxUse/GetOrder",params -> { -// params.put("orderNo","Fee2023112900000001"); -// }); -// JSONObject jsonResult = JsonHelper.parseObject(result); -// System.out.println(result); - } - -} diff --git a/src/main/java/com/ynxbd/common/service/RecipeService.java b/src/main/java/com/ynxbd/common/service/RecipeService.java index 9e137c6..1c7b187 100644 --- a/src/main/java/com/ynxbd/common/service/RecipeService.java +++ b/src/main/java/com/ynxbd/common/service/RecipeService.java @@ -222,7 +222,7 @@ public class RecipeService { public boolean isSaveRecipeInfo(String recipeJson, String payWay, String openid, String patientId, String treatNum, String outTradeNo, String totalFee) { log.info("[处方支付]预存信息 patientId={}, treatNum={}, recipeJson={}", patientId, treatNum, recipeJson); List recipeList = JsonHelper.parseArray(recipeJson, Recipe.class); - if (recipeList == null || recipeList.size() == 0) { + if (recipeList == null || recipeList.isEmpty()) { log.info("[处方支付]勾选处方数量为0 或 数据转换失败"); return false; } diff --git a/src/main/java/com/ynxbd/common/service/RegService.java b/src/main/java/com/ynxbd/common/service/RegService.java index 5ef9cdd..3737105 100644 --- a/src/main/java/com/ynxbd/common/service/RegService.java +++ b/src/main/java/com/ynxbd/common/service/RegService.java @@ -680,7 +680,7 @@ public class RegService { /** * 挂号下单 */ - public Result regPlaceOrder(String payCode, String ip, Boolean isOccupySource, Boolean isZeroPay, Register reg, boolean isHttps) { + public Result createRegOrder(String payCode, String ip, Boolean isOccupySource, Boolean isZeroPay, Register reg, boolean isHttps) { Result noPayTime = PayService.isPaymentPermittedByTime(); if (noPayTime != null) { return noPayTime; diff --git a/src/main/java/com/ynxbd/common/service/Test.java b/src/main/java/com/ynxbd/common/service/Test.java deleted file mode 100644 index 2cfa5bf..0000000 --- a/src/main/java/com/ynxbd/common/service/Test.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.ynxbd.common.service; - -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.digest.DigestUtils; - -@Slf4j -public class Test { - - public static void main(String[] args) { -// System.out.println(JsonHelper.toJsonString(queryOrder("WX7c1ea238c08f420d2bb8262f7254"))); - String piMd5 = "9444144" + "Z2007" + "xbd"; - piMd5 = DigestUtils.md5Hex(piMd5).toUpperCase(); - System.out.println(piMd5); - } -} diff --git a/src/main/java/com/ynxbd/wx/servlet/test/RefundTestServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/RefundTestServlet.java deleted file mode 100644 index bc5b940..0000000 --- a/src/main/java/com/ynxbd/wx/servlet/test/RefundTestServlet.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ynxbd.wx.servlet.test; - -import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.common.result.Result; -import com.ynxbd.wx.servlet.base.BaseServlet; - -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.math.BigDecimal; - -/** - * @Author wsq - * @Date 2021/3/4 17:57 - * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. - */ -@WebServlet("/refundTest") -public class RefundTestServlet extends BaseServlet { - - // show status like 'Threads%'; - private int i = 0; - - @Override - protected synchronized Result requestMapping(HttpServletRequest req, HttpServletResponse resp) throws Exception { - if (i == 0) { - i++; - // 1 - WxPayHelper.refund("", "", new BigDecimal("0.800"), new BigDecimal("0.800"), "手动退费"); - // 2 - } - return Result.success(); - } -} diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxIsAuthServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/WxIsAuthServlet.java index 3e4a64e..e69de29 100644 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxIsAuthServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/test/WxIsAuthServlet.java @@ -1,27 +0,0 @@ -//package com.ynxbd.wx.servlet; -// -//import com.ynxbd.common.result.Result; -//import com.ynxbd.wx.servlet.base.BaseServlet; -//import com.ynxbd.wx.wxfactory.WxAuthHelper; -//import lombok.extern.slf4j.Slf4j; -// -//import javax.servlet.annotation.WebServlet; -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -//import java.io.UnsupportedEncodingException; -// -///** -// * 判读微信是否已经认证 -// * -// * @author antgan -// */ -//@Slf4j -//@WebServlet("/is_auth") -//public class WxIsAuthServlet extends BaseServlet { -// -// @Override -// protected Result requestMapping(HttpServletRequest request, HttpServletResponse resp) throws Exception { -// return WxAuthHelper.isAuth(request); -// } -// -//} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java index 8cc385c..2de9e73 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java @@ -11,8 +11,6 @@ import com.ynxbd.wx.wxfactory.base.auth.models.AuthData; import com.ynxbd.wx.wxfactory.base.auth.models.SnsOath2AccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.SnsUserInfo; import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.RequestBody; import org.apache.commons.lang3.ObjectUtils; import org.ehcache.Cache; @@ -33,26 +31,27 @@ public class WxAuthHelper { public static String auth(HttpServletRequest request, HttpServletResponse response, boolean isUserInfo) { String code = request.getParameter("code"); String state = request.getParameter("state"); // base64 - String enuId = request.getParameter("enuId"); + String params = request.getParameter("params"); - log.info("[授权] code={}, state={}, enuId={}", code, state, enuId); + log.info("[授权] code={}, state={}, params={}", code, state, params); try { state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); String enUnionId = null; - String protocolState = null; + String authSessionId = null; - if (!ObjectUtils.isEmpty(enuId)) { - int index = enuId.indexOf("@protocolState="); - if (index == -1) index = enuId.indexOf("%40protocolState="); // 防止数据转义失败 + if (!ObjectUtils.isEmpty(params)) { + int index = params.indexOf("@SID="); + if (index == -1) index = params.indexOf("%40SID="); // 防止数据转义失败 if (index != -1) { - enUnionId = enuId.substring(0, index); - protocolState = enuId.substring(index); + enUnionId = params.substring(0, index); + authSessionId = params.substring(index); + authSessionId = AesWxHelper.decode(authSessionId); } } - - log.info("[授权-解码] enUnionId={}, protocolState={}, state={}", enUnionId, protocolState, state); + log.info("[授权-解码] enUnionId={}, authSessionId={}, state={}", enUnionId, authSessionId, state); SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); + log.info("[授权-用户]snsToken={}", JsonHelper.toJsonString(snsToken)); if (snsToken != null) { String openid = snsToken.getOpenid(); String unionId = snsToken.getUnionid(); @@ -63,6 +62,7 @@ public class WxAuthHelper { HttpSession session = request.getSession(); session.setMaxInactiveInterval(SESSION_MAX_INACTIVE_INTERVAL); session.setAttribute("openid", openid); + WxCacheHelper.putOpenIdToAIDCache(authSessionId, openid); Cache cache = WxCacheHelper.getUserCacheManager(); if (WeChatConfig.isDevUser(openid) || !cache.containsKey(openid)) { @@ -116,20 +116,26 @@ public class WxAuthHelper { } } } catch (Exception e) { + ErrorHelper.println(e); log.error("[微信][获取重定向链接异常]{}", e.getMessage()); } return null; } - public static Result isAuth(HttpServletRequest request, boolean isPayOAuth) throws Exception { + public static Result isAuth(HttpServletRequest request, HttpServletResponse response, boolean isPayOAuth) throws Exception { String token = request.getParameter("token"); // 前端缓存 String state = request.getParameter("state"); String isUserInfo = request.getParameter("isUserInfo"); - String protocolState = request.getParameter("protocolState"); - String enuId = ParamHelper.filterParamNull(request.getParameter("enuId"), ""); +// String protocolState = request.getParameter("protocolState"); + String enUID = ParamHelper.filterParamNull(request.getParameter("enUID"), ""); String deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); + String authSessionId = null; + if (WeChatConfig.IS_ENABLE_GMC && WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 是医共体主服务器 & 不是支付授权 + authSessionId = AesWxHelper.decode(request.getHeader("AID")); + } + log.info("[is_auth]token={}, state={}, isUserInfo={}, authSessionId={}, enUID={}, deState={}", token, state, isUserInfo, authSessionId, enUID, deState); if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权 try { // 请求转发 String serverDomain = WeChatConfig.getDomain(false, false); @@ -137,17 +143,26 @@ public class WxAuthHelper { return Result.error("授权域名不匹配"); } - RequestBody requestBody = new FormBody.Builder() - .add("token", token) - .add("state", state) - .add("isUserInfo", isUserInfo) - .add("enuId", enuId) - .add("protocolState", protocolState) - .build(); - log.info("[认证请求转发] URL:[{}]", WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true)); - String data = OkHttpHelper.post(WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true) + "wx_auth/is_auth", requestBody); + HttpSession session = request.getSession(); + String sessionId = session.getId(); + + log.info("[认证请求转发] [sessionId:{}]URL:[{}]", sessionId, WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true)); + String data = OkHttpHelper.postFormStr(WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true) + "wx_auth/is_auth", params -> { + params.put("token", token); + params.put("state", state); + params.put("isUserInfo", isUserInfo); + params.put("enuId", enUID); +// params.put("protocolState", protocolState); + }, headers -> { + if (!ObjectUtils.isEmpty(sessionId)) { + headers.add("AID", AesWxHelper.encode(sessionId)); + } + }); + Result result = Result.dataToResult(data, true); + System.out.println(JsonHelper.toJsonString(result)); return Result.dataToResult(data, true); } catch (Exception e) { + e.printStackTrace(); return Result.error(e); } } @@ -188,39 +203,51 @@ public class WxAuthHelper { } HttpSession session = request.getSession(); - Object openid = session.getAttribute("openid"); + Object sessionOpenId = session.getAttribute("openid"); + String openid = sessionOpenId == null ? null : sessionOpenId.toString(); + + log.info("[微信认证]获取 openid={}, authSessionId={}", openid, authSessionId); + if (!ObjectUtils.isEmpty(authSessionId) && ObjectUtils.isEmpty(openid)) { + openid = WxCacheHelper.getOpenIdByAIDCache(authSessionId); + log.info("[微信AID认证]openid={}", openid); + } + if (openid != null) { log.info("[微信认证]openid={}", openid); - User user = WxCacheHelper.getCacheUser((String) openid); + User user = WxCacheHelper.getCacheUser(openid); if (user == null) { - return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); + return Result.success(getAuthUrl(request, state, isFindUserInfo, enUID, authSessionId)); + } else { + if (ObjectUtils.isEmpty(openid)) { + openid = user.getOpenid(); // sessionId认证openid补充 + } } if (isFindUserInfo) { // 更换授权模式,需更新信息 if (user.getNickName() == null || user.getAvatar() == null) { - return Result.success(getAuthUrl(request, state, true, enuId, protocolState)); + return Result.success(getAuthUrl(request, state, true, enUID, authSessionId)); } } Map map = new HashMap<>(); map.put("openid", openid); - map.put("token", new AuthData().createToken(WeChatConfig.APP_ID, openid.toString(), user.getUnionId(), user.getAvatar(), user.getNickName())); - map.put("enOpenId", AesWxHelper.encode(openid.toString(), true)); + map.put("token", new AuthData().createToken(WeChatConfig.APP_ID, openid, user.getUnionId(), user.getAvatar(), user.getNickName())); + map.put("enOpenId", AesWxHelper.encode(openid, true)); map.put("enUnionId", AesWxHelper.encode(user.getUnionId(), true)); map.put("date", new Date()); map.put("avatar", user.getAvatar()); map.put("nickName", user.getNickName()); map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(user.getPatientList()), "UTF-8"))); - map.put("enParams", AesMicroHelper.encode(openid.toString())); + map.put("enParams", AesMicroHelper.encode(openid)); return Result.success(map); } - return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); + return Result.success(getAuthUrl(request, state, isFindUserInfo, enUID, authSessionId)); } private static final String OAUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri="; - private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String enuId, String protocolState) { + private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String enUID, String SID) { // StringBuffer url = request.getRequestURL(); // String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString(); if (state == null) { @@ -230,13 +257,22 @@ public class WxAuthHelper { String api = isFindUserInfo ? "u_auth" : "b_auth"; String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base"; + String enSID = ""; + try { + enSID = (SID == null ? "" : ("%40SID=" + URLEncoder.encode(AesWxHelper.encode(SID), "UTF-8"))); + } catch (Exception e) { + log.error(e.getMessage()); + } + + log.info("[认证链接] enSID={}, SID={}", enSID, SID); + state = OAUTH_URL + WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)) + "wx_auth/" + api + "?state=" + state + "&response_type=code" + "&scope=" + scope + "&forcePopup=true" + - "&enuId=" + (enuId == null ? "" : enuId) + - (protocolState == null ? "" : ("%40protocolState=" + protocolState)) + + "¶ms=" + (enUID == null ? "" : enUID) + + enSID + "#wechat_redirect"; return Base64Helper.encode(state); } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java index be202a3..3a0b050 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java @@ -2,9 +2,11 @@ package com.ynxbd.wx.wxfactory; import com.ynxbd.common.bean.User; import com.ynxbd.common.config.EhCacheConfig; +import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.base.auth.models.AccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.JsapiTicket; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; import org.ehcache.Cache; @Slf4j @@ -18,11 +20,16 @@ public class WxCacheHelper { private static Cache JSAPI_TICKET_CACHE; + private static Cache AID_CACHE; + static { createUserCacheManager(); createAccessTokenCache(); + createAuthSessionIdManager(); + } + private synchronized static void createUserCacheManager() { if (USER_CACHE == null) { USER_CACHE = EhCacheConfig.createCacheTTL(String.class, User.class, "wx_oauth_cache", (5400L)); // 一个半小时 @@ -127,7 +134,6 @@ public class WxCacheHelper { return token; } - public static String getJsapiTicket() { JsapiTicket jsapiTicket = getWxJsapiTicket(); if (jsapiTicket != null) { @@ -136,4 +142,36 @@ public class WxCacheHelper { return null; } + + private synchronized static void createAuthSessionIdManager() { + if (AID_CACHE == null) { + AID_CACHE = EhCacheConfig.createCacheTTL(String.class, String.class, "auth_session_id_cache", (3600L)); // 一个小时 + } + } + + public static String getOpenIdByAIDCache(String authSessionId) { + if (AID_CACHE == null) { + createAuthSessionIdManager(); + } + if (ObjectUtils.isEmpty(authSessionId)) { + return null; + } + if (AID_CACHE.containsKey(authSessionId)) { + return AID_CACHE.get(authSessionId); + } + return null; + } + + public static void putOpenIdToAIDCache(String authSessionId, String openId) { + if (AID_CACHE == null) { + createAuthSessionIdManager(); + } + if (ObjectUtils.isEmpty(authSessionId)) { + return; + } + if (!AID_CACHE.containsKey(authSessionId)) { + AID_CACHE.put(authSessionId, openId); + } + } + }