From a1385464497930a65e2bb3d8c7c11d05f89026c0 Mon Sep 17 00:00:00 2001 From: wangsq Date: Thu, 4 Dec 2025 16:32:06 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4=EF=BC=8C?= =?UTF-8?q?=E8=A2=AB=E5=8A=A8=E6=B6=88=E6=81=AF=E5=9B=9E=E5=A4=8D=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E6=8A=BD=E7=A6=BB=E7=AC=AC=E4=B8=89=E6=96=B9=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ynxbd/ali/helper/AliMedHelper.java | 2 +- src/main/java/com/ynxbd/common/TestA.java | 9 +- .../com/ynxbd/common/action/ApiAction.java | 2 +- .../common/action/pay/MedicalAction.java | 8 +- .../common/action/pay/MedicalTestAction.java | 2 +- .../ynxbd/common/action/pay/NotifyAction.java | 2 +- .../ynxbd/common/action/pay/PayAction.java | 2 +- .../ynxbd/common/action/pay/WxPayAction.java | 2 +- .../ynxbd/common/action/test/TestAction.java | 2 - .../com/ynxbd/common/dao/his/HisMedDao.java | 2 +- .../common/helper/common/MethodHelper.java | 2 +- .../common/helper/common/RepeatKeyHelper.java | 6 +- .../ynxbd/common/service/MedicalService.java | 8 +- .../com/ynxbd/common/service/PayService.java | 2 +- .../ynxbd/common/service/RecipeService.java | 2 +- .../com/ynxbd/common/service/RegService.java | 2 +- .../java/com/ynxbd/common/service/Test.java | 87 -- .../java/com/ynxbd/wx/config/WxEventEnum.java | 3 + .../java/com/ynxbd/wx/remove/dao/DBDao.java | 5 +- .../ynxbd/wx/remove/servlet/DemoServlet2.java | 11 +- .../ynxbd/wx/remove/servlet/OAuthServlet.java | 3 +- .../wx/remove/servlet/PayMchJsServlet.java | 5 +- .../remove/servlet/PayMchNotifyServlet.java | 6 +- .../ynxbd/wx/remove/servlet/PayServlet.java | 4 - .../com/ynxbd/wx/remove/servlet/PayTest.java | 5 +- .../wx/remove/servlet/QRPayUrlServlet.java | 5 +- .../wx/remove/servlet/RegPayMchJsServlet.java | 5 +- .../servlet/RegPayMchNotifyServlet.java | 6 +- .../servlet/Time_RegPayMchJsServlet.java | 5 +- .../servlet/Time_RegPayMchNotifyServlet.java | 6 +- .../com/ynxbd/wx/remove/util/CommonUtil.java | 4 +- .../wx/remove/util/DefaultExpireKey.java | 1 - .../com/ynxbd/wx/remove/util/MessageUtil.java | 3 +- .../java/com/ynxbd/wx/servlet/WxServlet.java | 6 +- .../wx/servlet/oldpay/PayNotifyServlet.java | 2 +- .../ynxbd/wx/servlet/oldpay/QRPayServlet.java | 77 +- .../wx/servlet/oldpay/QRPayServlet2.java | 189 --- .../com/ynxbd/wx/servlet/test/OrderTest.java | 96 -- .../ynxbd/wx/servlet/test/WxAuthServlet.java | 3 +- .../test/WxNativePayNotifyServlet.java | 2 +- .../ynxbd/wx/servlet/test/WxOrderTest.java | 66 +- .../wx/servlet/test/WxPayNotifyServlet.java | 2 +- .../ynxbd/wx/servlet/test/WxUAuthServlet.java | 30 - .../com/ynxbd/wx/wxfactory/AesWxHelper.java | 2 +- .../com/ynxbd/wx/wxfactory/WxAuthHelper.java | 568 ++++----- .../com/ynxbd/wx/wxfactory/WxCacheHelper.java | 4 +- .../com/ynxbd/wx/wxfactory/WxFactory.java | 10 +- .../com/ynxbd/wx/wxfactory/WxMedHelper.java | 11 +- .../{utils => }/WxPassiveReplyHelper.java | 1028 ++++++++--------- .../com/ynxbd/wx/wxfactory/WxPayHelper.java | 12 +- .../ynxbd/wx/wxfactory/base/auth/Client.java | 8 +- .../auth/models}/AccessToken.java | 40 +- .../auth => base/auth/models}/AuthData.java | 2 +- .../auth/models}/JsapiTicket.java | 2 +- .../base/auth/models/RespAccessToken.java | 1 - .../auth/models}/SnsOath2AccessToken.java | 56 +- .../auth/models}/SnsUserInfo.java | 66 +- .../auth/models}/WxBaseResult.java | 40 +- .../wx/wxfactory/base/passivemsg/Client.java | 68 ++ .../passivemsg}/event/WxEvent.java | 64 +- .../passivemsg}/event/WxEventMessage.java | 263 +++-- .../base/passivemsg/models/XMLBaseMsg.java | 93 ++ .../base/passivemsg/models/XMLImageMsg.java | 27 + .../base/passivemsg/models/XMLNewsMsg.java | 68 ++ .../base/passivemsg/models/XMLTextMsg.java | 29 + .../ynxbd/wx/wxfactory/medical/Client.java | 3 +- .../models/MedRespHelper.java} | 132 +-- .../{bean => medical/models}/MedicalBill.java | 6 +- .../{bean => medical/models}/MedicalInfo.java | 108 +- .../models}/MedicalNotify.java | 148 +-- .../models}/MedicalPayOrder.java | 40 +- .../models}/MedicalRefund.java | 42 +- .../models}/MedicalRefundInfo.java | 60 +- .../models}/MedicalUserInfo.java | 56 +- .../{bean => medical/models}/WxMedOrder.java | 2 +- .../wx/wxfactory/menu/bean/WxMsgConst.java | 225 ++-- .../wx/wxfactory/menu/bean/XMLParse.java | 5 +- .../ynxbd/wx/wxfactory/message/MdClient.java | 3 + .../{bean => payment}/OrderMIEnum.java | 2 +- .../wx/wxfactory/payment/WXPayUtility.java | 912 +++++++++++++++ .../wx/wxfactory/payment/jsapi/Client.java | 371 +++--- .../jsapi/models}/WxNativePayResult.java | 2 +- .../jsapi/models}/WxPayNotify.java | 81 +- .../{base => payment}/refund/Client.java | 72 +- .../payment/refund/models/RefundCoupon.java | 25 + .../refund/models}/WxRefundItem.java | 61 +- .../refund/models}/WxRefundQueryRoot.java | 159 ++- .../ynxbd/wx/wxfactory/utils/EmojiHelper.java | 51 + .../wx/wxfactory/utils/WechatPayHelper.java | 8 + .../wx/wxfactory/utils/WxEventHelper.java | 118 +- .../WxMedAssistantHelper.java} | 5 +- .../wx/wxfactory/utils/WxSignHelper.java | 61 +- .../ynxbd/wx/wxfactory/utils/XmlHelper.java | 2 +- 93 files changed, 3388 insertions(+), 2526 deletions(-) delete mode 100644 src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet2.java delete mode 100644 src/main/java/com/ynxbd/wx/servlet/test/OrderTest.java delete mode 100644 src/main/java/com/ynxbd/wx/servlet/test/WxUAuthServlet.java rename src/main/java/com/ynxbd/wx/wxfactory/{utils => }/WxPassiveReplyHelper.java (73%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/auth/models}/AccessToken.java (87%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean/auth => base/auth/models}/AuthData.java (98%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/auth/models}/JsapiTicket.java (90%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/auth/models}/SnsOath2AccessToken.java (91%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/auth/models}/SnsUserInfo.java (92%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/auth/models}/WxBaseResult.java (88%) create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/Client.java rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/passivemsg}/event/WxEvent.java (85%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => base/passivemsg}/event/WxEventMessage.java (75%) create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLBaseMsg.java create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLImageMsg.java create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLNewsMsg.java create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLTextMsg.java rename src/main/java/com/ynxbd/wx/wxfactory/{utils/MdRespHelper.java => medical/models/MedRespHelper.java} (91%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalBill.java (85%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalInfo.java (94%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalNotify.java (97%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalPayOrder.java (91%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalRefund.java (89%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalRefundInfo.java (92%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/MedicalUserInfo.java (86%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => medical/models}/WxMedOrder.java (97%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => payment}/OrderMIEnum.java (96%) create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/payment/WXPayUtility.java rename src/main/java/com/ynxbd/wx/wxfactory/{bean => payment/jsapi/models}/WxNativePayResult.java (82%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean => payment/jsapi/models}/WxPayNotify.java (92%) rename src/main/java/com/ynxbd/wx/wxfactory/{base => payment}/refund/Client.java (90%) create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/RefundCoupon.java rename src/main/java/com/ynxbd/wx/wxfactory/{bean/refund => payment/refund/models}/WxRefundItem.java (81%) rename src/main/java/com/ynxbd/wx/wxfactory/{bean/refund => payment/refund/models}/WxRefundQueryRoot.java (87%) create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/utils/EmojiHelper.java create mode 100644 src/main/java/com/ynxbd/wx/wxfactory/utils/WechatPayHelper.java rename src/main/java/com/ynxbd/wx/wxfactory/{WxMessageHelper.java => utils/WxMedAssistantHelper.java} (94%) diff --git a/src/main/java/com/ynxbd/ali/helper/AliMedHelper.java b/src/main/java/com/ynxbd/ali/helper/AliMedHelper.java index bb4ca9b..9e1907e 100644 --- a/src/main/java/com/ynxbd/ali/helper/AliMedHelper.java +++ b/src/main/java/com/ynxbd/ali/helper/AliMedHelper.java @@ -23,7 +23,7 @@ import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.common.ErrorHelper; import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.result.ServiceException; -import com.ynxbd.wx.wxfactory.bean.OrderMIEnum; +import com.ynxbd.wx.wxfactory.payment.OrderMIEnum; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; diff --git a/src/main/java/com/ynxbd/common/TestA.java b/src/main/java/com/ynxbd/common/TestA.java index b54440b..db75e77 100644 --- a/src/main/java/com/ynxbd/common/TestA.java +++ b/src/main/java/com/ynxbd/common/TestA.java @@ -1,12 +1,13 @@ package com.ynxbd.common; -import com.ynxbd.common.helper.common.Base64Helper; - -import java.io.UnsupportedEncodingException; +import com.ynxbd.wx.utils.DesEncryptHelper; public class TestA { - public static void main(String[] args) throws UnsupportedEncodingException { + 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/ApiAction.java b/src/main/java/com/ynxbd/common/action/ApiAction.java index 46f98d2..c46d7f0 100644 --- a/src/main/java/com/ynxbd/common/action/ApiAction.java +++ b/src/main/java/com/ynxbd/common/action/ApiAction.java @@ -11,7 +11,7 @@ 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.bean.AccessToken; +import com.ynxbd.wx.wxfactory.base.auth.models.AccessToken; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.convention.annotation.Action; diff --git a/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java b/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java index 5862686..7537d55 100644 --- a/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/MedicalAction.java @@ -20,9 +20,9 @@ import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.MedicalService; import com.ynxbd.common.service.params.RequestParams; import com.ynxbd.wx.wxfactory.*; -import com.ynxbd.wx.wxfactory.bean.*; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; -import com.ynxbd.wx.wxfactory.utils.MdRespHelper; +import com.ynxbd.wx.wxfactory.medical.models.*; +import com.ynxbd.wx.wxfactory.medical.models.MedRespHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.struts2.convention.annotation.Action; @@ -385,7 +385,7 @@ public class MedicalAction extends BaseAction { log.info("[微信医保]回调通知..."); MedicalNotify notifyInfo = WxMedHelper.paidMedNotify(request); // 成功返回 - Result.respXml(MdRespHelper.respOk(WxMedConfig.PAY_KEY)); + Result.respXml(MedRespHelper.respOk(WxMedConfig.PAY_KEY)); String openid = notifyInfo.getOpenid(); String bankTransNo = notifyInfo.getMedTransId(); @@ -403,7 +403,7 @@ public class MedicalAction extends BaseAction { new MedicalService().commonNotify(MerchantEnum.WX_MEDICAL, notifyType, outTradeNo, totalFee, bankTransNo, payDate, payTime, openid, payInfo); return null; } catch (ServiceException e) { - return Result.respXml(MdRespHelper.resp(e, WxMedConfig.PAY_KEY)); + return Result.respXml(MedRespHelper.resp(e, WxMedConfig.PAY_KEY)); } } diff --git a/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java b/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java index dcdea41..e9afe19 100644 --- a/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java @@ -21,7 +21,7 @@ import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.RecipeService; import com.ynxbd.wx.wxfactory.WxCacheHelper; import com.ynxbd.wx.wxfactory.WxMedHelper; -import com.ynxbd.wx.wxfactory.bean.WxMedOrder; +import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; 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 cdb3b96..b14e663 100644 --- a/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/NotifyAction.java @@ -6,7 +6,7 @@ import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.*; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; import com.ynxbd.wx.wxfactory.utils.WxRespHelper; import lombok.extern.slf4j.Slf4j; import org.apache.struts2.convention.annotation.Action; 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 75bd4b1..24e16e9 100644 --- a/src/main/java/com/ynxbd/common/action/pay/PayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/PayAction.java @@ -21,7 +21,7 @@ import com.ynxbd.common.service.*; import com.ynxbd.common.service.params.RequestParams; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxNativePayResult; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxNativePayResult; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.ObjectUtils; 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 28163a6..b40c58f 100644 --- a/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java +++ b/src/main/java/com/ynxbd/common/action/pay/WxPayAction.java @@ -7,7 +7,7 @@ import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.OutCollectService; import com.ynxbd.common.service.PayService; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; import com.ynxbd.wx.wxfactory.utils.WxRespHelper; import lombok.extern.slf4j.Slf4j; import org.apache.struts2.convention.annotation.Action; 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 ed40fa5..9f384e8 100644 --- a/src/main/java/com/ynxbd/common/action/test/TestAction.java +++ b/src/main/java/com/ynxbd/common/action/test/TestAction.java @@ -1,12 +1,10 @@ package com.ynxbd.common.action.test; import com.ynxbd.common.action.base.BaseAction; -import com.ynxbd.common.bean.pay.PayCasebook; 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.common.service.CasebookService; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import lombok.extern.slf4j.Slf4j; import org.apache.struts2.convention.annotation.Action; diff --git a/src/main/java/com/ynxbd/common/dao/his/HisMedDao.java b/src/main/java/com/ynxbd/common/dao/his/HisMedDao.java index 3e8b27a..bd01815 100644 --- a/src/main/java/com/ynxbd/common/dao/his/HisMedDao.java +++ b/src/main/java/com/ynxbd/common/dao/his/HisMedDao.java @@ -13,7 +13,7 @@ import com.ynxbd.common.helper.his.HisMedHelper; import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ResultEnum; -import com.ynxbd.wx.wxfactory.bean.MedicalInfo; +import com.ynxbd.wx.wxfactory.medical.models.MedicalInfo; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; diff --git a/src/main/java/com/ynxbd/common/helper/common/MethodHelper.java b/src/main/java/com/ynxbd/common/helper/common/MethodHelper.java index 5b4e472..661a2bb 100644 --- a/src/main/java/com/ynxbd/common/helper/common/MethodHelper.java +++ b/src/main/java/com/ynxbd/common/helper/common/MethodHelper.java @@ -7,7 +7,7 @@ package com.ynxbd.common.helper.common; //import javassist.bytecode.CodeAttribute; //import javassist.bytecode.LocalVariableAttribute; //import javassist.bytecode.MethodInfo; -//import weixin.popular.bean.user.User; + // //public class MethodUtil { // diff --git a/src/main/java/com/ynxbd/common/helper/common/RepeatKeyHelper.java b/src/main/java/com/ynxbd/common/helper/common/RepeatKeyHelper.java index 44a09df..f54f69b 100644 --- a/src/main/java/com/ynxbd/common/helper/common/RepeatKeyHelper.java +++ b/src/main/java/com/ynxbd/common/helper/common/RepeatKeyHelper.java @@ -36,7 +36,6 @@ public class RepeatKeyHelper { } private void timerTask() { - log.info("创建keyList"); if (scheduledExecutorService != null) { scheduledExecutorService.shutdownNow(); } @@ -65,7 +64,7 @@ public class RepeatKeyHelper { for (String key : removeKey) { KEY_MAP.remove(key); } - if (removeKey.size() > 0) { + if (!removeKey.isEmpty()) { log.info("clean {} keys, remain {} keys", removeKey.size(), KEY_MAP.size()); } }, 10, period, TimeUnit.SECONDS); @@ -95,7 +94,6 @@ public class RepeatKeyHelper { } } - log.info("add key=" + key); KEY_MAP.put(key, (System.currentTimeMillis() / 1000) + expire); return false; } @@ -111,7 +109,7 @@ public class RepeatKeyHelper { public void print() { for (String key : KEY_MAP.keySet()) { - log.info("key=" + key + ", value=" + KEY_MAP.get(key)); + log.info("key={}, value={}", key, KEY_MAP.get(key)); } } } diff --git a/src/main/java/com/ynxbd/common/service/MedicalService.java b/src/main/java/com/ynxbd/common/service/MedicalService.java index 2f057ae..905adb6 100644 --- a/src/main/java/com/ynxbd/common/service/MedicalService.java +++ b/src/main/java/com/ynxbd/common/service/MedicalService.java @@ -19,10 +19,10 @@ import com.ynxbd.common.result.ServiceException; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.MedicalInfo; -import com.ynxbd.wx.wxfactory.bean.WxMedOrder; -import com.ynxbd.wx.wxfactory.bean.MedicalUserInfo; -import com.ynxbd.wx.wxfactory.bean.OrderMIEnum; +import com.ynxbd.wx.wxfactory.medical.models.MedicalInfo; +import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; +import com.ynxbd.wx.wxfactory.medical.models.MedicalUserInfo; +import com.ynxbd.wx.wxfactory.payment.OrderMIEnum; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; diff --git a/src/main/java/com/ynxbd/common/service/PayService.java b/src/main/java/com/ynxbd/common/service/PayService.java index 999f7f2..7aa7b0f 100644 --- a/src/main/java/com/ynxbd/common/service/PayService.java +++ b/src/main/java/com/ynxbd/common/service/PayService.java @@ -17,7 +17,7 @@ import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.cache.PayCache; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; diff --git a/src/main/java/com/ynxbd/common/service/RecipeService.java b/src/main/java/com/ynxbd/common/service/RecipeService.java index 2b6e9bc..9e137c6 100644 --- a/src/main/java/com/ynxbd/common/service/RecipeService.java +++ b/src/main/java/com/ynxbd/common/service/RecipeService.java @@ -25,7 +25,7 @@ import com.ynxbd.wx.config.TZReserveConfig; import com.ynxbd.wx.utils.DateGenerate; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxMedOrder; +import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; diff --git a/src/main/java/com/ynxbd/common/service/RegService.java b/src/main/java/com/ynxbd/common/service/RegService.java index 54a9180..5ef9cdd 100644 --- a/src/main/java/com/ynxbd/common/service/RegService.java +++ b/src/main/java/com/ynxbd/common/service/RegService.java @@ -24,7 +24,7 @@ import com.ynxbd.wx.config.MessagePushConfig; import com.ynxbd.wx.utils.DateGenerate; import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxMedOrder; +import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; diff --git a/src/main/java/com/ynxbd/common/service/Test.java b/src/main/java/com/ynxbd/common/service/Test.java index c4e0363..2cfa5bf 100644 --- a/src/main/java/com/ynxbd/common/service/Test.java +++ b/src/main/java/com/ynxbd/common/service/Test.java @@ -1,102 +1,15 @@ package com.ynxbd.common.service; -import com.ynxbd.common.bean.enums.MerchantEnum; -import com.ynxbd.common.bean.pay.Order; -import com.ynxbd.common.dao.his.HisRecipeDao; -import com.ynxbd.common.helper.common.CodeHelper; -import com.ynxbd.common.helper.common.DateHelper; -import com.ynxbd.common.helper.common.ErrorHelper; -import com.ynxbd.common.helper.common.JsonHelper; -import com.ynxbd.common.result.JsonResult; -import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.config.WeChatConfig; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.digest.DigestUtils; -import weixin.popular.api.PayMchAPI; -import weixin.popular.bean.paymch.MchOrderInfoResult; -import weixin.popular.bean.paymch.MchOrderquery; - -import java.math.BigDecimal; -import java.util.ArrayList; @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); } - - /** - * 查询订单 - * - * @param outTradeNo 订单号 - * @return 订单信息 - */ - public static Order queryOrder(String outTradeNo) { - Order order = new Order(); - order.setOutTradeNo(outTradeNo); - try { - MchOrderquery mchOrderquery = new MchOrderquery(); - String appId = WeChatConfig.APP_ID; - String mchId = WeChatConfig.MCH_ID; - String mchKey = WeChatConfig.MCH_KEY; - - mchOrderquery.setAppid(appId); - mchOrderquery.setMch_id(mchId); - mchOrderquery.setOut_trade_no(outTradeNo); - mchOrderquery.setNonce_str(CodeHelper.get32UUID()); - - MchOrderInfoResult wxResult = PayMchAPI.payOrderquery(mchOrderquery, mchKey); - if (wxResult == null) { - order.setErrorMsg("【微信】查询订单失败"); - return order; - } - - // 调用错误 - if (WxPayHelper.FAIL.equals(wxResult.getReturn_code())) { - order.setErrorCode(wxResult.getReturn_code()); - order.setErrorMsg(wxResult.getReturn_msg()); - return order; - } - - // 业务错误 - if (WxPayHelper.FAIL.equals(wxResult.getResult_code())) { - order.setErrorCode(wxResult.getErr_code()); - order.setErrorMsg(wxResult.getErr_code_des()); - return order; - } - - String tradeState = wxResult.getTrade_state(); - order.setTradeState(tradeState); - - if (WxPayHelper.SUCCESS.equals(tradeState)) { - order.setSuccess(true); // 订单支付成功(判断条件) - - } else if (WxPayHelper.REFUND.equals(tradeState)) { - order.setErrorMsg(wxResult.getTrade_state_desc()); - order.setRefund(true); // 订单发生过退款 - } else { - // 交易错误 - order.setErrorCode(tradeState); - order.setErrorMsg(wxResult.getTrade_state_desc()); - return order; - } - - // 交易成功 - order.setOpenid(wxResult.getOpenid()); - order.setBankTransNo(wxResult.getTransaction_id()); - Integer totalFee = wxResult.getTotal_fee(); - if (totalFee != null) { - order.setTotalFee(new BigDecimal(totalFee).movePointLeft(2)); - } - } catch (Exception e) { - ErrorHelper.println(e); - order.setErrorMsg("异常信息:" + e.getMessage()); - } - return order; - } } diff --git a/src/main/java/com/ynxbd/wx/config/WxEventEnum.java b/src/main/java/com/ynxbd/wx/config/WxEventEnum.java index 9a5169a..385904e 100644 --- a/src/main/java/com/ynxbd/wx/config/WxEventEnum.java +++ b/src/main/java/com/ynxbd/wx/config/WxEventEnum.java @@ -32,4 +32,7 @@ public enum WxEventEnum { this.NAME = NAME; } + public boolean isEvent(String event) { + return this.CODE.equals(event); + } } diff --git a/src/main/java/com/ynxbd/wx/remove/dao/DBDao.java b/src/main/java/com/ynxbd/wx/remove/dao/DBDao.java index 8f68b39..19cfda8 100644 --- a/src/main/java/com/ynxbd/wx/remove/dao/DBDao.java +++ b/src/main/java/com/ynxbd/wx/remove/dao/DBDao.java @@ -6,10 +6,7 @@ //import org.apache.commons.lang.math.NumberUtils; //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.SecapiPayRefund; -//import weixin.popular.bean.paymch.SecapiPayRefundResult; -//import weixin.popular.client.LocalHttpClient; + // //import java.sql.Connection; //import java.sql.PreparedStatement; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/DemoServlet2.java b/src/main/java/com/ynxbd/wx/remove/servlet/DemoServlet2.java index 3ad5eff..e3e10a6 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/DemoServlet2.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/DemoServlet2.java @@ -3,16 +3,7 @@ //import com.ynxbd.api.utils.MessageUtil; //import com.ynxbd.api.config.WeChatConfig; //import org.apache.log4j.Logger; -//import weixin.popular.bean.message.EventMessage; -//import weixin.popular.bean.xmlmessage.XMLMessage; -//import weixin.popular.bean.xmlmessage.XMLNewsMessage; -//import weixin.popular.bean.xmlmessage.XMLNewsMessage.Article; -//import weixin.popular.bean.xmlmessage.XMLTextMessage; -//import weixin.popular.support.ExpireKey; -//import weixin.popular.support.expirekey.DefaultExpireKey; -//import weixin.popular.util.SignatureUtil; -//import weixin.popular.util.StreamUtils; -//import weixin.popular.util.XMLConverUtil; + // //import javax.servlet.ServletException; //import javax.servlet.ServletInputStream; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/OAuthServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/OAuthServlet.java index 112e2c5..7c13518 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/OAuthServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/OAuthServlet.java @@ -5,8 +5,7 @@ //import com.ynxbd.api.utils.Global; //import com.ynxbd.api.config.WxConfig; //import org.apache.log4j.NDC; -//import weixin.popular.api.SnsAPI; -//import weixin.popular.bean.sns.SnsToken; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/PayMchJsServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/PayMchJsServlet.java index 99703a6..88a87e7 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/PayMchJsServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/PayMchJsServlet.java @@ -9,10 +9,7 @@ //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.slf4j.MDC; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/PayMchNotifyServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/PayMchNotifyServlet.java index 543c0b7..8153ee6 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/PayMchNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/PayMchNotifyServlet.java @@ -12,11 +12,7 @@ //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.slf4j.MDC; -//import weixin.popular.bean.paymch.MchBaseResult; -//import weixin.popular.bean.paymch.MchPayNotify; -//import weixin.popular.util.SignatureUtil; -//import weixin.popular.util.StreamUtils; -//import weixin.popular.util.XMLConverUtil; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/PayServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/PayServlet.java index 7c65a3a..e97303a 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/PayServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/PayServlet.java @@ -15,10 +15,6 @@ //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.slf4j.MDC; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; // //import javax.servlet.ServletException; //import javax.servlet.annotation.WebServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/PayTest.java b/src/main/java/com/ynxbd/wx/remove/servlet/PayTest.java index a3ab12a..3100d77 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/PayTest.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/PayTest.java @@ -7,10 +7,7 @@ //import com.ynxbd.api.config.WeChatConfig; //import net.sf.json.JSONArray; //import org.apache.log4j.Logger; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/QRPayUrlServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/QRPayUrlServlet.java index e9565cd..142ed2e 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/QRPayUrlServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/QRPayUrlServlet.java @@ -6,10 +6,7 @@ //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.slf4j.MDC; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; + // //import javax.servlet.ServletException; //import javax.servlet.annotation.WebServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchJsServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchJsServlet.java index 5814419..89a3fc3 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchJsServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchJsServlet.java @@ -8,10 +8,7 @@ //import com.ynxbd.api.config.WeChatConfig; //import org.apache.log4j.Logger; //import org.apache.log4j.NDC; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchNotifyServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchNotifyServlet.java index b8751ea..f352b16 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchNotifyServlet.java @@ -13,11 +13,7 @@ //import com.ynxbd.api.utils.Global; //import org.apache.log4j.Logger; //import org.apache.log4j.NDC; -//import weixin.popular.bean.paymch.MchBaseResult; -//import weixin.popular.bean.paymch.MchPayNotify; -//import weixin.popular.util.SignatureUtil; -//import weixin.popular.util.StreamUtils; -//import weixin.popular.util.XMLConverUtil; + // //import javax.servlet.ServletInputStream; //import javax.servlet.ServletOutputStream; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchJsServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchJsServlet.java index f26d509..be4820e 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchJsServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchJsServlet.java @@ -8,10 +8,7 @@ //import com.ynxbd.api.config.WeChatConfig; //import org.apache.log4j.Logger; //import org.apache.log4j.NDC; -//import weixin.popular.api.PayMchAPI; -//import weixin.popular.bean.paymch.Unifiedorder; -//import weixin.popular.bean.paymch.UnifiedorderResult; -//import weixin.popular.util.PayUtil; + // //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; diff --git a/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchNotifyServlet.java b/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchNotifyServlet.java index e5dc7f1..9a66927 100644 --- a/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchNotifyServlet.java @@ -15,11 +15,7 @@ //import com.ynxbd.api.utils.Global; //import org.apache.log4j.Logger; //import org.apache.log4j.NDC; -//import weixin.popular.bean.paymch.MchBaseResult; -//import weixin.popular.bean.paymch.MchPayNotify; -//import weixin.popular.util.SignatureUtil; -//import weixin.popular.util.StreamUtils; -//import weixin.popular.util.XMLConverUtil; + // //import javax.servlet.ServletInputStream; //import javax.servlet.ServletOutputStream; diff --git a/src/main/java/com/ynxbd/wx/remove/util/CommonUtil.java b/src/main/java/com/ynxbd/wx/remove/util/CommonUtil.java index f44de5d..87629e0 100644 --- a/src/main/java/com/ynxbd/wx/remove/util/CommonUtil.java +++ b/src/main/java/com/ynxbd/wx/remove/util/CommonUtil.java @@ -3,9 +3,7 @@ //import com.ynxbd.wx.wxfactory.WxCacheHelper; //import lombok.extern.slf4j.Slf4j; //import org.apache.commons.lang3.StringUtils; -//import weixin.popular.api.MessageAPI; -//import weixin.popular.bean.message.massmessage.MassMPnewsMessage; -//import weixin.popular.bean.message.massmessage.MassTextMessage; + // //import java.text.SimpleDateFormat; //import java.util.Date; diff --git a/src/main/java/com/ynxbd/wx/remove/util/DefaultExpireKey.java b/src/main/java/com/ynxbd/wx/remove/util/DefaultExpireKey.java index f220b47..420c582 100644 --- a/src/main/java/com/ynxbd/wx/remove/util/DefaultExpireKey.java +++ b/src/main/java/com/ynxbd/wx/remove/util/DefaultExpireKey.java @@ -4,7 +4,6 @@ //import org.slf4j.Logger; //import org.slf4j.LoggerFactory; //import org.slf4j.MDC; -//import weixin.popular.support.ExpireKey; // //import java.util.ArrayList; //import java.util.List; diff --git a/src/main/java/com/ynxbd/wx/remove/util/MessageUtil.java b/src/main/java/com/ynxbd/wx/remove/util/MessageUtil.java index 984df51..82e83b2 100644 --- a/src/main/java/com/ynxbd/wx/remove/util/MessageUtil.java +++ b/src/main/java/com/ynxbd/wx/remove/util/MessageUtil.java @@ -1,8 +1,7 @@ //package com.ynxbd.wx.remove.util; // //import com.ynxbd.wx.config.WeChatConfig; -//import weixin.popular.bean.xmlmessage.XMLNewsMessage; -//import weixin.popular.bean.xmlmessage.XMLTextMessage; + // //import java.io.OutputStream; //import java.util.ArrayList; diff --git a/src/main/java/com/ynxbd/wx/servlet/WxServlet.java b/src/main/java/com/ynxbd/wx/servlet/WxServlet.java index d76a968..dddb4f9 100644 --- a/src/main/java/com/ynxbd/wx/servlet/WxServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/WxServlet.java @@ -3,9 +3,9 @@ package com.ynxbd.wx.servlet; import com.ynxbd.common.result.Result; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WxEventEnum; -import com.ynxbd.wx.wxfactory.bean.event.WxEvent; +import com.ynxbd.wx.wxfactory.base.passivemsg.event.WxEvent; import com.ynxbd.wx.wxfactory.utils.WxEventHelper; -import com.ynxbd.wx.wxfactory.utils.WxPassiveReplyHelper; +import com.ynxbd.wx.wxfactory.WxPassiveReplyHelper; import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -28,7 +28,7 @@ public class WxServlet extends HttpServlet { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); - WxEvent wxEvent = WxSignHelper.getReqXmlToBean(request, WxEvent.class); + WxEvent wxEvent = WxSignHelper.reqXmlToBean(request, WxEvent.class); if (wxEvent == null) { String echoStr = request.getParameter("echostr"); if (echoStr != null) { diff --git a/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java b/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java index 72cbd1c..c68b4e6 100644 --- a/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java @@ -6,7 +6,7 @@ import com.ynxbd.common.result.Result; import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.service.RecipeService; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; import com.ynxbd.wx.wxfactory.utils.WxRespHelper; import lombok.extern.slf4j.Slf4j; import org.slf4j.MDC; diff --git a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java b/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java index 51501c5..2ed87a6 100644 --- a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java @@ -4,27 +4,24 @@ import com.ynxbd.common.bean.enums.MerchantEnum; import com.ynxbd.common.dao.RecipeDao; import com.ynxbd.common.helper.common.CodeHelper; import com.ynxbd.common.helper.common.HttpHelper; +import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.service.RecipeService; import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.wxfactory.WxPayHelper; -import com.ynxbd.wx.wxfactory.bean.WxNativePayResult; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxNativePayResult; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; +import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.slf4j.MDC; -import weixin.popular.util.SignatureUtil; -import weixin.popular.util.XMLConverUtil; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; import java.util.Map; /** @@ -47,40 +44,54 @@ public class QRPayServlet extends HttpServlet { log.info("[Native]扫码支付收到支付请求,开始解析..."); - // 读取参数 - InputStream inputStream = request.getInputStream(); - StringBuilder sb = new StringBuilder(); - String s; - BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - while ((s = in.readLine()) != null) { - sb.append(s); - } - in.close(); - inputStream.close(); - // 解析xml成map - Map map = XMLConverUtil.convertToMap(sb.toString()); + Map map = WxSignHelper.reqXmlToMapByNativePay(request); + if (map == null) { + log.info("[Native]回调通知信息解析为空"); + HttpHelper.outRespAlert(response, "回调通知信息解析为空"); + return; + } - // 验证请求签名 - if (!map.get("sign").equals(SignatureUtil.generateSign(map, WeChatConfig.MCH_KEY))) { - log.info("收到扫码支付请求:签名无效!"); + // 签名验证 + if (!WxSignHelper.validateSign(map, WeChatConfig.MCH_KEY)) { // 验证未通过,通知支付失败 + log.info("[Native]收到扫码支付请求:签名无效!"); HttpHelper.outRespAlert(response, "收到扫码支付请求:签名无效!"); return; } + String json = JsonHelper.toJsonString(map); + if (ObjectUtils.isEmpty(json)) { + log.info("[Native]回调通知下单信息为空!"); + HttpHelper.outRespAlert(response, "回调通知下单信息为空"); + return; + } + + WxPayNotify notifyInfo = JsonHelper.parseObject(json, WxPayNotify.class); + if (notifyInfo == null) { + log.info("[Native]收到扫码支付请求:签名无效!"); + HttpHelper.outRespAlert(response, "回调通知下单信息转换失败"); + return; + } + +// // 验证请求签名 +// if (!map.get("sign").equals(SignatureUtil.generateSign(map, WeChatConfig.MCH_KEY))) { +// log.info("收到扫码支付请求:签名无效!"); +// HttpHelper.outRespAlert(response, "收到扫码支付请求:签名无效!"); +// return; +// } - String openid = map.get("openid"); - String product_id = map.get("product_id"); + String openid = notifyInfo.getOpenid(); + String productId = notifyInfo.getProductId(); - log.info("[Native]扫码支付 收到请求:product_id={}, openid={}", product_id, openid); - if (!product_id.contains("XBD")) { - log.info("[Native]扫码支付 不合规则的字符串,不允许支付!product_id={}", product_id); + log.info("[Native]扫码支付 收到请求:product_id={}, openid={}", productId, openid); + if (!"XBD".equals(productId)) { + log.info("[Native]扫码支付 不合规则的字符串,不允许支付!product_id={}", productId); HttpHelper.outRespAlert(response, "扫码支付:不合规则的字符串,不允许支付!"); return; } - String[] params = product_id.split("XBD"); // product_id=0XBD0XBD258597|80.00XBD80XBD1 + String[] params = productId.split("XBD"); // product_id=0XBD0XBD258597|80.00XBD80XBD1 if (params.length < 5) { - log.info("[Native]扫码支付 体检缴费参数少于5个,不允许支付!product_id={}", product_id); + log.info("[Native]扫码支付 体检缴费参数少于5个,不允许支付!product_id={}", productId); HttpHelper.outRespAlert(response, "扫码支付:参数少于5个"); return; } @@ -94,14 +105,14 @@ public class QRPayServlet extends HttpServlet { log.info("[Native]扫码支付 patientId={} treatNum={}, recipeId={}, payMoney={}, flag={}", patientId, treatNum, recipeId, payMoney, flag); if (ObjectUtils.isEmpty(patientId) || ObjectUtils.isEmpty(treatNum) || ObjectUtils.isEmpty(payMoney)) { - log.info("[Native]扫码支付 参数中有空值,不允许支付!product_id={}", product_id); + log.info("[Native]扫码支付 参数中有空值,不允许支付!product_id={}", productId); HttpHelper.outRespAlert(response, "扫码支付:参数中有空值,不允许支付!"); return; } // 是否重复支付 if (new RecipeDao().hasHisPaidByPatient(patientId, treatNum, recipeId)) { - log.info("[Native]扫码支付 已缴费成功,无需再次支付!product_id={}", product_id); + log.info("[Native]扫码支付 已缴费成功,无需再次支付!product_id={}", productId); HttpHelper.outRespAlert(response, "已缴费成功,无需支付!"); return; } @@ -115,13 +126,13 @@ public class QRPayServlet extends HttpServlet { } WxNativePayResult nativeOrder = WxPayHelper.createNativeOrder("old_pay_notify_servlet", title, new BigDecimal(payMoney), outTradeNo, "PEIS", request.getRemoteAddr()); if (nativeOrder == null) { - log.info("[Native]扫码支付 下单失败 product_id={}", product_id); + log.info("[Native]扫码支付 下单失败 product_id={}", productId); HttpHelper.outRespAlert(response, "已缴费成功,无需支付!"); return; } boolean isOk = new RecipeService().addOldPEISOrder(outTradeNo, payMoney, openid, patientId, treatNum, recipeId); if (!isOk) { - log.info("[Native]扫码支付 存储数据失败 product_id={}", product_id); + log.info("[Native]扫码支付 存储数据失败 product_id={}", productId); } String nativeReplyXML = WxPayHelper.toNativeReplyXML(nativeOrder.getPrepayId()); diff --git a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet2.java b/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet2.java deleted file mode 100644 index f5630dc..0000000 --- a/src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet2.java +++ /dev/null @@ -1,189 +0,0 @@ -package com.ynxbd.wx.servlet.oldpay; - -import com.ynxbd.common.bean.enums.MerchantEnum; -import com.ynxbd.common.bean.pay.Recipe; -import com.ynxbd.common.dao.RecipeDao; -import com.ynxbd.common.helper.common.CodeHelper; -import com.ynxbd.common.helper.common.HttpHelper; -import com.ynxbd.wx.config.WeChatConfig; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; -import org.slf4j.MDC; -import weixin.popular.api.PayMchAPI; -import weixin.popular.bean.paymch.MchPayNativeReply; -import weixin.popular.bean.paymch.Unifiedorder; -import weixin.popular.bean.paymch.UnifiedorderResult; -import weixin.popular.util.PayUtil; -import weixin.popular.util.SignatureUtil; -import weixin.popular.util.XMLConverUtil; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.math.BigDecimal; -import java.nio.charset.StandardCharsets; -import java.util.Map; -import java.util.UUID; - -/** - * 扫码支付接口(旧版) - * - * @author 张剑峰 - * @version v1.0.0 - * @Project:微信公众号 - * @date 2018年6月4日上午10:44:31 - * @Copyright: 2018云南新八达科技有限公司 All rights reserved. - */ -@Slf4j -@WebServlet("/qrpay2") -public class QRPayServlet2 extends HttpServlet { - - @Override - protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - MDC.remove("ip"); - MDC.put("ip", HttpHelper.getIpAddress(request)); - - log.info("[旧版]收到扫码支付请求,开始解析..."); - - // 读取参数 - InputStream inputStream = request.getInputStream(); - StringBuilder sb = new StringBuilder(); - String s; - BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)); - while ((s = in.readLine()) != null) { - sb.append(s); - } - in.close(); - inputStream.close(); - - // 解析xml成map - Map map = XMLConverUtil.convertToMap(sb.toString()); - // 过滤空 设置 TreeMap -// SortedMap payParams = new TreeMap<>(); -// Iterator it = map.keySet().iterator(); -// while (it.hasNext()) { -// String parameter = (String) it.next(); -// String parameterValue = map.get(parameter); -// String v = ""; -// if (null != parameterValue) { -// v = parameterValue.trim(); -// } -// payParams.put(parameter, v); -// } - - // 验证请求签名 - if (!map.get("sign").equals(SignatureUtil.generateSign(map, WeChatConfig.MCH_KEY))) { - log.info("收到扫码支付请求:签名无效!"); - HttpHelper.outRespAlert(response, "收到扫码支付请求:签名无效!"); - return; - } - - String product_id = map.get("product_id"); - log.info("收到扫码支付请求:product_id=" + product_id + ", open_id=" + map.get("openid")); - if (!product_id.contains("XBD")) { - log.info("扫码支付:不合规则的字符串,不允许支付!product_id=" + product_id); - HttpHelper.outRespAlert(response, "扫码支付:不合规则的字符串,不允许支付!"); - return; - } - - String[] array = product_id.split("XBD"); - if (array.length < 5) { - log.info("扫码支付:参数少于5个,不允许支付!product_id=" + product_id); - HttpHelper.outRespAlert(response, "扫码支付:参数少于5个"); - return; - } - - String patientId = array[0]; - String mzNum = array[1]; - String recipeId = array[2]; - String payMoney = array[3]; - String flag = array[4]; - // String recipeIdJson = "[{\"id\":" + "\"" + recipeId + "\"" + ",\"fee\":" + payMoney + "}]"; - - log.info("扫码支付:patientId={} treatNum={}, recipeId={}, payMoney={}, flag={}", patientId, mzNum, recipeId, payMoney, flag); - - if (ObjectUtils.isEmpty(patientId) || ObjectUtils.isEmpty(mzNum) || ObjectUtils.isEmpty(payMoney)) { - log.info("扫码支付:参数中有空值,不允许支付!product_id={}", product_id); - HttpHelper.outRespAlert(response, "扫码支付:参数中有空值,不允许支付!"); - return; - } - - // 是否重复支付 - log.info("判断是否支付过:patientId={}, mzNum={}, recipeId={}", patientId, mzNum, recipeId); - if (new RecipeDao().hasHisPaidByPatient(patientId, mzNum, recipeId)) { - log.info("该码已经缴费,无需支付!product_id={}", product_id); - HttpHelper.outRespAlert(response, "该码已经缴费,无需支付!"); - return; - } - - // 统一下单 - Unifiedorder unifiedorder = new Unifiedorder(); - String appID = WeChatConfig.APP_ID; - String mchID = WeChatConfig.MCH_ID; - String mchKey = WeChatConfig.MCH_KEY; - - unifiedorder.setAppid(appID); - unifiedorder.setMch_id(mchID); - unifiedorder.setNonce_str(UUID.randomUUID().toString().replace("-", "")); - if (flag.equals("1")) { - unifiedorder.setBody("ID:" + patientId + " 处方单号:" + recipeId); - } else if (flag.equals("2")) { - unifiedorder.setBody("ID:" + patientId + " 申请单号:" + recipeId); - } - - // unifiedorder.setBody("pay"); - unifiedorder.setOut_trade_no(CodeHelper.getOutTradeNo(MerchantEnum.WX)); - - // 此处使用Float或者Double转换金额会因为精度问题丢失1分钱,使用BigDecimal来转换 - BigDecimal v1 = new BigDecimal(payMoney); - BigDecimal v2 = new BigDecimal("100"); - double b = v1.multiply(v2).doubleValue(); - int fFee = (int) b; - - unifiedorder.setTotal_fee(String.valueOf(fFee)); - unifiedorder.setSpbill_create_ip(request.getRemoteAddr()); - unifiedorder.setNotify_url(WeChatConfig.getBaseURL() + "old_pay_notify_servlet"); - unifiedorder.setTrade_type("NATIVE"); - log.info("扫码回调地址:" + WeChatConfig.getBaseURL() + "old_pay_notify_servlet"); - - UnifiedorderResult unifiedorderResult = PayMchAPI.payUnifiedorder(unifiedorder, mchKey); - - Recipe recipe = new Recipe(); - - recipe.setOpenid(map.get("openid")); - recipe.setPatientId(patientId); - recipe.setTreatNum(mzNum); - recipe.setOutTradeNo(unifiedorder.getOut_trade_no()); - recipe.setPayWay("1"); - recipe.setPayMoney(new BigDecimal(payMoney)); - recipe.setRecipeId(recipeId); -// recipe.setTradeNo(CodeHelper.getHisTradeNo()); // 本次his交易流水号 - recipe.setTotalFee(new BigDecimal(payMoney)); - recipe.setHisStatus(-1); - recipe.setPayStatus(-1); - if (!new RecipeDao().insert(recipe)) { - log.info("[扫码支付]存储失败"); - } - - MchPayNativeReply reply = new MchPayNativeReply(); - reply.setAppid(appID); - reply.setMch_id(mchID); - reply.setNonce_str(UUID.randomUUID().toString().replace("-", "")); - reply.setPrepay_id(unifiedorderResult.getPrepay_id()); - reply.setResult_code("SUCCESS"); - reply.setReturn_code("SUCCESS"); - String string = PayUtil.generateMchPayNativeReplyXML(reply, mchKey); - response.getWriter().write(string); - } - - protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { - doPost(request, response); - } - -} diff --git a/src/main/java/com/ynxbd/wx/servlet/test/OrderTest.java b/src/main/java/com/ynxbd/wx/servlet/test/OrderTest.java deleted file mode 100644 index fe414f6..0000000 --- a/src/main/java/com/ynxbd/wx/servlet/test/OrderTest.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ynxbd.wx.servlet.test; - -import com.ynxbd.common.bean.pay.Order; -import com.ynxbd.common.bean.pay.Recipe; -import com.ynxbd.common.dao.RecipeDao; -import com.ynxbd.common.helper.common.CodeHelper; -import com.ynxbd.common.helper.common.ErrorHelper; -import com.ynxbd.wx.config.WeChatConfig; -import weixin.popular.api.PayMchAPI; -import weixin.popular.bean.paymch.MchOrderInfoResult; -import weixin.popular.bean.paymch.MchOrderquery; - -import java.math.BigDecimal; - -/** - * @Author wsq - * @Date 2021/6/28 16:10 - * @Copyright @ 2020 云南新八达科技有限公司 All rights reserved. - */ -public class OrderTest { - -// public static void main(String[] args) { -// Pay pay = queryOrder("WX560aae435d5940a677044b52df27"); -// System.out.println(JsonHelper.toJsonString(pay)); -// } - - /** - * 查询订单 - * - * @param outTradeNo 订单号 - * @return 订单信息 - */ - public static Order queryOrder(String outTradeNo) { - Order order = new Order(); - try { - MchOrderquery mchOrderquery = new MchOrderquery(); - String appId = WeChatConfig.APP_ID; - String mchId = WeChatConfig.MCH_ID; - String mchKey = WeChatConfig.MCH_KEY; - - mchOrderquery.setAppid(appId); - mchOrderquery.setMch_id(mchId); - mchOrderquery.setOut_trade_no(outTradeNo); - mchOrderquery.setNonce_str(CodeHelper.get32UUID()); - - MchOrderInfoResult mchOrderInfoResult = PayMchAPI.payOrderquery(mchOrderquery, mchKey); - if (!"SUCCESS".equals(mchOrderInfoResult.getReturn_code())) { - order.setErrorCode(mchOrderInfoResult.getReturn_code()); - order.setErrorMsg(mchOrderInfoResult.getReturn_msg()); - return order; - } - - // 业务发生错误 - if (!"SUCCESS".equals(mchOrderInfoResult.getResult_code())) { - order.setErrorCode(mchOrderInfoResult.getErr_code()); - order.setErrorMsg(mchOrderInfoResult.getErr_code_des()); - return order; - } - - // 交易成功 - if ("SUCCESS".equals(mchOrderInfoResult.getTrade_state())) { - order.setSuccess(true); - order.setBankTransNo(mchOrderInfoResult.getTransaction_id()); - } else { - order.setErrorCode(mchOrderInfoResult.getTrade_state()); - order.setErrorMsg(mchOrderInfoResult.getTrade_state_desc()); - } - - order.setOutTradeNo(outTradeNo); - order.setTotalFee(new BigDecimal(mchOrderInfoResult.getTotal_fee()).movePointLeft(2)); - } catch (Exception e) { - ErrorHelper.println(e); - order.setErrorMsg(e.getMessage()); - } - return order; - } - - public static void main(String[] args){ -// String piMd5 = "9444144" + "T2001" + "xbd"; -// piMd5 = DigestUtils.md5Hex(piMd5).toUpperCase(); -// System.out.println(piMd5); - Recipe recipe = new Recipe(); - recipe.setOpenid("test"); - recipe.setPatientId("test"); - recipe.setOutTradeNo("test"); - recipe.setRecipeFee(new BigDecimal(10)); - recipe.setTotalFee(new BigDecimal(10)); - recipe.setTreatNum("test"); - recipe.setPayWay("1"); - recipe.setRecipeId("1"); - recipe.setHisStatus(-1); - recipe.setPayStatus(-1); - new RecipeDao().insert(recipe); - - } -} diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxAuthServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/WxAuthServlet.java index 51eb641..20e15d8 100644 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxAuthServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/test/WxAuthServlet.java @@ -10,8 +10,7 @@ //import lombok.extern.slf4j.Slf4j; //import org.ehcache.Cache; //import org.slf4j.MDC; -//import weixin.popular.api.SnsAPI; -//import weixin.popular.bean.sns.SnsToken; + // //import javax.servlet.ServletException; //import javax.servlet.annotation.WebServlet; diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxNativePayNotifyServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/WxNativePayNotifyServlet.java index f7db869..19e7a25 100644 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxNativePayNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/test/WxNativePayNotifyServlet.java @@ -7,7 +7,7 @@ //import com.ynxbd.common.result.ServiceException; //import com.ynxbd.common.service.OutCollectService; //import com.ynxbd.wx.wxfactory.WxPayHelper; -//import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +//import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; //import com.ynxbd.wx.wxfactory.utils.WxRespHelper; //import lombok.extern.slf4j.Slf4j; //import org.slf4j.MDC; diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxOrderTest.java b/src/main/java/com/ynxbd/wx/servlet/test/WxOrderTest.java index cf0042d..372b61c 100644 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxOrderTest.java +++ b/src/main/java/com/ynxbd/wx/servlet/test/WxOrderTest.java @@ -7,37 +7,37 @@ import java.util.ArrayList; import java.util.List; public class WxOrderTest { - public static void main(String[] args) { - String orders = ""; - - String states = ""; - - String[] outTradeNoList = orders.split("\n"); - - String[] stateList = states.split("\n"); - - System.out.println("订单数量=" + outTradeNoList.length + ", 状态数量=" + stateList.length); - List errList = new ArrayList<>(); - List select; - for (int i = 0; i < outTradeNoList.length; i++) { - String outTradeNo = outTradeNoList[i].substring(1); - System.out.println("【" + i + "】" + outTradeNo); - select = DataBase.select("select * from pay where outTradeNo = ?", Recipe.class, ps -> { - ps.setString(1, outTradeNo); - }); - - String state = stateList[i]; - for (Recipe recipe : select) { - if (recipe.getHisStatus() == -1 && !"OK".equals(recipe.getRefundResult()) && state.equals("买家已支付")) { - System.out.println("outTradeNo=" + outTradeNo + ",状态=" + state + ",payMoney=" + recipe.getPayMoney() + ",tradeNo=" + recipe.getTradeNo() + ",RefundResult=" + recipe.getRefundResult() + ",患者id=" + recipe.getPatientId() + ",门诊号=" + recipe.getTreatNum()); - errList.add("outTradeNo=" + outTradeNo + ",状态=" + state + ",payMoney=" + recipe.getPayMoney() + ",tradeNo=" + recipe.getTradeNo() + ",RefundResult=" + recipe.getRefundResult() + ",患者id=" + recipe.getPatientId() + ",门诊号=" + recipe.getTreatNum()); - } - } - } - - for (String str : errList) { - System.out.println(str); - } -// System.out.println(refundList); - } +// public static void main(String[] args) { +// String orders = ""; +// +// String states = ""; +// +// String[] outTradeNoList = orders.split("\n"); +// +// String[] stateList = states.split("\n"); +// +// System.out.println("订单数量=" + outTradeNoList.length + ", 状态数量=" + stateList.length); +// List errList = new ArrayList<>(); +// List select; +// for (int i = 0; i < outTradeNoList.length; i++) { +// String outTradeNo = outTradeNoList[i].substring(1); +// System.out.println("【" + i + "】" + outTradeNo); +// select = DataBase.select("select * from pay where outTradeNo = ?", Recipe.class, ps -> { +// ps.setString(1, outTradeNo); +// }); +// +// String state = stateList[i]; +// for (Recipe recipe : select) { +// if (recipe.getHisStatus() == -1 && !"OK".equals(recipe.getRefundResult()) && state.equals("买家已支付")) { +// System.out.println("outTradeNo=" + outTradeNo + ",状态=" + state + ",payMoney=" + recipe.getPayMoney() + ",tradeNo=" + recipe.getTradeNo() + ",RefundResult=" + recipe.getRefundResult() + ",患者id=" + recipe.getPatientId() + ",门诊号=" + recipe.getTreatNum()); +// errList.add("outTradeNo=" + outTradeNo + ",状态=" + state + ",payMoney=" + recipe.getPayMoney() + ",tradeNo=" + recipe.getTradeNo() + ",RefundResult=" + recipe.getRefundResult() + ",患者id=" + recipe.getPatientId() + ",门诊号=" + recipe.getTreatNum()); +// } +// } +// } +// +// for (String str : errList) { +// System.out.println(str); +// } +//// System.out.println(refundList); +// } } diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxPayNotifyServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/WxPayNotifyServlet.java index b494368..b28e3a0 100644 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxPayNotifyServlet.java +++ b/src/main/java/com/ynxbd/wx/servlet/test/WxPayNotifyServlet.java @@ -7,7 +7,7 @@ //import com.ynxbd.common.result.ServiceException; //import com.ynxbd.common.service.*; //import com.ynxbd.wx.wxfactory.WxPayHelper; -//import com.ynxbd.wx.wxfactory.bean.WxPayNotify; +//import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; //import com.ynxbd.wx.wxfactory.utils.WxRespHelper; //import lombok.extern.slf4j.Slf4j; //import org.slf4j.MDC; diff --git a/src/main/java/com/ynxbd/wx/servlet/test/WxUAuthServlet.java b/src/main/java/com/ynxbd/wx/servlet/test/WxUAuthServlet.java deleted file mode 100644 index 91abf44..0000000 --- a/src/main/java/com/ynxbd/wx/servlet/test/WxUAuthServlet.java +++ /dev/null @@ -1,30 +0,0 @@ -//package com.ynxbd.wx.servlet; -// -//import com.ynxbd.wx.wxfactory.WxAuthHelper; -//import lombok.extern.slf4j.Slf4j; -// -//import javax.servlet.ServletException; -//import javax.servlet.annotation.WebServlet; -//import javax.servlet.http.HttpServlet; -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -//import java.io.IOException; -// -///** -// * 微信认证回调处理 -// * -// * @author antgan -// */ -//@Slf4j -//@WebServlet("/u_auth") -//public class WxUAuthServlet extends HttpServlet { -// -// protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { -// WxAuthHelper.auth(request, response, true); -// } -// -// protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { -// doGet(request, response); -// } -// -//} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java index fc63851..2da8998 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java @@ -30,7 +30,7 @@ public class AesWxHelper extends AesHelper { public static void main(String[] args) { // System.out.println(encode("397631")); System.out.println(encode("847149")); - System.out.println(decode("5ED36B8AF24847FBFFA6350642E38DBA")); + System.out.println(decode("E6835E243069406F53EC8464898B37C0")); // System.out.println(decode("FC0E7CBB32E595E2C84D44CE8B79E5325FA2C20E1090E9E5A5D7FBEA974023EB")); // System.out.println(encode("533103198603294034")); // System.out.println(decode("EF6115C81C9EA8FF79E21180FEC20294")); diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java index d1dcb05..8cc385c 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java @@ -1,284 +1,284 @@ -package com.ynxbd.wx.wxfactory; - -import com.ynxbd.common.bean.Patient; -import com.ynxbd.common.bean.User; -import com.ynxbd.common.helper.common.*; -import com.ynxbd.common.helper.http.OkHttpHelper; -import com.ynxbd.common.result.Result; -import com.ynxbd.common.service.PatientService; -import com.ynxbd.wx.config.WeChatConfig; -import com.ynxbd.wx.wxfactory.bean.SnsOath2AccessToken; -import com.ynxbd.wx.wxfactory.bean.SnsUserInfo; -import com.ynxbd.wx.wxfactory.bean.auth.AuthData; -import lombok.extern.slf4j.Slf4j; -import okhttp3.FormBody; -import okhttp3.RequestBody; -import org.apache.commons.lang3.ObjectUtils; -import org.ehcache.Cache; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import java.net.URLDecoder; -import java.net.URLEncoder; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -@Slf4j -public class WxAuthHelper { - private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60; // session最大存活时间 1H - - 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"); - - log.info("[授权] code={}, state={}, enuId={}", code, state, enuId); - try { - state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); - String enUnionId = null; - String protocolState = null; - - if (!ObjectUtils.isEmpty(enuId)) { - int index = enuId.indexOf("@protocolState="); - if (index == -1) index = enuId.indexOf("%40protocolState="); // 防止数据转义失败 - if (index != -1) { - enUnionId = enuId.substring(0, index); - protocolState = enuId.substring(index); - } - } - - log.info("[授权-解码] enUnionId={}, protocolState={}, state={}", enUnionId, protocolState, state); - - SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); - if (snsToken != null) { - String openid = snsToken.getOpenid(); - String unionId = snsToken.getUnionid(); - if (unionId == null) { - log.info("[测试] enUnionId={}", enUnionId); - } - if (openid != null) { - HttpSession session = request.getSession(); - session.setMaxInactiveInterval(SESSION_MAX_INACTIVE_INTERVAL); - session.setAttribute("openid", openid); - - Cache cache = WxCacheHelper.getUserCacheManager(); - if (WeChatConfig.isDevUser(openid) || !cache.containsKey(openid)) { - User user = new User(); - user.setUnionId(unionId); - user.setOpenid(openid); - user.setIsSnapShotUser(snsToken.getIsSnapShotUser()); - user.setPatientList(new PatientService().queryPatientList(openid, unionId, true)); - - if (isUserInfo) { - SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); - if (snsUser != null) { - user.setCountry(snsUser.getCountry()); - user.setAvatar(snsUser.getHeadImgUrl()); - user.setNickName(snsUser.getNickname_emoji()); - user.setProvince(snsUser.getProvince()); - user.setGenderByInt(snsUser.getSex()); - user.setCity(snsUser.getCity()); - user.setLanguage(snsUser.getLanguage()); - } - } - cache.put(openid, user); - } else { - if (isUserInfo) { - User user = cache.get(openid); - if (user != null && user.getAvatar() == null && user.getNickName() == null) { - SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); - if (snsUser != null) { - user.setAvatar(snsUser.getHeadImgUrl()); - user.setNickName(snsUser.getNickname_emoji()); - user.setGenderByInt(snsUser.getSex()); - } - } - } - } - } - } - - - if (WeChatConfig.HAS_HTTPS_BY_BASE_URL) { // 强制为https - String httpsURL = URLHelper.URLToHttps(state); - state = httpsURL == null ? "" : httpsURL; - } - - if (state.contains(".html")) { // 网页授权配置 - return state; - } else { - String baseUrl = WeChatConfig.getBaseURL(); - if (baseUrl != null && state.contains(baseUrl)) { - return state; - } - } - } catch (Exception e) { - log.error("[微信][获取重定向链接异常]{}", e.getMessage()); - } - return null; - } - - - public static Result isAuth(HttpServletRequest request, 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 deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); - - if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权 - try { // 请求转发 - String serverDomain = WeChatConfig.getDomain(false, false); - if (deState != null && serverDomain != null && !deState.contains(serverDomain)) { - 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); - return Result.dataToResult(data, true); - } catch (Exception e) { - return Result.error(e); - } - } - - boolean isFindUserInfo = ("true".equals(isUserInfo)); - - AuthData authData = new AuthData(); - String cacheOpenid = authData.decodeToken(token, WeChatConfig.APP_ID); - if (cacheOpenid != null) { - log.info("[微信token认证] token={}, openid={}", token, cacheOpenid); - User user = WxCacheHelper.getCacheUser(cacheOpenid); - List patients; - if (user == null) { - patients = new PatientService().queryPatientList(cacheOpenid, null, true); - Cache cache = WxCacheHelper.getUserCacheManager(); - User addCache = new User(); - addCache.setOpenid(cacheOpenid); - addCache.setUnionId(authData.getUnionId()); - addCache.setAvatar(authData.getAvatar()); - addCache.setNickName(authData.getNickName()); - addCache.setPatientList(patients); - cache.put(cacheOpenid, addCache); - } else { - patients = user.getPatientList(); - } - - Map map = new HashMap<>(); - map.put("openid", cacheOpenid); - map.put("token", token); - map.put("enOpenId", AesWxHelper.encode(cacheOpenid, true)); - map.put("enUnionId", AesWxHelper.encode(authData.getUnionId(), true)); - map.put("date", new Date()); - map.put("avatar", authData.getAvatar()); - map.put("nickName", authData.getNickName()); - map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(patients), "UTF-8"))); - map.put("enParams", AesMicroHelper.encode(cacheOpenid)); - return Result.success(map); - } - - HttpSession session = request.getSession(); - Object openid = session.getAttribute("openid"); - if (openid != null) { - log.info("[微信认证]openid={}", openid); - User user = WxCacheHelper.getCacheUser((String) openid); - if (user == null) { - return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); - } - - if (isFindUserInfo) { // 更换授权模式,需更新信息 - if (user.getNickName() == null || user.getAvatar() == null) { - return Result.success(getAuthUrl(request, state, true, enuId, protocolState)); - } - } - - 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("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())); - return Result.success(map); - } - - return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); - } - - 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) { -// StringBuffer url = request.getRequestURL(); -// String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString(); - if (state == null) { - return null; - } - - String api = isFindUserInfo ? "u_auth" : "b_auth"; - String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base"; - - 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)) + - "#wechat_redirect"; - return Base64Helper.encode(state); - } - - - // 是否为https请求 - public static boolean isHttpsWithProxy(HttpServletRequest request) { - // 优先检查代理头(适用于反向代理场景) - String forwardedProto = request.getHeader("X-Forwarded-Proto"); - if (forwardedProto != null) { - return "https".equalsIgnoreCase(forwardedProto); - } - // 未经过代理,直接检查原生请求 - return request.isSecure(); - } - - - // // 医共体开启 & 不是支付授权 -// private static boolean isAuthGMC(boolean isPayOAuth) { -// return WeChatConfig.IS_ENABLE_GMC && !isPayOAuth; -// } - -// private static String getOAuthURL(HttpServletRequest request, boolean isPayOAuth) { -// boolean isHttps = WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request); -// return isAuthGMC(isPayOAuth) -// ? "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.GMC_AUTH_APP_ID + "&redirect_uri=" + WeChatConfig.getGMCAuthDomain(isHttps, true) -// : "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri=" + WeChatConfig.getBaseURL(isHttps); -// } - -// private static SnsOath2AccessToken getOath2AccessToken(String code, boolean isPayOAuth) { -// if (isAuthGMC(isPayOAuth)) { -// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.GMC_AUTH_APP_ID, WeChatConfig.GMC_AUTH_APP_SECRET, code); -// } -// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); -// } - -// // 获取重定向链接 -// private static String getAuthDomain(HttpServletRequest request, boolean isPayOAuth) { -// if (isAuthGMC(isPayOAuth)) { -// return WeChatConfig.getGMCAuthDomain(true, false); // 强制为https -// } -// return WeChatConfig.getDomain(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)); // 配置中baseURL有"https"时优先级最高 ["@protocol=1"为https;"@protocol=0"为默认的http;] -// } - -} +package com.ynxbd.wx.wxfactory; + +import com.ynxbd.common.bean.Patient; +import com.ynxbd.common.bean.User; +import com.ynxbd.common.helper.common.*; +import com.ynxbd.common.helper.http.OkHttpHelper; +import com.ynxbd.common.result.Result; +import com.ynxbd.common.service.PatientService; +import com.ynxbd.wx.config.WeChatConfig; +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; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class WxAuthHelper { + private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60; // session最大存活时间 1H + + 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"); + + log.info("[授权] code={}, state={}, enuId={}", code, state, enuId); + try { + state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); + String enUnionId = null; + String protocolState = null; + + if (!ObjectUtils.isEmpty(enuId)) { + int index = enuId.indexOf("@protocolState="); + if (index == -1) index = enuId.indexOf("%40protocolState="); // 防止数据转义失败 + if (index != -1) { + enUnionId = enuId.substring(0, index); + protocolState = enuId.substring(index); + } + } + + log.info("[授权-解码] enUnionId={}, protocolState={}, state={}", enUnionId, protocolState, state); + + SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); + if (snsToken != null) { + String openid = snsToken.getOpenid(); + String unionId = snsToken.getUnionid(); + if (unionId == null) { + log.info("[测试] enUnionId={}", enUnionId); + } + if (openid != null) { + HttpSession session = request.getSession(); + session.setMaxInactiveInterval(SESSION_MAX_INACTIVE_INTERVAL); + session.setAttribute("openid", openid); + + Cache cache = WxCacheHelper.getUserCacheManager(); + if (WeChatConfig.isDevUser(openid) || !cache.containsKey(openid)) { + User user = new User(); + user.setUnionId(unionId); + user.setOpenid(openid); + user.setIsSnapShotUser(snsToken.getIsSnapShotUser()); + user.setPatientList(new PatientService().queryPatientList(openid, unionId, true)); + + if (isUserInfo) { + SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); + if (snsUser != null) { + user.setCountry(snsUser.getCountry()); + user.setAvatar(snsUser.getHeadImgUrl()); + user.setNickName(snsUser.getNickname_emoji()); + user.setProvince(snsUser.getProvince()); + user.setGenderByInt(snsUser.getSex()); + user.setCity(snsUser.getCity()); + user.setLanguage(snsUser.getLanguage()); + } + } + cache.put(openid, user); + } else { + if (isUserInfo) { + User user = cache.get(openid); + if (user != null && user.getAvatar() == null && user.getNickName() == null) { + SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); + if (snsUser != null) { + user.setAvatar(snsUser.getHeadImgUrl()); + user.setNickName(snsUser.getNickname_emoji()); + user.setGenderByInt(snsUser.getSex()); + } + } + } + } + } + } + + + if (WeChatConfig.HAS_HTTPS_BY_BASE_URL) { // 强制为https + String httpsURL = URLHelper.URLToHttps(state); + state = httpsURL == null ? "" : httpsURL; + } + + if (state.contains(".html")) { // 网页授权配置 + return state; + } else { + String baseUrl = WeChatConfig.getBaseURL(); + if (baseUrl != null && state.contains(baseUrl)) { + return state; + } + } + } catch (Exception e) { + log.error("[微信][获取重定向链接异常]{}", e.getMessage()); + } + return null; + } + + + public static Result isAuth(HttpServletRequest request, 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 deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); + + if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权 + try { // 请求转发 + String serverDomain = WeChatConfig.getDomain(false, false); + if (deState != null && serverDomain != null && !deState.contains(serverDomain)) { + 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); + return Result.dataToResult(data, true); + } catch (Exception e) { + return Result.error(e); + } + } + + boolean isFindUserInfo = ("true".equals(isUserInfo)); + + AuthData authData = new AuthData(); + String cacheOpenid = authData.decodeToken(token, WeChatConfig.APP_ID); + if (cacheOpenid != null) { + log.info("[微信token认证] token={}, openid={}", token, cacheOpenid); + User user = WxCacheHelper.getCacheUser(cacheOpenid); + List patients; + if (user == null) { + patients = new PatientService().queryPatientList(cacheOpenid, null, true); + Cache cache = WxCacheHelper.getUserCacheManager(); + User addCache = new User(); + addCache.setOpenid(cacheOpenid); + addCache.setUnionId(authData.getUnionId()); + addCache.setAvatar(authData.getAvatar()); + addCache.setNickName(authData.getNickName()); + addCache.setPatientList(patients); + cache.put(cacheOpenid, addCache); + } else { + patients = user.getPatientList(); + } + + Map map = new HashMap<>(); + map.put("openid", cacheOpenid); + map.put("token", token); + map.put("enOpenId", AesWxHelper.encode(cacheOpenid, true)); + map.put("enUnionId", AesWxHelper.encode(authData.getUnionId(), true)); + map.put("date", new Date()); + map.put("avatar", authData.getAvatar()); + map.put("nickName", authData.getNickName()); + map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(patients), "UTF-8"))); + map.put("enParams", AesMicroHelper.encode(cacheOpenid)); + return Result.success(map); + } + + HttpSession session = request.getSession(); + Object openid = session.getAttribute("openid"); + if (openid != null) { + log.info("[微信认证]openid={}", openid); + User user = WxCacheHelper.getCacheUser((String) openid); + if (user == null) { + return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); + } + + if (isFindUserInfo) { // 更换授权模式,需更新信息 + if (user.getNickName() == null || user.getAvatar() == null) { + return Result.success(getAuthUrl(request, state, true, enuId, protocolState)); + } + } + + 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("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())); + return Result.success(map); + } + + return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); + } + + 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) { +// StringBuffer url = request.getRequestURL(); +// String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString(); + if (state == null) { + return null; + } + + String api = isFindUserInfo ? "u_auth" : "b_auth"; + String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base"; + + 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)) + + "#wechat_redirect"; + return Base64Helper.encode(state); + } + + + // 是否为https请求 + public static boolean isHttpsWithProxy(HttpServletRequest request) { + // 优先检查代理头(适用于反向代理场景) + String forwardedProto = request.getHeader("X-Forwarded-Proto"); + if (forwardedProto != null) { + return "https".equalsIgnoreCase(forwardedProto); + } + // 未经过代理,直接检查原生请求 + return request.isSecure(); + } + + + // // 医共体开启 & 不是支付授权 +// private static boolean isAuthGMC(boolean isPayOAuth) { +// return WeChatConfig.IS_ENABLE_GMC && !isPayOAuth; +// } + +// private static String getOAuthURL(HttpServletRequest request, boolean isPayOAuth) { +// boolean isHttps = WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request); +// return isAuthGMC(isPayOAuth) +// ? "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.GMC_AUTH_APP_ID + "&redirect_uri=" + WeChatConfig.getGMCAuthDomain(isHttps, true) +// : "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri=" + WeChatConfig.getBaseURL(isHttps); +// } + +// private static SnsOath2AccessToken getOath2AccessToken(String code, boolean isPayOAuth) { +// if (isAuthGMC(isPayOAuth)) { +// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.GMC_AUTH_APP_ID, WeChatConfig.GMC_AUTH_APP_SECRET, code); +// } +// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); +// } + +// // 获取重定向链接 +// private static String getAuthDomain(HttpServletRequest request, boolean isPayOAuth) { +// if (isAuthGMC(isPayOAuth)) { +// return WeChatConfig.getGMCAuthDomain(true, false); // 强制为https +// } +// return WeChatConfig.getDomain(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)); // 配置中baseURL有"https"时优先级最高 ["@protocol=1"为https;"@protocol=0"为默认的http;] +// } + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java index dac16e3..be202a3 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java @@ -2,8 +2,8 @@ package com.ynxbd.wx.wxfactory; import com.ynxbd.common.bean.User; import com.ynxbd.common.config.EhCacheConfig; -import com.ynxbd.wx.wxfactory.bean.AccessToken; -import com.ynxbd.wx.wxfactory.bean.JsapiTicket; +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.ehcache.Cache; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxFactory.java b/src/main/java/com/ynxbd/wx/wxfactory/WxFactory.java index 86c717f..d07b7bf 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxFactory.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxFactory.java @@ -1,6 +1,7 @@ package com.ynxbd.wx.wxfactory; import com.ynxbd.common.result.JsonResult; +import com.ynxbd.wx.wxfactory.payment.refund.Client; import lombok.*; import java.io.Serializable; @@ -16,9 +17,14 @@ public class WxFactory { return new com.ynxbd.wx.wxfactory.base.auth.Client(); } - public static com.ynxbd.wx.wxfactory.base.refund.Client Refund() { - return new com.ynxbd.wx.wxfactory.base.refund.Client(); + public static Client Refund() { + return new Client(); } + + public static com.ynxbd.wx.wxfactory.base.passivemsg.Client PassiveMsg() { // 被动消息回复 + return new com.ynxbd.wx.wxfactory.base.passivemsg.Client(); + } + } // public static class Payment { diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxMedHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxMedHelper.java index a656c53..81886d3 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxMedHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxMedHelper.java @@ -6,11 +6,14 @@ import com.ynxbd.common.helper.common.*; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; 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 com.ynxbd.wx.wxfactory.base.auth.models.RespAccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.RespJsapiTicket; -import com.ynxbd.wx.wxfactory.bean.*; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import com.ynxbd.wx.wxfactory.medical.enums.MdRefundTypeEnum; +import com.ynxbd.wx.wxfactory.medical.models.*; +import com.ynxbd.wx.wxfactory.payment.OrderMIEnum; import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -25,7 +28,6 @@ import java.util.Map; public class WxMedHelper { private static final RepeatKeyHelper KEYS = new RepeatKeyHelper(60); - /** * [医保]获取用户信息 * @@ -72,7 +74,7 @@ public class WxMedHelper { public static MedicalNotify paidMedNotify(HttpServletRequest request) throws ServiceException { try { // 转换数据对象 - Map paramsMap = WxSignHelper.getReqXmlParamsMap(request); + Map paramsMap = WxSignHelper.reqXmlParamsMap(request); if (paramsMap == null) { throw new ServiceException("[医保]回调通知下单信息返回错误"); } @@ -82,7 +84,6 @@ public class WxMedHelper { throw new ServiceException("[医保]回调通知签名验证未通过!"); } - String json = JsonHelper.toJsonString(paramsMap); if (ObjectUtils.isEmpty(json)) { throw new ServiceException("[医保]回调通知下单信息为空"); @@ -310,7 +311,7 @@ public class WxMedHelper { /** * [医保]获取授权链接 */ - public static MedicalRefundInfo queryRefund( String outRefundNo, String outTradeNo, String mdTransId) { + public static MedicalRefundInfo queryRefund(String outRefundNo, String outTradeNo, String mdTransId) { return WxFactory.Medical.Common().queryRefund( WxCacheHelper.getAccessToken(), WxMedConfig.MD_APP_ID, diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxPassiveReplyHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java similarity index 73% rename from src/main/java/com/ynxbd/wx/wxfactory/utils/WxPassiveReplyHelper.java rename to src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java index 1ff6a49..1cddaeb 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxPassiveReplyHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java @@ -1,526 +1,502 @@ -package com.ynxbd.wx.wxfactory.utils; - -import com.ynxbd.common.helper.common.ErrorHelper; -import com.ynxbd.wx.config.HospConfigEnum; -import com.ynxbd.wx.config.WeChatConfig; -import com.ynxbd.wx.config.WxEventEnum; -import com.ynxbd.wx.wxfactory.bean.event.WxEvent; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; -import weixin.popular.bean.xmlmessage.XMLImageMessage; -import weixin.popular.bean.xmlmessage.XMLNewsMessage; -import weixin.popular.bean.xmlmessage.XMLTextMessage; -import weixin.popular.support.ExpireKey; -import weixin.popular.support.expirekey.DefaultExpireKey; - -import javax.servlet.http.HttpServletResponse; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -/** - * 微信被动回复推送 - */ -@Slf4j -public class WxPassiveReplyHelper { - // 重复通知过滤 - private static ExpireKey EXPIRE_KEY; - - public static final String SUCCESS = "success"; - - private synchronized static void getExpireKey() { - if (EXPIRE_KEY == null) { - EXPIRE_KEY = new DefaultExpireKey(); - } - } - - // 消息通知过滤 - public static boolean isRepeat(String key) { - if (EXPIRE_KEY == null) { - getExpireKey(); - } - if (EXPIRE_KEY.exists(key)) { - log.info("[公众号]重复通知不处理"); - return true; - } else { - EXPIRE_KEY.add(key); - } - return false; - } - - /** - * 关注 - * - * @param response - * @param content - * @param msgType - * @param fromUserName - * @param toUserName - * @return - */ - public static boolean subscribeCommon(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String event) { - log.info("event={}", event); - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { - String webUrl = WeChatConfig.getWebReqURL(); - return createLinkMsg(response, fromUserName, toUserName, "清廉承诺", msgType, content, - (webUrl + "wx-subscribe.html"), - (webUrl + "images/message/subscribe.png")); - } - return false; - } - - public static OutputStream getOutputStream(HttpServletResponse response) { - try { - return response.getOutputStream(); - } catch (Exception e) { - ErrorHelper.println(e); - } - return null; - } - - /** - * 信息回复 - * - * @param response - * @param fromUserName - * @param toUserName - * @param title - * @param msgType - * @param userText - * @param link - * @param imageUrl - * @return - */ - public static boolean createLinkMsg(HttpServletResponse response, String fromUserName, String toUserName, String title, String msgType, String userText, String link, String imageUrl) { - if (!WxEventEnum.MSG_TYPE_TEXT.CODE.equals(msgType)) { // 消息类型不为文本 - return false; - } - - if (ObjectUtils.isEmpty(userText)) { // 不存在 - return false; - } - - List articleList = new ArrayList<>(); - XMLNewsMessage.Article article; - - article = new XMLNewsMessage.Article(); - article.setTitle(title); - article.setUrl(link); - article.setPicurl(imageUrl); - articleList.add(article); - XMLNewsMessage xmlNewsMessage = new XMLNewsMessage(fromUserName, toUserName, articleList); - xmlNewsMessage.outputStreamWrite(getOutputStream(response)); - return true; - } - - /** - * 文字匹配 - */ - public static boolean textCommon(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName) { - String webUrl = WeChatConfig.getWebReqURL(); - - if (Arrays.asList(new String[]{ - "缓", - "缓存", - "用不了", - "页面", - "404", - "进不去" - }).contains(content)) { - return createLinkMsg(response, fromUserName, toUserName, "公众号用不了(缓存清理)", msgType, content, - (webUrl + "wx-cache.html"), - (webUrl + "images/message/cache.png")); - } - - if (Arrays.asList(new String[]{ - "你好", - "链接", - "指引", - "微官网", - }).contains(content)) { - return createLinkMsg(response, fromUserName, toUserName, "微官网链接", msgType, content, - (webUrl + "app.html"), - (webUrl + "images/message/hospital.png")); - } - - if (Arrays.asList(new String[]{ - "查", - "查询", - "报告" - }).contains(content)) { - return createLinkMsg(response, fromUserName, toUserName, "报告单查询", msgType, content, - (webUrl + "all-result.html"), - (webUrl + "images/message/report.png")); - } - return false; - } - - // 根据医院appId回复 - public static Boolean hospReply(HttpServletResponse response, WxEvent wxEvent, String msgId, String fromUserName, String toUserName) { - String event = wxEvent.getEvent(); - String eventKey = wxEvent.getEventKey(); - String msgType = wxEvent.getMsgType(); - String reqContent = wxEvent.getContent(); - if (reqContent != null) { - reqContent = reqContent.trim().toUpperCase(); - } - - WxPassiveReplyHelper.textCommon(response, reqContent, msgType, fromUserName, toUserName); - - HospConfigEnum hospConfigEnum = HospConfigEnum.findEnumByWxAppId(); - if (hospConfigEnum == null) { - return false; - } - switch (hospConfigEnum) { - 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); - - 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); - - case 芒市人民医院: - return WxPassiveReplyHelper.芒市人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); - - case 玉龙县人民医院: - return WxPassiveReplyHelper.玉龙县人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); - - default: - break; - } - return false; - } - - 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)) { - String respInfo = "欢迎关注武定忠爱医院!" + - "\n\uD83D\uDD17 今日挂号" + - "\n\uD83D\uDD17 预约挂号"; - XMLTextMessage msg = new XMLTextMessage(fromUserName, toUserName, respInfo); - msg.outputStreamWrite(getOutputStream(response)); - } - } - return true; - } - - - public static boolean 芒市人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - List articleList = new ArrayList<>(); - XMLNewsMessage.Article article; - - if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { - article = new XMLNewsMessage.Article(); - article.setTitle("微信预约挂号开通喽,大家快快用起来!"); - article.setUrl("https://mp.weixin.qq.com/s/rJF1qBo1-mV5CUdRsi4Z5g"); - article.setPicurl("https://mmbiz.qpic.cn/mmbiz_jpg/RUm4m8SVypy7nVubUuo6KgdlibcduK8l4tWnXrz7VfTO5EYOeDc9hZxR70wTQgX1sYhRR7SeND6426uczdpf1BA/0?wx_fmt=jpeg"); - articleList.add(article); - XMLNewsMessage xmlNewsMessage = new XMLNewsMessage(fromUserName, toUserName, articleList); - xmlNewsMessage.outputStreamWrite(getOutputStream(response)); - } - } - - String respInfo; - - if (content != null) { - if (content.contains("放射") || content.contains("影像") || content.contains("CT") || content.contains("核磁")) { - respInfo = "放射科:2116611、18869202310(值班)"; - - } else if (content.contains("B超")) { - respInfo = "B超室:2121651、18869202311(值班)"; - - } else if (content.contains("检验") || content.contains("化验") || content.contains("生化") || content.contains("免疫")) { - respInfo = "检验科:2130240"; - - } else if (content.contains("口 腔")) { - respInfo = "口腔科:2139404"; - - } else if (content.contains("皮肤")) { - respInfo = "皮肤科:2129260"; - - } else if (content.contains("急诊")) { - respInfo = "急诊科:2103068(护士站)"; - - } else if (content.contains("外三") || content.contains("泌尿")) { - respInfo = "外三科(泌尿):2113501(护士站)"; - - } else if (content.contains("麻醉")) { - respInfo = "麻醉科:18869202309"; - - } else if (content.contains("妇产") || content.contains("产科") || content.contains("妇科")) { - respInfo = "妇产科:2113504(护士站)"; - - } else if (content.contains("感染") || content.contains("传染")) { - respInfo = "感染科:2116031"; - - } else if (content.contains("内二")) { - respInfo = "内二科:2113503(护士站)"; - - } else if (content.contains("内一")) { - respInfo = "内一科:2113500(护士站)"; - - } else if (content.contains("外二") || content.contains("骨科")) { - respInfo = "外二科(骨 科):2122450(护士站) "; - - } else if (content.contains("儿") || content.contains("儿科")) { - respInfo = "儿科:2122381(护士站)"; - - } else if (content.contains("康复")) { - respInfo = "康复科:2116167(护士站)"; - - } else if (content.contains("体检")) { - respInfo = "体检科:2917280、18288102873"; - - } else if (content.contains("120") || content.contains("急救")) { - respInfo = "120急救中心:2107120"; - - } else if (content.contains("外一") || content.contains("普外")) { - respInfo = "外一科(普外):2133720"; - - } else { - respInfo = "办公室:2122460\n" + - "行政值班:18869202307\n" + - "放射科:2116611、18869202310(值班)\n\n" + - "B超室:2121651、 18869202311(值班)\n\n" + - "儿 科:2122381(护士站)\n" + - "康复科:2116167(护士站)\n" + - "检验科:2130240\n" + - "口腔科:2139404\n" + - "皮肤科:2129260\n" + - "麻醉科:18869202309\n" + - "感染科:2116031,\n" + - "急诊科:2103068(护士站)\n" + - "妇产科:2113504(护士站)\n" + - "内二科:2113503(护士站)\n" + - "内一科:2113500(护士站)\n" + - "外二科(骨 科):2122450(护士站)\n" + - "外三科(泌 尿):2113501(护士站)\n\n" + - "体检科:2917280、18288102873\n" + - "120急救中心:2107120,\n" + - "外一科(普外):2133720"; - } - XMLTextMessage msg = new XMLTextMessage(fromUserName, toUserName, respInfo); - msg.outputStreamWrite(getOutputStream(response)); - } - return true; - } - - public static boolean 华坪县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - List articleList = new ArrayList<>(); - XMLNewsMessage.Article article; - - if (content != null) { - String webUrl = WeChatConfig.getWebReqURL(); - if (content.equals("支付") || content.equals("微信支付") || content.contains("费")) { - article = new XMLNewsMessage.Article(); - article.setTitle("微信支付"); - article.setPicurl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); - article.setDescription("请点这里进入支付页面,支付您的账单,不用再去排队缴费。如需查看检查结果,请输入“检查”。如需查看化验结果,请输入“化验”。"); - article.setUrl(webUrl + "pay-info.html"); - articleList.add(article); - - } else if (content.equals("检查") || content.equals("检验") || content.equals("化验")) { - article = new XMLNewsMessage.Article(); - article.setTitle("查看检查结果"); - article.setPicurl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); - article.setDescription("请点这里查看您的检查结果,如要查看化验结果,请输入“化验”或“检验”。如需缴费,请输入“支付”。"); - article.setUrl(webUrl + "all-result.html"); - articleList.add(article); - } - } - - if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { - if (eventKey.equals("MYDDC")) { - article = new XMLNewsMessage.Article(); - article.setTitle("华坪县人民医院患者满意度调查"); - article.setUrl("http://mp.weixin.qq.com/s/MCswklxDHdmYr3sFP70Xdw"); - article.setPicurl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOwYlpPRQDFKpbFQsN2ibtZqcS9H9pqX4nOCzdaAHNiciaZubLF9jiayZJBV8ADxAqL6XdbpdqolJuwJIQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); - articleList.add(article); - - article = new XMLNewsMessage.Article(); - article.setTitle("患者满意度调查"); - article.setUrl("http://mp.weixin.qq.com/s/7l2YsE2Y-XSTWEXN7BJlIQ"); - article.setPicurl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOzYGDMbzzyKicXD9QlRA5MdmpGgicibSdY0A4kmgV94qibuKylgRXbMgPb4zGNw9BvWqDXiby1XyFCFCaQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); - articleList.add(article); - - article = new XMLNewsMessage.Article(); - article.setTitle("员工满意度调查"); - article.setUrl("http://mp.weixin.qq.com/s/VyoOCM8FoEZ53ZQC3yX-Yw"); - article.setPicurl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOzYGDMbzzyKicXD9QlRA5MdmpF19PW1oFibvCDj60twgfGC556fY3wThlAhIYJsHykiaDIU8h3Igh8Dw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); - articleList.add(article); - - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { - article = new XMLNewsMessage.Article(); - article.setTitle("微信支付使用流程!"); - article.setPicurl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); - article.setDescription("首先关注微信公众号“华坪县人民医院”,其次打开公众号,点击“微信支付”,首次需进行身份绑定,按要求输入相关内容,获取账单;最多可以绑定除本人外加4个人,在身份绑定页面,点“添加绑定”"); - - articleList.add(article); - } - } - } - - XMLNewsMessage msg = new XMLNewsMessage(fromUserName, toUserName, articleList); - msg.outputStreamWrite(getOutputStream(response)); - return true; - } - - public static boolean 巍山县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - - List articleList = new ArrayList<>(); - XMLNewsMessage.Article article; - - if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { - // 满意度 - if (eventKey.equals("MYDDC")) { - article = new XMLNewsMessage.Article(); - article.setTitle("巍山县人民医院患者满意度调查"); - article.setUrl("https://mp.weixin.qq.com/s/R-tX9YtRRM9Hpw2rMmw2iQ"); - article.setPicurl("https://mmbiz.qpic.cn/mmbiz_jpg/5kpYU2jcMVicvMfVRATtAKOEjh4A4VvtHmCMKgD9vAfr741FDDEwiccNdj2ZTicBibeeQZfwp6zbaYMI5ubib1TaaeA/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); - articleList.add(article); - - } - // 关注 - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { - article = new XMLNewsMessage.Article(); - article.setTitle("微信预约挂号开通喽,大家快快用起来!"); - article.setUrl("http://mp.weixin.qq.com/s/gl_NitQTP6_ZzoV8pwxOcw"); - article.setPicurl("http://mmbiz.qpic.cn/mmbiz_jpg/5kpYU2jcMVicNybruqia0dn6kBqiakDlrTgDkweiafibyRl9uK6bkKoiaXib0xktJIywqTDzfe9fHcq5x0gggKkurDicpg/0?wx_fmt=jpeg"); - articleList.add(article); - } - } - - XMLNewsMessage msg = new XMLNewsMessage(fromUserName, toUserName, articleList); - msg.outputStreamWrite(getOutputStream(response)); - return true; - } - - - public static boolean 红河州第一人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - if (content == null) { - return false; - } - - if (content.contains("食堂")) { - String webUrl = WeChatConfig.getWebReqURL(); - return createLinkMsg(response, fromUserName, toUserName, "食堂充值(温馨提示:第一次使用请进行电话号码绑定)", msgType, content, - ("https://passport.whdc2002.com/"), - (webUrl + "images/message/food.png")); - } - return false; - } - - public static boolean 玉龙县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - if (content == null) { - return false; - } - - String respInfo; - if (content.contains("核酸")) { - respInfo = " 您好,玉龙县人民医院自助核酸检测需要点击微信挂号—自助核算检测进行具体操作。核酸检测报告电子版可在云南健康码查询," + - "纸质版可到门诊楼一楼自助打印,如标本检测有异常的,报告出具时间将延迟,如到时间后未查询到结果或有其他疑问可拨打0888-5180762进行咨询。"; - - } else if (content.contains("投诉")) { - respInfo = "您好,您可以拨打投诉电话:0888-5112778或行政值班电话:0888-5115602进行投诉"; - - } else if (content.contains("电话")) { - respInfo = - "玉龙县人民医院行政值班电话:0888-5115602\n" + - "神经内科、内分泌科、血液内科、风湿免疫科(内一科):0888-5123615\n" + - "心血管内科、心电图室(内二科):0888-5163257\n" + - "消化内科、肿瘤科(内三科):0888-5179785\n" + - "感染性疾病科(内四科):0888-5102655\n" + - "呼吸与危重症医学科(内五科):0888-5390632\n" + - "泌尿外科(外一科):0888-5156546\n" + - "普通外科(外二科):0888-5172791\n" + - "骨科、神经外科(外三科):0888-5129570\n" + - "胸外科、心脏大血管外科、乳腺外科(外四科):0888-5172632\n" + - "急诊医学科:0888-5186934\n" + - "麻醉科、手术室(手术麻醉科):0888-5186925\n" + - "妇产科:0888-5180763\n" + - "儿科:0888-5110667\n" + - "眼科、耳鼻咽喉科:0888-5186747\n" + - "口腔科(门诊):0888-5179715\n" + - "健康体检管理中心咨询电话:0888-5182024\n" + - "中医科:0888-5110125\n" + - "康复医学科(高压氧治疗室):0888-5169002\n" + - "重症医学科:0888-5108252\n" + - "老年医学科、肾内科:0888-5169002\n" + - "医学检验科:0888-5180762\n" + - "临床营养科:0888-5135525\n" + - "病理科:0888-5127597\n" + - "医学影像科:0888-5187393\n" + - "超声医学科:0888-5116254\n" + - "内镜中心:0888-5304137\n" + - "药剂科:0888-5122672\n" + - "党委办公室:0888-5110767\n" + - "行政办公室:0888-5112778\n" + - "医疗事务部:0888-5109120\n" + - "护理部:0888-5122871\n" + - "感染管理部:0888-5115466\n" + - "采购管理部:0888-5307952\n" + - "后勤保障部:0888-5107111"; - - } else if (content.contains("体检")) { - respInfo = "您好,您可以拨打体检科电话:0888-5182024进行详细咨询"; - - } else if (content.contains("退")) { - respInfo = "您好,退费需要持身份证到医院门诊楼一楼收费窗口办理"; - - } else if (content.contains("上班")) { - respInfo = "玉龙县人民医院上班时间:8:00—12:00 13:00—17:00"; - - } else { - respInfo = null; - } - - if (respInfo == null) { - return false; - } - XMLTextMessage msg = new XMLTextMessage(fromUserName, toUserName, respInfo); - msg.outputStreamWrite(getOutputStream(response)); - return true; - } - - public static boolean 德宏州妇幼保健院(HttpServletResponse response, String content, 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)) { - String respInfo = "您好!欢迎关注德宏州妇幼保健院!如有疑问请拨打 24小时值班电话:15368666599"; - XMLTextMessage msg = new XMLTextMessage(fromUserName, toUserName, respInfo); - msg.outputStreamWrite(getOutputStream(response)); - } - } - return true; - } - - public static boolean 蒙自市妇幼保健院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { - String mediaId = "iJoe834_vhMOnlrUUCQF5jyeRvOTJ0sF-ly_vZrsGzPqEFY0kvdzr_p410e-lG0K"; //医院科室对应电话列表图片 - if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { - if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { - XMLImageMessage imageMessage = new XMLImageMessage(fromUserName, toUserName, mediaId); - imageMessage.outputStreamWrite(getOutputStream(response)); - } - } - if (content == null) { - return false; - } - XMLImageMessage imageMessage = new XMLImageMessage(fromUserName, toUserName, mediaId); - imageMessage.outputStreamWrite(getOutputStream(response)); - return true; - } - - -} +package com.ynxbd.wx.wxfactory; + +import com.ynxbd.common.helper.common.ErrorHelper; +import com.ynxbd.common.helper.common.RepeatKeyHelper; +import com.ynxbd.wx.config.HospConfigEnum; +import com.ynxbd.wx.config.WeChatConfig; +import com.ynxbd.wx.config.WxEventEnum; +import com.ynxbd.wx.wxfactory.base.passivemsg.event.WxEvent; +import com.ynxbd.wx.wxfactory.base.passivemsg.models.XMLNewsMsg; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ObjectUtils; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 微信被动回复推送 + */ +@Slf4j +public class WxPassiveReplyHelper { + public static final String SUCCESS = "success"; + + private static RepeatKeyHelper EXPIRE_KEYS; // 重复通知过滤 + + private synchronized static void createExpireKey() { + if (EXPIRE_KEYS == null) { + EXPIRE_KEYS = new RepeatKeyHelper(60); + } + } + + // 消息通知过滤 + public static boolean isRepeat(String key) { + if (EXPIRE_KEYS == null) { + createExpireKey(); + } + return EXPIRE_KEYS.isContainsKey(key); + } + + /** + * 关注 + * + * @param response + * @param content + * @param msgType + * @param fromUserName + * @param toUserName + * @return + */ + public static boolean subscribeCommon(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String event) { + log.info("event={}", event); + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + String webUrl = WeChatConfig.getWebReqURL(); + return createNewsMsg(response, fromUserName, toUserName, "清廉承诺", msgType, content, + (webUrl + "wx-subscribe.html"), + (webUrl + "images/message/subscribe.png")); + } + return false; + } + + /** + * 回复图文消息 + * + * @param response + * @param fromUserName + * @param toUserName + * @param title + * @param msgType + * @param userText + * @param link + * @param imageUrl + * @return + */ + public static boolean createNewsMsg(HttpServletResponse response, String fromUserName, String toUserName, String title, String msgType, String userText, String link, String imageUrl) { + if (!WxEventEnum.MSG_TYPE_TEXT.isEvent(msgType)) { // 消息类型不为文本 + return false; + } + + if (ObjectUtils.isEmpty(userText)) { // 不存在 + return false; + } + WxFactory.Base.PassiveMsg().createXmlNewsMsg(response, fromUserName, toUserName, + new XMLNewsMsg.Article(title, null, link, imageUrl)); + +// List articleList = new ArrayList<>(); +// XMLNewsMessage.Article article; +// +// article = new XMLNewsMessage.Article(); +// article.setTitle(title); +// article.setUrl(link); +// article.setPicUrl(imageUrl); +// articleList.add(article); +// XMLNewsMessage xmlNewsMessage = new XMLNewsMessage(fromUserName, toUserName, articleList); +// xmlNewsMessage.outputStreamWrite(getOutputStream(response)); + return true; + } + + + /** + * 文字匹配 + */ + public static boolean textCommon(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName) { + String webUrl = WeChatConfig.getWebReqURL(); + + if (Arrays.asList(new String[]{ + "缓", + "缓存", + "用不了", + "页面", + "404", + "进不去" + }).contains(content)) { + return createNewsMsg(response, fromUserName, toUserName, "公众号用不了(缓存清理)", msgType, content, + (webUrl + "wx-cache.html"), + (webUrl + "images/message/cache.png")); + } + + if (Arrays.asList(new String[]{ + "你好", + "链接", + "指引", + "微官网", + }).contains(content)) { + return createNewsMsg(response, fromUserName, toUserName, "微官网链接", msgType, content, + (webUrl + "app.html"), + (webUrl + "images/message/hospital.png")); + } + + if (Arrays.asList(new String[]{ + "查", + "查询", + "报告" + }).contains(content)) { + return createNewsMsg(response, fromUserName, toUserName, "报告单查询", msgType, content, + (webUrl + "all-result.html"), + (webUrl + "images/message/report.png")); + } + return false; + } + + // 根据医院appId回复 + public static Boolean hospReply(HttpServletResponse response, WxEvent wxEvent, String msgId, String fromUserName, String toUserName) { + String event = wxEvent.getEvent(); + String eventKey = wxEvent.getEventKey(); + String msgType = wxEvent.getMsgType(); + String reqContent = wxEvent.getContent(); + if (reqContent != null) { + reqContent = reqContent.trim().toUpperCase(); + } + + WxPassiveReplyHelper.textCommon(response, reqContent, msgType, fromUserName, toUserName); + + HospConfigEnum hospConfigEnum = HospConfigEnum.findEnumByWxAppId(); + if (hospConfigEnum == null) { + return false; + } + switch (hospConfigEnum) { + 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); + + 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); + + case 芒市人民医院: + return WxPassiveReplyHelper.芒市人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); + + case 玉龙县人民医院: + return WxPassiveReplyHelper.玉龙县人民医院(response, reqContent, msgType, fromUserName, toUserName, eventKey, event); + + default: + break; + } + return false; + } + + 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)) { + 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) { + + if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + XMLNewsMsg.Article article = new XMLNewsMsg.Article(); + article.setTitle("微信预约挂号开通喽,大家快快用起来!"); + article.setUrl("https://mp.weixin.qq.com/s/rJF1qBo1-mV5CUdRsi4Z5g"); + article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_jpg/RUm4m8SVypy7nVubUuo6KgdlibcduK8l4tWnXrz7VfTO5EYOeDc9hZxR70wTQgX1sYhRR7SeND6426uczdpf1BA/0?wx_fmt=jpeg"); + WxFactory.Base.PassiveMsg().createXmlNewsMsg(response, fromUserName, toUserName, article); + } + } + + String respContent; + + if (content != null) { + if (content.contains("放射") || content.contains("影像") || content.contains("CT") || content.contains("核磁")) { + respContent = "放射科:2116611、18869202310(值班)"; + + } else if (content.contains("B超")) { + respContent = "B超室:2121651、18869202311(值班)"; + + } else if (content.contains("检验") || content.contains("化验") || content.contains("生化") || content.contains("免疫")) { + respContent = "检验科:2130240"; + + } else if (content.contains("口 腔")) { + respContent = "口腔科:2139404"; + + } else if (content.contains("皮肤")) { + respContent = "皮肤科:2129260"; + + } else if (content.contains("急诊")) { + respContent = "急诊科:2103068(护士站)"; + + } else if (content.contains("外三") || content.contains("泌尿")) { + respContent = "外三科(泌尿):2113501(护士站)"; + + } else if (content.contains("麻醉")) { + respContent = "麻醉科:18869202309"; + + } else if (content.contains("妇产") || content.contains("产科") || content.contains("妇科")) { + respContent = "妇产科:2113504(护士站)"; + + } else if (content.contains("感染") || content.contains("传染")) { + respContent = "感染科:2116031"; + + } else if (content.contains("内二")) { + respContent = "内二科:2113503(护士站)"; + + } else if (content.contains("内一")) { + respContent = "内一科:2113500(护士站)"; + + } else if (content.contains("外二") || content.contains("骨科")) { + respContent = "外二科(骨 科):2122450(护士站) "; + + } else if (content.contains("儿") || content.contains("儿科")) { + respContent = "儿科:2122381(护士站)"; + + } else if (content.contains("康复")) { + respContent = "康复科:2116167(护士站)"; + + } else if (content.contains("体检")) { + respContent = "体检科:2917280、18288102873"; + + } else if (content.contains("120") || content.contains("急救")) { + respContent = "120急救中心:2107120"; + + } else if (content.contains("外一") || content.contains("普外")) { + respContent = "外一科(普外):2133720"; + + } else { + respContent = "办公室:2122460\n" + + "行政值班:18869202307\n" + + "放射科:2116611、18869202310(值班)\n\n" + + "B超室:2121651、 18869202311(值班)\n\n" + + "儿 科:2122381(护士站)\n" + + "康复科:2116167(护士站)\n" + + "检验科:2130240\n" + + "口腔科:2139404\n" + + "皮肤科:2129260\n" + + "麻醉科:18869202309\n" + + "感染科:2116031,\n" + + "急诊科:2103068(护士站)\n" + + "妇产科:2113504(护士站)\n" + + "内二科:2113503(护士站)\n" + + "内一科:2113500(护士站)\n" + + "外二科(骨 科):2122450(护士站)\n" + + "外三科(泌 尿):2113501(护士站)\n\n" + + "体检科:2917280、18288102873\n" + + "120急救中心:2107120,\n" + + "外一科(普外):2133720"; + } + WxFactory.Base.PassiveMsg().createXmlTextMsg(response, fromUserName, toUserName, respContent); + } + return true; + } + + public static boolean 华坪县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + List articleList = new ArrayList<>(); + XMLNewsMsg.Article article; + + if (content != null) { + String webUrl = WeChatConfig.getWebReqURL(); + if (content.equals("支付") || content.equals("微信支付") || content.contains("费")) { + article = new XMLNewsMsg.Article(); + article.setTitle("微信支付"); + article.setPicUrl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); + article.setDescription("请点这里进入支付页面,支付您的账单,不用再去排队缴费。如需查看检查结果,请输入“检查”。如需查看化验结果,请输入“化验”。"); + article.setUrl(webUrl + "pay-info.html"); + articleList.add(article); + + } else if (content.equals("检查") || content.equals("检验") || content.equals("化验")) { + article = new XMLNewsMsg.Article(); + article.setTitle("查看检查结果"); + article.setPicUrl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); + article.setDescription("请点这里查看您的检查结果,如要查看化验结果,请输入“化验”或“检验”。如需缴费,请输入“支付”。"); + article.setUrl(webUrl + "all-result.html"); + articleList.add(article); + } + } + + if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { + if (eventKey.equals("MYDDC")) { + article = new XMLNewsMsg.Article(); + article.setTitle("华坪县人民医院患者满意度调查"); + article.setUrl("http://mp.weixin.qq.com/s/MCswklxDHdmYr3sFP70Xdw"); + article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOwYlpPRQDFKpbFQsN2ibtZqcS9H9pqX4nOCzdaAHNiciaZubLF9jiayZJBV8ADxAqL6XdbpdqolJuwJIQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); + articleList.add(article); + + article = new XMLNewsMsg.Article(); + article.setTitle("患者满意度调查"); + article.setUrl("http://mp.weixin.qq.com/s/7l2YsE2Y-XSTWEXN7BJlIQ"); + article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOzYGDMbzzyKicXD9QlRA5MdmpGgicibSdY0A4kmgV94qibuKylgRXbMgPb4zGNw9BvWqDXiby1XyFCFCaQ/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); + articleList.add(article); + + article = new XMLNewsMsg.Article(); + article.setTitle("员工满意度调查"); + article.setUrl("http://mp.weixin.qq.com/s/VyoOCM8FoEZ53ZQC3yX-Yw"); + article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_jpg/0jg8QrIOHOzYGDMbzzyKicXD9QlRA5MdmpF19PW1oFibvCDj60twgfGC556fY3wThlAhIYJsHykiaDIU8h3Igh8Dw/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); + articleList.add(article); + + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + article = new XMLNewsMsg.Article(); + article.setTitle("微信支付使用流程!"); + article.setPicUrl("http://mmbiz.qpic.cn/mmbiz/0jg8QrIOHOydg7liaUzXoa7otFCiavYozxARcpnrxt5ibQ7Y8BewUOtKJPWRUATkaskjvHeeqmicDbovRwZic7BTSng/0?wx_fmt=jpeg"); + article.setDescription("首先关注微信公众号“华坪县人民医院”,其次打开公众号,点击“微信支付”,首次需进行身份绑定,按要求输入相关内容,获取账单;最多可以绑定除本人外加4个人,在身份绑定页面,点“添加绑定”"); + + articleList.add(article); + } + } + } + + return WxFactory.Base.PassiveMsg().createXmlNewsMsg(response, fromUserName, toUserName, articleList); + } + + public static boolean 巍山县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + List articleList = new ArrayList<>(); + XMLNewsMsg.Article article; + + if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { + // 满意度 + if (eventKey.equals("MYDDC")) { + article = new XMLNewsMsg.Article(); + article.setTitle("巍山县人民医院患者满意度调查"); + article.setUrl("https://mp.weixin.qq.com/s/R-tX9YtRRM9Hpw2rMmw2iQ"); + article.setPicUrl("https://mmbiz.qpic.cn/mmbiz_jpg/5kpYU2jcMVicvMfVRATtAKOEjh4A4VvtHmCMKgD9vAfr741FDDEwiccNdj2ZTicBibeeQZfwp6zbaYMI5ubib1TaaeA/640?wx_fmt=jpeg&tp=webp&wxfrom=5&wx_lazy=1"); + articleList.add(article); + + } + // 关注 + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + article = new XMLNewsMsg.Article(); + article.setTitle("微信预约挂号开通喽,大家快快用起来!"); + article.setUrl("http://mp.weixin.qq.com/s/gl_NitQTP6_ZzoV8pwxOcw"); + article.setPicUrl("http://mmbiz.qpic.cn/mmbiz_jpg/5kpYU2jcMVicNybruqia0dn6kBqiakDlrTgDkweiafibyRl9uK6bkKoiaXib0xktJIywqTDzfe9fHcq5x0gggKkurDicpg/0?wx_fmt=jpeg"); + articleList.add(article); + } + } + return WxFactory.Base.PassiveMsg().createXmlNewsMsg(response, fromUserName, toUserName, articleList); + } + + + public static boolean 红河州第一人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + if (content == null) { + return false; + } + + if (content.contains("食堂")) { + String webUrl = WeChatConfig.getWebReqURL(); + return createNewsMsg(response, fromUserName, toUserName, "食堂充值(温馨提示:第一次使用请进行电话号码绑定)", msgType, content, + ("https://passport.whdc2002.com/"), + (webUrl + "images/message/food.png")); + } + return false; + } + + public static boolean 玉龙县人民医院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + if (content == null) { + return false; + } + + String respInfo; + if (content.contains("核酸")) { + respInfo = " 您好,玉龙县人民医院自助核酸检测需要点击微信挂号—自助核算检测进行具体操作。核酸检测报告电子版可在云南健康码查询," + + "纸质版可到门诊楼一楼自助打印,如标本检测有异常的,报告出具时间将延迟,如到时间后未查询到结果或有其他疑问可拨打0888-5180762进行咨询。"; + + } else if (content.contains("投诉")) { + respInfo = "您好,您可以拨打投诉电话:0888-5112778或行政值班电话:0888-5115602进行投诉"; + + } else if (content.contains("电话")) { + respInfo = + "玉龙县人民医院行政值班电话:0888-5115602\n" + + "神经内科、内分泌科、血液内科、风湿免疫科(内一科):0888-5123615\n" + + "心血管内科、心电图室(内二科):0888-5163257\n" + + "消化内科、肿瘤科(内三科):0888-5179785\n" + + "感染性疾病科(内四科):0888-5102655\n" + + "呼吸与危重症医学科(内五科):0888-5390632\n" + + "泌尿外科(外一科):0888-5156546\n" + + "普通外科(外二科):0888-5172791\n" + + "骨科、神经外科(外三科):0888-5129570\n" + + "胸外科、心脏大血管外科、乳腺外科(外四科):0888-5172632\n" + + "急诊医学科:0888-5186934\n" + + "麻醉科、手术室(手术麻醉科):0888-5186925\n" + + "妇产科:0888-5180763\n" + + "儿科:0888-5110667\n" + + "眼科、耳鼻咽喉科:0888-5186747\n" + + "口腔科(门诊):0888-5179715\n" + + "健康体检管理中心咨询电话:0888-5182024\n" + + "中医科:0888-5110125\n" + + "康复医学科(高压氧治疗室):0888-5169002\n" + + "重症医学科:0888-5108252\n" + + "老年医学科、肾内科:0888-5169002\n" + + "医学检验科:0888-5180762\n" + + "临床营养科:0888-5135525\n" + + "病理科:0888-5127597\n" + + "医学影像科:0888-5187393\n" + + "超声医学科:0888-5116254\n" + + "内镜中心:0888-5304137\n" + + "药剂科:0888-5122672\n" + + "党委办公室:0888-5110767\n" + + "行政办公室:0888-5112778\n" + + "医疗事务部:0888-5109120\n" + + "护理部:0888-5122871\n" + + "感染管理部:0888-5115466\n" + + "采购管理部:0888-5307952\n" + + "后勤保障部:0888-5107111"; + + } else if (content.contains("体检")) { + respInfo = "您好,您可以拨打体检科电话:0888-5182024进行详细咨询"; + + } else if (content.contains("退")) { + respInfo = "您好,退费需要持身份证到医院门诊楼一楼收费窗口办理"; + + } else if (content.contains("上班")) { + respInfo = "玉龙县人民医院上班时间:8:00—12:00 13:00—17:00"; + + } else { + respInfo = null; + } + + if (respInfo == null) { + return false; + } + WxFactory.Base.PassiveMsg().createXmlTextMsg(response, fromUserName, toUserName, respInfo); + return true; + } + + public static boolean 德宏州妇幼保健院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + boolean isEventSubscribe = false; + if (WxEventEnum.MSG_TYPE_EVENT.isEvent(msgType)) { // 事件 + if (WxEventEnum.EVENT_SUBSCRIBE.isEvent(event)) { // 关注 + isEventSubscribe = true; + String respContent = "您好!欢迎关注德宏州妇幼保健院!如有疑问请拨打 24小时值班电话:15368666599"; + WxFactory.Base.PassiveMsg().createXmlTextMsg(response, fromUserName, toUserName, respContent); + } + } + if (content == null) { + content = ""; + } + + if (isEventSubscribe || content.contains("电话")) { + String mediaId = ""; // 图片ID + WxFactory.Base.PassiveMsg().createXmlImageMsg(response, fromUserName, toUserName, mediaId); + } + return true; + } + + public static boolean 蒙自市妇幼保健院(HttpServletResponse response, String content, String msgType, String fromUserName, String toUserName, String eventKey, String event) { + String mediaId = "iJoe834_vhMOnlrUUCQF5jyeRvOTJ0sF-ly_vZrsGzPqEFY0kvdzr_p410e-lG0K"; //医院科室对应电话列表图片 + if (WxEventEnum.MSG_TYPE_EVENT.CODE.equals(msgType)) { + if (WxEventEnum.EVENT_SUBSCRIBE.CODE.equals(event)) { + return WxFactory.Base.PassiveMsg().createXmlImageMsg(response, fromUserName, toUserName, mediaId); + } + } + if (content == null) { + return false; + } + return WxFactory.Base.PassiveMsg().createXmlImageMsg(response, fromUserName, toUserName, mediaId); + } + + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java index 12a2a88..df2d9af 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java @@ -9,10 +9,10 @@ import com.ynxbd.common.helper.common.*; import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ServiceException; import com.ynxbd.wx.config.WeChatConfig; -import com.ynxbd.wx.wxfactory.bean.WxNativePayResult; -import com.ynxbd.wx.wxfactory.bean.WxPayNotify; -import com.ynxbd.wx.wxfactory.bean.refund.WxRefundItem; -import com.ynxbd.wx.wxfactory.bean.refund.WxRefundQueryRoot; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxNativePayResult; +import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify; +import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundItem; +import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundQueryRoot; import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; @@ -79,7 +79,7 @@ public class WxPayHelper { public static WxPayNotify payNotify(HttpServletRequest request) throws ServiceException { try { // 转换数据对象 - Map paramsMap = WxSignHelper.getReqXmlParamsMap(request); + Map paramsMap = WxSignHelper.reqXmlParamsMap(request); log.info("【微信回调】map={}", paramsMap); if (paramsMap == null) { throw new ServiceException("【微信】回调通知下单信息返回错误"); @@ -91,7 +91,7 @@ public class WxPayHelper { } String json = JsonHelper.toJsonString(paramsMap); - if ("".equals(json)) { + if (ObjectUtils.isEmpty(json)) { throw new ServiceException("【微信】回调通知下单信息为空"); } 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 d03fe33..b42f4ce 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 @@ -5,11 +5,11 @@ 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.bean.SnsOath2AccessToken; -import com.ynxbd.wx.wxfactory.bean.SnsUserInfo; +import com.ynxbd.wx.wxfactory.base.auth.models.SnsOath2AccessToken; +import com.ynxbd.wx.wxfactory.base.auth.models.SnsUserInfo; +import com.ynxbd.wx.wxfactory.utils.EmojiHelper; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import weixin.popular.util.EmojiUtil; @Slf4j @NoArgsConstructor @@ -105,7 +105,7 @@ public class Client { } if (emoji != 0 && response.getNickname() != null) { - response.setNickname_emoji(EmojiUtil.parse(response.getNickname(), emoji)); + response.setNickname_emoji(EmojiHelper.parse(response.getNickname(), emoji)); } return response; } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/AccessToken.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AccessToken.java similarity index 87% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/AccessToken.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AccessToken.java index 282a205..4458932 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/AccessToken.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AccessToken.java @@ -1,20 +1,20 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.io.Serializable; - -@Getter -@Setter -@ToString -@NoArgsConstructor -public class AccessToken implements Serializable { - private static final long serialVersionUID = 36888886677781604L; - - private String accessToken; - // 创建时间 - private String createTime; -} +package com.ynxbd.wx.wxfactory.base.auth.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class AccessToken implements Serializable { + private static final long serialVersionUID = 36888886677781604L; + + private String accessToken; + // 创建时间 + private String createTime; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/auth/AuthData.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AuthData.java similarity index 98% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/auth/AuthData.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AuthData.java index 06a01e3..4c28069 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/auth/AuthData.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AuthData.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean.auth; +package com.ynxbd.wx.wxfactory.base.auth.models; import com.ynxbd.common.helper.common.DateHelper; import com.ynxbd.common.helper.common.JsonHelper; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/JsapiTicket.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/JsapiTicket.java similarity index 90% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/JsapiTicket.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/JsapiTicket.java index 060e46e..7af3c55 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/JsapiTicket.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/JsapiTicket.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean; +package com.ynxbd.wx.wxfactory.base.auth.models; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/RespAccessToken.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/RespAccessToken.java index d6c3a8a..2858ce2 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/RespAccessToken.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/RespAccessToken.java @@ -1,6 +1,5 @@ package com.ynxbd.wx.wxfactory.base.auth.models; -import com.ynxbd.wx.wxfactory.bean.WxBaseResult; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/SnsOath2AccessToken.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsOath2AccessToken.java similarity index 91% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/SnsOath2AccessToken.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsOath2AccessToken.java index 21d79b4..de4e3f1 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/SnsOath2AccessToken.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsOath2AccessToken.java @@ -1,28 +1,28 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -public class SnsOath2AccessToken extends WxBaseResult { - private String accessToken; - private Integer expiresIn; - private String refreshToken; - private String openid; - private String scope; - private String unionid; - // 是否为快照页模式虚拟账号,只有当用户是快照页模式虚拟账号是返回,值为1 - private String isSnapShotUser; - - public Boolean getIsSnapShotUser() { - if (isSnapShotUser == null) { - return null; - } - return "1".equals(isSnapShotUser); - } -} +package com.ynxbd.wx.wxfactory.base.auth.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class SnsOath2AccessToken extends WxBaseResult { + private String accessToken; + private Integer expiresIn; + private String refreshToken; + private String openid; + private String scope; + private String unionid; + // 是否为快照页模式虚拟账号,只有当用户是快照页模式虚拟账号是返回,值为1 + private String isSnapShotUser; + + public Boolean getIsSnapShotUser() { + if (isSnapShotUser == null) { + return null; + } + return "1".equals(isSnapShotUser); + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/SnsUserInfo.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsUserInfo.java similarity index 92% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/SnsUserInfo.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsUserInfo.java index 95a54f7..5b94948 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/SnsUserInfo.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsUserInfo.java @@ -1,33 +1,33 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.io.Serializable; - -@Getter -@Setter -@ToString(callSuper = true) -@NoArgsConstructor -public class SnsUserInfo extends WxBaseResult implements Serializable { - private static final long serialVersionUID = 20221025231300001L; - private Integer subscribe; - private String openid; - private String nickname; - private String nickname_emoji; - private Integer sex; - private String language; - private String city; - private String province; - private String country; - private String headImgUrl; - private Integer subscribe_time; - private String unionid; - private Integer groupid; - private String remark; - private String subscribe_scene; - private Integer qr_scene; - private String qr_scene_str; -} +package com.ynxbd.wx.wxfactory.base.auth.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.io.Serializable; + +@Getter +@Setter +@ToString(callSuper = true) +@NoArgsConstructor +public class SnsUserInfo extends WxBaseResult implements Serializable { + private static final long serialVersionUID = 20221025231300001L; + private Integer subscribe; + private String openid; + private String nickname; + private String nickname_emoji; + private Integer sex; + private String language; + private String city; + private String province; + private String country; + private String headImgUrl; + private Integer subscribe_time; + private String unionid; + private Integer groupid; + private String remark; + private String subscribe_scene; + private Integer qr_scene; + private String qr_scene_str; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxBaseResult.java b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/WxBaseResult.java similarity index 88% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/WxBaseResult.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/WxBaseResult.java index ce6bfde..9f44867 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxBaseResult.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/WxBaseResult.java @@ -1,20 +1,20 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString(callSuper = true) -@NoArgsConstructor -public class WxBaseResult { - private final String SUCCESS_CODE = "0"; - private String errCode; - private String errMsg; - - public boolean isSuccess() { - return this.errCode == null || this.errCode.isEmpty() || SUCCESS_CODE.equals(this.errCode); - } -} +package com.ynxbd.wx.wxfactory.base.auth.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString(callSuper = true) +@NoArgsConstructor +public class WxBaseResult { + private final String SUCCESS_CODE = "0"; + private String errCode; + private String errMsg; + + public boolean isSuccess() { + return this.errCode == null || this.errCode.isEmpty() || SUCCESS_CODE.equals(this.errCode); + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/Client.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/Client.java new file mode 100644 index 0000000..8d8cdd8 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/Client.java @@ -0,0 +1,68 @@ +package com.ynxbd.wx.wxfactory.base.passivemsg; + +import com.ynxbd.wx.wxfactory.base.passivemsg.models.XMLImageMsg; +import com.ynxbd.wx.wxfactory.base.passivemsg.models.XMLNewsMsg; +import com.ynxbd.wx.wxfactory.base.passivemsg.models.XMLTextMsg; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +// 被动消息回复 +@Slf4j +@NoArgsConstructor +public class Client { + + /** + * 回复图片消息 + * + * @param response + * @param fromUserName + * @param toUserName + * @param mediaId + * @return + */ + public boolean createXmlImageMsg(HttpServletResponse response, String fromUserName, String toUserName, String mediaId) { + return new XMLImageMsg(fromUserName, toUserName, mediaId).outputStreamWrite(response); + } + + /** + * 回复图文消息 + * + * @param response + * @param fromUserName + * @param toUserName + * @param article + * @return + */ + public boolean createXmlNewsMsg(HttpServletResponse response, String fromUserName, String toUserName, XMLNewsMsg.Article article) { + return new XMLNewsMsg(fromUserName, toUserName, article).outputStreamWrite(response); + } + + /** + * 回复图文消息 + * + * @param response + * @param fromUserName + * @param toUserName + * @param articles + * @return + */ + public boolean createXmlNewsMsg(HttpServletResponse response, String fromUserName, String toUserName, List articles) { + return new XMLNewsMsg(fromUserName, toUserName, articles).outputStreamWrite(response); + } + + /** + * 回复文本消息 + * + * @param response + * @param fromUserName + * @param toUserName + * @param content + * @return + */ + public boolean createXmlTextMsg(HttpServletResponse response, String fromUserName, String toUserName, String content) { + return new XMLTextMsg(fromUserName, toUserName, content).outputStreamWrite(response); + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEvent.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEvent.java similarity index 85% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEvent.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEvent.java index 2af8782..2b84b49 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEvent.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEvent.java @@ -1,32 +1,32 @@ -package com.ynxbd.wx.wxfactory.bean.event; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@NoArgsConstructor -@ToString -public class WxEvent { - - private String toUserName; - - private String fromUserName; - - private Integer createTime; - - private String msgType; - - private String event; - - private String eventKey; - - private String content; - - private String url; - - private String msgId; - -} +package com.ynxbd.wx.wxfactory.base.passivemsg.event; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@NoArgsConstructor +@ToString +public class WxEvent { + + private String toUserName; + + private String fromUserName; + + private Integer createTime; + + private String msgType; + + private String event; + + private String eventKey; + + private String content; + + private String url; + + private String msgId; + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEventMessage.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEventMessage.java similarity index 75% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEventMessage.java rename to src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEventMessage.java index bad3851..cda7bad 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/event/WxEventMessage.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEventMessage.java @@ -1,134 +1,129 @@ -package com.ynxbd.wx.wxfactory.bean.event; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import org.w3c.dom.Element; -import weixin.popular.bean.message.AroundBeacon; -import weixin.popular.bean.message.ChosenBeacon; -import weixin.popular.bean.message.CopyrightCheckResult; - -import java.util.List; - -@Getter -@Setter -@NoArgsConstructor -@ToString -public class WxEventMessage { - - private String toUserName; - - private String fromUserName; - - private Integer createTime; - - private String msgType; - - private String event; - - private String eventKey; - - private String msgId; - - private String content; - - private String picUrl; - - private String mediaId; - - private String format; - - private String recognition; - - private String thumbMediaId; - - private String location_X; - - private String location_Y; - - private String scale; - - private String label; - - private String title; - - private String description; - - private String url; - - private String ticket; - - private String latitude; - - private String longitude; - - private String precision; - - private String status; - - private Integer totalCount; - - private Integer filterCount; - - private Integer sentCount; - - private Integer errorCount; - - - private Integer expiredTime; - - private Integer failTime; - - private String failReason; - - private String uniqId; - - private String poiId; - - private String result; - - private String msg; - - private String lotteryId; - - private Integer money; - - private Integer bindTime; - - private Integer connectTime; - - private Integer expireTime; - - private String vendorId; - - private String shopId; - - private String deviceNo; - - private String keyStandard; - - private String keyStr; - - private String country; - - private String province; - - private String city; - - private Integer sex; - - private Integer scene; - - private String regionCode; - - private Integer reasonMsg; - - private ChosenBeacon chosenBeacon; - - private CopyrightCheckResult copyrightCheckResult; - - private List aroundBeacons; - - private List otherElements; -} +package com.ynxbd.wx.wxfactory.base.passivemsg.event; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + + +@Getter +@Setter +@NoArgsConstructor +@ToString +public class WxEventMessage { + + private String toUserName; + + private String fromUserName; + + private Integer createTime; + + private String msgType; + + private String event; + + private String eventKey; + + private String msgId; + + private String content; + + private String picUrl; + + private String mediaId; + + private String format; + + private String recognition; + + private String thumbMediaId; + + private String location_X; + + private String location_Y; + + private String scale; + + private String label; + + private String title; + + private String description; + + private String url; + + private String ticket; + + private String latitude; + + private String longitude; + + private String precision; + + private String status; + + private Integer totalCount; + + private Integer filterCount; + + private Integer sentCount; + + private Integer errorCount; + + + private Integer expiredTime; + + private Integer failTime; + + private String failReason; + + private String uniqId; + + private String poiId; + + private String result; + + private String msg; + + private String lotteryId; + + private Integer money; + + private Integer bindTime; + + private Integer connectTime; + + private Integer expireTime; + + private String vendorId; + + private String shopId; + + private String deviceNo; + + private String keyStandard; + + private String keyStr; + + private String country; + + private String province; + + private String city; + + private Integer sex; + + private Integer scene; + + private String regionCode; + + private Integer reasonMsg; + +// private ChosenBeacon chosenBeacon; +// +// private CopyrightCheckResult copyrightCheckResult; +// +// private List aroundBeacons; +// +// private List otherElements; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLBaseMsg.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLBaseMsg.java new file mode 100644 index 0000000..80a6d27 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLBaseMsg.java @@ -0,0 +1,93 @@ +package com.ynxbd.wx.wxfactory.base.passivemsg.models; + +import com.qq.weixin.mp.aes.AesException; +import com.qq.weixin.mp.aes.WXBizMsgCrypt; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.OutputStream; +import java.io.Serializable; +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +@Slf4j +@Getter +@Setter +@ToString +public abstract class XMLBaseMsg implements Serializable { + private static final long serialVersionUID = -20251201104500001L; + + private String toUserName; + private String fromUserName; + private String msgType; + + protected XMLBaseMsg(String toUserName, String fromUserName, String msgType) { + this.toUserName = toUserName; + this.fromUserName = fromUserName; + this.msgType = msgType; + } + + /** + * 非公共部分节点数据 + */ + public abstract String subXMLContent(); + + public String toXML() { + StringBuilder sb = new StringBuilder(); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append("").append(System.currentTimeMillis() / 1000L).append(""); + sb.append(""); + String subXml = this.subXMLContent(); + if (subXml != null) { + sb.append(subXml); + } + sb.append(""); + return sb.toString(); + } + + + public boolean outputStreamWrite(OutputStream outputStream) { + try { + outputStream.write(this.toXML().getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + return true; + } catch (IOException e) { + log.error("", e); + return false; + } + } + + public boolean outputStreamWrite(OutputStream outputStream, WXBizMsgCrypt bizMsgCrypt) { + if (bizMsgCrypt != null) { + try { + String outputStr = bizMsgCrypt.encryptMsg(this.toXML(), System.currentTimeMillis() + "", UUID.randomUUID().toString()); + outputStream.write(outputStr.getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + return true; + } catch (IOException | AesException e) { + log.error("", e); + return false; + } + } else { + return this.outputStreamWrite(outputStream); + } + } + + public boolean outputStreamWrite(HttpServletResponse response) { + try (ServletOutputStream outputStream = response.getOutputStream()) { + outputStream.write(this.toXML().getBytes(StandardCharsets.UTF_8)); + outputStream.flush(); + return true; + } catch (IOException e) { + log.error("", e); + return false; + } + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLImageMsg.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLImageMsg.java new file mode 100644 index 0000000..1813de7 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLImageMsg.java @@ -0,0 +1,27 @@ +package com.ynxbd.wx.wxfactory.base.passivemsg.models; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +// 回复图片消息 + +@Slf4j +@Getter +@Setter +@ToString(callSuper = true) +public class XMLImageMsg extends XMLBaseMsg { + private static final long serialVersionUID = -20251201104500002L; + private String mediaId; + + public XMLImageMsg(String toUserName, String fromUserName, String mediaId) { + super(toUserName, fromUserName, "image"); + this.mediaId = mediaId; + } + + public String subXMLContent() { + return ""; + } + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLNewsMsg.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLNewsMsg.java new file mode 100644 index 0000000..bbbdf06 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLNewsMsg.java @@ -0,0 +1,68 @@ +package com.ynxbd.wx.wxfactory.base.passivemsg.models; + +// 回复图文消息 + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +import java.util.Collections; +import java.util.List; + +@Slf4j +@Getter +@Setter +@ToString(callSuper = true) +public class XMLNewsMsg extends XMLBaseMsg { + private static final long serialVersionUID = -20251201104500003L; + private List articles; + + public XMLNewsMsg(String toUserName, String fromUserName, List articles) { + super(toUserName, fromUserName, "news"); + this.articles = articles; + } + + public XMLNewsMsg(String toUserName, String fromUserName, XMLNewsMsg.Article article) { + super(toUserName, fromUserName, "news"); + this.articles = Collections.singletonList(article); + } + + @Override + public String subXMLContent() { + StringBuilder sb = new StringBuilder(); + sb.append("").append(this.articles.size()).append(""); + sb.append(""); + + for (XMLNewsMsg.Article item : this.articles) { + sb.append(""); + sb.append("<![CDATA[").append(item.title == null ? "" : item.title).append("]]>"); + sb.append(""); + sb.append(""); + sb.append(""); + sb.append(""); + } + sb.append(""); + return sb.toString(); + } + + + @Getter + @Setter + @ToString + @NoArgsConstructor + public static class Article { + private String title; + private String description; + private String url; + private String picUrl; + + public Article(String title, String description, String url, String picUrl) { + this.title = title; + this.description = description; + this.url = url; + this.picUrl = picUrl; + } + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLTextMsg.java b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLTextMsg.java new file mode 100644 index 0000000..6ff630b --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLTextMsg.java @@ -0,0 +1,29 @@ +package com.ynxbd.wx.wxfactory.base.passivemsg.models; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@Getter +@Setter +@ToString(callSuper = true) +public class XMLTextMsg extends XMLBaseMsg { + private static final long serialVersionUID = -20251201104500004L; + private String content; + + public XMLTextMsg(String toUserName, String fromUserName, String content) { + super(toUserName, fromUserName, "text"); + this.content = content; + } + + public String subXML() { + return ""; + } + + @Override + public String subXMLContent() { + return ""; + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/medical/Client.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/Client.java index 12b9c55..86bb403 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/medical/Client.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/Client.java @@ -7,8 +7,9 @@ import com.ynxbd.common.helper.common.ErrorHelper; import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.common.result.JsonResult; -import com.ynxbd.wx.wxfactory.bean.*; import com.ynxbd.wx.wxfactory.medical.enums.MdRefundTypeEnum; +import com.ynxbd.wx.wxfactory.medical.models.*; +import com.ynxbd.wx.wxfactory.payment.OrderMIEnum; import com.ynxbd.wx.wxfactory.utils.WxRequestHelper; import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/MdRespHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedRespHelper.java similarity index 91% rename from src/main/java/com/ynxbd/wx/wxfactory/utils/MdRespHelper.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedRespHelper.java index c14180b..833d3c9 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/utils/MdRespHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedRespHelper.java @@ -1,65 +1,67 @@ -package com.ynxbd.wx.wxfactory.utils; - -import com.ynxbd.common.result.ResultEnum; -import com.ynxbd.common.result.ServiceException; -import lombok.extern.slf4j.Slf4j; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -// 医保回调 -@Slf4j -public class MdRespHelper { - /** - * 失败响应 - */ - public static String resp(ServiceException e, String mdPayKey) { - if (ResultEnum.PAY_NOTIFY_REPEAT.equals(e.getResultEnum())) { // 重复通知 - return respOk(mdPayKey); - } - return respFail(e.getMessage(), mdPayKey); - } - - /** - * 成功响应 - */ - public static String respOk(String mdPayKey) { - log.info("[医保]回调通知成功"); - try { - Map map = new HashMap<>(); - map.put("return_code", "SUCCESS"); - map.put("result_code", "SUCCESS"); - map.put("return_msg", "OK"); - map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); - map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); - return XmlHelper.mapToXml(map); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - - /** - * 成功响应 - */ - public static String respFail(String message, String mdPayKey) { - log.info("[医保]回调通知:{}", message); - if (message == null) { - message = "FAIL"; - } - try { - Map map = new HashMap<>(); - map.put("return_code", "FAIL"); - map.put("result_code", "FAIL"); - map.put("return_msg", message); - map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); - map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); - return XmlHelper.mapToXml(map); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } -} +package com.ynxbd.wx.wxfactory.medical.models; + +import com.ynxbd.common.result.ResultEnum; +import com.ynxbd.common.result.ServiceException; +import com.ynxbd.wx.wxfactory.utils.WxSignHelper; +import com.ynxbd.wx.wxfactory.utils.XmlHelper; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +// 医保回调 +@Slf4j +public class MedRespHelper { + /** + * 失败响应 + */ + public static String resp(ServiceException e, String mdPayKey) { + if (ResultEnum.PAY_NOTIFY_REPEAT.equals(e.getResultEnum())) { // 重复通知 + return respOk(mdPayKey); + } + return respFail(e.getMessage(), mdPayKey); + } + + /** + * 成功响应 + */ + public static String respOk(String mdPayKey) { + log.info("[医保]回调通知成功"); + try { + Map map = new HashMap<>(); + map.put("return_code", "SUCCESS"); + map.put("result_code", "SUCCESS"); + map.put("return_msg", "OK"); + map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); + map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); + return XmlHelper.mapToXml(map); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 成功响应 + */ + public static String respFail(String message, String mdPayKey) { + log.info("[医保]回调通知:{}", message); + if (message == null) { + message = "FAIL"; + } + try { + Map map = new HashMap<>(); + map.put("return_code", "FAIL"); + map.put("result_code", "FAIL"); + map.put("return_msg", message); + map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); + map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); + return XmlHelper.mapToXml(map); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalBill.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalBill.java similarity index 85% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalBill.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalBill.java index 356b52e..691bbf1 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalBill.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalBill.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean; +package com.ynxbd.wx.wxfactory.medical.models; import com.ynxbd.wx.wxfactory.WxFactory; import lombok.Getter; @@ -17,11 +17,11 @@ import lombok.ToString; @Getter @ToString(callSuper = true) @NoArgsConstructor -public class MedicalBill extends WxFactory.ResponseCheck.ResultBase{ +public class MedicalBill extends WxFactory.ResponseCheck.ResultBase { // 账单下载链接 private String downloadUrl; // 校验码值 - private String checksumValue; + private String checksumValue; // 校验算法 private String checksumType; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalInfo.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalInfo.java similarity index 94% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalInfo.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalInfo.java index 3898955..da58c3e 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalInfo.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalInfo.java @@ -1,54 +1,54 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.math.BigDecimal; - -@Getter -@Setter -@ToString -@NoArgsConstructor -public class MedicalInfo { - private BigDecimal acctFee; // 个人账户支付(医保账户) - private BigDecimal cashFee; // 现金 - private BigDecimal medFeeSumAmt; // 医保金额 - private BigDecimal hifpFee; // 统筹支付金额 - private BigDecimal totalFee; // 订单总金额 - - private BigDecimal insuranceFee; // 个账 + 统筹支付金额 - - private String payOrdId; // 订单号 - private String payToken; // token - private String payAuthNo; // 授权码 - private String chrgBchno; // 收费批次(去掉M作为发票号,用于退费)-医院订单号 - private String mdUserId; // 医保支付用户id - private String mdTrtId; // 医保就诊号 - - /** - * 医保结算状态 - *

- * 0 : 已保存 - * 1 : 预结算完成 - * 2 : 结算中 - * 3 : 自费完成 - * 4 : 医保支付完成 - * 5 : 院内结算完成 - * 6 : 结算完成 - * 7 : 已退款 - * 8 : 已医保全部退款 - * 9 : 仅自费全部退款 - * 10 : 仅自费部分退款 - * 11 : 医保全部退自费部分退款 - * 12 : 已撤销 - * 13 : 医保已撤销 - * 14 : 异常 - * 15 : 结算失败 - * -1 : 状态未知 - */ - private String statusCode; - // 医保结算说明 - private String status; -} +package com.ynxbd.wx.wxfactory.medical.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigDecimal; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class MedicalInfo { + private BigDecimal acctFee; // 个人账户支付(医保账户) + private BigDecimal cashFee; // 现金 + private BigDecimal medFeeSumAmt; // 医保金额 + private BigDecimal hifpFee; // 统筹支付金额 + private BigDecimal totalFee; // 订单总金额 + + private BigDecimal insuranceFee; // 个账 + 统筹支付金额 + + private String payOrdId; // 订单号 + private String payToken; // token + private String payAuthNo; // 授权码 + private String chrgBchno; // 收费批次(去掉M作为发票号,用于退费)-医院订单号 + private String mdUserId; // 医保支付用户id + private String mdTrtId; // 医保就诊号 + + /** + * 医保结算状态 + *

+ * 0 : 已保存 + * 1 : 预结算完成 + * 2 : 结算中 + * 3 : 自费完成 + * 4 : 医保支付完成 + * 5 : 院内结算完成 + * 6 : 结算完成 + * 7 : 已退款 + * 8 : 已医保全部退款 + * 9 : 仅自费全部退款 + * 10 : 仅自费部分退款 + * 11 : 医保全部退自费部分退款 + * 12 : 已撤销 + * 13 : 医保已撤销 + * 14 : 异常 + * 15 : 结算失败 + * -1 : 状态未知 + */ + private String statusCode; + // 医保结算说明 + private String status; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalNotify.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalNotify.java similarity index 97% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalNotify.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalNotify.java index 759589b..bb0cf06 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalNotify.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalNotify.java @@ -1,74 +1,74 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.math.BigDecimal; - -// 医保回调通知 - -@Setter -@Getter -@ToString -@NoArgsConstructor -public class MedicalNotify { - private String sign; - - private String openid; - - private String medTransId; - - private String hospOutTradeNo; - - // 总金额(分) - private BigDecimal totalFee; - // 支付现金(分) - private BigDecimal cashFee; - // 医保-个人账户(分) - private BigDecimal insuranceFee; - // - private String serialNo; - // - private String info; - - private String timeEnd; - private String cashOrderId; - // 类型标识 - private String attach; - // 分 - private BigDecimal insurance_self_fee; - private BigDecimal insurance_fund_fee; - private BigDecimal insurance_other_fee; - - private String payDate; - private String payTime; - - -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "3\n" + -// "597\n" + -// "297\n" + -// "300\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "\n" + -// "300\n" + -// "0\n" + -// "0\n" + - -} +package com.ynxbd.wx.wxfactory.medical.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigDecimal; + +// 医保回调通知 + +@Setter +@Getter +@ToString +@NoArgsConstructor +public class MedicalNotify { + private String sign; + + private String openid; + + private String medTransId; + + private String hospOutTradeNo; + + // 总金额(分) + private BigDecimal totalFee; + // 支付现金(分) + private BigDecimal cashFee; + // 医保-个人账户(分) + private BigDecimal insuranceFee; + // + private String serialNo; + // + private String info; + + private String timeEnd; + private String cashOrderId; + // 类型标识 + private String attach; + // 分 + private BigDecimal insurance_self_fee; + private BigDecimal insurance_fund_fee; + private BigDecimal insurance_other_fee; + + private String payDate; + private String payTime; + + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "3\n" + +// "597\n" + +// "297\n" + +// "300\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "\n" + +// "300\n" + +// "0\n" + +// "0\n" + + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalPayOrder.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalPayOrder.java similarity index 91% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalPayOrder.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalPayOrder.java index 5e77901..fded518 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalPayOrder.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalPayOrder.java @@ -1,20 +1,20 @@ -package com.ynxbd.wx.wxfactory.bean; - -import com.ynxbd.wx.wxfactory.WxFactory; -import lombok.*; - -// 医保下单返回 - -@Getter -@Setter -@ToString(callSuper = true) -@NoArgsConstructor -public class MedicalPayOrder extends WxFactory.ResponseCheck.ResultBase { - // 诊疗单id 微信生成的医疗订单id,用于后续调用接口使用 - private String medTransId; - // 支付链接 下单后跳转到此url,用户完成支付,使用app支付时1.5 APP支付说明 - private String payUrl; - // 支付小程序 当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付 - private String payAppId; - -} +package com.ynxbd.wx.wxfactory.medical.models; + +import com.ynxbd.wx.wxfactory.WxFactory; +import lombok.*; + +// 医保下单返回 + +@Getter +@Setter +@ToString(callSuper = true) +@NoArgsConstructor +public class MedicalPayOrder extends WxFactory.ResponseCheck.ResultBase { + // 诊疗单id 微信生成的医疗订单id,用于后续调用接口使用 + private String medTransId; + // 支付链接 下单后跳转到此url,用户完成支付,使用app支付时1.5 APP支付说明 + private String payUrl; + // 支付小程序 当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付 + private String payAppId; + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefund.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefund.java similarity index 89% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefund.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefund.java index 4493d41..ca5a07b 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefund.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefund.java @@ -1,21 +1,21 @@ -package com.ynxbd.wx.wxfactory.bean; - -import com.ynxbd.wx.wxfactory.WxFactory; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Setter -@Getter -@ToString(callSuper = true) -@NoArgsConstructor -public class MedicalRefund extends WxFactory.ResponseCheck.ResultBase { - private String totalFee; - private String cashRefundFee; - private String insuranceRefundFee; - private String medRefundId; - private String cashRefundId; - private String insuranceRefundId; - private String sign; -} +package com.ynxbd.wx.wxfactory.medical.models; + +import com.ynxbd.wx.wxfactory.WxFactory; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString(callSuper = true) +@NoArgsConstructor +public class MedicalRefund extends WxFactory.ResponseCheck.ResultBase { + private String totalFee; + private String cashRefundFee; + private String insuranceRefundFee; + private String medRefundId; + private String cashRefundId; + private String insuranceRefundId; + private String sign; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefundInfo.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefundInfo.java similarity index 92% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefundInfo.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefundInfo.java index 36c571f..53ce316 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalRefundInfo.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefundInfo.java @@ -1,30 +1,30 @@ -package com.ynxbd.wx.wxfactory.bean; - -import com.ynxbd.wx.wxfactory.WxFactory; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Setter -@Getter -@ToString(callSuper = true) -@NoArgsConstructor -public class MedicalRefundInfo extends WxFactory.ResponseCheck.ResultBase { - private String appid; - private String mchId; - private String nonce_str; - private String med_trans_id; - private String med_refund_id; - private String hosp_out_trade_no; - private String hosp_out_refund_no; - private String insurance_refund_fee; - private String cash_refund_fee; - private String cash_refund_stauts; - private String insurance_refund_status; - private String med_refund_state; - private String refund_end_time; - private String response_content; - private String cash_refund_id; - private String insurance_refund_id; -} +package com.ynxbd.wx.wxfactory.medical.models; + +import com.ynxbd.wx.wxfactory.WxFactory; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString(callSuper = true) +@NoArgsConstructor +public class MedicalRefundInfo extends WxFactory.ResponseCheck.ResultBase { + private String appid; + private String mchId; + private String nonce_str; + private String med_trans_id; + private String med_refund_id; + private String hosp_out_trade_no; + private String hosp_out_refund_no; + private String insurance_refund_fee; + private String cash_refund_fee; + private String cash_refund_stauts; + private String insurance_refund_status; + private String med_refund_state; + private String refund_end_time; + private String response_content; + private String cash_refund_id; + private String insurance_refund_id; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalUserInfo.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalUserInfo.java similarity index 86% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalUserInfo.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalUserInfo.java index 4d19d39..ff41bde 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/MedicalUserInfo.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalUserInfo.java @@ -1,28 +1,28 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@Getter -@Setter -@ToString -@NoArgsConstructor -public class MedicalUserInfo { - // 姓名 - private String userName; - // 授权码 - private String payAuthNo; - // 坐标 - private String longitude; - - private String latitude; - - private String cardNo; - - private boolean success; - - private String message; - -} +package com.ynxbd.wx.wxfactory.medical.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class MedicalUserInfo { + // 姓名 + private String userName; + // 授权码 + private String payAuthNo; + // 坐标 + private String longitude; + + private String latitude; + + private String cardNo; + + private boolean success; + + private String message; + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxMedOrder.java b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/WxMedOrder.java similarity index 97% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/WxMedOrder.java rename to src/main/java/com/ynxbd/wx/wxfactory/medical/models/WxMedOrder.java index ccd1783..15d7e81 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxMedOrder.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/medical/models/WxMedOrder.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean; +package com.ynxbd.wx.wxfactory.medical.models; import com.ynxbd.wx.wxfactory.WxFactory; import lombok.Getter; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/WxMsgConst.java b/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/WxMsgConst.java index 76ee2ab..c9352c0 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/WxMsgConst.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/WxMsgConst.java @@ -1,151 +1,90 @@ package com.ynxbd.wx.wxfactory.menu.bean; public class WxMsgConst { - public static final String XML_MSG_TEXT = "text"; - public static final String XML_MSG_IMAGE = "image"; - public static final String XML_MSG_VOICE = "voice"; - public static final String XML_MSG_VIDEO = "video"; - public static final String XML_MSG_NEWS = "news"; - public static final String XML_MSG_MUSIC = "music"; - public static final String XML_MSG_LOCATION = "location"; - public static final String XML_MSG_LINK = "link"; - public static final String XML_MSG_EVENT = "event"; - public static final String XML_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; - public static final String CUSTOM_MSG_TEXT = "text"; - public static final String CUSTOM_MSG_IMAGE = "image"; - public static final String CUSTOM_MSG_VOICE = "voice"; - public static final String CUSTOM_MSG_VIDEO = "video"; - public static final String CUSTOM_MSG_MUSIC = "music"; - public static final String CUSTOM_MSG_NEWS = "news"; - public static final String CUSTOM_MSG_FILE = "file"; - public static final String CUSTOM_MSG_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; - public static final String CUSTOM_MSG_SAFE_NO = "0"; - public static final String CUSTOM_MSG_SAFE_YES = "1"; - public static final String MASS_MSG_MPNEWS = "mpnews"; - public static final String MASS_MSG_NEWS = "news"; - public static final String MASS_MSG_TEXT = "text"; - public static final String MASS_MSG_VOICE = "voice"; - public static final String MASS_MSG_IMAGE = "image"; - public static final String MASS_MSG_MPVIDEO = "mpvideo"; - public static final String MASS_MSG_VIDEO = "video"; - public static final String MASS_MSG_MUSIC = "music"; - public static final String EVT_SUBSCRIBE = "subscribe"; - public static final String EVT_UNSUBSCRIBE = "unsubscribe"; - public static final String EVT_SCAN = "SCAN"; - public static final String EVT_LOCATION = "LOCATION"; - public static final String EVT_CLICK = "CLICK"; - public static final String EVT_VIEW = "VIEW"; - public static final String EVT_MASS_SEND_JOB_FINISH = "MASSSENDJOBFINISH"; - public static final String EVT_SCANCODE_PUSH = "scancode_push"; - public static final String EVT_SCANCODE_WAITMSG = "scancode_waitmsg"; - public static final String EVT_PIC_SYSPHOTO = "pic_sysphoto"; - public static final String EVT_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; - public static final String EVT_PIC_WEIXIN = "pic_weixin"; - public static final String EVT_LOCATION_SELECT = "location_select"; - public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH"; - public static final String EVT_ENTER_AGENT = "enter_agent"; - public static final String EVT_QUALIFICATION_VERIFY_SUCCESS = "qualification_verify_success"; - public static final String EVT_QUALIFICATION_VERIFY_FAIL = "qualification_verify_fail"; - public static final String EVT_NAMING_VERIFY_SUCCESS = "naming_verify_success"; - public static final String EVT_NAMING_VERIFY_FAIL = "naming_verify_fail"; - public static final String EVT_ANNUAL_RENEW = "annual_renew"; - public static final String EVT_VERIFY_EXPIRED = "verify_expired"; - public static final String MEDIA_IMAGE = "image"; - public static final String MEDIA_VOICE = "voice"; - public static final String MEDIA_VIDEO = "video"; - public static final String MEDIA_THUMB = "thumb"; - public static final String MEDIA_FILE = "file"; - public static final String FILE_JPG = "jpeg"; - public static final String FILE_MP3 = "mp3"; - public static final String FILE_AMR = "amr"; - public static final String FILE_MP4 = "mp4"; +// public static final String XML_MSG_TEXT = "text"; +// public static final String XML_MSG_IMAGE = "image"; +// public static final String XML_MSG_VOICE = "voice"; +// public static final String XML_MSG_VIDEO = "video"; +// public static final String XML_MSG_NEWS = "news"; +// public static final String XML_MSG_MUSIC = "music"; +// public static final String XML_MSG_LOCATION = "location"; +// public static final String XML_MSG_LINK = "link"; +// public static final String XML_MSG_EVENT = "event"; +// public static final String XML_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; +// public static final String CUSTOM_MSG_TEXT = "text"; +// public static final String CUSTOM_MSG_IMAGE = "image"; +// public static final String CUSTOM_MSG_VOICE = "voice"; +// public static final String CUSTOM_MSG_VIDEO = "video"; +// public static final String CUSTOM_MSG_MUSIC = "music"; +// public static final String CUSTOM_MSG_NEWS = "news"; +// public static final String CUSTOM_MSG_FILE = "file"; +// public static final String CUSTOM_MSG_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; +// public static final String CUSTOM_MSG_SAFE_NO = "0"; +// public static final String CUSTOM_MSG_SAFE_YES = "1"; +// public static final String MASS_MSG_MPNEWS = "mpnews"; +// public static final String MASS_MSG_NEWS = "news"; +// public static final String MASS_MSG_TEXT = "text"; +// public static final String MASS_MSG_VOICE = "voice"; +// public static final String MASS_MSG_IMAGE = "image"; +// public static final String MASS_MSG_MPVIDEO = "mpvideo"; +// public static final String MASS_MSG_VIDEO = "video"; +// public static final String MASS_MSG_MUSIC = "music"; +// public static final String EVT_SUBSCRIBE = "subscribe"; +// public static final String EVT_UNSUBSCRIBE = "unsubscribe"; +// public static final String EVT_SCAN = "SCAN"; +// public static final String EVT_LOCATION = "LOCATION"; +// public static final String EVT_CLICK = "CLICK"; +// public static final String EVT_VIEW = "VIEW"; +// public static final String EVT_MASS_SEND_JOB_FINISH = "MASSSENDJOBFINISH"; +// public static final String EVT_SCANCODE_PUSH = "scancode_push"; +// public static final String EVT_SCANCODE_WAITMSG = "scancode_waitmsg"; +// public static final String EVT_PIC_SYSPHOTO = "pic_sysphoto"; +// public static final String EVT_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; +// public static final String EVT_PIC_WEIXIN = "pic_weixin"; +// public static final String EVT_LOCATION_SELECT = "location_select"; +// public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH"; +// public static final String EVT_ENTER_AGENT = "enter_agent"; +// public static final String EVT_QUALIFICATION_VERIFY_SUCCESS = "qualification_verify_success"; +// public static final String EVT_QUALIFICATION_VERIFY_FAIL = "qualification_verify_fail"; +// public static final String EVT_NAMING_VERIFY_SUCCESS = "naming_verify_success"; +// public static final String EVT_NAMING_VERIFY_FAIL = "naming_verify_fail"; +// public static final String EVT_ANNUAL_RENEW = "annual_renew"; +// public static final String EVT_VERIFY_EXPIRED = "verify_expired"; +// public static final String MEDIA_IMAGE = "image"; +// public static final String MEDIA_VOICE = "voice"; +// public static final String MEDIA_VIDEO = "video"; +// public static final String MEDIA_THUMB = "thumb"; +// public static final String MEDIA_FILE = "file"; +// public static final String FILE_JPG = "jpeg"; +// public static final String FILE_MP3 = "mp3"; +// public static final String FILE_AMR = "amr"; +// public static final String FILE_MP4 = "mp4"; public static final String MENU_BUTTON_CLICK = "click"; public static final String MENU_BUTTON_VIEW = "view"; - public static final String MENU_SCANCODE_PUSH = "scancode_push"; - public static final String MENU_SCANCODE_WAITMSG = "scancode_waitmsg"; - public static final String MENU_PIC_SYSPHOTO = "pic_sysphoto"; - public static final String MENU_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; - public static final String MENU_PIC_WEIXIN = "pic_weixin"; - public static final String MENU_LOCATION_SELECT = "location_select"; - public static final String MENU_MEDIA_ID = "media_id"; - public static final String MENU_VIEW_LIMITED = "view_limited"; - public static final String QR_CODE_LIMIT_SCENE = "QR_LIMIT_SCENE"; - public static final String QR_CODE_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE"; - public static final String OAUTH2_SCOPE_BASE = "snsapi_base"; - public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; - public static final String LANG_CHINA = "zh_CN"; - public static final String LANG_CHINA_TAIWAN = "zh_TW"; - public static final String LANG_ENGLISH = "en"; - public static final String MATERIAL_NEWS = "news"; - public static final String MATERIAL_VOICE = "voice"; - public static final String MATERIAL_IMAGE = "image"; - public static final String MATERIAL_VIDEO = "video"; - public static final String SEND_ALL_NEWS = "mpnews"; - public static final String SEND_ALL_TEXT = "text"; - public static final String SEND_ALL_VOICE = "voice"; - public static final String SEND_ALL_IMAGE = "image"; - public static final String SEND_ALL_VIDEO = "mpvideo"; - public static final String URL_GET_ACCESSTOEKN = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; - public static final String URL_GET_WX_SERVICE_IP = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=ACCESS_TOKEN"; - public static final String URL_CREATE_MENU = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN"; - public static final String URL_CREATE_MENU_CONDITIONAL = "https://api.weixin.qq.com/cgi-bin/menu/addconditional?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_MENU = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_MENU_CONDITIONAL = "https://api.weixin.qq.com/cgi-bin/menu/delconditional?access_token=ACCESS_TOKEN"; - public static final String URL_GET_MENU = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN"; - public static final String URL_GET_CURRENT_MENU_INFO = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token=ACCESS_TOKEN"; - public static final String URL_TRYMATCH_MENU = "https://api.weixin.qq.com/cgi-bin/menu/trymatch?access_token=ACCESS_TOKEN"; - public static final String URL_UPLOAD_TEMP_MEDIA = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; - public static final String URL_DOWNLOAD_TEMP_MEDIA = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID"; - public static final String URL_UPLOAD_MATERIAL_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN"; - public static final String URL_BATCHGET_MATERIAL_MEDIA_LIST = "https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN"; - public static final String URL_DOWNLOAD_MATERIAL_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_MATERIAL_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN"; - public static final String URL_GET_MATERIAL_COUNT = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN"; - public static final String URL_ADD_NEWS_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN"; - public static final String URL_IMAGE_DOMAIN_CHANGE = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN"; - public static final String URL_UPDATE_NEWS_MEDIA = "https://api.weixin.qq.com/cgi-bin/material/update_news?access_token=ACCESS_TOKEN"; - public static final String URL_CREATE_USER_TAG = "https://api.weixin.qq.com/cgi-bin/tags/create?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_USER_TAG = "https://api.weixin.qq.com/cgi-bin/tags/delete?access_token=ACCESS_TOKEN"; - public static final String URL_QUERY_ALL_USER_TAG = "https://api.weixin.qq.com/cgi-bin/tags/get?access_token=ACCESS_TOKEN"; - public static final String URL_QUERY_ALL_USER_UNDER_TAG = "https://api.weixin.qq.com/cgi-bin/user/tag/get?access_token=ACCESS_TOKEN"; - public static final String URL_UPDATE_USER_TAG_NAME = "https://api.weixin.qq.com/cgi-bin/tags/update?access_token=ACCESS_TOKEN"; - public static final String URL_BATCH_MOVING_USER_TAG = "https://api.weixin.qq.com/cgi-bin/tags/members/batchtagging?access_token=ACCESS_TOKEN"; - public static final String URL_BATCH_UN_TAG_USER_TAG = "https://api.weixin.qq.com/cgi-bin/tags/members/batchuntagging?access_token=ACCESS_TOKEN"; - public static final String URL_UPDATE_USER_REMARK = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=ACCESS_TOKEN"; - public static final String URL_GET_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; - public static final String URL_BATCH_GET_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=ACCESS_TOKEN"; - public static final String URL_BATCH_GET_USER_OPENID = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID"; - public static final String URL_OAUTH2_GET_CODE = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect"; - public static final String URL_OAUTH2_GET_ACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; - public static final String URL_OAUTH2_GET_REFRESH_ACCESSTOKEN = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN"; - public static final String URL_OAUTH2_GET_USER_INFO = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN"; - public static final String URL_OAUTH2_CHECK_ACCESSTOKEN = "https://api.weixin.qq.com/sns/auth?access_token=ACCESS_TOKEN&openid=OPENID"; - public static final String URL_BATCH_ADD_USER_TO_BLACK_LISE = "https://api.weixin.qq.com/cgi-bin/tags/members/batchblacklist?access_token=ACCESS_TOKEN"; - public static final String URL_BATCH_REMOVE_USER_FROM_BLACK_LISE = "https://api.weixin.qq.com/cgi-bin/tags/members/batchunblacklist?access_token=ACCESS_TOKEN"; - public static final String URL_BATCH_GET_USERS_FROM_BLACK_LISE = "https://api.weixin.qq.com/cgi-bin/tags/members/getblacklist?access_token=ACCESS_TOKEN"; - public static final String URL_GET_QR_CODE = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN"; - public static final String URL_DOWNLOAD_QR_CODE = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET"; - public static final String URL_LONGURL_TO_SHORTURL = "https://api.weixin.qq.com/cgi-bin/shorturl?access_token=ACCESS_TOKEN"; - public static final String URL_GET_JS_API_TICKET = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi"; - public static final String URL_TAG_SEND_ALL = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN"; - public static final String URL_OPENID_SEND_ALL = "https://api.weixin.qq.com/cgi-bin/message/mass/send?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_SEND_ALL = "https://api.weixin.qq.com/cgi-bin/message/mass/delete?access_token=ACCESS_TOKEN"; - public static final String URL_PREVIEW_SEND_ALL = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN"; - public static final String URL_GET_STATUS_SEND_ALL = "https://api.weixin.qq.com/cgi-bin/message/mass/get?access_token=ACCESS_TOKEN"; - public static final String URL_PAY_UNIFIEORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder"; - public static final String URL_TEMPLATE_SET_INDUSTRY = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=ACCESS_TOKEN"; - public static final String URL_TEMPLATE_GET_INDUSTRY = "https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=ACCESS_TOKEN"; - public static final String URL_TEMPLATE_GET_ID = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=ACCESS_TOKEN"; - public static final String URL_TEMPLATE_GET_LIST = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=ACCESS_TOKEN"; - public static final String URL_TEMPLATE_DELETE = "https://api.weixin.qq.com/cgi-bin/template/del_private_template?access_token=ACCESS_TOKEN"; - public static final String URL_TEMPLATE_SEND = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN"; - public static final String URL_ADD_KF_ACCOUNT = "https://api.weixin.qq.com/customservice/kfaccount/add?access_token=ACCESS_TOKEN"; - public static final String URL_UPDATE_KF_ACCOUNT = "https://api.weixin.qq.com/customservice/kfaccount/update?access_token=ACCESS_TOKEN"; - public static final String URL_DELETE_KF_ACCOUNT = "https://api.weixin.qq.com/customservice/kfaccount/del?access_token=ACCESS_TOKEN"; - public static final String URL_UPDATE_KF_HEAD_IMAGE = "http://api.weixin.qq.com/customservice/kfaccount/uploadheadimg?access_token=ACCESS_TOKEN&kf_account=KFACCOUNT"; - public static final String URL_GET_ALL_KF_ACCOUNT = "https://api.weixin.qq.com/cgi-bin/customservice/getkflist?access_token=ACCESS_TOKEN"; - public static final String URL_KF_SEND_MESSAGE_TO_USER = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN"; - public static final String URL_KF_SEND_TYPING_TO_USER = "https://api.weixin.qq.com/cgi-bin/message/custom/typing?access_token=ACCESS_TOKEN"; +// public static final String MENU_SCANCODE_PUSH = "scancode_push"; +// public static final String MENU_SCANCODE_WAITMSG = "scancode_waitmsg"; +// public static final String MENU_PIC_SYSPHOTO = "pic_sysphoto"; +// public static final String MENU_PIC_PHOTO_OR_ALBUM = "pic_photo_or_album"; +// public static final String MENU_PIC_WEIXIN = "pic_weixin"; +// public static final String MENU_LOCATION_SELECT = "location_select"; +// public static final String MENU_MEDIA_ID = "media_id"; +// public static final String MENU_VIEW_LIMITED = "view_limited"; +// public static final String QR_CODE_LIMIT_SCENE = "QR_LIMIT_SCENE"; +// public static final String QR_CODE_LIMIT_STR_SCENE = "QR_LIMIT_STR_SCENE"; +// public static final String OAUTH2_SCOPE_BASE = "snsapi_base"; +// public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; +// public static final String LANG_CHINA = "zh_CN"; +// public static final String LANG_CHINA_TAIWAN = "zh_TW"; +// public static final String LANG_ENGLISH = "en"; +// public static final String MATERIAL_NEWS = "news"; +// public static final String MATERIAL_VOICE = "voice"; +// public static final String MATERIAL_IMAGE = "image"; +// public static final String MATERIAL_VIDEO = "video"; +// public static final String SEND_ALL_NEWS = "mpnews"; +// public static final String SEND_ALL_TEXT = "text"; +// public static final String SEND_ALL_VOICE = "voice"; +// public static final String SEND_ALL_IMAGE = "image"; +// public static final String SEND_ALL_VIDEO = "mpvideo"; } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/XMLParse.java b/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/XMLParse.java index bf91bab..cd485f6 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/XMLParse.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/menu/bean/XMLParse.java @@ -1,6 +1,5 @@ package com.ynxbd.wx.wxfactory.menu.bean; -import com.qq.weixin.mp.aes.AesException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -11,7 +10,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import java.io.StringReader; public class XMLParse { - public static Object[] extract(String xmltext) throws Exception { + public Object[] extract(String xmltext) throws Exception { Object[] result = new Object[3]; try { @@ -44,7 +43,7 @@ public class XMLParse { } } - public static String generate(String encrypt, String signature, String timestamp, String nonce) { + public String generate(String encrypt, String signature, String timestamp, String nonce) { String format = "\n\n\n%3$s\n\n"; return String.format(format, encrypt, signature, timestamp, nonce); } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/message/MdClient.java b/src/main/java/com/ynxbd/wx/wxfactory/message/MdClient.java index 930ae90..443e20c 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/message/MdClient.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/message/MdClient.java @@ -11,6 +11,9 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +/** + * 就医助手 + */ @Slf4j @NoArgsConstructor public class MdClient { diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/OrderMIEnum.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/OrderMIEnum.java similarity index 96% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/OrderMIEnum.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/OrderMIEnum.java index a6a8c7a..1fca948 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/OrderMIEnum.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/OrderMIEnum.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean; +package com.ynxbd.wx.wxfactory.payment; import lombok.ToString; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/payment/WXPayUtility.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/WXPayUtility.java new file mode 100644 index 0000000..0bb47fd --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/WXPayUtility.java @@ -0,0 +1,912 @@ +package com.ynxbd.wx.wxfactory.payment; + +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSyntaxException; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.List; +import java.util.Map.Entry; + +import okhttp3.Headers; +import okhttp3.Response; +import okio.BufferedSource; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.time.DateTimeException; +import java.time.Duration; +import java.time.Instant; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.security.MessageDigest; +import java.io.InputStream; + +import org.bouncycastle.crypto.digests.SM3Digest; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.Security; + +// 微信支付官方工具类 + +public class WXPayUtility { + + private static final Gson gson = new GsonBuilder() + .disableHtmlEscaping() + .addSerializationExclusionStrategy(new ExclusionStrategy() { + @Override + public boolean shouldSkipField(FieldAttributes fieldAttributes) { + final Expose expose = fieldAttributes.getAnnotation(Expose.class); + return expose != null && !expose.serialize(); + } + + @Override + public boolean shouldSkipClass(Class aClass) { + return false; + } + }) + .addDeserializationExclusionStrategy(new ExclusionStrategy() { + @Override + public boolean shouldSkipField(FieldAttributes fieldAttributes) { + final Expose expose = fieldAttributes.getAnnotation(Expose.class); + return expose != null && !expose.deserialize(); + } + + @Override + public boolean shouldSkipClass(Class aClass) { + return false; + } + }) + .create(); + private static final char[] SYMBOLS = + "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray(); + private static final SecureRandom random = new SecureRandom(); + + /** + * 将 Object 转换为 JSON 字符串 + */ + public static String toJson(Object object) { + return gson.toJson(object); + } + + /** + * 将 JSON 字符串解析为特定类型的实例 + */ + public static T fromJson(String json, Class classOfT) throws JsonSyntaxException { + return gson.fromJson(json, classOfT); + } + + /** + * 从公私钥文件路径中读取文件内容 + * + * @param keyPath 文件路径 + * @return 文件内容 + */ + private static String readKeyStringFromPath(String keyPath) { + try { + return new String(Files.readAllBytes(Paths.get(keyPath)), StandardCharsets.UTF_8); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * 读取 PKCS#8 格式的私钥字符串并加载为私钥对象 + * + * @param keyString 私钥文件内容,以 -----BEGIN PRIVATE KEY----- 开头 + * @return PrivateKey 对象 + */ + public static PrivateKey loadPrivateKeyFromString(String keyString) { + try { + keyString = keyString.replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA").generatePrivate( + new PKCS8EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从 PKCS#8 格式的私钥文件中加载私钥 + * + * @param keyPath 私钥文件路径 + * @return PrivateKey 对象 + */ + public static PrivateKey loadPrivateKeyFromPath(String keyPath) { + return loadPrivateKeyFromString(readKeyStringFromPath(keyPath)); + } + + /** + * 读取 PKCS#8 格式的公钥字符串并加载为公钥对象 + * + * @param keyString 公钥文件内容,以 -----BEGIN PUBLIC KEY----- 开头 + * @return PublicKey 对象 + */ + public static PublicKey loadPublicKeyFromString(String keyString) { + try { + keyString = keyString.replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replaceAll("\\s+", ""); + return KeyFactory.getInstance("RSA").generatePublic( + new X509EncodedKeySpec(Base64.getDecoder().decode(keyString))); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(e); + } catch (InvalidKeySpecException e) { + throw new IllegalArgumentException(e); + } + } + + /** + * 从 PKCS#8 格式的公钥文件中加载公钥 + * + * @param keyPath 公钥文件路径 + * @return PublicKey 对象 + */ + public static PublicKey loadPublicKeyFromPath(String keyPath) { + return loadPublicKeyFromString(readKeyStringFromPath(keyPath)); + } + + /** + * 创建指定长度的随机字符串,字符集为[0-9a-zA-Z],可用于安全相关用途 + */ + public static String createNonce(int length) { + char[] buf = new char[length]; + for (int i = 0; i < length; ++i) { + buf[i] = SYMBOLS[random.nextInt(SYMBOLS.length)]; + } + return new String(buf); + } + + /** + * 使用公钥按照 RSA_PKCS1_OAEP_PADDING 算法进行加密 + * + * @param publicKey 加密用公钥对象 + * @param plaintext 待加密明文 + * @return 加密后密文 + */ + public static String encrypt(PublicKey publicKey, String plaintext) { + final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; + + try { + Cipher cipher = Cipher.getInstance(transformation); + cipher.init(Cipher.ENCRYPT_MODE, publicKey); + return Base64.getEncoder().encodeToString(cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8))); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new IllegalArgumentException("The current Java environment does not support " + transformation, e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("RSA encryption using an illegal publicKey", e); + } catch (BadPaddingException | IllegalBlockSizeException e) { + throw new IllegalArgumentException("Plaintext is too long", e); + } + } + + /** + * 使用私钥按照 RSA_PKCS1_OAEP_PADDING 算法进行解密 + * + * @param privateKey 解密用私钥对象 + * @param ciphertext 待解密密文(Base64编码的字符串) + * @return 解密后明文 + */ + public static String rsaOaepDecrypt(PrivateKey privateKey, String ciphertext) { + final String transformation = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding"; + + try { + Cipher cipher = Cipher.getInstance(transformation); + cipher.init(Cipher.DECRYPT_MODE, privateKey); + byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(ciphertext)); + return new String(decryptedBytes, StandardCharsets.UTF_8); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new IllegalArgumentException("The current Java environment does not support " + transformation, e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("RSA decryption using an illegal privateKey", e); + } catch (BadPaddingException | IllegalBlockSizeException e) { + throw new IllegalArgumentException("Ciphertext decryption failed", e); + } + } + + public static String aesAeadDecrypt(byte[] key, byte[] associatedData, byte[] nonce, + byte[] ciphertext) { + final String transformation = "AES/GCM/NoPadding"; + final String algorithm = "AES"; + final int tagLengthBit = 128; + + try { + Cipher cipher = Cipher.getInstance(transformation); + cipher.init( + Cipher.DECRYPT_MODE, + new SecretKeySpec(key, algorithm), + new GCMParameterSpec(tagLengthBit, nonce)); + if (associatedData != null) { + cipher.updateAAD(associatedData); + } + return new String(cipher.doFinal(ciphertext), StandardCharsets.UTF_8); + } catch (InvalidKeyException + | InvalidAlgorithmParameterException + | BadPaddingException + | IllegalBlockSizeException + | NoSuchAlgorithmException + | NoSuchPaddingException e) { + throw new IllegalArgumentException(String.format("AesAeadDecrypt with %s Failed", + transformation), e); + } + } + + /** + * 使用私钥按照指定算法进行签名 + * + * @param message 待签名串 + * @param algorithm 签名算法,如 SHA256withRSA + * @param privateKey 签名用私钥对象 + * @return 签名结果 + */ + public static String sign(String message, String algorithm, PrivateKey privateKey) { + byte[] sign; + try { + Signature signature = Signature.getInstance(algorithm); + signature.initSign(privateKey); + signature.update(message.getBytes(StandardCharsets.UTF_8)); + sign = signature.sign(); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("The current Java environment does not support " + algorithm, e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException(algorithm + " signature uses an illegal privateKey.", e); + } catch (SignatureException e) { + throw new RuntimeException("An error occurred during the sign process.", e); + } + return Base64.getEncoder().encodeToString(sign); + } + + /** + * 使用公钥按照特定算法验证签名 + * + * @param message 待签名串 + * @param signature 待验证的签名内容 + * @param algorithm 签名算法,如:SHA256withRSA + * @param publicKey 验签用公钥对象 + * @return 签名验证是否通过 + */ + public static boolean verify(String message, String signature, String algorithm, + PublicKey publicKey) { + try { + Signature sign = Signature.getInstance(algorithm); + sign.initVerify(publicKey); + sign.update(message.getBytes(StandardCharsets.UTF_8)); + return sign.verify(Base64.getDecoder().decode(signature)); + } catch (SignatureException e) { + return false; + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("verify uses an illegal publickey.", e); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("The current Java environment does not support" + algorithm, e); + } + } + + /** + * 根据微信支付APIv3请求签名规则构造 Authorization 签名 + * + * @param mchid 商户号 + * @param certificateSerialNo 商户API证书序列号 + * @param privateKey 商户API证书私钥 + * @param method 请求接口的HTTP方法,请使用全大写表述,如 GET、POST、PUT、DELETE + * @param uri 请求接口的URL + * @param body 请求接口的Body + * @return 构造好的微信支付APIv3 Authorization 头 + */ + public static String buildAuthorization(String mchid, String certificateSerialNo, + PrivateKey privateKey, + String method, String uri, String body) { + String nonce = createNonce(32); + long timestamp = Instant.now().getEpochSecond(); + + String message = String.format("%s\n%s\n%d\n%s\n%s\n", method, uri, timestamp, nonce, + body == null ? "" : body); + + String signature = sign(message, "SHA256withRSA", privateKey); + + return String.format( + "WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\"," + + "timestamp=\"%d\",serial_no=\"%s\"", + mchid, nonce, signature, timestamp, certificateSerialNo); + } + + /** + * 计算输入流的哈希值 + * + * @param inputStream 输入流 + * @param algorithm 哈希算法名称,如 "SHA-256", "SHA-1" + * @return 哈希值的十六进制字符串 + */ + private static String calculateHash(InputStream inputStream, String algorithm) { + try { + MessageDigest digest = MessageDigest.getInstance(algorithm); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + digest.update(buffer, 0, bytesRead); + } + byte[] hashBytes = digest.digest(); + StringBuilder hexString = new StringBuilder(); + for (byte b : hashBytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException(algorithm + " algorithm not available", e); + } catch (IOException e) { + throw new RuntimeException("Error reading from input stream", e); + } + } + + /** + * 计算输入流的 SHA256 哈希值 + * + * @param inputStream 输入流 + * @return SHA256 哈希值的十六进制字符串 + */ + public static String sha256(InputStream inputStream) { + return calculateHash(inputStream, "SHA-256"); + } + + /** + * 计算输入流的 SHA1 哈希值 + * + * @param inputStream 输入流 + * @return SHA1 哈希值的十六进制字符串 + */ + public static String sha1(InputStream inputStream) { + return calculateHash(inputStream, "SHA-1"); + } + + /** + * 计算输入流的 SM3 哈希值 + * + * @param inputStream 输入流 + * @return SM3 哈希值的十六进制字符串 + */ + public static String sm3(InputStream inputStream) { + // 确保Bouncy Castle Provider已注册 + if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { + Security.addProvider(new BouncyCastleProvider()); + } + + try { + SM3Digest digest = new SM3Digest(); + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + digest.update(buffer, 0, bytesRead); + } + byte[] hashBytes = new byte[digest.getDigestSize()]; + digest.doFinal(hashBytes, 0); + + StringBuilder hexString = new StringBuilder(); + for (byte b : hashBytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } catch (IOException e) { + throw new RuntimeException("Error reading from input stream", e); + } + } + + /** + * 对参数进行 URL 编码 + * + * @param content 参数内容 + * @return 编码后的内容 + */ + public static String urlEncode(String content) { + try { + return URLEncoder.encode(content, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + /** + * 对参数Map进行 URL 编码,生成 QueryString + * + * @param params Query参数Map + * @return QueryString + */ + public static String urlEncode(Map params) { + if (params == null || params.isEmpty()) { + return ""; + } + + StringBuilder result = new StringBuilder(); + for (Entry entry : params.entrySet()) { + if (entry.getValue() == null) { + continue; + } + + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof List) { + List list = (List) entry.getValue(); + for (Object temp : list) { + appendParam(result, key, temp); + } + } else { + appendParam(result, key, value); + } + } + return result.toString(); + } + + /** + * 将键值对 放入返回结果 + * + * @param result 返回的query string + * @param key 属性 + * @param value 属性值 + */ + private static void appendParam(StringBuilder result, String key, Object value) { + if (result.length() > 0) { + result.append("&"); + } + + String valueString; + // 如果是基本类型、字符串或枚举,直接转换;如果是对象,序列化为JSON + if (value instanceof String || value instanceof Number || + value instanceof Boolean || value instanceof Enum) { + valueString = value.toString(); + } else { + valueString = toJson(value); + } + + result.append(key) + .append("=") + .append(urlEncode(valueString)); + } + + /** + * 从应答中提取 Body + * + * @param response HTTP 请求应答对象 + * @return 应答中的Body内容,Body为空时返回空字符串 + */ + public static String extractBody(Response response) { + if (response.body() == null) { + return ""; + } + + try { + BufferedSource source = response.body().source(); + return source.readUtf8(); + } catch (IOException e) { + throw new RuntimeException(String.format("An error occurred during reading response body. " + + "Status: %d", response.code()), e); + } + } + + /** + * 根据微信支付APIv3应答验签规则对应答签名进行验证,验证不通过时抛出异常 + * + * @param wechatpayPublicKeyId 微信支付公钥ID + * @param wechatpayPublicKey 微信支付公钥对象 + * @param headers 微信支付应答 Header 列表 + * @param body 微信支付应答 Body + */ + public static void validateResponse(String wechatpayPublicKeyId, PublicKey wechatpayPublicKey, + Headers headers, + String body) { + String timestamp = headers.get("Wechatpay-Timestamp"); + String requestId = headers.get("Request-ID"); + try { + Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp)); + // 拒绝过期请求 + if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) { + throw new IllegalArgumentException( + String.format("Validate response failed, timestamp[%s] is expired, request-id[%s]", + timestamp, requestId)); + } + } catch (DateTimeException | NumberFormatException e) { + throw new IllegalArgumentException( + String.format("Validate response failed, timestamp[%s] is invalid, request-id[%s]", + timestamp, requestId)); + } + String serialNumber = headers.get("Wechatpay-Serial"); + if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) { + throw new IllegalArgumentException( + String.format("Validate response failed, Invalid Wechatpay-Serial, Local: %s, Remote: " + + "%s", wechatpayPublicKeyId, serialNumber)); + } + + String signature = headers.get("Wechatpay-Signature"); + String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"), + body == null ? "" : body); + + boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey); + if (!success) { + throw new IllegalArgumentException( + String.format("Validate response failed,the WechatPay signature is incorrect.%n" + + "Request-ID[%s]\tresponseHeader[%s]\tresponseBody[%.1024s]", + headers.get("Request-ID"), headers, body)); + } + } + + /** + * 根据微信支付APIv3通知验签规则对通知签名进行验证,验证不通过时抛出异常 + * + * @param wechatpayPublicKeyId 微信支付公钥ID + * @param wechatpayPublicKey 微信支付公钥对象 + * @param headers 微信支付通知 Header 列表 + * @param body 微信支付通知 Body + */ + public static void validateNotification(String wechatpayPublicKeyId, + PublicKey wechatpayPublicKey, Headers headers, + String body) { + String timestamp = headers.get("Wechatpay-Timestamp"); + try { + Instant responseTime = Instant.ofEpochSecond(Long.parseLong(timestamp)); + // 拒绝过期请求 + if (Duration.between(responseTime, Instant.now()).abs().toMinutes() >= 5) { + throw new IllegalArgumentException( + String.format("Validate notification failed, timestamp[%s] is expired", timestamp)); + } + } catch (DateTimeException | NumberFormatException e) { + throw new IllegalArgumentException( + String.format("Validate notification failed, timestamp[%s] is invalid", timestamp)); + } + String serialNumber = headers.get("Wechatpay-Serial"); + if (!Objects.equals(serialNumber, wechatpayPublicKeyId)) { + throw new IllegalArgumentException( + String.format("Validate notification failed, Invalid Wechatpay-Serial, Local: %s, " + + "Remote: %s", + wechatpayPublicKeyId, + serialNumber)); + } + + String signature = headers.get("Wechatpay-Signature"); + String message = String.format("%s\n%s\n%s\n", timestamp, headers.get("Wechatpay-Nonce"), + body == null ? "" : body); + + boolean success = verify(message, signature, "SHA256withRSA", wechatpayPublicKey); + if (!success) { + throw new IllegalArgumentException( + String.format("Validate notification failed, WechatPay signature is incorrect.\n" + + "responseHeader[%s]\tresponseBody[%.1024s]", + headers, body)); + } + } + + /** + * 对微信支付通知进行签名验证、解析,同时将业务数据解密。验签名失败、解析失败、解密失败时抛出异常 + * + * @param apiv3Key 商户的 APIv3 Key + * @param wechatpayPublicKeyId 微信支付公钥ID + * @param wechatpayPublicKey 微信支付公钥对象 + * @param headers 微信支付请求 Header 列表 + * @param body 微信支付请求 Body + * @return 解析后的通知内容,解密后的业务数据可以使用 Notification.getPlaintext() 访问 + */ + public static Notification parseNotification(String apiv3Key, String wechatpayPublicKeyId, + PublicKey wechatpayPublicKey, Headers headers, + String body) { + validateNotification(wechatpayPublicKeyId, wechatpayPublicKey, headers, body); + Notification notification = gson.fromJson(body, Notification.class); + notification.decrypt(apiv3Key); + return notification; + } + + /** + * 微信支付API错误异常,发送HTTP请求成功,但返回状态码不是 2XX 时抛出本异常 + */ + public static class ApiException extends RuntimeException { + private static final long serialVersionUID = 2261086748874802175L; + + private final int statusCode; + private final String body; + private final Headers headers; + private final String errorCode; + private final String errorMessage; + + public ApiException(int statusCode, String body, Headers headers) { + super(String.format("微信支付API访问失败,StatusCode: [%s], Body: [%s], Headers: [%s]", statusCode, + body, headers)); + this.statusCode = statusCode; + this.body = body; + this.headers = headers; + + if (body != null && !body.isEmpty()) { + JsonElement code; + JsonElement message; + + try { + JsonObject jsonObject = gson.fromJson(body, JsonObject.class); + code = jsonObject.get("code"); + message = jsonObject.get("message"); + } catch (JsonSyntaxException ignored) { + code = null; + message = null; + } + this.errorCode = code == null ? null : code.getAsString(); + this.errorMessage = message == null ? null : message.getAsString(); + } else { + this.errorCode = null; + this.errorMessage = null; + } + } + + /** + * 获取 HTTP 应答状态码 + */ + public int getStatusCode() { + return statusCode; + } + + /** + * 获取 HTTP 应答包体内容 + */ + public String getBody() { + return body; + } + + /** + * 获取 HTTP 应答 Header + */ + public Headers getHeaders() { + return headers; + } + + /** + * 获取 错误码 (错误应答中的 code 字段) + */ + public String getErrorCode() { + return errorCode; + } + + /** + * 获取 错误消息 (错误应答中的 message 字段) + */ + public String getErrorMessage() { + return errorMessage; + } + } + + public static class Notification { + @SerializedName("id") + private String id; + @SerializedName("create_time") + private String createTime; + @SerializedName("event_type") + private String eventType; + @SerializedName("resource_type") + private String resourceType; + @SerializedName("summary") + private String summary; + @SerializedName("resource") + private Resource resource; + private String plaintext; + + public String getId() { + return id; + } + + public String getCreateTime() { + return createTime; + } + + public String getEventType() { + return eventType; + } + + public String getResourceType() { + return resourceType; + } + + public String getSummary() { + return summary; + } + + public Resource getResource() { + return resource; + } + + /** + * 获取解密后的业务数据(JSON字符串,需要自行解析) + */ + public String getPlaintext() { + return plaintext; + } + + private void validate() { + if (resource == null) { + throw new IllegalArgumentException("Missing required field `resource` in notification"); + } + resource.validate(); + } + + /** + * 使用 APIv3Key 对通知中的业务数据解密,解密结果可以通过 getPlainText 访问。 + * 外部拿到的 Notification 一定是解密过的,因此本方法没有设置为 public + * + * @param apiv3Key 商户APIv3 Key + */ + private void decrypt(String apiv3Key) { + validate(); + + plaintext = aesAeadDecrypt( + apiv3Key.getBytes(StandardCharsets.UTF_8), + resource.associatedData.getBytes(StandardCharsets.UTF_8), + resource.nonce.getBytes(StandardCharsets.UTF_8), + Base64.getDecoder().decode(resource.ciphertext) + ); + } + + public static class Resource { + @SerializedName("algorithm") + private String algorithm; + + @SerializedName("ciphertext") + private String ciphertext; + + @SerializedName("associated_data") + private String associatedData; + + @SerializedName("nonce") + private String nonce; + + @SerializedName("original_type") + private String originalType; + + public String getAlgorithm() { + return algorithm; + } + + public String getCiphertext() { + return ciphertext; + } + + public String getAssociatedData() { + return associatedData; + } + + public String getNonce() { + return nonce; + } + + public String getOriginalType() { + return originalType; + } + + private void validate() { + if (algorithm == null || algorithm.isEmpty()) { + throw new IllegalArgumentException("Missing required field `algorithm` in Notification" + + ".Resource"); + } + if (!Objects.equals(algorithm, "AEAD_AES_256_GCM")) { + throw new IllegalArgumentException(String.format("Unsupported `algorithm`[%s] in " + + "Notification.Resource", algorithm)); + } + + if (ciphertext == null || ciphertext.isEmpty()) { + throw new IllegalArgumentException("Missing required field `ciphertext` in Notification" + + ".Resource"); + } + + if (associatedData == null || associatedData.isEmpty()) { + throw new IllegalArgumentException("Missing required field `associatedData` in " + + "Notification.Resource"); + } + + if (nonce == null || nonce.isEmpty()) { + throw new IllegalArgumentException("Missing required field `nonce` in Notification" + + ".Resource"); + } + + if (originalType == null || originalType.isEmpty()) { + throw new IllegalArgumentException("Missing required field `originalType` in " + + "Notification.Resource"); + } + } + } + } + + /** + * 根据文件名获取对应的Content-Type + * + * @param fileName 文件名 + * @return Content-Type字符串 + */ + public static String getContentTypeByFileName(String fileName) { + if (fileName == null || fileName.isEmpty()) { + return "application/octet-stream"; + } + + // 获取文件扩展名 + String extension = ""; + int lastDotIndex = fileName.lastIndexOf('.'); + if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) { + extension = fileName.substring(lastDotIndex + 1).toLowerCase(); + } + + // 常见文件类型映射 + Map contentTypeMap = new HashMap<>(); + // 图片类型 + contentTypeMap.put("png", "image/png"); + contentTypeMap.put("jpg", "image/jpeg"); + contentTypeMap.put("jpeg", "image/jpeg"); + contentTypeMap.put("gif", "image/gif"); + contentTypeMap.put("bmp", "image/bmp"); + contentTypeMap.put("webp", "image/webp"); + contentTypeMap.put("svg", "image/svg+xml"); + contentTypeMap.put("ico", "image/x-icon"); + + // 文档类型 + contentTypeMap.put("pdf", "application/pdf"); + contentTypeMap.put("doc", "application/msword"); + contentTypeMap.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + contentTypeMap.put("xls", "application/vnd.ms-excel"); + contentTypeMap.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + contentTypeMap.put("ppt", "application/vnd.ms-powerpoint"); + contentTypeMap.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); + + // 文本类型 + contentTypeMap.put("txt", "text/plain"); + contentTypeMap.put("html", "text/html"); + contentTypeMap.put("css", "text/css"); + contentTypeMap.put("js", "application/javascript"); + contentTypeMap.put("json", "application/json"); + contentTypeMap.put("xml", "application/xml"); + contentTypeMap.put("csv", "text/csv"); + + // 音视频类型 + contentTypeMap.put("mp3", "audio/mpeg"); + contentTypeMap.put("wav", "audio/wav"); + contentTypeMap.put("mp4", "video/mp4"); + contentTypeMap.put("avi", "video/x-msvideo"); + contentTypeMap.put("mov", "video/quicktime"); + + // 压缩文件类型 + contentTypeMap.put("zip", "application/zip"); + contentTypeMap.put("rar", "application/x-rar-compressed"); + contentTypeMap.put("7z", "application/x-7z-compressed"); + + + return contentTypeMap.getOrDefault(extension, "application/octet-stream"); + } +} \ No newline at end of file diff --git a/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/Client.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/Client.java index 5e717ea..25fb1ac 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/Client.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/Client.java @@ -1,188 +1,239 @@ -//package com.ynxbd.wx.wxfactory.payment.jsapi; -// -//import com.ynxbd.common.helper.common.ErrorHelper; -//import com.ynxbd.common.helper.common.JsonHelper; -//import com.ynxbd.common.result.JsonResult; -//import com.ynxbd.wx.wxfactory.bean.MedicalPayOrder; -//import com.ynxbd.wx.wxfactory.utils.WxRequestHelper; -//import lombok.extern.slf4j.Slf4j; -// -//import java.math.BigDecimal; -//import java.util.HashMap; -//import java.util.Map; -// -//@Slf4j -//public class Client { -// -// /** -// * 微信JSAPI下单 -// * -// * @param appId 应用ID -// * @param mchId 直连商户号 -// * @param description 商品描述 -// * @param out_trade_no 商户订单号 -// * @param time_expire 交易结束时间(yyyy-MM-DDTHH:mm:ss+TIMEZONE 示例值:2018-06-08T10:34:56+08:00) -// * @param notify_url 通知地址 -// * @param totalFee 订单金额(元) -// * @param openid openid -// * @param attach 附加数据 -// */ -// public MedicalPayOrder createOrder(String appId, String mchId, String description, String out_trade_no, -// String time_expire, String attach, String notify_url, BigDecimal totalFee, -// String openid) { -// +package com.ynxbd.wx.wxfactory.payment.jsapi; + +import com.google.gson.annotations.SerializedName; +import com.ynxbd.wx.wxfactory.payment.WXPayUtility; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.util.ArrayList; +import java.util.List; + +/** + * JSAPI下单 + */ + + +@Slf4j +public class Client { + private static String HOST = "https://api.mch.weixin.qq.com"; + private static String METHOD = "POST"; + private static String PATH = "/v3/pay/transactions/jsapi"; + + +// JsapiPrepay client = new JsapiPrepay( +// "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756 +// "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053 +// "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径 +// "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816 +// "/path/to/wxp_pub.pem" // 微信支付公钥文件路径,本地文件路径 +// ); + +// public DirectAPIv3JsapiPrepayResponse jsapiPrepay(String appId, +// String mchId, +// String certificateSerialNo, +// PrivateKey privateKey, +// String wechatPayPublicKeyId, +// PublicKey wechatPayPublicKey) { +// DirectAPIv3JsapiPrepayRequest request = new DirectAPIv3JsapiPrepayRequest(); +// request.appid = appId; +// request.mchid = mchId; +// request.description = "Image形象店-深圳腾大-QQ公仔"; +// request.outTradeNo = "1217752501201407033233368018"; +// request.timeExpire = "2018-06-08T10:34:56+08:00"; +// request.attach = "自定义数据说明"; +// request.notifyUrl = " https://www.weixin.qq.com/wxpay/pay.php"; +// request.goodsTag = "WXG"; +// request.supportFapiao = false; +// request.amount = new CommonAmountInfo(); +// request.amount.total = 100L; +// request.amount.currency = "CNY"; +// request.payer = new JsapiReqPayerInfo(); +// request.payer.openid = "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"; +// request.detail = new CouponInfo(); +// request.detail.costPrice = 608800L; +// request.detail.invoiceId = "微信123"; +// request.detail.goodsDetail = new ArrayList<>(); +// { +// GoodsDetail goodsDetailItem = new Client.GoodsDetail(); +// goodsDetailItem.merchantGoodsId = "1246464644"; +// goodsDetailItem.wechatpayGoodsId = "1001"; +// goodsDetailItem.goodsName = "iPhoneX 256G"; +// goodsDetailItem.quantity = 1L; +// goodsDetailItem.unitPrice = 528800L; +// request.detail.goodsDetail.add(goodsDetailItem); +// } +// ; +// request.sceneInfo = new Client.CommonSceneInfo(); +// request.sceneInfo.payerClientIp = "14.23.150.211"; +// request.sceneInfo.deviceId = "013467007045764"; +// request.sceneInfo.storeInfo = new Client.StoreInfo(); +// request.sceneInfo.storeInfo.id = "0001"; +// request.sceneInfo.storeInfo.name = "腾讯大厦分店"; +// request.sceneInfo.storeInfo.areaCode = "440305"; +// request.sceneInfo.storeInfo.address = "广东省深圳市南山区科技中一道10000号"; +// request.settleInfo = new Client.SettleInfo(); +// request.settleInfo.profitSharing = false; // try { -// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", params -> { -// params.put("appid", appId); -// params.put("mchid", mchId); -// params.put("description", description); -// params.put("out_trade_no", out_trade_no); -// if (time_expire != null) { -// params.put("time_expire", time_expire); -// } -// Map amountMap = new HashMap<>(); -// amountMap.put("total", totalFee.movePointRight(2)); // 分 -// params.put("amount", amountMap); -// -// params.put("notify_url", notify_url); -// params.put("openid", openid); -// -// if (attach != null) { -// params.put("attach", attach); +// String uri = PATH; +// String reqBody = WXPayUtility.toJson(request); +// +// Request.Builder reqBuilder = new Request.Builder().url(HOST + uri); +// reqBuilder.addHeader("Accept", "application/json"); +// reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId); +// reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchId, certificateSerialNo, privateKey, METHOD, uri, reqBody)); +// reqBuilder.addHeader("Content-Type", "application/json"); +// RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody); +// reqBuilder.method(METHOD, requestBody); +// Request httpRequest = reqBuilder.build(); +// +// // 发送HTTP请求 +// OkHttpClient client = new OkHttpClient.Builder().build(); +// try (Response httpResponse = client.newCall(httpRequest).execute()) { +// String respBody = WXPayUtility.extractBody(httpResponse); +// if (httpResponse.code() >= 200 && httpResponse.code() < 300) { +// // 2XX 成功,验证应答签名 +// WXPayUtility.validateResponse(wechatPayPublicKeyId, wechatPayPublicKey, httpResponse.headers(), respBody); +// +// // 从HTTP应答报文构建返回数据 +// DirectAPIv3JsapiPrepayResponse response = WXPayUtility.fromJson(respBody, DirectAPIv3JsapiPrepayResponse.class); +// // TODO: 请求成功,继续业务逻辑 +// System.out.println(response); +// } else { +// throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers()); // } -// }); -// log.info("[医保]下单返回:{}", JsonHelper.toJsonString(jsonResult)); -// if (!jsonResult.success()) { -// return new MedicalPayOrder().createResult(jsonResult); +// } catch (IOException e) { +// throw new UncheckedIOException("Sending request to " + uri + " failed.", e); // } -// return jsonResult.dataMapToBean(MedicalPayOrder.class); -// } catch (Exception e) { -// ErrorHelper.println(e); +// } catch (WXPayUtility.ApiException e) { +// // TODO: 请求失败,根据状态码执行不同的逻辑 +// e.printStackTrace(); // } // return null; // } + + +// public static class DirectAPIv3JsapiPrepayRequest { +// @SerializedName("appid") +// public String appid; // +// @SerializedName("mchid") +// public String mchid; // -// /** -// * 查询订单 -// * -// * @param mchId 直连商户号 -// * @param outTradeNo 商品描述 -// * @param transId 微信支付订单号 -// */ -// public MedicalPayOrder queryOrder(String mchId, String outTradeNo, String transId) { +// @SerializedName("description") +// public String description; // -// try { -// JsonResult jsonResult = null; +// @SerializedName("out_trade_no") +// public String outTradeNo; // -// if (outTradeNo != null) { -// jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "?" + mchId, params -> { -// }); +// @SerializedName("time_expire") +// public String timeExpire; // -// } else { -// if (transId != null) { -// jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/id/" + transId + "?" + mchId, params -> { -// }); -// } -// } +// @SerializedName("attach") +// public String attach; // -// log.info("[医保]查询订单:{}", JsonHelper.toJsonString(jsonResult)); -// if (!jsonResult.success()) { -// return new MedicalPayOrder().createResult(jsonResult); -// } -// return jsonResult.dataMapToBean(MedicalPayOrder.class); -// } catch (Exception e) { -// ErrorHelper.println(e); -// } -// return null; +// @SerializedName("notify_url") +// public String notifyUrl; +// +// @SerializedName("goods_tag") +// public String goodsTag; +// +// @SerializedName("support_fapiao") +// public Boolean supportFapiao; +// +// @SerializedName("amount") +// public CommonAmountInfo amount; +// +// @SerializedName("payer") +// public JsapiReqPayerInfo payer; +// +// @SerializedName("detail") +// public CouponInfo detail; +// +// @SerializedName("scene_info") +// public CommonSceneInfo sceneInfo; +// +// @SerializedName("settle_info") +// public SettleInfo settleInfo; // } // +// public static class DirectAPIv3JsapiPrepayResponse { +// @SerializedName("prepay_id") +// public String prepayId; +// } // -// /** -// * 关闭订单 -// * -// * @param mchId 直连商户号 -// * @param outTradeNo 商品描述 -// * @param transId 微信支付订单号 -// */ -// public MedicalPayOrder closeOrder(String mchId, String outTradeNo, String transId) { +// public static class CommonAmountInfo { +// @SerializedName("total") +// public Long total; // -// try { -// JsonResult jsonResult = WxRequestHelper.postMdXml(" https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "/close", params -> { -// params.put("mchId", mchId); -// }); +// @SerializedName("currency") +// public String currency; +// } // -// log.info("[医保]关闭订单返回:{}", JsonHelper.toJsonString(jsonResult)); -// if (!jsonResult.success()) { -// return new MedicalPayOrder().createResult(jsonResult); -// } -// return jsonResult.dataMapToBean(MedicalPayOrder.class); -// } catch (Exception e) { -// ErrorHelper.println(e); -// } -// return null; +// public static class JsapiReqPayerInfo { +// @SerializedName("openid") +// public String openid; // } // +// public static class CouponInfo { +// @SerializedName("cost_price") +// public Long costPrice; // -// /** -// * 微信JSAPI下单 -// * -// * @param outTradeNo 商品描述 -// * @param transId 微信支付订单号 -// */ -// public MedicalPayOrder refund(String outTradeNo, String transId, String outRefundNo, BigDecimal refundFee, BigDecimal totalFee, String reason, String notify_url) { +// @SerializedName("invoice_id") +// public String invoiceId; // -// try { -// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", params -> { -// params.put("transaction_id", transId); -// params.put("out_trade_no", outTradeNo); -// params.put("out_refund_no", outRefundNo); -// -// Map amountMap = new HashMap<>(); -// amountMap.put("refund", refundFee.movePointRight(2)); // 分 -// amountMap.put("total", totalFee.movePointRight(2)); // 分 -// amountMap.put("currency", "CNY"); // 分 -// params.put("amount", amountMap); -// -// if (notify_url != null) { -// params.put("notify_url", notify_url); -// } +// @SerializedName("goods_detail") +// public List goodsDetail; +// } // -// if (reason != null) { -// params.put("reason", reason); -// } -// }); -// log.info("[微信]退费返回:{}", JsonHelper.toJsonString(jsonResult)); -// if (!jsonResult.success()) { -// return new MedicalPayOrder().createResult(jsonResult); -// } -// return jsonResult.dataMapToBean(MedicalPayOrder.class); -// } catch (Exception e) { -// ErrorHelper.println(e); -// } -// return null; +// public static class CommonSceneInfo { +// @SerializedName("payer_client_ip") +// public String payerClientIp; +// +// @SerializedName("device_id") +// public String deviceId; +// +// @SerializedName("store_info") +// public StoreInfo storeInfo; +// } +// +// public static class SettleInfo { +// @SerializedName("profit_sharing") +// public Boolean profitSharing; // } // +// public static class GoodsDetail { +// @SerializedName("merchant_goods_id") +// public String merchantGoodsId; // -// /** -// * 查询退费订单 -// * -// * @param outRefundNo 退费订单号 -// */ -// public MedicalPayOrder queryRefund(String outRefundNo) { +// @SerializedName("wechatpay_goods_id") +// public String wechatpayGoodsId; // -// try { -// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + outRefundNo, params -> { +// @SerializedName("goods_name") +// public String goodsName; // -// }); -// log.info("[微信]查询退费订单:{}", JsonHelper.toJsonString(jsonResult)); -// if (!jsonResult.success()) { -// return new MedicalPayOrder().createResult(jsonResult); -// } -// return jsonResult.dataMapToBean(MedicalPayOrder.class); -// } catch (Exception e) { -// ErrorHelper.println(e); -// } -// return null; +// @SerializedName("quantity") +// public Long quantity; +// +// @SerializedName("unit_price") +// public Long unitPrice; +// } +// +// public static class StoreInfo { +// @SerializedName("id") +// public String id; +// +// @SerializedName("name") +// public String name; +// +// @SerializedName("area_code") +// public String areaCode; +// +// @SerializedName("address") +// public String address; // } -//} + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxNativePayResult.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxNativePayResult.java similarity index 82% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/WxNativePayResult.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxNativePayResult.java index 9dc6efe..5832be8 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxNativePayResult.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxNativePayResult.java @@ -1,4 +1,4 @@ -package com.ynxbd.wx.wxfactory.bean; +package com.ynxbd.wx.wxfactory.payment.jsapi.models; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxPayNotify.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxPayNotify.java similarity index 92% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/WxPayNotify.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxPayNotify.java index 3509d30..d2568d2 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/WxPayNotify.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxPayNotify.java @@ -1,40 +1,41 @@ -package com.ynxbd.wx.wxfactory.bean; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -import java.math.BigDecimal; - -@Getter -@Setter -@ToString -@NoArgsConstructor -public class WxPayNotify { - private String openid; - private String outTradeNo; - private String tradeType; - private String bankType; - private String timeEnd; - private String attach; - private String transactionId; - private BigDecimal totalFee; - // -------------------------------------- - private String feeType; - private String cashFeeType; - private BigDecimal cashFee; - private BigDecimal settlementTotalFee; - private BigDecimal couponFee; - private Integer couponCount; - private String contractId; - private String tradeState; - // 微信支付分配的终端设备号 - private String deviceInfo; - private String isSubscribe; - - // 自定义参数----------------------------- - private String payInfo; - private String payDate; - private String payTime; -} +package com.ynxbd.wx.wxfactory.payment.jsapi.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.math.BigDecimal; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class WxPayNotify { + private String openid; + private String productId; + private String outTradeNo; + private String tradeType; + private String bankType; + private String timeEnd; + private String attach; + private String transactionId; + private BigDecimal totalFee; + // -------------------------------------- + private String feeType; + private String cashFeeType; + private BigDecimal cashFee; + private BigDecimal settlementTotalFee; + private BigDecimal couponFee; + private Integer couponCount; + private String contractId; + private String tradeState; + // 微信支付分配的终端设备号 + private String deviceInfo; + private String isSubscribe; + + // 自定义参数----------------------------- + private String payInfo; + private String payDate; + private String payTime; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/base/refund/Client.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/Client.java similarity index 90% rename from src/main/java/com/ynxbd/wx/wxfactory/base/refund/Client.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/refund/Client.java index e3c7063..4dce3f4 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/base/refund/Client.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/Client.java @@ -1,36 +1,36 @@ -package com.ynxbd.wx.wxfactory.base.refund; - -import com.ynxbd.wx.wxfactory.bean.refund.WxRefundQueryRoot; -import lombok.NoArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.methods.RequestBuilder; - -import org.apache.http.entity.ContentType; -import org.apache.http.entity.StringEntity; -import org.apache.http.message.BasicHeader; -import weixin.popular.bean.paymch.Refundquery; -import weixin.popular.client.LocalHttpClient; -import weixin.popular.util.MapUtil; -import weixin.popular.util.SignatureUtil; -import weixin.popular.util.XMLConverUtil; - -import java.nio.charset.StandardCharsets; -import java.util.Map; - -@Slf4j -@NoArgsConstructor -public class Client { - - public WxRefundQueryRoot refundQuery(Refundquery refundquery, String mchKey) { - Map map = MapUtil.objectToMap(refundquery); - String sign = SignatureUtil.generateSign(map, refundquery.getSign_type(), mchKey); - refundquery.setSign(sign); - String reqXml = XMLConverUtil.convertToXML(refundquery); - HttpUriRequest httpUriRequest = RequestBuilder.post() - .setHeader(new BasicHeader("Content-Type", ContentType.APPLICATION_XML.toString())).setUri("https://api.mch.weixin.qq.com/pay/refundquery").setEntity(new StringEntity(reqXml, StandardCharsets.UTF_8)).build(); - return LocalHttpClient.executeXmlResult(httpUriRequest, WxRefundQueryRoot.class, refundquery.getSign_type(), mchKey); - } - - -} +package com.ynxbd.wx.wxfactory.payment.refund; + +import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundQueryRoot; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.methods.RequestBuilder; + +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.message.BasicHeader; +import weixin.popular.bean.paymch.Refundquery; +import weixin.popular.client.LocalHttpClient; +import weixin.popular.util.MapUtil; +import weixin.popular.util.SignatureUtil; +import weixin.popular.util.XMLConverUtil; + +import java.nio.charset.StandardCharsets; +import java.util.Map; + +@Slf4j +@NoArgsConstructor +public class Client { + + public WxRefundQueryRoot refundQuery(Refundquery refundquery, String mchKey) { + Map map = MapUtil.objectToMap(refundquery); + String sign = SignatureUtil.generateSign(map, refundquery.getSign_type(), mchKey); + refundquery.setSign(sign); + String reqXml = XMLConverUtil.convertToXML(refundquery); + HttpUriRequest httpUriRequest = RequestBuilder.post() + .setHeader(new BasicHeader("Content-Type", ContentType.APPLICATION_XML.toString())).setUri("https://api.mch.weixin.qq.com/pay/refundquery").setEntity(new StringEntity(reqXml, StandardCharsets.UTF_8)).build(); + return LocalHttpClient.executeXmlResult(httpUriRequest, WxRefundQueryRoot.class, refundquery.getSign_type(), mchKey); + } + + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/RefundCoupon.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/RefundCoupon.java new file mode 100644 index 0000000..abbbbb4 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/RefundCoupon.java @@ -0,0 +1,25 @@ +package com.ynxbd.wx.wxfactory.payment.refund.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +@NoArgsConstructor +public class RefundCoupon { + private String type; + private String id; + private Integer fee; + private Integer n; + + + public RefundCoupon(String type, String id, Integer fee, Integer n) { + this.type = type; + this.id = id; + this.fee = fee; + this.n = n; + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundItem.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundItem.java similarity index 81% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundItem.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundItem.java index e6072e8..a1fe382 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundItem.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundItem.java @@ -1,31 +1,30 @@ -package com.ynxbd.wx.wxfactory.bean.refund; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import weixin.popular.bean.paymch.Coupon; - -import java.util.List; - - -@Getter -@Setter -@NoArgsConstructor -@ToString -public class WxRefundItem { - private String out_refund_no; - private String refund_id; - private String refund_channel; - private Integer refund_fee; - private Integer settlement_refund_fee; - private String coupon_type; - private Integer coupon_refund_fee; - private Integer coupon_refund_count; - private String coupon_refund; - private String refund_status; - private String refund_recv_accout; - private String refund_success_time; - private Integer n; - private List coupons; -} +package com.ynxbd.wx.wxfactory.payment.refund.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; + +import java.util.List; + + +@Getter +@Setter +@NoArgsConstructor +@ToString +public class WxRefundItem { + private String out_refund_no; + private String refund_id; + private String refund_channel; + private Integer refund_fee; + private Integer settlement_refund_fee; + private String coupon_type; + private Integer coupon_refund_fee; + private Integer coupon_refund_count; + private String coupon_refund; + private String refund_status; + private String refund_recv_accout; + private String refund_success_time; + private Integer n; + private List coupons; +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundQueryRoot.java b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundQueryRoot.java similarity index 87% rename from src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundQueryRoot.java rename to src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundQueryRoot.java index d15076e..82f5cb1 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/bean/refund/WxRefundQueryRoot.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundQueryRoot.java @@ -1,80 +1,79 @@ -package com.ynxbd.wx.wxfactory.bean.refund; - -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; -import weixin.popular.bean.DynamicField; -import weixin.popular.bean.paymch.Coupon; -import weixin.popular.bean.paymch.MchBase; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - - -@Getter -@Setter -@NoArgsConstructor -@ToString -@XmlRootElement(name = "xml") -@XmlAccessorType(XmlAccessType.FIELD) -public class WxRefundQueryRoot extends MchBase implements DynamicField { - private String device_info; - private String transaction_id; - private String out_trade_no; - private Integer total_fee; - private Integer settlement_total_fee; - private String fee_type; - private Integer cash_fee; - private Integer refund_count; - private String refund_account; - private Integer total_refund_count; - @XmlTransient - private List items; - - public void buildDynamicField(Map dataMap) { - if (dataMap != null) { - String refund_countStr = dataMap.get("refund_count"); - if (refund_countStr != null) { - List list = new ArrayList<>(); - - WxRefundItem item; - List couponList; - for (int i = 0; i < Integer.parseInt(refund_countStr); ++i) { - item = new WxRefundItem(); - item.setOut_refund_no(dataMap.get("out_refund_no_" + i)); - item.setRefund_id(dataMap.get("refund_id_" + i)); - item.setRefund_channel(dataMap.get("refund_channel_" + i)); - item.setRefund_fee(dataMap.get("refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("refund_fee_" + i))); - item.setSettlement_refund_fee(dataMap.get("settlement_refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("settlement_refund_fee_" + i))); - item.setCoupon_type(dataMap.get("coupon_type_" + i)); - item.setCoupon_refund_fee(dataMap.get("coupon_refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_fee_" + i))); - item.setCoupon_refund_count(dataMap.get("coupon_refund_count_" + i) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_count_" + i))); - item.setCoupon_refund(dataMap.get("coupon_refund_" + i)); - item.setRefund_status(dataMap.get("refund_status_" + i)); - item.setRefund_recv_accout(dataMap.get("refund_recv_accout_" + i)); - // 新增 - item.setRefund_success_time(dataMap.get("refund_success_time_" + i)); - item.setN(i); - if (item.getCoupon_refund_count() != null) { - couponList = new ArrayList<>(); - - for (int j = 0; j < item.getCoupon_refund_count(); ++j) { - Coupon coupon = new Coupon(null, dataMap.get("coupon_refund_id_" + i + "_" + j), dataMap.get("coupon_refund_fee_" + i + "_" + j) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_fee_" + i + "_" + j)), j); - couponList.add(coupon); - } - item.setCoupons(couponList); - } - list.add(item); - } - this.items = list; - } - } - - } -} +package com.ynxbd.wx.wxfactory.payment.refund.models; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.ToString; +import weixin.popular.bean.DynamicField; +import weixin.popular.bean.paymch.MchBase; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +@Getter +@Setter +@NoArgsConstructor +@ToString +@XmlRootElement(name = "xml") +@XmlAccessorType(XmlAccessType.FIELD) +public class WxRefundQueryRoot extends MchBase implements DynamicField { + private String device_info; + private String transaction_id; + private String out_trade_no; + private Integer total_fee; + private Integer settlement_total_fee; + private String fee_type; + private Integer cash_fee; + private Integer refund_count; + private String refund_account; + private Integer total_refund_count; + @XmlTransient + private List items; + + public void buildDynamicField(Map dataMap) { + if (dataMap != null) { + String refund_countStr = dataMap.get("refund_count"); + if (refund_countStr != null) { + List list = new ArrayList<>(); + + WxRefundItem item; + List couponList; + for (int i = 0; i < Integer.parseInt(refund_countStr); ++i) { + item = new WxRefundItem(); + item.setOut_refund_no(dataMap.get("out_refund_no_" + i)); + item.setRefund_id(dataMap.get("refund_id_" + i)); + item.setRefund_channel(dataMap.get("refund_channel_" + i)); + item.setRefund_fee(dataMap.get("refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("refund_fee_" + i))); + item.setSettlement_refund_fee(dataMap.get("settlement_refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("settlement_refund_fee_" + i))); + item.setCoupon_type(dataMap.get("coupon_type_" + i)); + item.setCoupon_refund_fee(dataMap.get("coupon_refund_fee_" + i) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_fee_" + i))); + item.setCoupon_refund_count(dataMap.get("coupon_refund_count_" + i) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_count_" + i))); + item.setCoupon_refund(dataMap.get("coupon_refund_" + i)); + item.setRefund_status(dataMap.get("refund_status_" + i)); + item.setRefund_recv_accout(dataMap.get("refund_recv_accout_" + i)); + // 新增 + item.setRefund_success_time(dataMap.get("refund_success_time_" + i)); + item.setN(i); + if (item.getCoupon_refund_count() != null) { + couponList = new ArrayList<>(); + + for (int j = 0; j < item.getCoupon_refund_count(); ++j) { + RefundCoupon coupon = new RefundCoupon(null, dataMap.get("coupon_refund_id_" + i + "_" + j), dataMap.get("coupon_refund_fee_" + i + "_" + j) == null ? null : Integer.parseInt(dataMap.get("coupon_refund_fee_" + i + "_" + j)), j); + couponList.add(coupon); + } + item.setCoupons(couponList); + } + list.add(item); + } + this.items = list; + } + } + + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/EmojiHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/EmojiHelper.java new file mode 100644 index 0000000..6238e20 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/EmojiHelper.java @@ -0,0 +1,51 @@ +package com.ynxbd.wx.wxfactory.utils; + +import com.vdurmont.emoji.EmojiParser; + +public class EmojiHelper { + public static String parseToHtmlHexadecimal(String emoji_str) { + return EmojiParser.parseToHtmlHexadecimal(emoji_str); + } + + public static String parseToHtmlTag(String emoji_str) { + if (emoji_str != null) { + String str = EmojiParser.parseToHtmlHexadecimal(emoji_str); + return htmlHexadecimalToHtmlTag(str); + } else { + return null; + } + } + + public static String parseToAliases(String emoji_str) { + return EmojiParser.parseToAliases(emoji_str); + } + + public static String parseToHtmlDecimal(String emoji_str) { + return EmojiParser.parseToHtmlDecimal(emoji_str); + } + + public static String removeAllEmojis(String emoji_str) { + return EmojiParser.removeAllEmojis(emoji_str); + } + + public static String htmlHexadecimalToHtmlTag(String emoji_str) { + return emoji_str != null ? emoji_str.replaceAll("&#x([^;]*);", "") : null; + } + + public static String parse(String emoji_str, int type) { + switch (type) { + case 1: + return parseToHtmlHexadecimal(emoji_str); + case 2: + return parseToHtmlTag(emoji_str); + case 3: + return parseToAliases(emoji_str); + case 4: + return parseToHtmlDecimal(emoji_str); + case 5: + return removeAllEmojis(emoji_str); + default: + return null; + } + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/WechatPayHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/WechatPayHelper.java new file mode 100644 index 0000000..e65d550 --- /dev/null +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/WechatPayHelper.java @@ -0,0 +1,8 @@ +package com.ynxbd.wx.wxfactory.utils; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class WechatPayHelper { + +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxEventHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxEventHelper.java index af7e72e..a3d3862 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxEventHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxEventHelper.java @@ -1,58 +1,60 @@ -package com.ynxbd.wx.wxfactory.utils; - -import com.ynxbd.wx.wxfactory.bean.event.WxEvent; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.codec.digest.DigestUtils; - -import javax.servlet.http.HttpServletRequest; -import java.util.Arrays; - -@Slf4j -public class WxEventHelper { - - /** - * 过滤内容可以直接返回 - * - * @param wxEvent 事件 - */ - public static boolean filter(WxEvent wxEvent) { - String event = wxEvent.getEvent(); - if (event != null) { - event = event.toUpperCase(); - } - String msgType = wxEvent.getMsgType(); - if (msgType != null) { - msgType = msgType.toUpperCase(); - } - if ("VIEW".equals(event) && "EVENT".equals(msgType)) { // 点击菜单 - return true; - } - - if ("TEMPLATESENDJOBFINISH".equals(event)) { // 模板发送作业完成-->直接返回success - log.warn("[公众号]模板消息推送 fromUserName={}, msgType={}, eventKey={}, event={}", wxEvent.getFromUserName(), msgType, wxEvent.getEventKey(), event); - return true; - } - return false; - } - - - /** - * 消息验签 - * - * @param request request - * @param wxToken wxToken - */ - public static boolean verifyEventSign(HttpServletRequest request, String wxToken) { - String nonce = request.getParameter("nonce"); - String timestamp = request.getParameter("timestamp"); - - String[] array = new String[]{wxToken, timestamp, nonce}; - Arrays.sort(array); - - StringBuilder sb = new StringBuilder(); - for (String s : array) { - sb.append(s); - } - return DigestUtils.sha1Hex(sb.toString()).equals(request.getParameter("signature")); - } -} +package com.ynxbd.wx.wxfactory.utils; + +import com.ynxbd.wx.wxfactory.base.passivemsg.event.WxEvent; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.codec.digest.DigestUtils; + +import javax.servlet.http.HttpServletRequest; +import java.util.Arrays; + +@Slf4j +public class WxEventHelper { + + private static final String TEMPLATE_SEND_JOB_FINISH = "TEMPLATESENDJOBFINISH"; + + /** + * 过滤内容可以直接返回 + * + * @param wxEvent 事件 + */ + public static boolean filter(WxEvent wxEvent) { + String event = wxEvent.getEvent(); + if (event != null) { + event = event.toUpperCase(); + } + String msgType = wxEvent.getMsgType(); + if (msgType != null) { + msgType = msgType.toUpperCase(); + } + if ("VIEW".equals(event) && "EVENT".equals(msgType)) { // 点击菜单 + return true; + } + + if (TEMPLATE_SEND_JOB_FINISH.equals(event)) { // 模板发送作业完成-->直接返回success + log.warn("[公众号]模板消息推送 fromUserName={}, msgType={}, eventKey={}, event={}", wxEvent.getFromUserName(), msgType, wxEvent.getEventKey(), event); + return true; + } + return false; + } + + + /** + * 消息验签 + * + * @param request request + * @param wxToken wxToken + */ + public static boolean verifyEventSign(HttpServletRequest request, String wxToken) { + String nonce = request.getParameter("nonce"); + String timestamp = request.getParameter("timestamp"); + + String[] array = new String[]{wxToken, timestamp, nonce}; + Arrays.sort(array); + + StringBuilder sb = new StringBuilder(); + for (String s : array) { + sb.append(s); + } + return DigestUtils.sha1Hex(sb.toString()).equals(request.getParameter("signature")); + } +} diff --git a/src/main/java/com/ynxbd/wx/wxfactory/WxMessageHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxMedAssistantHelper.java similarity index 94% rename from src/main/java/com/ynxbd/wx/wxfactory/WxMessageHelper.java rename to src/main/java/com/ynxbd/wx/wxfactory/utils/WxMedAssistantHelper.java index fa17f6a..99b59a5 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/WxMessageHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxMedAssistantHelper.java @@ -1,7 +1,8 @@ -package com.ynxbd.wx.wxfactory; +package com.ynxbd.wx.wxfactory.utils; import com.ynxbd.common.result.JsonResult; import com.ynxbd.wx.config.WeChatConfig; +import com.ynxbd.wx.wxfactory.WxCacheHelper; import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import com.ynxbd.wx.wxfactory.message.MdClient; import lombok.extern.slf4j.Slf4j; @@ -10,7 +11,7 @@ import lombok.extern.slf4j.Slf4j; * 就医助手 */ @Slf4j -public class WxMessageHelper { +public class WxMedAssistantHelper { /** * 就医助手授权 diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxSignHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxSignHelper.java index ac8db82..f74d9fc 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/utils/WxSignHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/WxSignHelper.java @@ -5,17 +5,27 @@ import com.ynxbd.common.helper.common.JsonHelper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; @Slf4j @@ -46,7 +56,7 @@ public class WxSignHelper { if (signType == null) { signType = SIGN_TYPE_MD5; } - log.info("[医保]签名前参数:paramsStr-{}",paramsStr + "&key=" + key); + log.info("[医保]签名前参数:paramsStr-{} key-{}", paramsStr, key); if (SIGN_TYPE_HMAC_SHA256.equalsIgnoreCase(signType)) { Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); @@ -80,8 +90,8 @@ public class WxSignHelper { * @param key 密钥 * @return t | f */ - public static boolean validateSign(Map map, String sign_type, String key) { - return map.get("sign") != null && map.get("sign").equals(generateSign(map, sign_type, key)); + public static boolean validateSign(Map map, String signType, String key) { + return map.get("sign") != null && map.get("sign").equals(generateSign(map, signType, key)); } /** @@ -101,7 +111,7 @@ public class WxSignHelper { sb.append(buffer, 0, len); } String respData = sb.toString(); - if ("".equals(respData)) { + if (ObjectUtils.isEmpty(respData)) { return null; } return respData; @@ -117,7 +127,7 @@ public class WxSignHelper { * @param request 请求 * @return map */ - public static Map getReqXmlParamsMap(HttpServletRequest request) { + public static Map reqXmlParamsMap(HttpServletRequest request) { String reqXml = getReqData(request); if (reqXml == null) { return null; @@ -131,8 +141,8 @@ public class WxSignHelper { * @param request 请求 * @return 对象 */ - public static T getReqXmlToBean(HttpServletRequest request ,Class clazz) { - Map paramsMap = getReqXmlParamsMap(request); + public static T reqXmlToBean(HttpServletRequest request, Class clazz) { + Map paramsMap = reqXmlParamsMap(request); if (paramsMap == null) { return null; } @@ -178,4 +188,41 @@ public class WxSignHelper { return info.toString(); } + + public static Map reqXmlToMapByNativePay(HttpServletRequest request) { + String xml = getReqData(request); + if (xml == null) { + return null; + } + Map map = new LinkedHashMap<>(); + try (StringReader sr = new StringReader(xml)) { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + dbf.setFeature("http://xml.org/sax/features/external-general-entities", false); + dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + dbf.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true); + dbf.setXIncludeAware(false); + dbf.setExpandEntityReferences(false); + DocumentBuilder db = dbf.newDocumentBuilder(); + InputSource is = new InputSource(sr); + Document document = db.parse(is); + Element root = document.getDocumentElement(); + if (root != null) { + NodeList childNodes = root.getChildNodes(); + if (childNodes.getLength() > 0) { + for (int i = 0; i < childNodes.getLength(); ++i) { + Node node = childNodes.item(i); + if (node != null && node.getNodeType() == 1) { + map.put(node.getNodeName(), node.getTextContent()); + } + } + } + } + } catch (Exception e) { + log.error(e.getMessage()); + } + return map; + } + } diff --git a/src/main/java/com/ynxbd/wx/wxfactory/utils/XmlHelper.java b/src/main/java/com/ynxbd/wx/wxfactory/utils/XmlHelper.java index 51814ec..8c36287 100644 --- a/src/main/java/com/ynxbd/wx/wxfactory/utils/XmlHelper.java +++ b/src/main/java/com/ynxbd/wx/wxfactory/utils/XmlHelper.java @@ -1,7 +1,7 @@ package com.ynxbd.wx.wxfactory.utils; import com.alibaba.fastjson.JSON; -import com.ynxbd.wx.wxfactory.bean.MedicalNotify; +import com.ynxbd.wx.wxfactory.medical.models.MedicalNotify; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.ObjectUtils; import org.dom4j.*;