From c692f7fef54f1f80263365eeccc8c2ee6430dd1d Mon Sep 17 00:00:00 2001 From: wangsq Date: Mon, 20 Apr 2026 17:28:25 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=85=AC=E4=BC=97=E5=8F=B7=E4=BA=8C=E7=BB=B4=E7=A0=81=202?= =?UTF-8?q?=E3=80=81=E5=90=8D=E5=8C=BB=E9=A6=86=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=EF=BC=8C=E8=B0=83=E6=95=B4=E6=9F=A5=E8=AF=A2=E5=8C=BB?= =?UTF-8?q?=E7=94=9F=E5=92=8C=E6=9F=A5=E8=AF=A2=E5=8F=B7=E6=BA=90=E7=9A=84?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=BF=94=E5=9B=9E=E3=80=82=203=E3=80=81?= =?UTF-8?q?=E6=89=AB=E7=A0=81=E7=BC=B4=E8=B4=B9=E6=96=B0=E5=A2=9E=E6=97=A0?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=97=B6=E8=B7=B3=E8=BD=AC=E5=88=B0=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E8=BF=9B=E8=A1=8C=E6=8F=90=E7=A4=BA=E3=80=82=204?= =?UTF-8?q?=E3=80=81=E5=8C=BB=E5=85=B1=E4=BD=93=E6=82=A3=E8=80=85=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=90=8C=E6=AD=A5=E5=92=8C=E5=88=A0=E9=99=A4=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E3=80=82=205=E3=80=81=E6=AD=A6=E5=AE=9A=E5=BF=A0?= =?UTF-8?q?=E7=88=B1=E5=8C=BB=E9=99=A2=E5=92=8C=E6=99=AF=E6=B4=AA=E7=AC=AC?= =?UTF-8?q?=E4=B8=89=E4=BA=BA=E6=B0=91=E5=8C=BB=E9=99=A2=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E5=85=B3=E6=B3=A8=E8=BF=94=E5=9B=9E=E6=B6=88=E6=81=AF=EF=BC=8C?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=8F=B7=E5=8F=AF=E4=BB=A5=E7=94=9F=E6=88=90?= =?UTF-8?q?=E4=BA=8C=E7=BB=B4=E7=A0=81=EF=BC=8C=E6=89=AB=E7=A0=81=E5=90=8E?= =?UTF-8?q?=E6=8E=A8=E9=80=81=E6=B6=88=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ynxbd/common/action/ApiAction.java | 40 ++++- .../ynxbd/common/action/HealthCodeAction.java | 1 - .../ynxbd/common/action/PatientAction.java | 6 + .../java/com/ynxbd/common/bean/Doctor.java | 3 + .../java/com/ynxbd/common/dao/PatientDao.java | 35 ++-- .../ynxbd/common/dao/his/HisRegisterDao.java | 122 +++++++++----- .../common/helper/common/QRCodeHelper.java | 1 - .../com/ynxbd/common/result/JsonResult.java | 6 +- .../com/ynxbd/common/service/GMCService.java | 119 ++++++++++++-- .../ynxbd/common/service/PatientService.java | 150 +++++++++++++++--- .../ynxbd/common/service/RecipeService.java | 1 - .../com/ynxbd/wx/config/HospConfigEnum.java | 1 + .../java/com/ynxbd/wx/servlet/QServlet.java | 10 +- .../java/com/ynxbd/wx/servlet/WxServlet.java | 1 + .../java/com/ynxbd/wx/utils/QRCodeUtil.java | 138 ---------------- .../com/ynxbd/wx/wxfactory/WxAuthHelper.java | 22 ++- .../wx/wxfactory/WxPassiveReplyHelper.java | 17 +- .../com/ynxbd/wx/wxfactory/WxPayHelper.java | 7 +- .../ynxbd/wx/wxfactory/base/auth/Client.java | 32 +++- .../base/auth/models/QRCodeInfo.java | 20 +++ src/main/resources/webservice.properties | 2 +- src/main/resources/wx.properties | 19 ++- 22 files changed, 497 insertions(+), 256 deletions(-) delete mode 100644 src/main/java/com/ynxbd/wx/utils/QRCodeUtil.java create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/QRCodeInfo.java diff --git a/src/main/java/com/ynxbd/common/action/ApiAction.java b/src/main/java/com/ynxbd/common/action/ApiAction.java index 996aad9..c8ada8d 100644 --- a/src/main/java/com/ynxbd/common/action/ApiAction.java +++ b/src/main/java/com/ynxbd/common/action/ApiAction.java @@ -12,13 +12,14 @@ import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.utils.DesEncryptHelper; import com.ynxbd.wx.wxfactory.AesWxHelper; import com.ynxbd.wx.wxfactory.WxCacheHelper; +import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.base.auth.models.AccessToken; +import com.ynxbd.wx.wxfactory.base.auth.models.QRCodeInfo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; -import java.util.Base64; import java.util.HashMap; import java.util.Map; @@ -47,7 +48,7 @@ public class ApiAction extends BaseAction { if (accessToken == null) { return Result.error(); } - log.warn(accessToken); + System.out.println(accessToken); accessToken = DesEncryptHelper.enCode(accessToken); if (accessToken == null) { @@ -59,6 +60,41 @@ public class ApiAction extends BaseAction { } + /** + * + * @return 公钥 + */ + @Action("getQRCode") + public Result getQRCode(String accessToken, Integer size) { + if (accessToken == null) { + return Result.error(ResultEnum.PARAM_IS_DEFECT); + } + accessToken = DesEncryptHelper.deCode(accessToken); + if (ObjectUtils.isEmpty(accessToken)) { + return Result.error(ResultEnum.PARAM_IS_INVALID); + } + + if (size == null) { + size = 430; + } else if (size == 8) { // 厘米 + size = 258; + } else if (size == 12) { + size = 344; + } else if (size == 15) { + size = 430; + } else if (size == 30) { + size = 860; + } else if (size == 50) { + size = 1028; + } + + QRCodeInfo qrcode = WxFactory.Base.OAuth().getQRCode(accessToken, "WX001"); + if (qrcode != null && !ObjectUtils.isEmpty(qrcode.getUrl())) { + qrcode.setQrcode(QRCodeHelper.encodeToBase64(qrcode.getUrl(), size, size)); + } + return Result.success(qrcode); + } + @Action("getWxJsapiTicket") public Result getWxJsapiTicket() { String ticket = WxCacheHelper.getJsapiTicket(); diff --git a/src/main/java/com/ynxbd/common/action/HealthCodeAction.java b/src/main/java/com/ynxbd/common/action/HealthCodeAction.java index 5cd5df3..323a571 100644 --- a/src/main/java/com/ynxbd/common/action/HealthCodeAction.java +++ b/src/main/java/com/ynxbd/common/action/HealthCodeAction.java @@ -237,7 +237,6 @@ public class HealthCodeAction extends BaseAction { return Result.error(ResultEnum.PARAM_ADDRESS_ERROR); } - String uuid = null; if (HCodeService.isEnableHCode() && isHealthCard && healthCardId == null) { // 没有禁用电子健康卡 log.info("[电子健康卡]绑定 wechatCode={}", wechatCode); diff --git a/src/main/java/com/ynxbd/common/action/PatientAction.java b/src/main/java/com/ynxbd/common/action/PatientAction.java index 08250a9..40b3ad3 100644 --- a/src/main/java/com/ynxbd/common/action/PatientAction.java +++ b/src/main/java/com/ynxbd/common/action/PatientAction.java @@ -13,6 +13,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.GMCService; import com.ynxbd.common.service.PatientService; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.WxCacheHelper; @@ -320,6 +321,11 @@ public class PatientAction extends BaseAction { return Result.error(ResultEnum.PARAM_IS_DEFECT); } try { + if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER) { // 开启医共体 && 不是医共体主体 + boolean isOK = new GMCService().unBindGmcServer(request, openid, patientId); + return Result.success(isOK); + } + Patient patient = new PatientDao().selectByOpenidAndPatientId(openid, patientId); if (patient == null) { log.info("[患者解绑]失败,库中不存在该患者 patientId={}", patientId); diff --git a/src/main/java/com/ynxbd/common/bean/Doctor.java b/src/main/java/com/ynxbd/common/bean/Doctor.java index 313b255..921262c 100644 --- a/src/main/java/com/ynxbd/common/bean/Doctor.java +++ b/src/main/java/com/ynxbd/common/bean/Doctor.java @@ -68,6 +68,9 @@ public class Doctor implements Serializable { private Integer skillState; // 0 显示微官网,1:显示HIS private Integer descriptionState; + + private String famousGroupCode; + private String famousGroupName; } diff --git a/src/main/java/com/ynxbd/common/dao/PatientDao.java b/src/main/java/com/ynxbd/common/dao/PatientDao.java index eaea676..d436041 100644 --- a/src/main/java/com/ynxbd/common/dao/PatientDao.java +++ b/src/main/java/com/ynxbd/common/dao/PatientDao.java @@ -458,7 +458,7 @@ public class PatientDao { * * @return list */ - public List selectNoneGmcList() { + public synchronized List selectNoneGmcList() { if (!WeChatConfig.IS_ENABLE_GMC) { log.warn("[医共体]功能未开启-禁止查询不是医共体的用户信息"); return new ArrayList<>(); @@ -467,23 +467,40 @@ public class PatientDao { return DataBase.select(sql, Patient.class, null); } + public boolean removePatient(Integer id, String remark){ + String sql = "update patientBase set deletedState=1, remark=? where id=?"; + return DataBase.update(sql, ps -> { + ps.setString(1, remark); + ps.setLong(2, id); + }) > 0; + } + public boolean updateGmcInfo(boolean hasCard, Integer id, String gmcPatientId, String hisPatientId) { if (!hasCard) { // 无证绑定->标记为已删除 - String sql = "update patientBase set deletedState= 1 where id=?"; - return DataBase.update(sql, ps -> { - ps.setLong(1, id); - }) > 0; + return removePatient(id, "无证绑定"); } if (ObjectUtils.isEmpty(gmcPatientId)) { return false; } - String sql = "update patientBase set gmcBindState= 1, patientId=?, hisPatientId=? where id=?"; + int gmcBindState = WeChatConfig.IS_ENABLE_GMC && WeChatConfig.IS_GMC_SERVER ? 1 : 0; // 医共体主服务器直接标识为1,其他医院的服务器同步时为0,后续使用时同步 + String sql = "update patientBase set gmcBindState=?, patientId=?, hisPatientId=? where id=?"; + return DataBase.update(sql, ps -> { + ps.setInt(1, gmcBindState); + ps.setString(2, gmcPatientId); + ps.setString(3, hisPatientId); + // 条件 + ps.setLong(4, id); + }) > 0; + } + + public boolean updateGmcBindState(String gmcUniqueId, Integer id, String gmcPatientId) { + String sql = "update patientBase set gmcBindState= 1, gmcUniqueId=? where id=? and patientId=?"; return DataBase.update(sql, ps -> { - ps.setString(1, gmcPatientId); - ps.setString(2, hisPatientId); + ps.setString(1, gmcUniqueId); // 条件 - ps.setLong(3, id); + ps.setLong(2, id); + ps.setString(3, gmcPatientId); }) > 0; } } 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 23b5a1f..b8799c1 100644 --- a/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java +++ b/src/main/java/com/ynxbd/common/dao/his/HisRegisterDao.java @@ -757,6 +757,7 @@ public class HisRegisterDao { JSONArray doctorJsonList; for (int i = 0; i < deptJsonList.size(); i++) { deptJson = deptJsonList.getJSONObject(i); + deptCode = ParamHelper.spaceFormat(deptJson.getString("DeptCode")); deptName = ParamHelper.spaceFormat(deptJson.getString("DeptName")); doctorJsonList = deptJson.getJSONArray("Doct"); @@ -873,6 +874,8 @@ public class HisRegisterDao { return dataList; } + + /** * [分时段]根据科室code和医生code查询医生号源 * @@ -906,47 +909,95 @@ public class HisRegisterDao { } try { - JSONArray jsonArray = jsonResult.getJsonArray("Dept", "Doct", "TimeInterval"); - JSONObject timeNode, sourceNode; + JSONArray deptJsonArr = jsonResult.getJsonArray("Dept"); + if (deptJsonArr == null || deptJsonArr.isEmpty()) { + return dataList; + } + + JSONObject deptJsonItem, doctJsonItem, timeJsonItem, sourceJsonItem; + JSONArray doctJsonArr, timeJsonArr, sourceJsonArr; + Register sourceItem; - JSONArray sourceArr; BigDecimal regMoney; - String tid, tName; - for (int i = 0; i < jsonArray.size(); i++) { - timeNode = jsonArray.getJSONObject(i); - tid = timeNode.getString("TID"); - tid = tid == null ? null : tid.trim(); - tName = timeNode.getString("TName"); - tName = tName == null ? null : tName.trim(); + String sourceDeptCode, sourceDeptName, sourceDoctName, sourceDoctCode, sourceTId, sourceTName; + for (int deptIndex = 0; deptIndex < deptJsonArr.size(); deptIndex++) { + deptJsonItem = deptJsonArr.getJSONObject(deptIndex); + if (deptJsonItem == null) { + continue; + } + sourceDeptCode = ParamHelper.spaceFormat(deptJsonItem.getString("DeptCode")); + sourceDeptName = ParamHelper.spaceFormat(deptJsonItem.getString("DeptName")); - sourceArr = timeNode.getJSONArray("Source"); - for (int k = 0; k < sourceArr.size(); k++) { - sourceNode = sourceArr.getJSONObject(k); - regMoney = sourceNode.getBigDecimal("RegistPrice"); - if (regMoney == null) { - regMoney = BigDecimal.ZERO; + doctJsonArr = deptJsonItem.getJSONArray("Doct"); + if (doctJsonArr == null || doctJsonArr.isEmpty()) { + continue; + } + + for (int doctIndex = 0; doctIndex < doctJsonArr.size(); doctIndex++) { + doctJsonItem = doctJsonArr.getJSONObject(doctIndex); + if (doctJsonItem == null) { + continue; } + sourceDoctCode = ParamHelper.spaceFormat(doctJsonItem.getString("DoctCode")); + sourceDoctName = ParamHelper.spaceFormat(doctJsonItem.getString("DoctName")); - sourceItem = new Register(); - sourceItem.setTid(tid); - sourceItem.setTName(tName); - sourceItem.setRegFee(regMoney); - // ----------------------- - sourceItem.setSourceId(sourceNode.getString("SourceId")); - sourceItem.setQueueNum(sourceNode.getString("QueueNumber")); - sourceItem.setBegTime(sourceNode.getString("BegTime")); - sourceItem.setEndTime(sourceNode.getString("EndTime")); - sourceItem.setRegCode(sourceNode.getString("RegistCode")); - sourceItem.setRegName(sourceNode.getString("RegistName")); - sourceItem.setRegDate(sourceNode.getString("RegistDate")); - sourceItem.setAddress(sourceNode.getString("ClinicAddress")); - sourceItem.setAllowReg(sourceNode.getInteger("AllowOnline")); - sourceItem.setIsUsed(sourceNode.getInteger("IsUsed")); + timeJsonArr = doctJsonItem.getJSONArray("TimeInterval"); + if (timeJsonArr == null || timeJsonArr.isEmpty()) { + continue; + } - sourceItem.setTotalFee(regMoney); - sourceItem.setPayMoney(regMoney); - sourceItem.setEnPayMoney(AesWxHelper.encode(regMoney)); - dataList.add(sourceItem); + for (int timeIndex = 0; timeIndex < timeJsonArr.size(); timeIndex++) { + timeJsonItem = timeJsonArr.getJSONObject(timeIndex); + if (timeJsonItem == null) { + continue; + } + + sourceTId = ParamHelper.spaceFormat(timeJsonItem.getString("TID")); + sourceTName = ParamHelper.spaceFormat(timeJsonItem.getString("TName")); + + sourceJsonArr = timeJsonItem.getJSONArray("Source"); + if (sourceJsonArr == null || sourceJsonArr.isEmpty()) { + continue; + } + + for (int sourceIndex = 0; sourceIndex < sourceJsonArr.size(); sourceIndex++) { + sourceJsonItem = sourceJsonArr.getJSONObject(sourceIndex); + if (sourceJsonItem == null) { + continue; + } + + regMoney = sourceJsonItem.getBigDecimal("RegistPrice"); + if (regMoney == null) { + regMoney = BigDecimal.ZERO; + } + + sourceItem = new Register(); + sourceItem.setDeptCode(sourceDeptCode); + sourceItem.setDeptName(sourceDeptName); + sourceItem.setDoctCode(sourceDoctCode); + sourceItem.setDoctName(sourceDoctName); + + sourceItem.setTid(sourceTId); + sourceItem.setTName(sourceTName); + sourceItem.setRegFee(regMoney); + // ----------------------- + sourceItem.setSourceId(sourceJsonItem.getString("SourceId")); + sourceItem.setQueueNum(sourceJsonItem.getString("QueueNumber")); + sourceItem.setBegTime(sourceJsonItem.getString("BegTime")); + sourceItem.setEndTime(sourceJsonItem.getString("EndTime")); + sourceItem.setRegCode(sourceJsonItem.getString("RegistCode")); + sourceItem.setRegName(sourceJsonItem.getString("RegistName")); + sourceItem.setRegDate(sourceJsonItem.getString("RegistDate")); + sourceItem.setAddress(sourceJsonItem.getString("ClinicAddress")); + sourceItem.setAllowReg(sourceJsonItem.getInteger("AllowOnline")); + sourceItem.setIsUsed(sourceJsonItem.getInteger("IsUsed")); + + sourceItem.setTotalFee(regMoney); + sourceItem.setPayMoney(regMoney); + sourceItem.setEnPayMoney(AesWxHelper.encode(regMoney)); + dataList.add(sourceItem); + } + } } } } catch (Exception e) { @@ -1180,5 +1231,4 @@ public class HisRegisterDao { return HisHelper.getJsonResult(HisEnum.TPP_QR_Reg, params); } - } diff --git a/src/main/java/com/ynxbd/common/helper/common/QRCodeHelper.java b/src/main/java/com/ynxbd/common/helper/common/QRCodeHelper.java index 7bc5cb5..3f4598b 100644 --- a/src/main/java/com/ynxbd/common/helper/common/QRCodeHelper.java +++ b/src/main/java/com/ynxbd/common/helper/common/QRCodeHelper.java @@ -94,7 +94,6 @@ public class QRCodeHelper { //输出二维码图片流 ImageIO.write(image, "png", outputStream); return "data:image/png;base64," + Base64.encodeBase64String(outputStream.toByteArray()); - } catch (Exception e) { e.printStackTrace(); } diff --git a/src/main/java/com/ynxbd/common/result/JsonResult.java b/src/main/java/com/ynxbd/common/result/JsonResult.java index a6c0b91..716eb4a 100644 --- a/src/main/java/com/ynxbd/common/result/JsonResult.java +++ b/src/main/java/com/ynxbd/common/result/JsonResult.java @@ -10,6 +10,7 @@ import com.ynxbd.common.helper.common.ErrorHelper; import com.ynxbd.common.helper.common.JsonHelper; import lombok.*; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentHelper; @@ -116,7 +117,7 @@ public class JsonResult { */ public static JsonResult xmlToBean(String xml, JsonResultEnum jsonResultEnum, String... ignoreParams) { try { - if (xml == null || "".equals(xml)) { + if (ObjectUtils.isEmpty(xml)) { log.info("【{}】 response xml is null", jsonResultEnum.getSYS()); return null; // 不能判断是否为调用超时 } @@ -528,6 +529,9 @@ public class JsonResult { } + + + // public static void main(String[] args) { // String test = "70090成功3605059297520余艳聪0312心病科0721李曰富2024-12-1014:42:0014:45:002024-12-10 12:36:203605213411671杨丽麟2101精神科(神志病科)0970付丽娜2024-12-1015:57:0016:00:002024-12-10 14:55:113605216821300段贵成1201口腔科任意医师2024-12-1014:51:0014:58:002024-12-10 14:56:293605336679882段李情1201口腔科1599唐德芝2024-12-1015:42:0015:45:002024-12-10 15:42:313605339509469李进才0403骨伤科1272沈自启2024-12-1017:27:0017:30:002024-12-10 15:44:003605381372552思安翠0403骨伤科1272沈自启2024-12-1016:03:0016:06:002024-12-10 16:00:413605454811419胡铭城1102眼耳鼻喉科1254安兴有2024-12-1016:33:2616:36:002024-12-10 16:35:04"; // JsonResult jsonResult = JsonResult.xmlToBean(test,JsonResultEnum.SYS_HIS); diff --git a/src/main/java/com/ynxbd/common/service/GMCService.java b/src/main/java/com/ynxbd/common/service/GMCService.java index 00adf0d..d08f599 100644 --- a/src/main/java/com/ynxbd/common/service/GMCService.java +++ b/src/main/java/com/ynxbd/common/service/GMCService.java @@ -1,7 +1,10 @@ package com.ynxbd.common.service; +import com.alibaba.fastjson.JSONObject; +import com.ynxbd.common.bean.GMCUser; import com.ynxbd.common.bean.Patient; import com.ynxbd.common.bean.enums.HCardTypeEnum; +import com.ynxbd.common.dao.GMCUserDao; import com.ynxbd.common.dao.PatientDao; import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.http.OkHttpHelper; @@ -17,7 +20,6 @@ import org.apache.commons.lang3.ObjectUtils; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.List; -import java.util.Map; @Slf4j public class GMCService { @@ -38,10 +40,10 @@ public class GMCService { if (!WeChatConfig.IS_ENABLE_GMC || WeChatConfig.IS_GMC_SERVER) { // 医共体开关未开启 || 是主服务器 return new ArrayList<>(); } - + String enGmcOpenId = AesWxHelper.encode(gmcOpenId); long begTime = System.currentTimeMillis(); JsonResult jsonResult = postFormGMC(request, "/patient/queryPatientList", params -> { - params.put("openId", AesWxHelper.encode(gmcOpenId)); + params.put("openId", enGmcOpenId); params.put("hospAppId", AesWxHelper.encode(WeChatConfig.GMC_APP_ID)); }, null); if (!jsonResult.success()) { @@ -51,10 +53,11 @@ public class GMCService { } List gmcPatients = jsonResult.getDataMapList(Patient.class, "data"); - List removeIds = new ArrayList<>(); // 需删除用户ids List addList = new ArrayList<>(); // 需添加用户 + List removeIds = new ArrayList<>(); // 需删除用户ids List dbPatients = new PatientDao().selectListByToken(wxOpenId, unionId); + for (Patient item : gmcPatients) { item.setId(null); item.setOpenid(wxOpenId); @@ -64,6 +67,7 @@ public class GMCService { Patient findDBItem = dbPatients.isEmpty() ? null : dbPatients.stream().filter(o -> ( !ObjectUtils.isEmpty(o.getPatientId()) && o.getPatientId().equals(item.getPatientId()) + && !ObjectUtils.isEmpty(o.getIdCardNo()) && o.getIdCardNo().equals(item.getIdCardNo()) )).findFirst().orElse(null); if (findDBItem == null) { // 需新增 @@ -78,9 +82,39 @@ public class GMCService { } for (Patient item : dbPatients) { - Patient findItem = gmcPatients.stream().filter(o -> (!ObjectUtils.isEmpty(o.getPatientId()) && o.getPatientId().equals(item.getPatientId()))).findFirst().orElse(null); - if (findItem == null) { // 本地数据多余->移除 - removeIds.add(item.getId()); + Patient findItem = gmcPatients.stream().filter(o -> ( + !ObjectUtils.isEmpty(o.getPatientId()) && o.getPatientId().equals(item.getPatientId())) + && !ObjectUtils.isEmpty(o.getIdCardNo()) && o.getIdCardNo().equals(item.getIdCardNo()) + ).findFirst().orElse(null); + if (findItem == null) { // 本地数据多余->发送给主体医院=>进行绑定 + Integer gmcBindState = item.getGmcBindState(); + if (gmcBindState == null || gmcBindState == 0) { // 未与主体医院交互校验过 + System.out.println("[医共体]向主体医院同步数据..."); + System.out.println(JsonHelper.toJsonString(item)); + item.setEnGmcOpenId(enGmcOpenId); + Patient patient = new GMCService().bindGmcServer(request, item); + if (patient == null) { + log.error("[医共体]同步用户数据,返回数据为空 id:{}", item.getId()); + continue; + } + String gmcPatientId = patient.getPatientId(); + String gmcUniqueId = patient.getGmcUniqueId(); + if (ObjectUtils.isEmpty(gmcUniqueId) || ObjectUtils.isEmpty(gmcPatientId)) { + log.error("[医共体]同步用户数据,返回唯一键为空 id:{}", item.getId()); + continue; + } + if (!gmcPatientId.equals(item.getPatientId())) { + removeIds.add(item.getId()); + continue; + } + if (new PatientDao().updateGmcBindState(gmcUniqueId, item.getId(), item.getPatientId())) { + log.error("[医共体]同步用户数据,修改医共体绑定状态失败 id:{}", item.getId()); + item.setGmcUniqueId(gmcUniqueId); + gmcPatients.add(item); + } + } else { // 已校验过=>多余数据=>移除 + removeIds.add(item.getId()); + } } } @@ -105,15 +139,26 @@ public class GMCService { * @param request request * @param bindInfo 绑定信息 */ - public Map bindGmcServer(HttpServletRequest request, Patient bindInfo) throws ServiceException { + public Patient bindGmcServer(HttpServletRequest request, Patient bindInfo) throws ServiceException { String enGmcOpenId = bindInfo.getEnGmcOpenId(); // 只有子服务器有主服务器的openId String gmcOpenId = AesWxHelper.decode(enGmcOpenId); - log.info("[转发]enGmcOpenId={}, gmcOpenId={}", enGmcOpenId, gmcOpenId); + log.info("[医共体绑定-转发]enGmcOpenId={}, gmcOpenId={}", enGmcOpenId, gmcOpenId); if (ObjectUtils.isEmpty(gmcOpenId)) { throw new ServiceException("医共体非主体公众号ID参数异常"); } + String idCardNo = bindInfo.getIdCardNo(); + if (ObjectUtils.isEmpty(idCardNo)) { + throw new ServiceException("[医共体绑定]证件号缺失"); + } + + String areaCode = bindInfo.getAreaCode(); + if (ObjectUtils.isEmpty(areaCode)) { + areaCode = idCardNo.substring(0, 6); + } + + String finalAreaCode = areaCode; JsonResult jsonResult = postFormGMC(request, "/healthCode/bind", params -> { params.put("isAreaCode", false); params.put("isFace", false); @@ -121,7 +166,7 @@ public class GMCService { params.put("openid", gmcOpenId); // 主服务器的openId params.put("address", bindInfo.getAddress()); - params.put("areaCode", bindInfo.getAreaCode()); + params.put("areaCode", finalAreaCode); params.put("areaAddress", bindInfo.getAreaAddress()); params.put("tel", bindInfo.getTel()); params.put("sex", bindInfo.getSex()); @@ -136,11 +181,61 @@ public class GMCService { if (!jsonResult.success()) { throw new ServiceException(jsonResult.getMessage()); } - log.info("[医供体]绑定转发 resp={}", JsonHelper.toJsonString(jsonResult)); - return jsonResult.getDataMap(); + JSONObject resp = jsonResult.dataMapGetNodeToJsonObj(); + log.info("[医供体]绑定转发 resp={}", JsonHelper.toJsonString(resp)); + if (resp == null) { + return null; + } + + String gmcUniqueId = resp.getString("gmcUniqueId"); + String enPatientId = resp.getString("enPatientId"); + String enOpenId = resp.getString("enOpenId"); + if (ObjectUtils.isEmpty(gmcUniqueId) || ObjectUtils.isEmpty(enPatientId) || ObjectUtils.isEmpty(enOpenId)) { + return null; + } + String patientId = AesWxHelper.decode(enPatientId); + if (ObjectUtils.isEmpty(patientId)) { + log.error("[医共体]主体绑定,返回patientId解密失败"); + return null; + } + + Patient patient = new Patient(); + patient.setPatientId(patientId); + patient.setEnPatientId(enPatientId); + patient.setEnOpenId(enOpenId); + patient.setGmcUniqueId(gmcUniqueId); + return patient; } + /** + * 医共体解绑 + * + * @param request request + */ + public boolean unBindGmcServer(HttpServletRequest request, String openId, String patientId) throws ServiceException { + log.info("[医共体解绑-转发]openId={}, patientId={}", openId, patientId); + if (ObjectUtils.isEmpty(openId) || ObjectUtils.isEmpty(patientId)) { + throw new ServiceException("[医共体解绑-转发]参数缺失"); + } + + GMCUser gmcUser = new GMCUserDao().selectByOpenId(openId); + if (gmcUser == null) { + throw new ServiceException("[医共体解绑-转发]未匹配到用户id"); + } + String gmcOpenId = gmcUser.getGmcOpenId(); + + JsonResult jsonResult = postFormGMC(request, "/patient/unBind", params -> { + params.put("openid", gmcOpenId); + params.put("patientId", patientId); + params.put("hospAppId", WeChatConfig.APP_ID); + }, null); + if (!jsonResult.success()) { + throw new ServiceException(jsonResult.getMessage()); + } + return true; + } + public static JsonResult postForm(String url, OkHttpHelper.MapParams params, OkHttpHelper.Header header) { return OkHttpHelper.postForm(url, params, header, JsonResultEnum.SYS_COMMON); } diff --git a/src/main/java/com/ynxbd/common/service/PatientService.java b/src/main/java/com/ynxbd/common/service/PatientService.java index 98747ad..0f324d1 100644 --- a/src/main/java/com/ynxbd/common/service/PatientService.java +++ b/src/main/java/com/ynxbd/common/service/PatientService.java @@ -20,6 +20,9 @@ import org.apache.commons.lang3.ObjectUtils; import javax.servlet.http.HttpServletRequest; import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -132,13 +135,13 @@ public class PatientService { if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER) { // 开启医共体 && 不是医共体主体 try { - Map dataMap = new GMCService().bindGmcServer(request, bindInfo); - if (dataMap == null) { - return Result.error("[医共体]绑定返回空map"); + Patient patient = new GMCService().bindGmcServer(request, bindInfo); + if (patient == null) { + return Result.error("[医共体]绑定返回数据为空"); } WxCacheHelper.removeUser(openid); Map map = new HashMap<>(); - map.put("gmcUniqueId", dataMap.get("gmcUniqueId")); + map.put("gmcUniqueId", patient.getGmcUniqueId()); map.put("enOpenId", AesWxHelper.encode(openid)); return Result.success(map); } catch (Exception e) { @@ -185,7 +188,7 @@ public class PatientService { bindInfo.setHisTransNo(hisTransNo); // bindInfo.setGmcHospId(gmcHospId); - // 判断是否已有数据 + try { List dbPatients = patientDao.selectByOpenIdAndCardNo(openid, idCardNo); if (dbPatients.isEmpty()) { // 数据库没有-->添加 @@ -223,6 +226,7 @@ public class PatientService { Map map = new HashMap<>(); map.put("gmcUniqueId", bindInfo.getGmcUniqueId()); map.put("enOpenId", AesWxHelper.encode(openid)); + map.put("enPatientId", AesWxHelper.encode(patientId)); return Result.success(map); } @@ -437,19 +441,15 @@ public class PatientService { * [维护]替换患者id为医共体id * */ - public void wh_gmc_patient_ids() { - List patients = new PatientDao().selectNoneGmcList(); + public void replaceHisGmcId(List patients) { if (patients.isEmpty()) { return; } - log.warn("[医共体]患者id替换开始......共:[{}]条", patients.size()); - PatientDao patientDao = new PatientDao(); int errNum = 0; - int index = 0; + log.warn("[医共体][线程]患者id替换开始......共:[{}]条", patients.size()); + PatientDao patientDao = new PatientDao(); + HisPatientDao hisPatientDao = new HisPatientDao(); for (Patient patient : patients) { - index = index + 1; - log.warn("[医共体替换]index={}", index); - if (HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType()) || ObjectUtils.isEmpty(patient.getIdCardNo())) { // 无证绑定 continue; } @@ -461,17 +461,104 @@ public class PatientService { boolean hasCard = !HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType()) && !ObjectUtils.isEmpty(patient.getIdCardNo()); if (hasCard) { - gmcPatientId = new HisPatientDao().getGMCPatientId(hisPatientId); // 医共体患者id + gmcPatientId = hisPatientDao.getGMCPatientId(hisPatientId); // 医共体患者id if (ObjectUtils.isEmpty(gmcPatientId)) { + patientDao.removePatient(id, "医共体"); log.warn("[医共体id]替换失败 hisPatientId={}", hisPatientId); continue; } } + boolean isUpdate = patientDao.updateGmcInfo(hasCard, id, gmcPatientId, hisPatientId); + if (!isUpdate) { + errNum = errNum + 1; + log.warn("[医共体]患者id替换更新数据失败 id={}, hisPatientId={}", id, hisPatientId); + } + } + log.warn("[医共体]患者id替换 共:[{}]条, 失败:[{}]条", patients.size(), errNum); + } + + + /** + * [维护][多线程]替换患者id为医共体id + * + */ + public synchronized void wh_gmc_patient_ids() { + if (!WeChatConfig.IS_ENABLE_GMC) { + log.info("[医共体]数据同步开关未开启..."); + return; + } + List patients = new PatientDao().selectNoneGmcList(); + if (patients.isEmpty()) { + return; + } + log.warn("[医共体]患者id替换开始......共:[{}]条", patients.size()); + + int threadCount = 22; // 线程数量 + if (patients.size() <= threadCount) { + replaceHisGmcId(patients); + return; + } + + List> partitions = splitList(patients, threadCount); + // 2. 创建线程池 + ExecutorService executor = Executors.newFixedThreadPool(threadCount); + // 3. 每个线程处理一份数据 + for (List part : partitions) { + executor.submit(() -> replaceHisGmcId(part)); + } + + try { + // 关闭线程池并等待所有线程执行完毕 + executor.shutdown(); + boolean isResult = executor.awaitTermination(120, TimeUnit.MINUTES);// 最多等待120分钟 + System.out.println(isResult); + } catch (InterruptedException e) { + log.error("线程等待异常", e); + Thread.currentThread().interrupt(); + } + } + + + // ==================== 工具方法:把大集合平均分成 N 份 ==================== + private List> splitList(List list, int partitionSize) { + List> partitions = new ArrayList<>(); + int size = list.size(); + int chunk = size / partitionSize; + int remainder = size % partitionSize; + + int fromIndex = 0; + for (int i = 0; i < partitionSize; i++) { + int toIndex = fromIndex + chunk + (remainder-- > 0 ? 1 : 0); + if (fromIndex < toIndex) { + partitions.add(list.subList(fromIndex, toIndex)); + } + fromIndex = toIndex; + } + return partitions; + } + + + +// /** +// * [维护]替换患者id为医共体id +// * +// */ +// public void wh_gmc_bind() { +// List patients = new PatientDao().selectNoneGmcList(); +// log.warn("[医共体]患者id替换开始......共:[{}]条", patients.size()); +// PatientDao patientDao = new PatientDao(); +// +// int errNum = 0; +// for (Patient patient : patients) { +// String gmcPatientId = null; // 医共体患者id +// +// Integer id = patient.getId(); +// String hisPatientId = patient.getPatientId(); // 旧id // Patient hisPatient; // if (!HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType())) { // 不为无证绑定 // try { -// hisPatient = new HisPatientDao().getGMCPatientId(false, patient); +// hisPatient = new HisPatientDao().bind(false, patient); // if (hisPatient == null || ObjectUtils.isEmpty(hisPatient.getPatientId())) { // log.warn("[医共体]患者id替换-调用HIS绑定接口异常,未返回患者信息 id={}, hisPatientId={}", id, hisPatientId); // continue; @@ -482,14 +569,29 @@ public class PatientService { // continue; // } // } +// +// boolean isUpdate = patientDao.updateGmcInfo(patient.getId(), patient.getIdCardNo(), patient.getCardType(), gmcPatientId, hisPatientId); +// if (!isUpdate) { +// errNum = errNum + 1; +// log.warn("[医共体]患者id替换更新数据失败 id={}, hisPatientId={}", id, hisPatientId); +// } +// +// log.warn("[医共体]患者id替换 共:[{}]条, 失败:[{}]条", patients.size(), errNum); +// } +// } - boolean isUpdate = patientDao.updateGmcInfo(hasCard ,id, gmcPatientId, hisPatientId); - if (!isUpdate) { - errNum = errNum + 1; - log.warn("[医共体]患者id替换更新数据失败 id={}, hisPatientId={}", id, hisPatientId); - } - } - log.warn("[医共体]患者id替换 共:[{}]条, 失败:[{}]条", patients.size(), errNum); - } - + // Patient hisPatient; +// if (!HCardTypeEnum.NO_CARD.WX_CODE.equals(patient.getCardType())) { // 不为无证绑定 +// try { +// hisPatient = new HisPatientDao().getGMCPatientId(false, patient); +// if (hisPatient == null || ObjectUtils.isEmpty(hisPatient.getPatientId())) { +// log.warn("[医共体]患者id替换-调用HIS绑定接口异常,未返回患者信息 id={}, hisPatientId={}", id, hisPatientId); +// continue; +// } +// gmcPatientId = hisPatient.getPatientId(); +// } catch (Exception e) { +// log.warn(e.getMessage()); +// continue; +// } +// } } diff --git a/src/main/java/com/ynxbd/common/service/RecipeService.java b/src/main/java/com/ynxbd/common/service/RecipeService.java index a522eaf..ac81fd6 100644 --- a/src/main/java/com/ynxbd/common/service/RecipeService.java +++ b/src/main/java/com/ynxbd/common/service/RecipeService.java @@ -469,7 +469,6 @@ public class RecipeService { QuickDrugDispenseHelper.quickDrug(drugInfo, invoiceTransNo); } - // 更新支付信息 if (!recipeDao.updateHisPaidByTradeNo(tradeNo, hisTransNo, invoiceTransNo)) { log.info("[处方]更新HIS返回数据失败 outTradeNo={}, tradeNo={}, recipeId={}", outTradeNo, tradeNo, recipeId); diff --git a/src/main/java/com/ynxbd/wx/config/HospConfigEnum.java b/src/main/java/com/ynxbd/wx/config/HospConfigEnum.java index 84cf662..4fe34e4 100644 --- a/src/main/java/com/ynxbd/wx/config/HospConfigEnum.java +++ b/src/main/java/com/ynxbd/wx/config/HospConfigEnum.java @@ -14,6 +14,7 @@ public enum HospConfigEnum { 巍山县人民医院("巍山县人民医院", "wx1e30610a28d189a8", null, null), 芒市人民医院("芒市人民医院", "wxca97aaeb3c40c0d0", null, null), 玉龙县人民医院("玉龙县人民医院", "wx1f1e9d29f9b44c36", null, null), + 景洪第三人民医院("景洪第三人民医院", "wxd19b076c0695589b", null, null), ; public final String NAME; diff --git a/src/main/java/com/ynxbd/wx/servlet/QServlet.java b/src/main/java/com/ynxbd/wx/servlet/QServlet.java index fcc2ca8..91cc63a 100644 --- a/src/main/java/com/ynxbd/wx/servlet/QServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/QServlet.java @@ -59,17 +59,20 @@ public class QServlet extends HttpServlet { log.info("{} [patientId={} {}]多张处方扫码请求,开始解析...", merchantEnum.NAME, patientId, hasTreatNum ? (", treatNum=" + groupTreatNum) : ""); if (ObjectUtils.isEmpty(patientId) && ObjectUtils.isEmpty(cardNo)) { - log.info("[支付] 多张扫码请求 patientId is null and idCardNo is null"); + log.info("[支付]多张处方扫码请求 patientId is null and idCardNo is null"); + if (MerchantEnum.WX.equals(merchantEnum)) { + response.sendRedirect(WeChatConfig.getWebReqURL() + "pay-qr-recipe.html"); + } return; } - // 新版体检缴费,patientId赋值为0 + // 新版体检缴费:patientId赋值为0 if (!ObjectUtils.isEmpty(cardNo) && ObjectUtils.isEmpty(patientId)) { patientId = "0"; //patientId 赋值0 } if (patientId.contains(".") || patientId.contains("/") || patientId.contains("http")) { - log.info("[支付] 多张扫码请求 参数无效"); + log.info("[支付]多张处方扫码请求 参数无效"); return; } cardNo = ObjectUtils.isEmpty(cardNo) ? "" : Base64Helper.decode(cardNo); @@ -80,7 +83,6 @@ public class QServlet extends HttpServlet { groupTreatNum = hasTreatNum ? ("&treatNum=" + groupTreatNum) : ""; String params = "?p=" + patientId + "&enp=" + AesWxHelper.encode(patientId) + cardNo + groupTreatNum; - if (MerchantEnum.WX.equals(merchantEnum)) { response.sendRedirect(WeChatConfig.getWebReqURL() + "pay-qr-recipe.html" + params); } diff --git a/src/main/java/com/ynxbd/wx/servlet/WxServlet.java b/src/main/java/com/ynxbd/wx/servlet/WxServlet.java index dddb4f9..a0c909a 100644 --- a/src/main/java/com/ynxbd/wx/servlet/WxServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/WxServlet.java @@ -1,5 +1,6 @@ package com.ynxbd.wx.servlet; +import com.alibaba.fastjson.JSON; import com.ynxbd.common.result.Result; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WxEventEnum; diff --git a/src/main/java/com/ynxbd/wx/utils/QRCodeUtil.java b/src/main/java/com/ynxbd/wx/utils/QRCodeUtil.java deleted file mode 100644 index 0c149ee..0000000 --- a/src/main/java/com/ynxbd/wx/utils/QRCodeUtil.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.ynxbd.wx.utils; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.EncodeHintType; -import com.google.zxing.MultiFormatWriter; -import com.google.zxing.common.BitMatrix; -import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.util.Hashtable; -import java.util.Map; - -/** - * @author 张剑峰 - * @date 2018年6月4日下午12:38:39 - * @version v1.0.0 - * @Copyright: 2018云南新八达科技有限公司 All rights reserved. - */ -public class QRCodeUtil { - - private static final int BLACK = 0xFF000000; - private static final int WHITE = 0xFFFFFFFF; - private static final int GREEN = 0xFFAAAAAA; - - private static BufferedImage toBufferedImage(BitMatrix matrix) { - int width = matrix.getWidth(); - int height = matrix.getHeight(); - BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE); - } - } - return image; - } - - private static void writeToFile(BitMatrix matrix, String format, File file) throws IOException { - BufferedImage image = toBufferedImage(matrix); - if (!ImageIO.write(image, format, file)) { - throw new IOException("Could not write an image of format " + format + " to " + file); - } - } - - /** - * 将内容contents生成长宽均为width的图片,图片路径由imgPath指定 - */ - public static File getQRCodeImage(String contents, int size, String imgPath) { - return getQRCodeImage(contents, size, size, imgPath); - } - - /** - * 将内容contents生成长为width,宽为width的图片,图片路径由imgPath指定 - */ - public static File getQRCodeImage(String contents, int width, int height, String imgPath) { - try { - Map hints = new Hashtable<>(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); - hints.put(EncodeHintType.CHARACTER_SET, "UTF8"); - - BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints); - - File imageFile = new File(imgPath); - writeToFile(bitMatrix, "png", imageFile); - return imageFile; - } catch (Exception e) { - return null; - } - } - - /** - * 将内容contents生成长为width,宽为width的图片,图片路径由imgPath指定 - */ - public static String getQRCodeImgBase64(String contents, int width, int height) { - String resultBase64 = null; - try { - Map hints = new Hashtable<>(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); - hints.put(EncodeHintType.CHARACTER_SET, "UTF8"); - - BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints); - -// File imageFile = new File(imgPath); -// writeToFile(bitMatrix, "svg", imageFile); - return resultBase64; - } catch (Exception e) { - return null; - } - } - - - - public static void main(String[] args) { - -// String product_id = "999981XBD100XBD200XBD0.01XBD1"; -// // product_id = MD5Util.MD5Encode(product_id, "UTF-8"); -// String sec = Long.toString(System.currentTimeMillis()); -// String timeStamp = Long.toString(System.currentTimeMillis() / 1000); -// SimpleDateFormat formatter = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒"); -// Date date = new Date(System.currentTimeMillis()); -// String s = formatter.format(date); -// String nonceStr = Long.toString(System.currentTimeMillis()); -// Map packageParams = new HashMap<>(); -// packageParams.put("appid", WeChatConfig.getAppId()); -// packageParams.put("mch_id", WeChatConfig.getMchId()); -// packageParams.put("product_id", product_id); -// packageParams.put("time_stamp", timeStamp); -// packageParams.put("nonce_str", nonceStr); -// String sign = SignatureUtil.generateSign(packageParams, WeChatConfig.getMchKey()); -// String url = "weixin://wxpay/bizpayurl?sign=" + sign + "&appid=" + -// WxConfig.getInstance().getAppId() -// + "&mch_id=" + WxConfig.getInstance().getMchId() + "&product_id=" + -// product_id + "&time_stamp=" -// + timeStamp + "&nonce_str=" + nonceStr; -//// String url = "http://lhxrmyy1.natapp1.cc/wx/q?p=10000005"; -// // String url = -// // "weixin:/pay/bizpayurl?sign=38128468EEFC56C19EDEAD077E8BD38B&appid=wx940ec0975be0daf4&mchid=1354195702&product_id=123815|814994|2074382|0.90|1&time_stamp=1533309475&nonce_str=1533309475421&"; -// -// // String[] array = product_id.split("\\|"); -// // String patientId = array[0]; -// // String mzNum = array[1]; -// // String recipeId = array[2]; -// // String payMoney = array[3]; -// // if (patientId.equals("") || mzNum.equals("") || recipeId.equals("") -// // || payMoney.equals("")) { -// // System.out.println("扫码支付:参数中有空值,不允许支付!product_id=" + product_id); -// // return; -// // } - - getQRCodeImage("http://www.wsxrmyy.cn/wx/qr-questionnaire.html", 300, "C:\\Users\\Administrator\\Desktop\\qr_questionnaire"); - } - - - - -} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java index 0d391bd..92225d0 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java @@ -61,7 +61,7 @@ public class WxAuthHelper { log.info("[认证授权-解码] authSessionId={}, param={}", authSessionId, param); SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); - log.info("[认证授权]信息 snsToken={}", JsonHelper.toJsonString(snsToken)); +// log.info("[认证授权]信息 snsToken={}", JsonHelper.toJsonString(snsToken)); if (snsToken != null) { String openid = snsToken.getOpenid(); String unionId = snsToken.getUnionid(); @@ -147,7 +147,7 @@ public class WxAuthHelper { AuthTokenData authTokenData = new AuthTokenData(); String cacheTokenOpenId = authTokenData.decodeToken(token, WeChatConfig.APP_ID); - log.warn("[授权is_auth] has_token={}, state={}, isUserInfo={}, deState={}", !ObjectUtils.isEmpty(token), state, isUserInfo, deState); + log.info("[授权is_auth] has_token={}, state={}, isUserInfo={}, deState={}", !ObjectUtils.isEmpty(token), state, isUserInfo, deState); String authSessionId = null; if (WeChatConfig.IS_ENABLE_GMC) { // 开启医共体开关 @@ -206,8 +206,6 @@ public class WxAuthHelper { String gmcOpenId = sessionGmcOpenId == null ? null : sessionGmcOpenId.toString(); log.info("[向主服务器请求认证] gmcOpenId={}", gmcOpenId); - - if (gmcOpenId == null) { GMCUser gmcUser = new GMCUserService().queryInfoByOpenId(openId); if (gmcUser != null) { @@ -331,12 +329,12 @@ public class WxAuthHelper { /** * 从缓存获取数据 * - * @param request - * @param openId - * @param state - * @param isUserInfo - * @param authSessionId - * @return + * @param request request + * @param openId openId + * @param state state + * @param isUserInfo isUserInfo + * @param authSessionId authSessionId + * @return AuthResultData */ public static AuthResultData getCacheUserData(HttpServletRequest request, String openId, String state, String isUserInfo, String authSessionId) throws ServiceException { log.info("[微信认证]openid={}", openId); @@ -408,7 +406,7 @@ public class WxAuthHelper { ? WeChatConfig.getBackupURL(isHttpsWithProxy(request)) : WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)); - log.warn("[微信认证][getAuthUrl] baseURL={}, serverName={}, state={}, authState={}", baseURL, serverName, state, authState); +// log.info("[微信认证][getAuthUrl] baseURL={}, serverName={}, state={}, authState={}", baseURL, serverName, state, authState); state = OAUTH_URL + baseURL + "wx_auth/" + api + "?p=" + state + // 发起认证的网页链接 @@ -417,7 +415,7 @@ public class WxAuthHelper { "&forcePopup=true" + "&state=" + authState + // state位置固定 "#wechat_redirect"; - log.warn("[认证授权链接]{}", state); +// log.info("[认证授权链接]{}", state); return Base64Helper.encode(state); } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java index 75388ca..268f0d7 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java @@ -157,6 +157,9 @@ public class WxPassiveReplyHelper { case 武定忠爱医院: return WxPassiveReplyHelper.武定忠爱医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); + case 景洪第三人民医院: + return WxPassiveReplyHelper.景洪第三人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); + case 华坪县人民医院: return WxPassiveReplyHelper.华坪县人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); @@ -177,7 +180,7 @@ public class WxPassiveReplyHelper { private static Boolean 武定忠爱医院(HttpServletResponse response, String reqContent, String msgType, String fromUserName, String toUserName, String eventKey, String event) { if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event) || WxEventEnum.EVENT_SCAN.CODE.equals(event)) { // 关注 || 扫描接口生成公众号的二维码 String content = "欢迎关注武定忠爱医院!" + "\n\uD83D\uDD17 今日挂号" + "\n\uD83D\uDD17 预约挂号"; @@ -187,6 +190,18 @@ public class WxPassiveReplyHelper { return true; } + private static Boolean 景洪第三人民医院(HttpServletResponse response, String reqContent, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event) || WxEventEnum.EVENT_SCAN.CODE.equals(event)) { + String content = "首次预约心理治疗/咨询,或六从上未进行心理治疗/咨询的来访请务必先挂号“心理门诊”。" + + "\n\uD83D\uDD17 今日挂号" + + "\n\uD83D\uDD17 预约挂号"; + WxFactory.Base.PassiveMsg().createXmlTextMsg(response, fromUserName, toUserName, content); + } + } + return true; + } + public static boolean 芒市人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java index 62631e4..901a502 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java @@ -266,17 +266,20 @@ public class WxPayHelper { try { refundResult = PayMchAPI.secapiPayRefund(refund, WeChatConfig.MCH_KEY); if (refundResult == null) { + log.error("【微信】退款返回为空"); throw new Exception(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message); } } catch (Exception e) { - log.error("【微信】退款接口调用异常 outTradeNo={}", outTradeNo); + log.error("【微信】退费证书过期或接口调用异常 outTradeNo={}", outTradeNo); order.setErrorMsg(ResultEnum.INTERFACE_WX_INVOKE_ERROR.message); + order.setRefundResult("退费证书过期或接口调用异常"); return order; } String code = refundResult.getReturn_code(); String message = refundResult.getReturn_msg(); String resultCode = refundResult.getResult_code(); + if (!SUCCESS.equals(resultCode)) { String errCode = refundResult.getErr_code(); String errCodeDesc = refundResult.getErr_code_des(); @@ -351,7 +354,7 @@ public class WxPayHelper { long endTime = System.currentTimeMillis(); // 结束时间 long takeTime = endTime - begTime; if (takeTime > 6000) { - log.warn("【微信】[扫码盒子]下单耗时超过6s [{}]", outTradeNo); + log.warn("【微信】[扫码盒子]下单耗时超过6s 耗时[{}][{}]", (takeTime + "ms"), outTradeNo); } log.info("【微信】[扫码盒子]下单完成-耗时:[{}] [{}]", (takeTime + "ms"), outTradeNo); diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/auth/Client.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/Client.java index b42f4ce..66b829c 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/base/auth/Client.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/Client.java @@ -1,16 +1,17 @@ package com.ynxbd.wx.wxfactory.base.auth; +import com.alibaba.fastjson.JSONObject; import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.wx.wxfactory.WxCacheHelper; -import com.ynxbd.wx.wxfactory.base.auth.models.RespAccessToken; -import com.ynxbd.wx.wxfactory.base.auth.models.RespJsapiTicket; -import com.ynxbd.wx.wxfactory.base.auth.models.SnsOath2AccessToken; -import com.ynxbd.wx.wxfactory.base.auth.models.SnsUserInfo; +import com.ynxbd.wx.wxfactory.base.auth.models.*; import com.ynxbd.wx.wxfactory.utils.EmojiHelper; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import java.util.HashMap; +import java.util.Map; + @Slf4j @NoArgsConstructor public class Client { @@ -111,6 +112,29 @@ public class Client { } + /** + * 获取微信token + * + * @return accessToken + */ + public synchronized QRCodeInfo getQRCode(String token, String scene_str) { + Map action_info = new HashMap<>(); + Map scene = new HashMap<>(); + scene.put("scene_str", scene_str); // 字符串类型,长度限制为1到64 + action_info.put("scene", scene); + System.out.println(JsonHelper.toJsonString(action_info)); + + String respJson = OkHttpHelper.postJsonStr("https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + token, params -> { + params.put("action_name", "QR_LIMIT_STR_SCENE"); // 二维码类型:QR_SCENE(临时整型)/QR_STR_SCENE(临时字符串)/QR_LIMIT_SCENE(永久整型)/QR_LIMIT_STR_SCENE(永久字符串) + params.put("action_info", action_info); + }, null); + log.info("[创建公众号二维码]{}", respJson); + if(respJson == null) { + return null; + } + return JsonHelper.parseObject(respJson, QRCodeInfo.class); + } + // public static String getSnsToken() { // if (ACCESS_TOKEN_CACHE == null) { // createAccessTokenCache(); diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/QRCodeInfo.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/QRCodeInfo.java new file mode 100644 index 0000000..2fecd27 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/QRCodeInfo.java @@ -0,0 +1,20 @@ +package com.ynxbd.wx.wxfactory.base.auth.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Getter +@Setter +@ToString +@NoArgsConstructor +@Slf4j +public class QRCodeInfo { + private String ticket; + + private String url; + + private String qrcode; +} diff --git a/src/main/resources/webservice.properties b/src/main/resources/webservice.properties index 14fa25f..8788884 100644 --- a/src/main/resources/webservice.properties +++ b/src/main/resources/webservice.properties @@ -1 +1 @@ -# \u5F00\u542F\u5904\u65B9\u9884\u7ED3\u7B97\uFF08\u7B2C2\u5F00\u5173\uFF09\uFF08\u6CE8\u610F\u8BE5\u914D\u7F6E\u9700\u8054\u7CFBhis\u5F00\u53D1\u8005\u786E\u8BA4\u652F\u6301\u624D\u80FD\u5F00\u542F\uFF0C\u5426\u5219\u5B58\u5728\u98CE\u9669\uFF01\uFF09 his.is_recipe_prepay=false # \u672C\u5730 #his.url=127.0.0.1:8888 # HIS\u662F\u5426\u5F00\u542F\u652F\u4ED8\u5B9D\u5206\u5F00\u5BF9\u8D26 his.is_ali_mer=false # \u662F\u5426\u5F3A\u5236\u6253\u5370webservice\u7684xml\u8FD4\u56DE\u6570\u636E his.is_log_resp=true # \u662F\u5426\u4F20\u9012openid\u7ED9his\u63A8\u9001\u6D88\u606F his.is_push_msg=false #------------------------------- # \u6D4B\u8BD5\u73AF\u5883 his.dev_url=200.200.200.105:8888 # \u533B\u4FDD=========================== # \u65E7\u914D\u7F6E his.md_url=127.0.0.1:7777 # \u5FAE\u4FE1\u533B\u4FDD his.wx_med_url=10.20.10.7:7885 # \u652F\u4ED8\u5B9D\u533B\u4FDD his.ali_med_url=10.20.10.7:7885 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u77F3\u6797\u6D4B\u8BD5 #his.url=200.200.200.105:8888 # \u6D4B\u8BD5============================================================ # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u7EA2\u6CB3\u5DDE\u533B\u9662 #his.url=10.20.10.6:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # \u5B81\u8497\u5987\u5E7C #his.url=172.19.3.15:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.39:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u7EA2\u6CB3 #his.url=10.20.10.6:8888 # \u7EA2\u6CB3\u533B\u4FDD #his.url=10.20.10.6:8888 #his.url=192.168.12.10:8888 #his.md_url=192.168.1.128:7885 #his.dev_url=10.20.10.6:9988 # \u6C38\u80DC #his.url=200.200.200.20:8888 # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u534E\u576A #his.url=192.168.1.115:8888 # \u8499\u81EA\u4E2D\u533B #his.url=192.168.0.228:8888 # \u7389\u9F99 his.url=192.168.0.17:8888 # #his.url=172.16.10.15:8888 # \u7984\u529D\u949F\u7231 #his.url=200.200.200.5:8888 # \u8499\u81EA\u5E02\u4EBA\u6C11\u533B\u9662 #his.url=200.200.200.174:8080 # \u5143\u8C0B #his.url=200.200.200.29:8888 # \u5143\u8C0B\u533B\u4FDD #his.dev_url=200.200.200.36:9999 # \u8292\u5E02 #his.url=192.168.100.8:8888 # \u7EA2\u6CB3\u5987\u5E7C\u4FDD\u5065\u9662 #his.url=192.168.1.204:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # #his.url=10.10.11.23:8888 # \u77F3\u6797 #his.url=192.168.10.10:8888 # \u5BCC\u6C11 #his.url=200.200.201.27:8888 # \u897F\u53CC\u7248\u7EB3 #his.url=10.10.11.23:8888 #wx.password=ynxbd@6910 \ No newline at end of file +# \u5F00\u542F\u5904\u65B9\u9884\u7ED3\u7B97\uFF08\u7B2C2\u5F00\u5173\uFF09\uFF08\u6CE8\u610F\u8BE5\u914D\u7F6E\u9700\u8054\u7CFBhis\u5F00\u53D1\u8005\u786E\u8BA4\u652F\u6301\u624D\u80FD\u5F00\u542F\uFF0C\u5426\u5219\u5B58\u5728\u98CE\u9669\uFF01\uFF09 his.is_recipe_prepay=false # \u672C\u5730 #his.url=127.0.0.1:8888 # HIS\u662F\u5426\u5F00\u542F\u652F\u4ED8\u5B9D\u5206\u5F00\u5BF9\u8D26 his.is_ali_mer=false # \u662F\u5426\u5F3A\u5236\u6253\u5370webservice\u7684xml\u8FD4\u56DE\u6570\u636E his.is_log_resp=false # \u662F\u5426\u4F20\u9012openid\u7ED9his\u63A8\u9001\u6D88\u606F his.is_push_msg=false #------------------------------- # \u6D4B\u8BD5\u73AF\u5883 his.dev_url=200.200.200.105:8888 # \u533B\u4FDD=========================== # \u65E7\u914D\u7F6E his.md_url=127.0.0.1:7777 # \u5FAE\u4FE1\u533B\u4FDD his.wx_med_url=10.20.10.7:7885 # \u652F\u4ED8\u5B9D\u533B\u4FDD his.ali_med_url=10.20.10.7:7885 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u77F3\u6797\u6D4B\u8BD5 #his.url=200.200.200.105:8888 # \u6D4B\u8BD5============================================================ # \u5FB7\u5B8F\u4E2D\u533B his.url=200.200.200.60:9999 # \u7EA2\u6CB3\u5DDE\u533B\u9662 #his.url=10.20.10.6:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # \u5B81\u8497\u5987\u5E7C #his.url=172.19.3.15:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.39:8888 # \u516C\u53F8\u6D4B\u8BD5 #his.url=192.168.12.10:8888 # \u7EA2\u6CB3 #his.url=10.20.10.6:8888 # \u7EA2\u6CB3\u533B\u4FDD #his.url=10.20.10.6:8888 #his.url=192.168.12.10:8888 #his.md_url=192.168.1.128:7885 #his.dev_url=10.20.10.6:9988 # \u6C38\u80DC #his.url=200.200.200.20:8888 # \u5FB7\u5B8F\u4E2D\u533B #his.url=200.200.200.60:8888 # \u534E\u576A #his.url=192.168.1.115:8888 # \u8499\u81EA\u4E2D\u533B #his.url=192.168.0.228:8888 # \u7389\u9F99 #his.url=192.168.0.17:8888 # #his.url=172.16.10.15:8888 # \u7984\u529D\u949F\u7231 #his.url=200.200.200.5:8888 # \u8499\u81EA\u5E02\u4EBA\u6C11\u533B\u9662 #his.url=200.200.200.174:8080 # \u5143\u8C0B #his.url=200.200.200.29:8888 # \u5143\u8C0B\u533B\u4FDD #his.dev_url=200.200.200.36:9999 # \u8292\u5E02 #his.url=192.168.100.8:8888 # \u7EA2\u6CB3\u5987\u5E7C\u4FDD\u5065\u9662 #his.url=192.168.1.204:8888 # \u8292\u5E02\u5987\u5E7C #his.url=192.168.11.7:8888 # #his.url=10.10.11.23:8888 # \u77F3\u6797 #his.url=192.168.10.10:8888 # \u5BCC\u6C11 #his.url=200.200.201.27:8888 # \u897F\u53CC\u7248\u7EB3 #his.url=10.10.11.23:8888 #wx.password=ynxbd@6910 \ No newline at end of file diff --git a/src/main/resources/wx.properties b/src/main/resources/wx.properties index 7d1fc89..143a229 100644 --- a/src/main/resources/wx.properties +++ b/src/main/resources/wx.properties @@ -5,7 +5,9 @@ wx.aes_key= wx.mch_id= wx.mch_key= # \u57DF\u540D -wx.domain= +wx.domain=http://www.baidu.com +# \u5907\u7528\u57DF\u540D\uFF08\u4E3B\u8981\u7528\u4E8E\u533B\u5171\u4F53\u8BA4\u8BC1\u6216\u4F5C\u4E3A\u7B2C\u4E8C\u57DF\u540D\uFF09 +wx.backup_domain= # \u9879\u76EE\u90E8\u7F72\u670D\u52A1\u540D wx.deploy_server_name=wx # \u9759\u6001\u8D44\u6E90\u8DEF\u5F84 @@ -14,13 +16,16 @@ wx.web_static_path=/web wx.password=ynxbd@6910 -# \u662F\u5426\u4E3A\u6D4B\u8BD5\u73AF\u5883 +# \u662F\u5426\u4E3A\u6D4B\u8BD5\u73AF\u5883================================= wx.is_dev=true # \u7528\u4E8E\u6388\u6743\u7684\u533B\u5171\u4F53\u516C\u4F17\u53F7\u914D\u7F6E======================= -wx.gmc.is_enable= -wx.gmc.auth_domain= -wx.gmc.app_id= -# \u5C0F\u7A0B\u5E8F\u4E3B\u4F53AppId -wx.gmc.mini.app_id= +wx.gmc.is_enable=false +wx.gmc.auth_domain=https://www.slxrmyy.cn +# \u516C\u4F17\u53F7\u4E3B\u4F53AppId\uFF08\u53BF\u533B\u9662\u516C\u4F17\u53F7AppId\uFF0C\u4E3B\u4F53\u533B\u9662\u65E0\u9700\u914D\u7F6E\uFF09 +wx.gmc.app_id=wxe53f0f528bb16d9f + +# \u5C0F\u7A0B\u5E8F\u4E3B\u4F53AppId[\u7528\u4E8E\u652F\u4ED8]======================== +wx.gmc.mini.app_id=wx80685a7daa772a0b +# \u5C0F\u7A0B\u5E8F\u4E3B\u4F53AppSecret\uFF08\u4EC5\u9700\u4E3B\u4F53\u53BF\u533B\u9662\u914D\u7F6E\uFF09 wx.gmc.mini.app_secret= \ No newline at end of file