结构调整,被动消息回复全部抽离第三方包

debug
王绍全 6 months ago
parent bd12b21d5e
commit a138546449
  1. 2
      src/main/java/com/ynxbd/ali/helper/AliMedHelper.java
  2. 9
      src/main/java/com/ynxbd/common/TestA.java
  3. 2
      src/main/java/com/ynxbd/common/action/ApiAction.java
  4. 8
      src/main/java/com/ynxbd/common/action/pay/MedicalAction.java
  5. 2
      src/main/java/com/ynxbd/common/action/pay/MedicalTestAction.java
  6. 2
      src/main/java/com/ynxbd/common/action/pay/NotifyAction.java
  7. 2
      src/main/java/com/ynxbd/common/action/pay/PayAction.java
  8. 2
      src/main/java/com/ynxbd/common/action/pay/WxPayAction.java
  9. 2
      src/main/java/com/ynxbd/common/action/test/TestAction.java
  10. 2
      src/main/java/com/ynxbd/common/dao/his/HisMedDao.java
  11. 2
      src/main/java/com/ynxbd/common/helper/common/MethodHelper.java
  12. 6
      src/main/java/com/ynxbd/common/helper/common/RepeatKeyHelper.java
  13. 8
      src/main/java/com/ynxbd/common/service/MedicalService.java
  14. 2
      src/main/java/com/ynxbd/common/service/PayService.java
  15. 2
      src/main/java/com/ynxbd/common/service/RecipeService.java
  16. 2
      src/main/java/com/ynxbd/common/service/RegService.java
  17. 87
      src/main/java/com/ynxbd/common/service/Test.java
  18. 3
      src/main/java/com/ynxbd/wx/config/WxEventEnum.java
  19. 5
      src/main/java/com/ynxbd/wx/remove/dao/DBDao.java
  20. 11
      src/main/java/com/ynxbd/wx/remove/servlet/DemoServlet2.java
  21. 3
      src/main/java/com/ynxbd/wx/remove/servlet/OAuthServlet.java
  22. 5
      src/main/java/com/ynxbd/wx/remove/servlet/PayMchJsServlet.java
  23. 6
      src/main/java/com/ynxbd/wx/remove/servlet/PayMchNotifyServlet.java
  24. 4
      src/main/java/com/ynxbd/wx/remove/servlet/PayServlet.java
  25. 5
      src/main/java/com/ynxbd/wx/remove/servlet/PayTest.java
  26. 5
      src/main/java/com/ynxbd/wx/remove/servlet/QRPayUrlServlet.java
  27. 5
      src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchJsServlet.java
  28. 6
      src/main/java/com/ynxbd/wx/remove/servlet/RegPayMchNotifyServlet.java
  29. 5
      src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchJsServlet.java
  30. 6
      src/main/java/com/ynxbd/wx/remove/servlet/Time_RegPayMchNotifyServlet.java
  31. 4
      src/main/java/com/ynxbd/wx/remove/util/CommonUtil.java
  32. 1
      src/main/java/com/ynxbd/wx/remove/util/DefaultExpireKey.java
  33. 3
      src/main/java/com/ynxbd/wx/remove/util/MessageUtil.java
  34. 6
      src/main/java/com/ynxbd/wx/servlet/WxServlet.java
  35. 2
      src/main/java/com/ynxbd/wx/servlet/oldpay/PayNotifyServlet.java
  36. 77
      src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet.java
  37. 189
      src/main/java/com/ynxbd/wx/servlet/oldpay/QRPayServlet2.java
  38. 96
      src/main/java/com/ynxbd/wx/servlet/test/OrderTest.java
  39. 3
      src/main/java/com/ynxbd/wx/servlet/test/WxAuthServlet.java
  40. 2
      src/main/java/com/ynxbd/wx/servlet/test/WxNativePayNotifyServlet.java
  41. 66
      src/main/java/com/ynxbd/wx/servlet/test/WxOrderTest.java
  42. 2
      src/main/java/com/ynxbd/wx/servlet/test/WxPayNotifyServlet.java
  43. 30
      src/main/java/com/ynxbd/wx/servlet/test/WxUAuthServlet.java
  44. 2
      src/main/java/com/ynxbd/wx/wxfactory/AesWxHelper.java
  45. 568
      src/main/java/com/ynxbd/wx/wxfactory/WxAuthHelper.java
  46. 4
      src/main/java/com/ynxbd/wx/wxfactory/WxCacheHelper.java
  47. 10
      src/main/java/com/ynxbd/wx/wxfactory/WxFactory.java
  48. 11
      src/main/java/com/ynxbd/wx/wxfactory/WxMedHelper.java
  49. 1028
      src/main/java/com/ynxbd/wx/wxfactory/WxPassiveReplyHelper.java
  50. 12
      src/main/java/com/ynxbd/wx/wxfactory/WxPayHelper.java
  51. 8
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/Client.java
  52. 40
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AccessToken.java
  53. 2
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/AuthData.java
  54. 2
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/JsapiTicket.java
  55. 1
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/RespAccessToken.java
  56. 56
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsOath2AccessToken.java
  57. 66
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/SnsUserInfo.java
  58. 40
      src/main/java/com/ynxbd/wx/wxfactory/base/auth/models/WxBaseResult.java
  59. 68
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/Client.java
  60. 64
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEvent.java
  61. 263
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/event/WxEventMessage.java
  62. 93
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLBaseMsg.java
  63. 27
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLImageMsg.java
  64. 68
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLNewsMsg.java
  65. 29
      src/main/java/com/ynxbd/wx/wxfactory/base/passivemsg/models/XMLTextMsg.java
  66. 3
      src/main/java/com/ynxbd/wx/wxfactory/medical/Client.java
  67. 132
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedRespHelper.java
  68. 6
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalBill.java
  69. 108
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalInfo.java
  70. 148
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalNotify.java
  71. 40
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalPayOrder.java
  72. 42
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefund.java
  73. 60
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalRefundInfo.java
  74. 56
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/MedicalUserInfo.java
  75. 2
      src/main/java/com/ynxbd/wx/wxfactory/medical/models/WxMedOrder.java
  76. 225
      src/main/java/com/ynxbd/wx/wxfactory/menu/bean/WxMsgConst.java
  77. 5
      src/main/java/com/ynxbd/wx/wxfactory/menu/bean/XMLParse.java
  78. 3
      src/main/java/com/ynxbd/wx/wxfactory/message/MdClient.java
  79. 2
      src/main/java/com/ynxbd/wx/wxfactory/payment/OrderMIEnum.java
  80. 912
      src/main/java/com/ynxbd/wx/wxfactory/payment/WXPayUtility.java
  81. 371
      src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/Client.java
  82. 2
      src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxNativePayResult.java
  83. 81
      src/main/java/com/ynxbd/wx/wxfactory/payment/jsapi/models/WxPayNotify.java
  84. 72
      src/main/java/com/ynxbd/wx/wxfactory/payment/refund/Client.java
  85. 25
      src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/RefundCoupon.java
  86. 61
      src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundItem.java
  87. 159
      src/main/java/com/ynxbd/wx/wxfactory/payment/refund/models/WxRefundQueryRoot.java
  88. 51
      src/main/java/com/ynxbd/wx/wxfactory/utils/EmojiHelper.java
  89. 8
      src/main/java/com/ynxbd/wx/wxfactory/utils/WechatPayHelper.java
  90. 118
      src/main/java/com/ynxbd/wx/wxfactory/utils/WxEventHelper.java
  91. 5
      src/main/java/com/ynxbd/wx/wxfactory/utils/WxMedAssistantHelper.java
  92. 61
      src/main/java/com/ynxbd/wx/wxfactory/utils/WxSignHelper.java
  93. 2
      src/main/java/com/ynxbd/wx/wxfactory/utils/XmlHelper.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.ErrorHelper;
import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.common.JsonHelper;
import com.ynxbd.common.result.ServiceException; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -1,12 +1,13 @@
package com.ynxbd.common; package com.ynxbd.common;
import com.ynxbd.common.helper.common.Base64Helper; import com.ynxbd.wx.utils.DesEncryptHelper;
import java.io.UnsupportedEncodingException;
public class TestA { 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);
} }
} }

@ -11,7 +11,7 @@ import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.utils.DesEncryptHelper; import com.ynxbd.wx.utils.DesEncryptHelper;
import com.ynxbd.wx.wxfactory.AesWxHelper; import com.ynxbd.wx.wxfactory.AesWxHelper;
import com.ynxbd.wx.wxfactory.WxCacheHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Action;

@ -20,9 +20,9 @@ import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.MedicalService; import com.ynxbd.common.service.MedicalService;
import com.ynxbd.common.service.params.RequestParams; import com.ynxbd.common.service.params.RequestParams;
import com.ynxbd.wx.wxfactory.*; import com.ynxbd.wx.wxfactory.*;
import com.ynxbd.wx.wxfactory.bean.*;
import com.ynxbd.wx.wxfactory.medical.WxMedConfig; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Action;
@ -385,7 +385,7 @@ public class MedicalAction extends BaseAction {
log.info("[微信医保]回调通知..."); log.info("[微信医保]回调通知...");
MedicalNotify notifyInfo = WxMedHelper.paidMedNotify(request); MedicalNotify notifyInfo = WxMedHelper.paidMedNotify(request);
// 成功返回 // 成功返回
Result.respXml(MdRespHelper.respOk(WxMedConfig.PAY_KEY)); Result.respXml(MedRespHelper.respOk(WxMedConfig.PAY_KEY));
String openid = notifyInfo.getOpenid(); String openid = notifyInfo.getOpenid();
String bankTransNo = notifyInfo.getMedTransId(); 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); new MedicalService().commonNotify(MerchantEnum.WX_MEDICAL, notifyType, outTradeNo, totalFee, bankTransNo, payDate, payTime, openid, payInfo);
return null; return null;
} catch (ServiceException e) { } catch (ServiceException e) {
return Result.respXml(MdRespHelper.resp(e, WxMedConfig.PAY_KEY)); return Result.respXml(MedRespHelper.resp(e, WxMedConfig.PAY_KEY));
} }
} }

@ -21,7 +21,7 @@ import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.RecipeService; import com.ynxbd.common.service.RecipeService;
import com.ynxbd.wx.wxfactory.WxCacheHelper; import com.ynxbd.wx.wxfactory.WxCacheHelper;
import com.ynxbd.wx.wxfactory.WxMedHelper; 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 com.ynxbd.wx.wxfactory.medical.WxMedConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -6,7 +6,7 @@ import com.ynxbd.common.result.Result;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.*; import com.ynxbd.common.service.*;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 com.ynxbd.wx.wxfactory.utils.WxRespHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Action;

@ -21,7 +21,7 @@ import com.ynxbd.common.service.*;
import com.ynxbd.common.service.params.RequestParams; import com.ynxbd.common.service.params.RequestParams;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -7,7 +7,7 @@ import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.OutCollectService; import com.ynxbd.common.service.OutCollectService;
import com.ynxbd.common.service.PayService; import com.ynxbd.common.service.PayService;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 com.ynxbd.wx.wxfactory.utils.WxRespHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Action;

@ -1,12 +1,10 @@
package com.ynxbd.common.action.test; package com.ynxbd.common.action.test;
import com.ynxbd.common.action.base.BaseAction; 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.helper.common.DateHelper;
import com.ynxbd.common.result.Result; import com.ynxbd.common.result.Result;
import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ResultEnum;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.CasebookService;
import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import com.ynxbd.wx.wxfactory.medical.WxMedConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Action;

@ -13,7 +13,7 @@ import com.ynxbd.common.helper.his.HisMedHelper;
import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.JsonResult;
import com.ynxbd.common.result.Result; import com.ynxbd.common.result.Result;
import com.ynxbd.common.result.ResultEnum; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -7,7 +7,7 @@ package com.ynxbd.common.helper.common;
//import javassist.bytecode.CodeAttribute; //import javassist.bytecode.CodeAttribute;
//import javassist.bytecode.LocalVariableAttribute; //import javassist.bytecode.LocalVariableAttribute;
//import javassist.bytecode.MethodInfo; //import javassist.bytecode.MethodInfo;
//import weixin.popular.bean.user.User;
// //
//public class MethodUtil { //public class MethodUtil {
// //

@ -36,7 +36,6 @@ public class RepeatKeyHelper {
} }
private void timerTask() { private void timerTask() {
log.info("创建keyList");
if (scheduledExecutorService != null) { if (scheduledExecutorService != null) {
scheduledExecutorService.shutdownNow(); scheduledExecutorService.shutdownNow();
} }
@ -65,7 +64,7 @@ public class RepeatKeyHelper {
for (String key : removeKey) { for (String key : removeKey) {
KEY_MAP.remove(key); KEY_MAP.remove(key);
} }
if (removeKey.size() > 0) { if (!removeKey.isEmpty()) {
log.info("clean {} keys, remain {} keys", removeKey.size(), KEY_MAP.size()); log.info("clean {} keys, remain {} keys", removeKey.size(), KEY_MAP.size());
} }
}, 10, period, TimeUnit.SECONDS); }, 10, period, TimeUnit.SECONDS);
@ -95,7 +94,6 @@ public class RepeatKeyHelper {
} }
} }
log.info("add key=" + key);
KEY_MAP.put(key, (System.currentTimeMillis() / 1000) + expire); KEY_MAP.put(key, (System.currentTimeMillis() / 1000) + expire);
return false; return false;
} }
@ -111,7 +109,7 @@ public class RepeatKeyHelper {
public void print() { public void print() {
for (String key : KEY_MAP.keySet()) { for (String key : KEY_MAP.keySet()) {
log.info("key=" + key + ", value=" + KEY_MAP.get(key)); log.info("key={}, value={}", key, KEY_MAP.get(key));
} }
} }
} }

@ -19,10 +19,10 @@ import com.ynxbd.common.result.ServiceException;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxMedHelper;
import com.ynxbd.wx.wxfactory.WxPayHelper; import com.ynxbd.wx.wxfactory.WxPayHelper;
import com.ynxbd.wx.wxfactory.bean.MedicalInfo; import com.ynxbd.wx.wxfactory.medical.models.MedicalInfo;
import com.ynxbd.wx.wxfactory.bean.WxMedOrder; import com.ynxbd.wx.wxfactory.medical.models.WxMedOrder;
import com.ynxbd.wx.wxfactory.bean.MedicalUserInfo; import com.ynxbd.wx.wxfactory.medical.models.MedicalUserInfo;
import com.ynxbd.wx.wxfactory.bean.OrderMIEnum; import com.ynxbd.wx.wxfactory.payment.OrderMIEnum;
import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import com.ynxbd.wx.wxfactory.medical.WxMedConfig;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -17,7 +17,7 @@ import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.cache.PayCache; import com.ynxbd.common.service.cache.PayCache;
import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxMedHelper;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

@ -25,7 +25,7 @@ import com.ynxbd.wx.config.TZReserveConfig;
import com.ynxbd.wx.utils.DateGenerate; import com.ynxbd.wx.utils.DateGenerate;
import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxMedHelper;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -24,7 +24,7 @@ import com.ynxbd.wx.config.MessagePushConfig;
import com.ynxbd.wx.utils.DateGenerate; import com.ynxbd.wx.utils.DateGenerate;
import com.ynxbd.wx.wxfactory.WxMedHelper; import com.ynxbd.wx.wxfactory.WxMedHelper;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;

@ -1,102 +1,15 @@
package com.ynxbd.common.service; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils; 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 @Slf4j
public class Test { public class Test {
public static void main(String[] args) { public static void main(String[] args) {
// System.out.println(JsonHelper.toJsonString(queryOrder("WX7c1ea238c08f420d2bb8262f7254"))); // System.out.println(JsonHelper.toJsonString(queryOrder("WX7c1ea238c08f420d2bb8262f7254")));
String piMd5 = "9444144" + "Z2007" + "xbd"; String piMd5 = "9444144" + "Z2007" + "xbd";
piMd5 = DigestUtils.md5Hex(piMd5).toUpperCase(); piMd5 = DigestUtils.md5Hex(piMd5).toUpperCase();
System.out.println(piMd5); 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;
}
} }

@ -32,4 +32,7 @@ public enum WxEventEnum {
this.NAME = NAME; this.NAME = NAME;
} }
public boolean isEvent(String event) {
return this.CODE.equals(event);
}
} }

@ -6,10 +6,7 @@
//import org.apache.commons.lang.math.NumberUtils; //import org.apache.commons.lang.math.NumberUtils;
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //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.Connection;
//import java.sql.PreparedStatement; //import java.sql.PreparedStatement;

@ -3,16 +3,7 @@
//import com.ynxbd.api.utils.MessageUtil; //import com.ynxbd.api.utils.MessageUtil;
//import com.ynxbd.api.config.WeChatConfig; //import com.ynxbd.api.config.WeChatConfig;
//import org.apache.log4j.Logger; //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.ServletException;
//import javax.servlet.ServletInputStream; //import javax.servlet.ServletInputStream;

@ -5,8 +5,7 @@
//import com.ynxbd.api.utils.Global; //import com.ynxbd.api.utils.Global;
//import com.ynxbd.api.config.WxConfig; //import com.ynxbd.api.config.WxConfig;
//import org.apache.log4j.NDC; //import org.apache.log4j.NDC;
//import weixin.popular.api.SnsAPI;
//import weixin.popular.bean.sns.SnsToken;
// //
//import javax.servlet.ServletException; //import javax.servlet.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -9,10 +9,7 @@
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//import org.slf4j.MDC; //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.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -12,11 +12,7 @@
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//import org.slf4j.MDC; //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.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -15,10 +15,6 @@
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//import org.slf4j.MDC; //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.ServletException;
//import javax.servlet.annotation.WebServlet; //import javax.servlet.annotation.WebServlet;

@ -7,10 +7,7 @@
//import com.ynxbd.api.config.WeChatConfig; //import com.ynxbd.api.config.WeChatConfig;
//import net.sf.json.JSONArray; //import net.sf.json.JSONArray;
//import org.apache.log4j.Logger; //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.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -6,10 +6,7 @@
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//import org.slf4j.MDC; //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.ServletException;
//import javax.servlet.annotation.WebServlet; //import javax.servlet.annotation.WebServlet;

@ -8,10 +8,7 @@
//import com.ynxbd.api.config.WeChatConfig; //import com.ynxbd.api.config.WeChatConfig;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
//import org.apache.log4j.NDC; //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.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -13,11 +13,7 @@
//import com.ynxbd.api.utils.Global; //import com.ynxbd.api.utils.Global;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
//import org.apache.log4j.NDC; //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.ServletInputStream;
//import javax.servlet.ServletOutputStream; //import javax.servlet.ServletOutputStream;

@ -8,10 +8,7 @@
//import com.ynxbd.api.config.WeChatConfig; //import com.ynxbd.api.config.WeChatConfig;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
//import org.apache.log4j.NDC; //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.ServletException;
//import javax.servlet.http.HttpServlet; //import javax.servlet.http.HttpServlet;

@ -15,11 +15,7 @@
//import com.ynxbd.api.utils.Global; //import com.ynxbd.api.utils.Global;
//import org.apache.log4j.Logger; //import org.apache.log4j.Logger;
//import org.apache.log4j.NDC; //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.ServletInputStream;
//import javax.servlet.ServletOutputStream; //import javax.servlet.ServletOutputStream;

@ -3,9 +3,7 @@
//import com.ynxbd.wx.wxfactory.WxCacheHelper; //import com.ynxbd.wx.wxfactory.WxCacheHelper;
//import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils; //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.text.SimpleDateFormat;
//import java.util.Date; //import java.util.Date;

@ -4,7 +4,6 @@
//import org.slf4j.Logger; //import org.slf4j.Logger;
//import org.slf4j.LoggerFactory; //import org.slf4j.LoggerFactory;
//import org.slf4j.MDC; //import org.slf4j.MDC;
//import weixin.popular.support.ExpireKey;
// //
//import java.util.ArrayList; //import java.util.ArrayList;
//import java.util.List; //import java.util.List;

@ -1,8 +1,7 @@
//package com.ynxbd.wx.remove.util; //package com.ynxbd.wx.remove.util;
// //
//import com.ynxbd.wx.config.WeChatConfig; //import com.ynxbd.wx.config.WeChatConfig;
//import weixin.popular.bean.xmlmessage.XMLNewsMessage;
//import weixin.popular.bean.xmlmessage.XMLTextMessage;
// //
//import java.io.OutputStream; //import java.io.OutputStream;
//import java.util.ArrayList; //import java.util.ArrayList;

@ -3,9 +3,9 @@ package com.ynxbd.wx.servlet;
import com.ynxbd.common.result.Result; import com.ynxbd.common.result.Result;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.config.WxEventEnum; 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.WxEventHelper;
import com.ynxbd.wx.wxfactory.utils.WxPassiveReplyHelper; import com.ynxbd.wx.wxfactory.WxPassiveReplyHelper;
import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import com.ynxbd.wx.wxfactory.utils.WxSignHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
@ -28,7 +28,7 @@ public class WxServlet extends HttpServlet {
request.setCharacterEncoding("UTF-8"); request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8");
WxEvent wxEvent = WxSignHelper.getReqXmlToBean(request, WxEvent.class); WxEvent wxEvent = WxSignHelper.reqXmlToBean(request, WxEvent.class);
if (wxEvent == null) { if (wxEvent == null) {
String echoStr = request.getParameter("echostr"); String echoStr = request.getParameter("echostr");
if (echoStr != null) { if (echoStr != null) {

@ -6,7 +6,7 @@ import com.ynxbd.common.result.Result;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import com.ynxbd.common.service.RecipeService; import com.ynxbd.common.service.RecipeService;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 com.ynxbd.wx.wxfactory.utils.WxRespHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC; import org.slf4j.MDC;

@ -4,27 +4,24 @@ import com.ynxbd.common.bean.enums.MerchantEnum;
import com.ynxbd.common.dao.RecipeDao; import com.ynxbd.common.dao.RecipeDao;
import com.ynxbd.common.helper.common.CodeHelper; import com.ynxbd.common.helper.common.CodeHelper;
import com.ynxbd.common.helper.common.HttpHelper; import com.ynxbd.common.helper.common.HttpHelper;
import com.ynxbd.common.helper.common.JsonHelper;
import com.ynxbd.common.service.RecipeService; import com.ynxbd.common.service.RecipeService;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.WxPayHelper; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.MDC; import org.slf4j.MDC;
import weixin.popular.util.SignatureUtil;
import weixin.popular.util.XMLConverUtil;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet; import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
/** /**
@ -47,40 +44,54 @@ public class QRPayServlet extends HttpServlet {
log.info("[Native]扫码支付收到支付请求,开始解析..."); 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 // 解析xml成map
Map<String, String> map = XMLConverUtil.convertToMap(sb.toString()); Map<String, Object> 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))) { if (!WxSignHelper.validateSign(map, WeChatConfig.MCH_KEY)) { // 验证未通过,通知支付失败
log.info("收到扫码支付请求:签名无效!"); log.info("[Native]收到扫码支付请求:签名无效!");
HttpHelper.outRespAlert(response, "收到扫码支付请求:签名无效!"); HttpHelper.outRespAlert(response, "收到扫码支付请求:签名无效!");
return; 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 openid = notifyInfo.getOpenid();
String product_id = map.get("product_id"); String productId = notifyInfo.getProductId();
log.info("[Native]扫码支付 收到请求:product_id={}, openid={}", product_id, openid); log.info("[Native]扫码支付 收到请求:product_id={}, openid={}", productId, openid);
if (!product_id.contains("XBD")) { if (!"XBD".equals(productId)) {
log.info("[Native]扫码支付 不合规则的字符串,不允许支付!product_id={}", product_id); log.info("[Native]扫码支付 不合规则的字符串,不允许支付!product_id={}", productId);
HttpHelper.outRespAlert(response, "扫码支付:不合规则的字符串,不允许支付!"); HttpHelper.outRespAlert(response, "扫码支付:不合规则的字符串,不允许支付!");
return; 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) { if (params.length < 5) {
log.info("[Native]扫码支付 体检缴费参数少于5个,不允许支付!product_id={}", product_id); log.info("[Native]扫码支付 体检缴费参数少于5个,不允许支付!product_id={}", productId);
HttpHelper.outRespAlert(response, "扫码支付:参数少于5个"); HttpHelper.outRespAlert(response, "扫码支付:参数少于5个");
return; return;
} }
@ -94,14 +105,14 @@ public class QRPayServlet extends HttpServlet {
log.info("[Native]扫码支付 patientId={} treatNum={}, recipeId={}, payMoney={}, flag={}", patientId, treatNum, recipeId, payMoney, flag); log.info("[Native]扫码支付 patientId={} treatNum={}, recipeId={}, payMoney={}, flag={}", patientId, treatNum, recipeId, payMoney, flag);
if (ObjectUtils.isEmpty(patientId) || ObjectUtils.isEmpty(treatNum) || ObjectUtils.isEmpty(payMoney)) { 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, "扫码支付:参数中有空值,不允许支付!"); HttpHelper.outRespAlert(response, "扫码支付:参数中有空值,不允许支付!");
return; return;
} }
// 是否重复支付 // 是否重复支付
if (new RecipeDao().hasHisPaidByPatient(patientId, treatNum, recipeId)) { if (new RecipeDao().hasHisPaidByPatient(patientId, treatNum, recipeId)) {
log.info("[Native]扫码支付 已缴费成功,无需再次支付!product_id={}", product_id); log.info("[Native]扫码支付 已缴费成功,无需再次支付!product_id={}", productId);
HttpHelper.outRespAlert(response, "已缴费成功,无需支付!"); HttpHelper.outRespAlert(response, "已缴费成功,无需支付!");
return; 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()); WxNativePayResult nativeOrder = WxPayHelper.createNativeOrder("old_pay_notify_servlet", title, new BigDecimal(payMoney), outTradeNo, "PEIS", request.getRemoteAddr());
if (nativeOrder == null) { if (nativeOrder == null) {
log.info("[Native]扫码支付 下单失败 product_id={}", product_id); log.info("[Native]扫码支付 下单失败 product_id={}", productId);
HttpHelper.outRespAlert(response, "已缴费成功,无需支付!"); HttpHelper.outRespAlert(response, "已缴费成功,无需支付!");
return; return;
} }
boolean isOk = new RecipeService().addOldPEISOrder(outTradeNo, payMoney, openid, patientId, treatNum, recipeId); boolean isOk = new RecipeService().addOldPEISOrder(outTradeNo, payMoney, openid, patientId, treatNum, recipeId);
if (!isOk) { if (!isOk) {
log.info("[Native]扫码支付 存储数据失败 product_id={}", product_id); log.info("[Native]扫码支付 存储数据失败 product_id={}", productId);
} }
String nativeReplyXML = WxPayHelper.toNativeReplyXML(nativeOrder.getPrepayId()); String nativeReplyXML = WxPayHelper.toNativeReplyXML(nativeOrder.getPrepayId());

@ -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<String, String> map = XMLConverUtil.convertToMap(sb.toString());
// 过滤空 设置 TreeMap
// SortedMap<Object, Object> 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);
}
}

@ -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);
}
}

@ -10,8 +10,7 @@
//import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
//import org.ehcache.Cache; //import org.ehcache.Cache;
//import org.slf4j.MDC; //import org.slf4j.MDC;
//import weixin.popular.api.SnsAPI;
//import weixin.popular.bean.sns.SnsToken;
// //
//import javax.servlet.ServletException; //import javax.servlet.ServletException;
//import javax.servlet.annotation.WebServlet; //import javax.servlet.annotation.WebServlet;

@ -7,7 +7,7 @@
//import com.ynxbd.common.result.ServiceException; //import com.ynxbd.common.result.ServiceException;
//import com.ynxbd.common.service.OutCollectService; //import com.ynxbd.common.service.OutCollectService;
//import com.ynxbd.wx.wxfactory.WxPayHelper; //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 com.ynxbd.wx.wxfactory.utils.WxRespHelper;
//import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
//import org.slf4j.MDC; //import org.slf4j.MDC;

@ -7,37 +7,37 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class WxOrderTest { public class WxOrderTest {
public static void main(String[] args) { // public static void main(String[] args) {
String orders = ""; // String orders = "";
//
String states = ""; // String states = "";
//
String[] outTradeNoList = orders.split("\n"); // String[] outTradeNoList = orders.split("\n");
//
String[] stateList = states.split("\n"); // String[] stateList = states.split("\n");
//
System.out.println("订单数量=" + outTradeNoList.length + ", 状态数量=" + stateList.length); // System.out.println("订单数量=" + outTradeNoList.length + ", 状态数量=" + stateList.length);
List<String> errList = new ArrayList<>(); // List<String> errList = new ArrayList<>();
List<Recipe> select; // List<Recipe> select;
for (int i = 0; i < outTradeNoList.length; i++) { // for (int i = 0; i < outTradeNoList.length; i++) {
String outTradeNo = outTradeNoList[i].substring(1); // String outTradeNo = outTradeNoList[i].substring(1);
System.out.println("【" + i + "】" + outTradeNo); // System.out.println("【" + i + "】" + outTradeNo);
select = DataBase.select("select * from pay where outTradeNo = ?", Recipe.class, ps -> { // select = DataBase.select("select * from pay where outTradeNo = ?", Recipe.class, ps -> {
ps.setString(1, outTradeNo); // ps.setString(1, outTradeNo);
}); // });
//
String state = stateList[i]; // String state = stateList[i];
for (Recipe recipe : select) { // for (Recipe recipe : select) {
if (recipe.getHisStatus() == -1 && !"OK".equals(recipe.getRefundResult()) && state.equals("买家已支付")) { // 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()); // 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()); // errList.add("outTradeNo=" + outTradeNo + ",状态=" + state + ",payMoney=" + recipe.getPayMoney() + ",tradeNo=" + recipe.getTradeNo() + ",RefundResult=" + recipe.getRefundResult() + ",患者id=" + recipe.getPatientId() + ",门诊号=" + recipe.getTreatNum());
} // }
} // }
} // }
//
for (String str : errList) { // for (String str : errList) {
System.out.println(str); // System.out.println(str);
} // }
// System.out.println(refundList); //// System.out.println(refundList);
} // }
} }

@ -7,7 +7,7 @@
//import com.ynxbd.common.result.ServiceException; //import com.ynxbd.common.result.ServiceException;
//import com.ynxbd.common.service.*; //import com.ynxbd.common.service.*;
//import com.ynxbd.wx.wxfactory.WxPayHelper; //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 com.ynxbd.wx.wxfactory.utils.WxRespHelper;
//import lombok.extern.slf4j.Slf4j; //import lombok.extern.slf4j.Slf4j;
//import org.slf4j.MDC; //import org.slf4j.MDC;

@ -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);
// }
//
//}

@ -30,7 +30,7 @@ public class AesWxHelper extends AesHelper {
public static void main(String[] args) { public static void main(String[] args) {
// System.out.println(encode("397631")); // System.out.println(encode("397631"));
System.out.println(encode("847149")); System.out.println(encode("847149"));
System.out.println(decode("5ED36B8AF24847FBFFA6350642E38DBA")); System.out.println(decode("E6835E243069406F53EC8464898B37C0"));
// System.out.println(decode("FC0E7CBB32E595E2C84D44CE8B79E5325FA2C20E1090E9E5A5D7FBEA974023EB")); // System.out.println(decode("FC0E7CBB32E595E2C84D44CE8B79E5325FA2C20E1090E9E5A5D7FBEA974023EB"));
// System.out.println(encode("533103198603294034")); // System.out.println(encode("533103198603294034"));
// System.out.println(decode("EF6115C81C9EA8FF79E21180FEC20294")); // System.out.println(decode("EF6115C81C9EA8FF79E21180FEC20294"));

@ -1,284 +1,284 @@
package com.ynxbd.wx.wxfactory; package com.ynxbd.wx.wxfactory;
import com.ynxbd.common.bean.Patient; import com.ynxbd.common.bean.Patient;
import com.ynxbd.common.bean.User; import com.ynxbd.common.bean.User;
import com.ynxbd.common.helper.common.*; import com.ynxbd.common.helper.common.*;
import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.common.helper.http.OkHttpHelper;
import com.ynxbd.common.result.Result; import com.ynxbd.common.result.Result;
import com.ynxbd.common.service.PatientService; import com.ynxbd.common.service.PatientService;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.bean.SnsOath2AccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.AuthData;
import com.ynxbd.wx.wxfactory.bean.SnsUserInfo; import com.ynxbd.wx.wxfactory.base.auth.models.SnsOath2AccessToken;
import com.ynxbd.wx.wxfactory.bean.auth.AuthData; import com.ynxbd.wx.wxfactory.base.auth.models.SnsUserInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import okhttp3.FormBody; import okhttp3.FormBody;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.ehcache.Cache; import org.ehcache.Cache;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
public class WxAuthHelper { public class WxAuthHelper {
private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60; // session最大存活时间 1H private static final int SESSION_MAX_INACTIVE_INTERVAL = 60 * 60; // session最大存活时间 1H
public static String auth(HttpServletRequest request, HttpServletResponse response, boolean isUserInfo) { public static String auth(HttpServletRequest request, HttpServletResponse response, boolean isUserInfo) {
String code = request.getParameter("code"); String code = request.getParameter("code");
String state = request.getParameter("state"); // base64 String state = request.getParameter("state"); // base64
String enuId = request.getParameter("enuId"); String enuId = request.getParameter("enuId");
log.info("[授权] code={}, state={}, enuId={}", code, state, enuId); log.info("[授权] code={}, state={}, enuId={}", code, state, enuId);
try { try {
state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); state = state == null ? "" : URLDecoder.decode(Base64Helper.decode(state), "UTF-8");
String enUnionId = null; String enUnionId = null;
String protocolState = null; String protocolState = null;
if (!ObjectUtils.isEmpty(enuId)) { if (!ObjectUtils.isEmpty(enuId)) {
int index = enuId.indexOf("@protocolState="); int index = enuId.indexOf("@protocolState=");
if (index == -1) index = enuId.indexOf("%40protocolState="); // 防止数据转义失败 if (index == -1) index = enuId.indexOf("%40protocolState="); // 防止数据转义失败
if (index != -1) { if (index != -1) {
enUnionId = enuId.substring(0, index); enUnionId = enuId.substring(0, index);
protocolState = enuId.substring(index); protocolState = enuId.substring(index);
} }
} }
log.info("[授权-解码] enUnionId={}, protocolState={}, state={}", enUnionId, protocolState, state); log.info("[授权-解码] enUnionId={}, protocolState={}, state={}", enUnionId, protocolState, state);
SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); SnsOath2AccessToken snsToken = WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code);
if (snsToken != null) { if (snsToken != null) {
String openid = snsToken.getOpenid(); String openid = snsToken.getOpenid();
String unionId = snsToken.getUnionid(); String unionId = snsToken.getUnionid();
if (unionId == null) { if (unionId == null) {
log.info("[测试] enUnionId={}", enUnionId); log.info("[测试] enUnionId={}", enUnionId);
} }
if (openid != null) { if (openid != null) {
HttpSession session = request.getSession(); HttpSession session = request.getSession();
session.setMaxInactiveInterval(SESSION_MAX_INACTIVE_INTERVAL); session.setMaxInactiveInterval(SESSION_MAX_INACTIVE_INTERVAL);
session.setAttribute("openid", openid); session.setAttribute("openid", openid);
Cache<String, User> cache = WxCacheHelper.getUserCacheManager(); Cache<String, User> cache = WxCacheHelper.getUserCacheManager();
if (WeChatConfig.isDevUser(openid) || !cache.containsKey(openid)) { if (WeChatConfig.isDevUser(openid) || !cache.containsKey(openid)) {
User user = new User(); User user = new User();
user.setUnionId(unionId); user.setUnionId(unionId);
user.setOpenid(openid); user.setOpenid(openid);
user.setIsSnapShotUser(snsToken.getIsSnapShotUser()); user.setIsSnapShotUser(snsToken.getIsSnapShotUser());
user.setPatientList(new PatientService().queryPatientList(openid, unionId, true)); user.setPatientList(new PatientService().queryPatientList(openid, unionId, true));
if (isUserInfo) { if (isUserInfo) {
SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3);
if (snsUser != null) { if (snsUser != null) {
user.setCountry(snsUser.getCountry()); user.setCountry(snsUser.getCountry());
user.setAvatar(snsUser.getHeadImgUrl()); user.setAvatar(snsUser.getHeadImgUrl());
user.setNickName(snsUser.getNickname_emoji()); user.setNickName(snsUser.getNickname_emoji());
user.setProvince(snsUser.getProvince()); user.setProvince(snsUser.getProvince());
user.setGenderByInt(snsUser.getSex()); user.setGenderByInt(snsUser.getSex());
user.setCity(snsUser.getCity()); user.setCity(snsUser.getCity());
user.setLanguage(snsUser.getLanguage()); user.setLanguage(snsUser.getLanguage());
} }
} }
cache.put(openid, user); cache.put(openid, user);
} else { } else {
if (isUserInfo) { if (isUserInfo) {
User user = cache.get(openid); User user = cache.get(openid);
if (user != null && user.getAvatar() == null && user.getNickName() == null) { if (user != null && user.getAvatar() == null && user.getNickName() == null) {
SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3); SnsUserInfo snsUser = WxFactory.Base.OAuth().snsUserInfo(snsToken.getAccessToken(), openid, "zh_CN", 3);
if (snsUser != null) { if (snsUser != null) {
user.setAvatar(snsUser.getHeadImgUrl()); user.setAvatar(snsUser.getHeadImgUrl());
user.setNickName(snsUser.getNickname_emoji()); user.setNickName(snsUser.getNickname_emoji());
user.setGenderByInt(snsUser.getSex()); user.setGenderByInt(snsUser.getSex());
} }
} }
} }
} }
} }
} }
if (WeChatConfig.HAS_HTTPS_BY_BASE_URL) { // 强制为https if (WeChatConfig.HAS_HTTPS_BY_BASE_URL) { // 强制为https
String httpsURL = URLHelper.URLToHttps(state); String httpsURL = URLHelper.URLToHttps(state);
state = httpsURL == null ? "" : httpsURL; state = httpsURL == null ? "" : httpsURL;
} }
if (state.contains(".html")) { // 网页授权配置 if (state.contains(".html")) { // 网页授权配置
return state; return state;
} else { } else {
String baseUrl = WeChatConfig.getBaseURL(); String baseUrl = WeChatConfig.getBaseURL();
if (baseUrl != null && state.contains(baseUrl)) { if (baseUrl != null && state.contains(baseUrl)) {
return state; return state;
} }
} }
} catch (Exception e) { } catch (Exception e) {
log.error("[微信][获取重定向链接异常]{}", e.getMessage()); log.error("[微信][获取重定向链接异常]{}", e.getMessage());
} }
return null; return null;
} }
public static Result isAuth(HttpServletRequest request, boolean isPayOAuth) throws Exception { public static Result isAuth(HttpServletRequest request, boolean isPayOAuth) throws Exception {
String token = request.getParameter("token"); // 前端缓存 String token = request.getParameter("token"); // 前端缓存
String state = request.getParameter("state"); String state = request.getParameter("state");
String isUserInfo = request.getParameter("isUserInfo"); String isUserInfo = request.getParameter("isUserInfo");
String protocolState = request.getParameter("protocolState"); String protocolState = request.getParameter("protocolState");
String enuId = ParamHelper.filterParamNull(request.getParameter("enuId"), ""); String enuId = ParamHelper.filterParamNull(request.getParameter("enuId"), "");
String deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8"); String deState = URLDecoder.decode(Base64Helper.decode(state), "UTF-8");
if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权 if (WeChatConfig.IS_ENABLE_GMC && !WeChatConfig.IS_GMC_SERVER && !isPayOAuth) { // 开启医共体开关 & 不是医共体主服务器 & 不是支付授权
try { // 请求转发 try { // 请求转发
String serverDomain = WeChatConfig.getDomain(false, false); String serverDomain = WeChatConfig.getDomain(false, false);
if (deState != null && serverDomain != null && !deState.contains(serverDomain)) { if (deState != null && serverDomain != null && !deState.contains(serverDomain)) {
return Result.error("授权域名不匹配"); return Result.error("授权域名不匹配");
} }
RequestBody requestBody = new FormBody.Builder() RequestBody requestBody = new FormBody.Builder()
.add("token", token) .add("token", token)
.add("state", state) .add("state", state)
.add("isUserInfo", isUserInfo) .add("isUserInfo", isUserInfo)
.add("enuId", enuId) .add("enuId", enuId)
.add("protocolState", protocolState) .add("protocolState", protocolState)
.build(); .build();
log.info("[认证请求转发] URL:[{}]", WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true)); log.info("[认证请求转发] URL:[{}]", WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true));
String data = OkHttpHelper.post(WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true) + "wx_auth/is_auth", requestBody); String data = OkHttpHelper.post(WeChatConfig.getGMCAuthDomain(isHttpsWithProxy(request), true) + "wx_auth/is_auth", requestBody);
return Result.dataToResult(data, true); return Result.dataToResult(data, true);
} catch (Exception e) { } catch (Exception e) {
return Result.error(e); return Result.error(e);
} }
} }
boolean isFindUserInfo = ("true".equals(isUserInfo)); boolean isFindUserInfo = ("true".equals(isUserInfo));
AuthData authData = new AuthData(); AuthData authData = new AuthData();
String cacheOpenid = authData.decodeToken(token, WeChatConfig.APP_ID); String cacheOpenid = authData.decodeToken(token, WeChatConfig.APP_ID);
if (cacheOpenid != null) { if (cacheOpenid != null) {
log.info("[微信token认证] token={}, openid={}", token, cacheOpenid); log.info("[微信token认证] token={}, openid={}", token, cacheOpenid);
User user = WxCacheHelper.getCacheUser(cacheOpenid); User user = WxCacheHelper.getCacheUser(cacheOpenid);
List<Patient> patients; List<Patient> patients;
if (user == null) { if (user == null) {
patients = new PatientService().queryPatientList(cacheOpenid, null, true); patients = new PatientService().queryPatientList(cacheOpenid, null, true);
Cache<String, User> cache = WxCacheHelper.getUserCacheManager(); Cache<String, User> cache = WxCacheHelper.getUserCacheManager();
User addCache = new User(); User addCache = new User();
addCache.setOpenid(cacheOpenid); addCache.setOpenid(cacheOpenid);
addCache.setUnionId(authData.getUnionId()); addCache.setUnionId(authData.getUnionId());
addCache.setAvatar(authData.getAvatar()); addCache.setAvatar(authData.getAvatar());
addCache.setNickName(authData.getNickName()); addCache.setNickName(authData.getNickName());
addCache.setPatientList(patients); addCache.setPatientList(patients);
cache.put(cacheOpenid, addCache); cache.put(cacheOpenid, addCache);
} else { } else {
patients = user.getPatientList(); patients = user.getPatientList();
} }
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("openid", cacheOpenid); map.put("openid", cacheOpenid);
map.put("token", token); map.put("token", token);
map.put("enOpenId", AesWxHelper.encode(cacheOpenid, true)); map.put("enOpenId", AesWxHelper.encode(cacheOpenid, true));
map.put("enUnionId", AesWxHelper.encode(authData.getUnionId(), true)); map.put("enUnionId", AesWxHelper.encode(authData.getUnionId(), true));
map.put("date", new Date()); map.put("date", new Date());
map.put("avatar", authData.getAvatar()); map.put("avatar", authData.getAvatar());
map.put("nickName", authData.getNickName()); map.put("nickName", authData.getNickName());
map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(patients), "UTF-8"))); map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(patients), "UTF-8")));
map.put("enParams", AesMicroHelper.encode(cacheOpenid)); map.put("enParams", AesMicroHelper.encode(cacheOpenid));
return Result.success(map); return Result.success(map);
} }
HttpSession session = request.getSession(); HttpSession session = request.getSession();
Object openid = session.getAttribute("openid"); Object openid = session.getAttribute("openid");
if (openid != null) { if (openid != null) {
log.info("[微信认证]openid={}", openid); log.info("[微信认证]openid={}", openid);
User user = WxCacheHelper.getCacheUser((String) openid); User user = WxCacheHelper.getCacheUser((String) openid);
if (user == null) { if (user == null) {
return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState));
} }
if (isFindUserInfo) { // 更换授权模式,需更新信息 if (isFindUserInfo) { // 更换授权模式,需更新信息
if (user.getNickName() == null || user.getAvatar() == null) { if (user.getNickName() == null || user.getAvatar() == null) {
return Result.success(getAuthUrl(request, state, true, enuId, protocolState)); return Result.success(getAuthUrl(request, state, true, enuId, protocolState));
} }
} }
Map<String, Object> map = new HashMap<>(); Map<String, Object> map = new HashMap<>();
map.put("openid", openid); map.put("openid", openid);
map.put("token", new AuthData().createToken(WeChatConfig.APP_ID, openid.toString(), user.getUnionId(), user.getAvatar(), user.getNickName())); 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("enOpenId", AesWxHelper.encode(openid.toString(), true));
map.put("enUnionId", AesWxHelper.encode(user.getUnionId(), true)); map.put("enUnionId", AesWxHelper.encode(user.getUnionId(), true));
map.put("date", new Date()); map.put("date", new Date());
map.put("avatar", user.getAvatar()); map.put("avatar", user.getAvatar());
map.put("nickName", user.getNickName()); map.put("nickName", user.getNickName());
map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(user.getPatientList()), "UTF-8"))); map.put("patients", CodeHelper.get28UUID() + Base64Helper.encode(URLEncoder.encode(JsonHelper.toJsonString(user.getPatientList()), "UTF-8")));
map.put("enParams", AesMicroHelper.encode(openid.toString())); map.put("enParams", AesMicroHelper.encode(openid.toString()));
return Result.success(map); return Result.success(map);
} }
return Result.success(getAuthUrl(request, state, isFindUserInfo, enuId, protocolState)); 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 final String OAUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + WeChatConfig.APP_ID + "&redirect_uri=";
private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String enuId, String protocolState) { private static String getAuthUrl(HttpServletRequest request, String state, boolean isFindUserInfo, String enuId, String protocolState) {
// StringBuffer url = request.getRequestURL(); // StringBuffer url = request.getRequestURL();
// String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString(); // String baseUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).append(request.getServletContext().getContextPath()).append("/").toString();
if (state == null) { if (state == null) {
return null; return null;
} }
String api = isFindUserInfo ? "u_auth" : "b_auth"; String api = isFindUserInfo ? "u_auth" : "b_auth";
String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base"; String scope = isFindUserInfo ? "snsapi_userinfo" : "snsapi_base";
state = OAUTH_URL + WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)) + state = OAUTH_URL + WeChatConfig.getBaseURL(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)) +
"wx_auth/" + api + "wx_auth/" + api +
"?state=" + state + "?state=" + state +
"&response_type=code" + "&response_type=code" +
"&scope=" + scope + "&forcePopup=true" + "&scope=" + scope + "&forcePopup=true" +
"&enuId=" + (enuId == null ? "" : enuId) + "&enuId=" + (enuId == null ? "" : enuId) +
(protocolState == null ? "" : ("%40protocolState=" + protocolState)) + (protocolState == null ? "" : ("%40protocolState=" + protocolState)) +
"#wechat_redirect"; "#wechat_redirect";
return Base64Helper.encode(state); return Base64Helper.encode(state);
} }
// 是否为https请求 // 是否为https请求
public static boolean isHttpsWithProxy(HttpServletRequest request) { public static boolean isHttpsWithProxy(HttpServletRequest request) {
// 优先检查代理头(适用于反向代理场景) // 优先检查代理头(适用于反向代理场景)
String forwardedProto = request.getHeader("X-Forwarded-Proto"); String forwardedProto = request.getHeader("X-Forwarded-Proto");
if (forwardedProto != null) { if (forwardedProto != null) {
return "https".equalsIgnoreCase(forwardedProto); return "https".equalsIgnoreCase(forwardedProto);
} }
// 未经过代理,直接检查原生请求 // 未经过代理,直接检查原生请求
return request.isSecure(); return request.isSecure();
} }
// // 医共体开启 & 不是支付授权 // // 医共体开启 & 不是支付授权
// private static boolean isAuthGMC(boolean isPayOAuth) { // private static boolean isAuthGMC(boolean isPayOAuth) {
// return WeChatConfig.IS_ENABLE_GMC && !isPayOAuth; // return WeChatConfig.IS_ENABLE_GMC && !isPayOAuth;
// } // }
// private static String getOAuthURL(HttpServletRequest request, boolean isPayOAuth) { // private static String getOAuthURL(HttpServletRequest request, boolean isPayOAuth) {
// boolean isHttps = WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request); // boolean isHttps = WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request);
// return isAuthGMC(isPayOAuth) // 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.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); // : "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) { // private static SnsOath2AccessToken getOath2AccessToken(String code, boolean isPayOAuth) {
// if (isAuthGMC(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.GMC_AUTH_APP_ID, WeChatConfig.GMC_AUTH_APP_SECRET, code);
// } // }
// return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code); // return WxFactory.Base.OAuth().oauth2AccessToken(WeChatConfig.APP_ID, WeChatConfig.APP_SECRET, code);
// } // }
// // 获取重定向链接 // // 获取重定向链接
// private static String getAuthDomain(HttpServletRequest request, boolean isPayOAuth) { // private static String getAuthDomain(HttpServletRequest request, boolean isPayOAuth) {
// if (isAuthGMC(isPayOAuth)) { // if (isAuthGMC(isPayOAuth)) {
// return WeChatConfig.getGMCAuthDomain(true, false); // 强制为https // 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;] // return WeChatConfig.getDomain(WeChatConfig.HAS_HTTPS_BY_BASE_URL || isHttpsWithProxy(request)); // 配置中baseURL有"https"时优先级最高 ["@protocol=1"为https;"@protocol=0"为默认的http;]
// } // }
} }

@ -2,8 +2,8 @@ package com.ynxbd.wx.wxfactory;
import com.ynxbd.common.bean.User; import com.ynxbd.common.bean.User;
import com.ynxbd.common.config.EhCacheConfig; import com.ynxbd.common.config.EhCacheConfig;
import com.ynxbd.wx.wxfactory.bean.AccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.AccessToken;
import com.ynxbd.wx.wxfactory.bean.JsapiTicket; import com.ynxbd.wx.wxfactory.base.auth.models.JsapiTicket;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.ehcache.Cache; import org.ehcache.Cache;

@ -1,6 +1,7 @@
package com.ynxbd.wx.wxfactory; package com.ynxbd.wx.wxfactory;
import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.JsonResult;
import com.ynxbd.wx.wxfactory.payment.refund.Client;
import lombok.*; import lombok.*;
import java.io.Serializable; import java.io.Serializable;
@ -16,9 +17,14 @@ public class WxFactory {
return new com.ynxbd.wx.wxfactory.base.auth.Client(); return new com.ynxbd.wx.wxfactory.base.auth.Client();
} }
public static com.ynxbd.wx.wxfactory.base.refund.Client Refund() { public static Client Refund() {
return new com.ynxbd.wx.wxfactory.base.refund.Client(); 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 { // public static class Payment {

@ -6,11 +6,14 @@ import com.ynxbd.common.helper.common.*;
import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ResultEnum;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import com.ynxbd.wx.config.WeChatConfig; 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.RespAccessToken;
import com.ynxbd.wx.wxfactory.base.auth.models.RespJsapiTicket; 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.WxMedConfig;
import com.ynxbd.wx.wxfactory.medical.enums.MdRefundTypeEnum; 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 com.ynxbd.wx.wxfactory.utils.WxSignHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
@ -25,7 +28,6 @@ import java.util.Map;
public class WxMedHelper { public class WxMedHelper {
private static final RepeatKeyHelper KEYS = new RepeatKeyHelper(60); private static final RepeatKeyHelper KEYS = new RepeatKeyHelper(60);
/** /**
* [医保]获取用户信息 * [医保]获取用户信息
* *
@ -72,7 +74,7 @@ public class WxMedHelper {
public static MedicalNotify paidMedNotify(HttpServletRequest request) throws ServiceException { public static MedicalNotify paidMedNotify(HttpServletRequest request) throws ServiceException {
try { try {
// 转换数据对象 // 转换数据对象
Map<String, Object> paramsMap = WxSignHelper.getReqXmlParamsMap(request); Map<String, Object> paramsMap = WxSignHelper.reqXmlParamsMap(request);
if (paramsMap == null) { if (paramsMap == null) {
throw new ServiceException("[医保]回调通知下单信息返回错误"); throw new ServiceException("[医保]回调通知下单信息返回错误");
} }
@ -82,7 +84,6 @@ public class WxMedHelper {
throw new ServiceException("[医保]回调通知签名验证未通过!"); throw new ServiceException("[医保]回调通知签名验证未通过!");
} }
String json = JsonHelper.toJsonString(paramsMap); String json = JsonHelper.toJsonString(paramsMap);
if (ObjectUtils.isEmpty(json)) { if (ObjectUtils.isEmpty(json)) {
throw new ServiceException("[医保]回调通知下单信息为空"); 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( return WxFactory.Medical.Common().queryRefund(
WxCacheHelper.getAccessToken(), WxCacheHelper.getAccessToken(),
WxMedConfig.MD_APP_ID, WxMedConfig.MD_APP_ID,

@ -9,10 +9,10 @@ import com.ynxbd.common.helper.common.*;
import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ResultEnum;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.bean.WxNativePayResult; import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxNativePayResult;
import com.ynxbd.wx.wxfactory.bean.WxPayNotify; import com.ynxbd.wx.wxfactory.payment.jsapi.models.WxPayNotify;
import com.ynxbd.wx.wxfactory.bean.refund.WxRefundItem; import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundItem;
import com.ynxbd.wx.wxfactory.bean.refund.WxRefundQueryRoot; import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundQueryRoot;
import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import com.ynxbd.wx.wxfactory.utils.WxSignHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
@ -79,7 +79,7 @@ public class WxPayHelper {
public static WxPayNotify payNotify(HttpServletRequest request) throws ServiceException { public static WxPayNotify payNotify(HttpServletRequest request) throws ServiceException {
try { try {
// 转换数据对象 // 转换数据对象
Map<String, Object> paramsMap = WxSignHelper.getReqXmlParamsMap(request); Map<String, Object> paramsMap = WxSignHelper.reqXmlParamsMap(request);
log.info("【微信回调】map={}", paramsMap); log.info("【微信回调】map={}", paramsMap);
if (paramsMap == null) { if (paramsMap == null) {
throw new ServiceException("【微信】回调通知下单信息返回错误"); throw new ServiceException("【微信】回调通知下单信息返回错误");
@ -91,7 +91,7 @@ public class WxPayHelper {
} }
String json = JsonHelper.toJsonString(paramsMap); String json = JsonHelper.toJsonString(paramsMap);
if ("".equals(json)) { if (ObjectUtils.isEmpty(json)) {
throw new ServiceException("【微信】回调通知下单信息为空"); throw new ServiceException("【微信】回调通知下单信息为空");
} }

@ -5,11 +5,11 @@ import com.ynxbd.common.helper.http.OkHttpHelper;
import com.ynxbd.wx.wxfactory.WxCacheHelper; import com.ynxbd.wx.wxfactory.WxCacheHelper;
import com.ynxbd.wx.wxfactory.base.auth.models.RespAccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.RespAccessToken;
import com.ynxbd.wx.wxfactory.base.auth.models.RespJsapiTicket; import com.ynxbd.wx.wxfactory.base.auth.models.RespJsapiTicket;
import com.ynxbd.wx.wxfactory.bean.SnsOath2AccessToken; import com.ynxbd.wx.wxfactory.base.auth.models.SnsOath2AccessToken;
import com.ynxbd.wx.wxfactory.bean.SnsUserInfo; import com.ynxbd.wx.wxfactory.base.auth.models.SnsUserInfo;
import com.ynxbd.wx.wxfactory.utils.EmojiHelper;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import weixin.popular.util.EmojiUtil;
@Slf4j @Slf4j
@NoArgsConstructor @NoArgsConstructor
@ -105,7 +105,7 @@ public class Client {
} }
if (emoji != 0 && response.getNickname() != null) { if (emoji != 0 && response.getNickname() != null) {
response.setNickname_emoji(EmojiUtil.parse(response.getNickname(), emoji)); response.setNickname_emoji(EmojiHelper.parse(response.getNickname(), emoji));
} }
return response; return response;
} }

@ -1,20 +1,20 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.base.auth.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.io.Serializable; import java.io.Serializable;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class AccessToken implements Serializable { public class AccessToken implements Serializable {
private static final long serialVersionUID = 36888886677781604L; private static final long serialVersionUID = 36888886677781604L;
private String accessToken; private String accessToken;
// 创建时间 // 创建时间
private String createTime; private String createTime;
} }

@ -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.DateHelper;
import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.common.JsonHelper;

@ -1,4 +1,4 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.base.auth.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

@ -1,6 +1,5 @@
package com.ynxbd.wx.wxfactory.base.auth.models; package com.ynxbd.wx.wxfactory.base.auth.models;
import com.ynxbd.wx.wxfactory.bean.WxBaseResult;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;

@ -1,28 +1,28 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.base.auth.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class SnsOath2AccessToken extends WxBaseResult { public class SnsOath2AccessToken extends WxBaseResult {
private String accessToken; private String accessToken;
private Integer expiresIn; private Integer expiresIn;
private String refreshToken; private String refreshToken;
private String openid; private String openid;
private String scope; private String scope;
private String unionid; private String unionid;
// 是否为快照页模式虚拟账号,只有当用户是快照页模式虚拟账号是返回,值为1 // 是否为快照页模式虚拟账号,只有当用户是快照页模式虚拟账号是返回,值为1
private String isSnapShotUser; private String isSnapShotUser;
public Boolean getIsSnapShotUser() { public Boolean getIsSnapShotUser() {
if (isSnapShotUser == null) { if (isSnapShotUser == null) {
return null; return null;
} }
return "1".equals(isSnapShotUser); return "1".equals(isSnapShotUser);
} }
} }

@ -1,33 +1,33 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.base.auth.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.io.Serializable; import java.io.Serializable;
@Getter @Getter
@Setter @Setter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class SnsUserInfo extends WxBaseResult implements Serializable { public class SnsUserInfo extends WxBaseResult implements Serializable {
private static final long serialVersionUID = 20221025231300001L; private static final long serialVersionUID = 20221025231300001L;
private Integer subscribe; private Integer subscribe;
private String openid; private String openid;
private String nickname; private String nickname;
private String nickname_emoji; private String nickname_emoji;
private Integer sex; private Integer sex;
private String language; private String language;
private String city; private String city;
private String province; private String province;
private String country; private String country;
private String headImgUrl; private String headImgUrl;
private Integer subscribe_time; private Integer subscribe_time;
private String unionid; private String unionid;
private Integer groupid; private Integer groupid;
private String remark; private String remark;
private String subscribe_scene; private String subscribe_scene;
private Integer qr_scene; private Integer qr_scene;
private String qr_scene_str; private String qr_scene_str;
} }

@ -1,20 +1,20 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.base.auth.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter @Setter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class WxBaseResult { public class WxBaseResult {
private final String SUCCESS_CODE = "0"; private final String SUCCESS_CODE = "0";
private String errCode; private String errCode;
private String errMsg; private String errMsg;
public boolean isSuccess() { public boolean isSuccess() {
return this.errCode == null || this.errCode.isEmpty() || SUCCESS_CODE.equals(this.errCode); return this.errCode == null || this.errCode.isEmpty() || SUCCESS_CODE.equals(this.errCode);
} }
} }

@ -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<XMLNewsMsg.Article> 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);
}
}

@ -1,32 +1,32 @@
package com.ynxbd.wx.wxfactory.bean.event; package com.ynxbd.wx.wxfactory.base.passivemsg.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter @Setter
@NoArgsConstructor @NoArgsConstructor
@ToString @ToString
public class WxEvent { public class WxEvent {
private String toUserName; private String toUserName;
private String fromUserName; private String fromUserName;
private Integer createTime; private Integer createTime;
private String msgType; private String msgType;
private String event; private String event;
private String eventKey; private String eventKey;
private String content; private String content;
private String url; private String url;
private String msgId; private String msgId;
} }

@ -1,134 +1,129 @@
package com.ynxbd.wx.wxfactory.bean.event; package com.ynxbd.wx.wxfactory.base.passivemsg.event;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import org.w3c.dom.Element;
import weixin.popular.bean.message.AroundBeacon;
import weixin.popular.bean.message.ChosenBeacon; @Getter
import weixin.popular.bean.message.CopyrightCheckResult; @Setter
@NoArgsConstructor
import java.util.List; @ToString
public class WxEventMessage {
@Getter
@Setter private String toUserName;
@NoArgsConstructor
@ToString private String fromUserName;
public class WxEventMessage {
private Integer createTime;
private String toUserName;
private String msgType;
private String fromUserName;
private String event;
private Integer createTime;
private String eventKey;
private String msgType;
private String msgId;
private String event;
private String content;
private String eventKey;
private String picUrl;
private String msgId;
private String mediaId;
private String content;
private String format;
private String picUrl;
private String recognition;
private String mediaId;
private String thumbMediaId;
private String format;
private String location_X;
private String recognition;
private String location_Y;
private String thumbMediaId;
private String scale;
private String location_X;
private String label;
private String location_Y;
private String title;
private String scale;
private String description;
private String label;
private String url;
private String title;
private String ticket;
private String description;
private String latitude;
private String url;
private String longitude;
private String ticket;
private String precision;
private String latitude;
private String status;
private String longitude;
private Integer totalCount;
private String precision;
private Integer filterCount;
private String status;
private Integer sentCount;
private Integer totalCount;
private Integer errorCount;
private Integer filterCount;
private Integer sentCount; private Integer expiredTime;
private Integer errorCount; private Integer failTime;
private String failReason;
private Integer expiredTime;
private String uniqId;
private Integer failTime;
private String poiId;
private String failReason;
private String result;
private String uniqId;
private String msg;
private String poiId;
private String lotteryId;
private String result;
private Integer money;
private String msg;
private Integer bindTime;
private String lotteryId;
private Integer connectTime;
private Integer money;
private Integer expireTime;
private Integer bindTime;
private String vendorId;
private Integer connectTime;
private String shopId;
private Integer expireTime;
private String deviceNo;
private String vendorId;
private String keyStandard;
private String shopId;
private String keyStr;
private String deviceNo;
private String country;
private String keyStandard;
private String province;
private String keyStr;
private String city;
private String country;
private Integer sex;
private String province;
private Integer scene;
private String city;
private String regionCode;
private Integer sex;
private Integer reasonMsg;
private Integer scene;
// private ChosenBeacon chosenBeacon;
private String regionCode; //
// private CopyrightCheckResult copyrightCheckResult;
private Integer reasonMsg; //
// private List<AroundBeacon> aroundBeacons;
private ChosenBeacon chosenBeacon; //
// private List<Element> otherElements;
private CopyrightCheckResult copyrightCheckResult; }
private List<AroundBeacon> aroundBeacons;
private List<Element> otherElements;
}

@ -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("<xml>");
sb.append("<ToUserName><![CDATA[").append(this.toUserName).append("]]></ToUserName>");
sb.append("<FromUserName><![CDATA[").append(this.fromUserName).append("]]></FromUserName>");
sb.append("<CreateTime>").append(System.currentTimeMillis() / 1000L).append("</CreateTime>");
sb.append("<MsgType><![CDATA[").append(this.msgType).append("]]></MsgType>");
String subXml = this.subXMLContent();
if (subXml != null) {
sb.append(subXml);
}
sb.append("</xml>");
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;
}
}
}

@ -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 "<Image><MediaId><![CDATA[" + this.mediaId + "]]></MediaId></Image>";
}
}

@ -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<XMLNewsMsg.Article> articles;
public XMLNewsMsg(String toUserName, String fromUserName, List<XMLNewsMsg.Article> 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("<ArticleCount>").append(this.articles.size()).append("</ArticleCount>");
sb.append("<Articles>");
for (XMLNewsMsg.Article item : this.articles) {
sb.append("<item>");
sb.append("<Title><![CDATA[").append(item.title == null ? "" : item.title).append("]]></Title>");
sb.append("<Description><![CDATA[").append(item.description == null ? "" : item.description).append("]]></Description>");
sb.append("<PicUrl><![CDATA[").append(item.picUrl == null ? "" : item.picUrl).append("]]></PicUrl>");
sb.append("<Url><![CDATA[").append(item.url == null ? "" : item.url).append("]]></Url>");
sb.append("</item>");
}
sb.append("</Articles>");
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;
}
}
}

@ -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 "<Content><![CDATA[" + this.content + "]]></Content>";
}
@Override
public String subXMLContent() {
return "<Content><![CDATA[" + this.content + "]]></Content>";
}
}

@ -7,8 +7,9 @@ import com.ynxbd.common.helper.common.ErrorHelper;
import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.common.helper.common.JsonHelper;
import com.ynxbd.common.helper.http.OkHttpHelper; import com.ynxbd.common.helper.http.OkHttpHelper;
import com.ynxbd.common.result.JsonResult; 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.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.WxRequestHelper;
import com.ynxbd.wx.wxfactory.utils.WxSignHelper; import com.ynxbd.wx.wxfactory.utils.WxSignHelper;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

@ -1,65 +1,67 @@
package com.ynxbd.wx.wxfactory.utils; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.common.result.ResultEnum; import com.ynxbd.common.result.ResultEnum;
import com.ynxbd.common.result.ServiceException; import com.ynxbd.common.result.ServiceException;
import lombok.extern.slf4j.Slf4j; import com.ynxbd.wx.wxfactory.utils.WxSignHelper;
import com.ynxbd.wx.wxfactory.utils.XmlHelper;
import java.util.HashMap; import lombok.extern.slf4j.Slf4j;
import java.util.Map;
import java.util.UUID; import java.util.HashMap;
import java.util.Map;
// 医保回调 import java.util.UUID;
@Slf4j
public class MdRespHelper { // 医保回调
/** @Slf4j
* 失败响应 public class MedRespHelper {
*/ /**
public static String resp(ServiceException e, String mdPayKey) { * 失败响应
if (ResultEnum.PAY_NOTIFY_REPEAT.equals(e.getResultEnum())) { // 重复通知 */
return respOk(mdPayKey); public static String resp(ServiceException e, String mdPayKey) {
} if (ResultEnum.PAY_NOTIFY_REPEAT.equals(e.getResultEnum())) { // 重复通知
return respFail(e.getMessage(), mdPayKey); return respOk(mdPayKey);
} }
return respFail(e.getMessage(), mdPayKey);
/** }
* 成功响应
*/ /**
public static String respOk(String mdPayKey) { * 成功响应
log.info("[医保]回调通知成功"); */
try { public static String respOk(String mdPayKey) {
Map<String, Object> map = new HashMap<>(); log.info("[医保]回调通知成功");
map.put("return_code", "SUCCESS"); try {
map.put("result_code", "SUCCESS"); Map<String, Object> map = new HashMap<>();
map.put("return_msg", "OK"); map.put("return_code", "SUCCESS");
map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); map.put("result_code", "SUCCESS");
map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); map.put("return_msg", "OK");
return XmlHelper.mapToXml(map); map.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
} catch (Exception e) { map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey));
e.printStackTrace(); return XmlHelper.mapToXml(map);
} } catch (Exception e) {
return null; e.printStackTrace();
} }
return null;
}
/**
* 成功响应
*/ /**
public static String respFail(String message, String mdPayKey) { * 成功响应
log.info("[医保]回调通知:{}", message); */
if (message == null) { public static String respFail(String message, String mdPayKey) {
message = "FAIL"; log.info("[医保]回调通知:{}", message);
} if (message == null) {
try { message = "FAIL";
Map<String, Object> map = new HashMap<>(); }
map.put("return_code", "FAIL"); try {
map.put("result_code", "FAIL"); Map<String, Object> map = new HashMap<>();
map.put("return_msg", message); map.put("return_code", "FAIL");
map.put("nonce_str", UUID.randomUUID().toString().replace("-", "")); map.put("result_code", "FAIL");
map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey)); map.put("return_msg", message);
return XmlHelper.mapToXml(map); map.put("nonce_str", UUID.randomUUID().toString().replace("-", ""));
} catch (Exception e) { map.put("sign", WxSignHelper.generateSign(map, WxSignHelper.SIGN_TYPE_MD5, mdPayKey));
e.printStackTrace(); return XmlHelper.mapToXml(map);
} } catch (Exception e) {
return null; e.printStackTrace();
} }
} return null;
}
}

@ -1,4 +1,4 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.WxFactory;
import lombok.Getter; import lombok.Getter;
@ -17,11 +17,11 @@ import lombok.ToString;
@Getter @Getter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class MedicalBill extends WxFactory.ResponseCheck.ResultBase{ public class MedicalBill extends WxFactory.ResponseCheck.ResultBase {
// 账单下载链接 // 账单下载链接
private String downloadUrl; private String downloadUrl;
// 校验码值 // 校验码值
private String checksumValue; private String checksumValue;
// 校验算法 // 校验算法
private String checksumType; private String checksumType;

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

@ -1,74 +1,74 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.math.BigDecimal; import java.math.BigDecimal;
// 医保回调通知 // 医保回调通知
@Setter @Setter
@Getter @Getter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class MedicalNotify { public class MedicalNotify {
private String sign; private String sign;
private String openid; private String openid;
private String medTransId; private String medTransId;
private String hospOutTradeNo; private String hospOutTradeNo;
// 总金额(分) // 总金额(分)
private BigDecimal totalFee; private BigDecimal totalFee;
// 支付现金(分) // 支付现金(分)
private BigDecimal cashFee; private BigDecimal cashFee;
// 医保-个人账户(分) // 医保-个人账户(分)
private BigDecimal insuranceFee; private BigDecimal insuranceFee;
// //
private String serialNo; private String serialNo;
// //
private String info; private String info;
private String timeEnd; private String timeEnd;
private String cashOrderId; private String cashOrderId;
// 类型标识 // 类型标识
private String attach; private String attach;
// 分 // 分
private BigDecimal insurance_self_fee; private BigDecimal insurance_self_fee;
private BigDecimal insurance_fund_fee; private BigDecimal insurance_fund_fee;
private BigDecimal insurance_other_fee; private BigDecimal insurance_other_fee;
private String payDate; private String payDate;
private String payTime; private String payTime;
// "<return_code><![CDATA[SUCCESS]]></return_code>\n" + // "<return_code><![CDATA[SUCCESS]]></return_code>\n" +
// "<return_msg><![CDATA[SUCCESS]]></return_msg>\n" + // "<return_msg><![CDATA[SUCCESS]]></return_msg>\n" +
// "<appid><![CDATA[wxd503671f502bd89d]]></appid>\n" + // "<appid><![CDATA[wxd503671f502bd89d]]></appid>\n" +
// "<mch_id><![CDATA[1288583001]]></mch_id>\n" + // "<mch_id><![CDATA[1288583001]]></mch_id>\n" +
// "<openid><![CDATA[oeso-t5DIu2qpb0LJaKeJ06TRgzw]]></openid>\n" + // "<openid><![CDATA[oeso-t5DIu2qpb0LJaKeJ06TRgzw]]></openid>\n" +
// "<nonce_str><![CDATA[90690d6cf32c62ea]]></nonce_str>\n" + // "<nonce_str><![CDATA[90690d6cf32c62ea]]></nonce_str>\n" +
// "<med_trans_id><![CDATA[M22062955949633669]]></med_trans_id>\n" + // "<med_trans_id><![CDATA[M22062955949633669]]></med_trans_id>\n" +
// "<hosp_out_trade_no><![CDATA[WXa4820ed35506439d45d9d6d0635f]]></hosp_out_trade_no>\n" + // "<hosp_out_trade_no><![CDATA[WXa4820ed35506439d45d9d6d0635f]]></hosp_out_trade_no>\n" +
// "<result_code><![CDATA[SUCCESS]]></result_code>\n" + // "<result_code><![CDATA[SUCCESS]]></result_code>\n" +
// "<time_end><![CDATA[20220629142511]]></time_end>\n" + // "<time_end><![CDATA[20220629142511]]></time_end>\n" +
// "<pay_type>3</pay_type>\n" + // "<pay_type>3</pay_type>\n" +
// "<total_fee>597</total_fee>\n" + // "<total_fee>597</total_fee>\n" +
// "<cash_fee>297</cash_fee>\n" + // "<cash_fee>297</cash_fee>\n" +
// "<insurance_fee>300</insurance_fee>\n" + // "<insurance_fee>300</insurance_fee>\n" +
// "<response_content><![CDATA[{\"directUrl\":\"http://dzpz.ynylbz.cn/test/hicashier/#payResult?encData=c785ab466a6d13d2a3f3f84c47bcc80fef109d5bc5212327aeac8687555eef618b9b77d789eebfcfa5021cd36a43a3f17d71daabe194f29565d530567c756072091e895012e6c3dda1042eac5b08e5fb98801010896c6bc3891314aa46b230a30c59aa91f8dbaf2ae3a5d1ec700154db8f7e4381a9b72e3dee8747e6811bd8fd8c90ff1411c42fa49ff871c1370ad791dc030b4c2185a515b2902c293cd2fb4661acdbc8457f5a7cc7dd801885d1a94162b72ee49f305a260894e10c7488f3325b5fcd21afa639392afb322c68101df10489b710394321e549fde466c19d4f25d70440bd496c2ba695b798ae4e90642b\",\"feeSumamt\":5.97,\"fundPay\":0.00,\"medSetlFlag\":\"SUCC\",\"ownPayAmt\":2.97,\"psnAcctPay\":3.00,\"setlSn\":\"SET530100202206291425070000006\"}]]></response_content>\n" + // "<response_content><![CDATA[{\"directUrl\":\"http://dzpz.ynylbz.cn/test/hicashier/#payResult?encData=c785ab466a6d13d2a3f3f84c47bcc80fef109d5bc5212327aeac8687555eef618b9b77d789eebfcfa5021cd36a43a3f17d71daabe194f29565d530567c756072091e895012e6c3dda1042eac5b08e5fb98801010896c6bc3891314aa46b230a30c59aa91f8dbaf2ae3a5d1ec700154db8f7e4381a9b72e3dee8747e6811bd8fd8c90ff1411c42fa49ff871c1370ad791dc030b4c2185a515b2902c293cd2fb4661acdbc8457f5a7cc7dd801885d1a94162b72ee49f305a260894e10c7488f3325b5fcd21afa639392afb322c68101df10489b710394321e549fde466c19d4f25d70440bd496c2ba695b798ae4e90642b\",\"feeSumamt\":5.97,\"fundPay\":0.00,\"medSetlFlag\":\"SUCC\",\"ownPayAmt\":2.97,\"psnAcctPay\":3.00,\"setlSn\":\"SET530100202206291425070000006\"}]]></response_content>\n" +
// "<medical_card_id><![CDATA[]]></medical_card_id>\n" + // "<medical_card_id><![CDATA[]]></medical_card_id>\n" +
// "<serial_no><![CDATA[WXa4820ed35506439d45d9d6d0635f]]></serial_no>\n" + // "<serial_no><![CDATA[WXa4820ed35506439d45d9d6d0635f]]></serial_no>\n" +
// "<attach><![CDATA[recipe=1]]></attach>\n" + // "<attach><![CDATA[recipe=1]]></attach>\n" +
// "<cash_order_id><![CDATA[C22062955949633669]]></cash_order_id>\n" + // "<cash_order_id><![CDATA[C22062955949633669]]></cash_order_id>\n" +
// "<insurance_order_id><![CDATA[I22062955949633669]]></insurance_order_id>\n" + // "<insurance_order_id><![CDATA[I22062955949633669]]></insurance_order_id>\n" +
// "<sign><![CDATA[1FA8E91777A02ADDDCE2AB02D96B20A3]]></sign>\n" + // "<sign><![CDATA[1FA8E91777A02ADDDCE2AB02D96B20A3]]></sign>\n" +
// "<insurance_self_fee>300</insurance_self_fee>\n" + // "<insurance_self_fee>300</insurance_self_fee>\n" +
// "<insurance_fund_fee>0</insurance_fund_fee>\n" + // "<insurance_fund_fee>0</insurance_fund_fee>\n" +
// "<insurance_other_fee>0</insurance_other_fee>\n" + // "<insurance_other_fee>0</insurance_other_fee>\n" +
} }

@ -1,20 +1,20 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.WxFactory;
import lombok.*; import lombok.*;
// 医保下单返回 // 医保下单返回
@Getter @Getter
@Setter @Setter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class MedicalPayOrder extends WxFactory.ResponseCheck.ResultBase { public class MedicalPayOrder extends WxFactory.ResponseCheck.ResultBase {
// 诊疗单id 微信生成的医疗订单id,用于后续调用接口使用 // 诊疗单id 微信生成的医疗订单id,用于后续调用接口使用
private String medTransId; private String medTransId;
// 支付链接 下单后跳转到此url,用户完成支付,使用app支付时1.5 APP支付说明 // 支付链接 下单后跳转到此url,用户完成支付,使用app支付时1.5 APP支付说明
private String payUrl; private String payUrl;
// 支付小程序 当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付 // 支付小程序 当使用医院小程序进行下单时,会返回此参数,医院小程序跳转至该支付小程序进行支付
private String payAppId; private String payAppId;
} }

@ -1,21 +1,21 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.WxFactory;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Setter @Setter
@Getter @Getter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class MedicalRefund extends WxFactory.ResponseCheck.ResultBase { public class MedicalRefund extends WxFactory.ResponseCheck.ResultBase {
private String totalFee; private String totalFee;
private String cashRefundFee; private String cashRefundFee;
private String insuranceRefundFee; private String insuranceRefundFee;
private String medRefundId; private String medRefundId;
private String cashRefundId; private String cashRefundId;
private String insuranceRefundId; private String insuranceRefundId;
private String sign; private String sign;
} }

@ -1,30 +1,30 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.WxFactory;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Setter @Setter
@Getter @Getter
@ToString(callSuper = true) @ToString(callSuper = true)
@NoArgsConstructor @NoArgsConstructor
public class MedicalRefundInfo extends WxFactory.ResponseCheck.ResultBase { public class MedicalRefundInfo extends WxFactory.ResponseCheck.ResultBase {
private String appid; private String appid;
private String mchId; private String mchId;
private String nonce_str; private String nonce_str;
private String med_trans_id; private String med_trans_id;
private String med_refund_id; private String med_refund_id;
private String hosp_out_trade_no; private String hosp_out_trade_no;
private String hosp_out_refund_no; private String hosp_out_refund_no;
private String insurance_refund_fee; private String insurance_refund_fee;
private String cash_refund_fee; private String cash_refund_fee;
private String cash_refund_stauts; private String cash_refund_stauts;
private String insurance_refund_status; private String insurance_refund_status;
private String med_refund_state; private String med_refund_state;
private String refund_end_time; private String refund_end_time;
private String response_content; private String response_content;
private String cash_refund_id; private String cash_refund_id;
private String insurance_refund_id; private String insurance_refund_id;
} }

@ -1,28 +1,28 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class MedicalUserInfo { public class MedicalUserInfo {
// 姓名 // 姓名
private String userName; private String userName;
// 授权码 // 授权码
private String payAuthNo; private String payAuthNo;
// 坐标 // 坐标
private String longitude; private String longitude;
private String latitude; private String latitude;
private String cardNo; private String cardNo;
private boolean success; private boolean success;
private String message; private String message;
} }

@ -1,4 +1,4 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.medical.models;
import com.ynxbd.wx.wxfactory.WxFactory; import com.ynxbd.wx.wxfactory.WxFactory;
import lombok.Getter; import lombok.Getter;

@ -1,151 +1,90 @@
package com.ynxbd.wx.wxfactory.menu.bean; package com.ynxbd.wx.wxfactory.menu.bean;
public class WxMsgConst { public class WxMsgConst {
public static final String XML_MSG_TEXT = "text"; // public static final String XML_MSG_TEXT = "text";
public static final String XML_MSG_IMAGE = "image"; // public static final String XML_MSG_IMAGE = "image";
public static final String XML_MSG_VOICE = "voice"; // public static final String XML_MSG_VOICE = "voice";
public static final String XML_MSG_VIDEO = "video"; // public static final String XML_MSG_VIDEO = "video";
public static final String XML_MSG_NEWS = "news"; // public static final String XML_MSG_NEWS = "news";
public static final String XML_MSG_MUSIC = "music"; // public static final String XML_MSG_MUSIC = "music";
public static final String XML_MSG_LOCATION = "location"; // public static final String XML_MSG_LOCATION = "location";
public static final String XML_MSG_LINK = "link"; // public static final String XML_MSG_LINK = "link";
public static final String XML_MSG_EVENT = "event"; // public static final String XML_MSG_EVENT = "event";
public static final String XML_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service"; // 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_TEXT = "text";
public static final String CUSTOM_MSG_IMAGE = "image"; // public static final String CUSTOM_MSG_IMAGE = "image";
public static final String CUSTOM_MSG_VOICE = "voice"; // public static final String CUSTOM_MSG_VOICE = "voice";
public static final String CUSTOM_MSG_VIDEO = "video"; // public static final String CUSTOM_MSG_VIDEO = "video";
public static final String CUSTOM_MSG_MUSIC = "music"; // public static final String CUSTOM_MSG_MUSIC = "music";
public static final String CUSTOM_MSG_NEWS = "news"; // public static final String CUSTOM_MSG_NEWS = "news";
public static final String CUSTOM_MSG_FILE = "file"; // 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_TRANSFER_CUSTOMER_SERVICE = "transfer_customer_service";
public static final String CUSTOM_MSG_SAFE_NO = "0"; // public static final String CUSTOM_MSG_SAFE_NO = "0";
public static final String CUSTOM_MSG_SAFE_YES = "1"; // public static final String CUSTOM_MSG_SAFE_YES = "1";
public static final String MASS_MSG_MPNEWS = "mpnews"; // public static final String MASS_MSG_MPNEWS = "mpnews";
public static final String MASS_MSG_NEWS = "news"; // public static final String MASS_MSG_NEWS = "news";
public static final String MASS_MSG_TEXT = "text"; // public static final String MASS_MSG_TEXT = "text";
public static final String MASS_MSG_VOICE = "voice"; // public static final String MASS_MSG_VOICE = "voice";
public static final String MASS_MSG_IMAGE = "image"; // public static final String MASS_MSG_IMAGE = "image";
public static final String MASS_MSG_MPVIDEO = "mpvideo"; // public static final String MASS_MSG_MPVIDEO = "mpvideo";
public static final String MASS_MSG_VIDEO = "video"; // public static final String MASS_MSG_VIDEO = "video";
public static final String MASS_MSG_MUSIC = "music"; // public static final String MASS_MSG_MUSIC = "music";
public static final String EVT_SUBSCRIBE = "subscribe"; // public static final String EVT_SUBSCRIBE = "subscribe";
public static final String EVT_UNSUBSCRIBE = "unsubscribe"; // public static final String EVT_UNSUBSCRIBE = "unsubscribe";
public static final String EVT_SCAN = "SCAN"; // public static final String EVT_SCAN = "SCAN";
public static final String EVT_LOCATION = "LOCATION"; // public static final String EVT_LOCATION = "LOCATION";
public static final String EVT_CLICK = "CLICK"; // public static final String EVT_CLICK = "CLICK";
public static final String EVT_VIEW = "VIEW"; // public static final String EVT_VIEW = "VIEW";
public static final String EVT_MASS_SEND_JOB_FINISH = "MASSSENDJOBFINISH"; // 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_PUSH = "scancode_push";
public static final String EVT_SCANCODE_WAITMSG = "scancode_waitmsg"; // public static final String EVT_SCANCODE_WAITMSG = "scancode_waitmsg";
public static final String EVT_PIC_SYSPHOTO = "pic_sysphoto"; // 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_PHOTO_OR_ALBUM = "pic_photo_or_album";
public static final String EVT_PIC_WEIXIN = "pic_weixin"; // public static final String EVT_PIC_WEIXIN = "pic_weixin";
public static final String EVT_LOCATION_SELECT = "location_select"; // public static final String EVT_LOCATION_SELECT = "location_select";
public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH"; // public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH";
public static final String EVT_ENTER_AGENT = "enter_agent"; // 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_SUCCESS = "qualification_verify_success";
public static final String EVT_QUALIFICATION_VERIFY_FAIL = "qualification_verify_fail"; // 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_SUCCESS = "naming_verify_success";
public static final String EVT_NAMING_VERIFY_FAIL = "naming_verify_fail"; // 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_ANNUAL_RENEW = "annual_renew";
public static final String EVT_VERIFY_EXPIRED = "verify_expired"; // public static final String EVT_VERIFY_EXPIRED = "verify_expired";
public static final String MEDIA_IMAGE = "image"; // public static final String MEDIA_IMAGE = "image";
public static final String MEDIA_VOICE = "voice"; // public static final String MEDIA_VOICE = "voice";
public static final String MEDIA_VIDEO = "video"; // public static final String MEDIA_VIDEO = "video";
public static final String MEDIA_THUMB = "thumb"; // public static final String MEDIA_THUMB = "thumb";
public static final String MEDIA_FILE = "file"; // public static final String MEDIA_FILE = "file";
public static final String FILE_JPG = "jpeg"; // public static final String FILE_JPG = "jpeg";
public static final String FILE_MP3 = "mp3"; // public static final String FILE_MP3 = "mp3";
public static final String FILE_AMR = "amr"; // public static final String FILE_AMR = "amr";
public static final String FILE_MP4 = "mp4"; // public static final String FILE_MP4 = "mp4";
public static final String MENU_BUTTON_CLICK = "click"; public static final String MENU_BUTTON_CLICK = "click";
public static final String MENU_BUTTON_VIEW = "view"; public static final String MENU_BUTTON_VIEW = "view";
public static final String MENU_SCANCODE_PUSH = "scancode_push"; // public static final String MENU_SCANCODE_PUSH = "scancode_push";
public static final String MENU_SCANCODE_WAITMSG = "scancode_waitmsg"; // public static final String MENU_SCANCODE_WAITMSG = "scancode_waitmsg";
public static final String MENU_PIC_SYSPHOTO = "pic_sysphoto"; // 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_PHOTO_OR_ALBUM = "pic_photo_or_album";
public static final String MENU_PIC_WEIXIN = "pic_weixin"; // public static final String MENU_PIC_WEIXIN = "pic_weixin";
public static final String MENU_LOCATION_SELECT = "location_select"; // public static final String MENU_LOCATION_SELECT = "location_select";
public static final String MENU_MEDIA_ID = "media_id"; // public static final String MENU_MEDIA_ID = "media_id";
public static final String MENU_VIEW_LIMITED = "view_limited"; // 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_SCENE = "QR_LIMIT_SCENE";
public static final String QR_CODE_LIMIT_STR_SCENE = "QR_LIMIT_STR_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_BASE = "snsapi_base";
public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo"; // public static final String OAUTH2_SCOPE_USER_INFO = "snsapi_userinfo";
public static final String LANG_CHINA = "zh_CN"; // public static final String LANG_CHINA = "zh_CN";
public static final String LANG_CHINA_TAIWAN = "zh_TW"; // public static final String LANG_CHINA_TAIWAN = "zh_TW";
public static final String LANG_ENGLISH = "en"; // public static final String LANG_ENGLISH = "en";
public static final String MATERIAL_NEWS = "news"; // public static final String MATERIAL_NEWS = "news";
public static final String MATERIAL_VOICE = "voice"; // public static final String MATERIAL_VOICE = "voice";
public static final String MATERIAL_IMAGE = "image"; // public static final String MATERIAL_IMAGE = "image";
public static final String MATERIAL_VIDEO = "video"; // public static final String MATERIAL_VIDEO = "video";
public static final String SEND_ALL_NEWS = "mpnews"; // public static final String SEND_ALL_NEWS = "mpnews";
public static final String SEND_ALL_TEXT = "text"; // public static final String SEND_ALL_TEXT = "text";
public static final String SEND_ALL_VOICE = "voice"; // public static final String SEND_ALL_VOICE = "voice";
public static final String SEND_ALL_IMAGE = "image"; // public static final String SEND_ALL_IMAGE = "image";
public static final String SEND_ALL_VIDEO = "mpvideo"; // 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";
} }

@ -1,6 +1,5 @@
package com.ynxbd.wx.wxfactory.menu.bean; package com.ynxbd.wx.wxfactory.menu.bean;
import com.qq.weixin.mp.aes.AesException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@ -11,7 +10,7 @@ import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader; import java.io.StringReader;
public class XMLParse { public class XMLParse {
public static Object[] extract(String xmltext) throws Exception { public Object[] extract(String xmltext) throws Exception {
Object[] result = new Object[3]; Object[] result = new Object[3];
try { 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 = "<xml>\n<Encrypt><![CDATA[%1$s]]></Encrypt>\n<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n<TimeStamp>%3$s</TimeStamp>\n<Nonce><![CDATA[%4$s]]></Nonce>\n</xml>"; String format = "<xml>\n<Encrypt><![CDATA[%1$s]]></Encrypt>\n<MsgSignature><![CDATA[%2$s]]></MsgSignature>\n<TimeStamp>%3$s</TimeStamp>\n<Nonce><![CDATA[%4$s]]></Nonce>\n</xml>";
return String.format(format, encrypt, signature, timestamp, nonce); return String.format(format, encrypt, signature, timestamp, nonce);
} }

@ -11,6 +11,9 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
/**
* 就医助手
*/
@Slf4j @Slf4j
@NoArgsConstructor @NoArgsConstructor
public class MdClient { public class MdClient {

@ -1,4 +1,4 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.payment;
import lombok.ToString; import lombok.ToString;

@ -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> T fromJson(String json, Class<T> 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方法请使用全大写表述 GETPOSTPUTDELETE
* @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<String, Object> params) {
if (params == null || params.isEmpty()) {
return "";
}
StringBuilder result = new StringBuilder();
for (Entry<String, Object> 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<String, String> 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");
}
}

@ -1,188 +1,239 @@
//package com.ynxbd.wx.wxfactory.payment.jsapi; package com.ynxbd.wx.wxfactory.payment.jsapi;
//
//import com.ynxbd.common.helper.common.ErrorHelper; import com.google.gson.annotations.SerializedName;
//import com.ynxbd.common.helper.common.JsonHelper; import com.ynxbd.wx.wxfactory.payment.WXPayUtility;
//import com.ynxbd.common.result.JsonResult; import lombok.extern.slf4j.Slf4j;
//import com.ynxbd.wx.wxfactory.bean.MedicalPayOrder; import okhttp3.*;
//import com.ynxbd.wx.wxfactory.utils.WxRequestHelper;
//import lombok.extern.slf4j.Slf4j; import java.io.IOException;
// import java.io.UncheckedIOException;
//import java.math.BigDecimal; import java.security.PrivateKey;
//import java.util.HashMap; import java.security.PublicKey;
//import java.util.Map; import java.util.ArrayList;
// import java.util.List;
//@Slf4j
//public class Client { /**
// * JSAPI下单
// /** */
// * 微信JSAPI下单
// *
// * @param appId 应用ID @Slf4j
// * @param mchId 直连商户号 public class Client {
// * @param description 商品描述 private static String HOST = "https://api.mch.weixin.qq.com";
// * @param out_trade_no 商户订单号 private static String METHOD = "POST";
// * @param time_expire 交易结束时间(yyyy-MM-DDTHH:mm:ss+TIMEZONE 示例值:2018-06-08T10:34:56+08:00) private static String PATH = "/v3/pay/transactions/jsapi";
// * @param notify_url 通知地址
// * @param totalFee 订单金额(元)
// * @param openid openid // JsapiPrepay client = new JsapiPrepay(
// * @param attach 附加数据 // "19xxxxxxxx", // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
// */ // "1DDE55AD98Exxxxxxxxxx", // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
// public MedicalPayOrder createOrder(String appId, String mchId, String description, String out_trade_no, // "/path/to/apiclient_key.pem", // 商户API证书私钥文件路径,本地文件路径
// String time_expire, String attach, String notify_url, BigDecimal totalFee, // "PUB_KEY_ID_xxxxxxxxxxxxx", // 微信支付公钥ID,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
// String openid) { // "/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 { // try {
// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi", params -> { // String uri = PATH;
// params.put("appid", appId); // String reqBody = WXPayUtility.toJson(request);
// params.put("mchid", mchId); //
// params.put("description", description); // Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
// params.put("out_trade_no", out_trade_no); // reqBuilder.addHeader("Accept", "application/json");
// if (time_expire != null) { // reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
// params.put("time_expire", time_expire); // reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchId, certificateSerialNo, privateKey, METHOD, uri, reqBody));
// } // reqBuilder.addHeader("Content-Type", "application/json");
// Map<String, Object> amountMap = new HashMap<>(); // RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
// amountMap.put("total", totalFee.movePointRight(2)); // 分 // reqBuilder.method(METHOD, requestBody);
// params.put("amount", amountMap); // Request httpRequest = reqBuilder.build();
// //
// params.put("notify_url", notify_url); // // 发送HTTP请求
// params.put("openid", openid); // OkHttpClient client = new OkHttpClient.Builder().build();
// // try (Response httpResponse = client.newCall(httpRequest).execute()) {
// if (attach != null) { // String respBody = WXPayUtility.extractBody(httpResponse);
// params.put("attach", attach); // 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());
// } // }
// }); // } catch (IOException e) {
// log.info("[医保]下单返回:{}", JsonHelper.toJsonString(jsonResult)); // throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
// if (!jsonResult.success()) {
// return new MedicalPayOrder().createResult(jsonResult);
// } // }
// return jsonResult.dataMapToBean(MedicalPayOrder.class); // } catch (WXPayUtility.ApiException e) {
// } catch (Exception e) { // // TODO: 请求失败,根据状态码执行不同的逻辑
// ErrorHelper.println(e); // e.printStackTrace();
// } // }
// return null; // return null;
// } // }
// public static class DirectAPIv3JsapiPrepayRequest {
// @SerializedName("appid")
// public String appid;
// //
// @SerializedName("mchid")
// public String mchid;
// //
// /** // @SerializedName("description")
// * 查询订单 // public String description;
// *
// * @param mchId 直连商户号
// * @param outTradeNo 商品描述
// * @param transId 微信支付订单号
// */
// public MedicalPayOrder queryOrder(String mchId, String outTradeNo, String transId) {
// //
// try { // @SerializedName("out_trade_no")
// JsonResult jsonResult = null; // public String outTradeNo;
// //
// if (outTradeNo != null) { // @SerializedName("time_expire")
// jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "?" + mchId, params -> { // public String timeExpire;
// });
// //
// } else { // @SerializedName("attach")
// if (transId != null) { // public String attach;
// jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/pay/transactions/id/" + transId + "?" + mchId, params -> {
// });
// }
// }
// //
// log.info("[医保]查询订单:{}", JsonHelper.toJsonString(jsonResult)); // @SerializedName("notify_url")
// if (!jsonResult.success()) { // public String notifyUrl;
// return new MedicalPayOrder().createResult(jsonResult); //
// } // @SerializedName("goods_tag")
// return jsonResult.dataMapToBean(MedicalPayOrder.class); // public String goodsTag;
// } catch (Exception e) { //
// ErrorHelper.println(e); // @SerializedName("support_fapiao")
// } // public Boolean supportFapiao;
// return null; //
// @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;
// }
// //
// /** // public static class CommonAmountInfo {
// * 关闭订单 // @SerializedName("total")
// * // public Long total;
// * @param mchId 直连商户号
// * @param outTradeNo 商品描述
// * @param transId 微信支付订单号
// */
// public MedicalPayOrder closeOrder(String mchId, String outTradeNo, String transId) {
// //
// try { // @SerializedName("currency")
// JsonResult jsonResult = WxRequestHelper.postMdXml(" https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/" + outTradeNo + "/close", params -> { // public String currency;
// params.put("mchId", mchId); // }
// });
// //
// log.info("[医保]关闭订单返回:{}", JsonHelper.toJsonString(jsonResult)); // public static class JsapiReqPayerInfo {
// if (!jsonResult.success()) { // @SerializedName("openid")
// return new MedicalPayOrder().createResult(jsonResult); // public String openid;
// }
// return jsonResult.dataMapToBean(MedicalPayOrder.class);
// } catch (Exception e) {
// ErrorHelper.println(e);
// }
// return null;
// } // }
// //
// public static class CouponInfo {
// @SerializedName("cost_price")
// public Long costPrice;
// //
// /** // @SerializedName("invoice_id")
// * 微信JSAPI下单 // public String invoiceId;
// *
// * @param outTradeNo 商品描述
// * @param transId 微信支付订单号
// */
// public MedicalPayOrder refund(String outTradeNo, String transId, String outRefundNo, BigDecimal refundFee, BigDecimal totalFee, String reason, String notify_url) {
// //
// try { // @SerializedName("goods_detail")
// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds", params -> { // public List<GoodsDetail> goodsDetail;
// params.put("transaction_id", transId); // }
// params.put("out_trade_no", outTradeNo);
// params.put("out_refund_no", outRefundNo);
//
// Map<String, Object> 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);
// }
// //
// if (reason != null) { // public static class CommonSceneInfo {
// params.put("reason", reason); // @SerializedName("payer_client_ip")
// } // public String payerClientIp;
// }); //
// log.info("[微信]退费返回:{}", JsonHelper.toJsonString(jsonResult)); // @SerializedName("device_id")
// if (!jsonResult.success()) { // public String deviceId;
// return new MedicalPayOrder().createResult(jsonResult); //
// } // @SerializedName("store_info")
// return jsonResult.dataMapToBean(MedicalPayOrder.class); // public StoreInfo storeInfo;
// } catch (Exception e) { // }
// ErrorHelper.println(e); //
// } // public static class SettleInfo {
// return null; // @SerializedName("profit_sharing")
// public Boolean profitSharing;
// } // }
// //
// public static class GoodsDetail {
// @SerializedName("merchant_goods_id")
// public String merchantGoodsId;
// //
// /** // @SerializedName("wechatpay_goods_id")
// * 查询退费订单 // public String wechatpayGoodsId;
// *
// * @param outRefundNo 退费订单号
// */
// public MedicalPayOrder queryRefund(String outRefundNo) {
// //
// try { // @SerializedName("goods_name")
// JsonResult jsonResult = WxRequestHelper.postMdXml("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/" + outRefundNo, params -> { // public String goodsName;
// //
// }); // @SerializedName("quantity")
// log.info("[微信]查询退费订单:{}", JsonHelper.toJsonString(jsonResult)); // public Long quantity;
// if (!jsonResult.success()) { //
// return new MedicalPayOrder().createResult(jsonResult); // @SerializedName("unit_price")
// } // public Long unitPrice;
// return jsonResult.dataMapToBean(MedicalPayOrder.class); // }
// } catch (Exception e) { //
// ErrorHelper.println(e); // public static class StoreInfo {
// } // @SerializedName("id")
// return null; // public String id;
//
// @SerializedName("name")
// public String name;
//
// @SerializedName("area_code")
// public String areaCode;
//
// @SerializedName("address")
// public String address;
// } // }
//}
}

@ -1,4 +1,4 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.payment.jsapi.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;

@ -1,40 +1,41 @@
package com.ynxbd.wx.wxfactory.bean; package com.ynxbd.wx.wxfactory.payment.jsapi.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.math.BigDecimal; import java.math.BigDecimal;
@Getter @Getter
@Setter @Setter
@ToString @ToString
@NoArgsConstructor @NoArgsConstructor
public class WxPayNotify { public class WxPayNotify {
private String openid; private String openid;
private String outTradeNo; private String productId;
private String tradeType; private String outTradeNo;
private String bankType; private String tradeType;
private String timeEnd; private String bankType;
private String attach; private String timeEnd;
private String transactionId; private String attach;
private BigDecimal totalFee; private String transactionId;
// -------------------------------------- private BigDecimal totalFee;
private String feeType; // --------------------------------------
private String cashFeeType; private String feeType;
private BigDecimal cashFee; private String cashFeeType;
private BigDecimal settlementTotalFee; private BigDecimal cashFee;
private BigDecimal couponFee; private BigDecimal settlementTotalFee;
private Integer couponCount; private BigDecimal couponFee;
private String contractId; private Integer couponCount;
private String tradeState; private String contractId;
// 微信支付分配的终端设备号 private String tradeState;
private String deviceInfo; // 微信支付分配的终端设备号
private String isSubscribe; private String deviceInfo;
private String isSubscribe;
// 自定义参数-----------------------------
private String payInfo; // 自定义参数-----------------------------
private String payDate; private String payInfo;
private String payTime; private String payDate;
} private String payTime;
}

@ -1,36 +1,36 @@
package com.ynxbd.wx.wxfactory.base.refund; package com.ynxbd.wx.wxfactory.payment.refund;
import com.ynxbd.wx.wxfactory.bean.refund.WxRefundQueryRoot; import com.ynxbd.wx.wxfactory.payment.refund.models.WxRefundQueryRoot;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder; import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity; import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import weixin.popular.bean.paymch.Refundquery; import weixin.popular.bean.paymch.Refundquery;
import weixin.popular.client.LocalHttpClient; import weixin.popular.client.LocalHttpClient;
import weixin.popular.util.MapUtil; import weixin.popular.util.MapUtil;
import weixin.popular.util.SignatureUtil; import weixin.popular.util.SignatureUtil;
import weixin.popular.util.XMLConverUtil; import weixin.popular.util.XMLConverUtil;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
@NoArgsConstructor @NoArgsConstructor
public class Client { public class Client {
public WxRefundQueryRoot refundQuery(Refundquery refundquery, String mchKey) { public WxRefundQueryRoot refundQuery(Refundquery refundquery, String mchKey) {
Map<String, String> map = MapUtil.objectToMap(refundquery); Map<String, String> map = MapUtil.objectToMap(refundquery);
String sign = SignatureUtil.generateSign(map, refundquery.getSign_type(), mchKey); String sign = SignatureUtil.generateSign(map, refundquery.getSign_type(), mchKey);
refundquery.setSign(sign); refundquery.setSign(sign);
String reqXml = XMLConverUtil.convertToXML(refundquery); String reqXml = XMLConverUtil.convertToXML(refundquery);
HttpUriRequest httpUriRequest = RequestBuilder.post() 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(); .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); return LocalHttpClient.executeXmlResult(httpUriRequest, WxRefundQueryRoot.class, refundquery.getSign_type(), mchKey);
} }
} }

@ -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;
}
}

@ -1,31 +1,30 @@
package com.ynxbd.wx.wxfactory.bean.refund; package com.ynxbd.wx.wxfactory.payment.refund.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import weixin.popular.bean.paymch.Coupon;
import java.util.List;
import java.util.List;
@Getter
@Getter @Setter
@Setter @NoArgsConstructor
@NoArgsConstructor @ToString
@ToString public class WxRefundItem {
public class WxRefundItem { private String out_refund_no;
private String out_refund_no; private String refund_id;
private String refund_id; private String refund_channel;
private String refund_channel; private Integer refund_fee;
private Integer refund_fee; private Integer settlement_refund_fee;
private Integer settlement_refund_fee; private String coupon_type;
private String coupon_type; private Integer coupon_refund_fee;
private Integer coupon_refund_fee; private Integer coupon_refund_count;
private Integer coupon_refund_count; private String coupon_refund;
private String coupon_refund; private String refund_status;
private String refund_status; private String refund_recv_accout;
private String refund_recv_accout; private String refund_success_time;
private String refund_success_time; private Integer n;
private Integer n; private List<RefundCoupon> coupons;
private List<Coupon> coupons; }
}

@ -1,80 +1,79 @@
package com.ynxbd.wx.wxfactory.bean.refund; package com.ynxbd.wx.wxfactory.payment.refund.models;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import weixin.popular.bean.DynamicField; import weixin.popular.bean.DynamicField;
import weixin.popular.bean.paymch.Coupon; import weixin.popular.bean.paymch.MchBase;
import weixin.popular.bean.paymch.MchBase;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlTransient; import java.util.ArrayList;
import java.util.ArrayList; import java.util.List;
import java.util.List; import java.util.Map;
import java.util.Map;
@Getter
@Getter @Setter
@Setter @NoArgsConstructor
@NoArgsConstructor @ToString
@ToString @XmlRootElement(name = "xml")
@XmlRootElement(name = "xml") @XmlAccessorType(XmlAccessType.FIELD)
@XmlAccessorType(XmlAccessType.FIELD) public class WxRefundQueryRoot extends MchBase implements DynamicField {
public class WxRefundQueryRoot extends MchBase implements DynamicField { private String device_info;
private String device_info; private String transaction_id;
private String transaction_id; private String out_trade_no;
private String out_trade_no; private Integer total_fee;
private Integer total_fee; private Integer settlement_total_fee;
private Integer settlement_total_fee; private String fee_type;
private String fee_type; private Integer cash_fee;
private Integer cash_fee; private Integer refund_count;
private Integer refund_count; private String refund_account;
private String refund_account; private Integer total_refund_count;
private Integer total_refund_count; @XmlTransient
@XmlTransient private List<WxRefundItem> items;
private List<WxRefundItem> items;
public void buildDynamicField(Map<String, String> dataMap) {
public void buildDynamicField(Map<String, String> dataMap) { if (dataMap != null) {
if (dataMap != null) { String refund_countStr = dataMap.get("refund_count");
String refund_countStr = dataMap.get("refund_count"); if (refund_countStr != null) {
if (refund_countStr != null) { List<WxRefundItem> list = new ArrayList<>();
List<WxRefundItem> list = new ArrayList<>();
WxRefundItem item;
WxRefundItem item; List<RefundCoupon> couponList;
List<Coupon> couponList; for (int i = 0; i < Integer.parseInt(refund_countStr); ++i) {
for (int i = 0; i < Integer.parseInt(refund_countStr); ++i) { item = new WxRefundItem();
item = new WxRefundItem(); item.setOut_refund_no(dataMap.get("out_refund_no_" + i));
item.setOut_refund_no(dataMap.get("out_refund_no_" + i)); item.setRefund_id(dataMap.get("refund_id_" + i));
item.setRefund_id(dataMap.get("refund_id_" + i)); item.setRefund_channel(dataMap.get("refund_channel_" + 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.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.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_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_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_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.setCoupon_refund(dataMap.get("coupon_refund_" + i)); item.setRefund_status(dataMap.get("refund_status_" + i));
item.setRefund_status(dataMap.get("refund_status_" + i)); item.setRefund_recv_accout(dataMap.get("refund_recv_accout_" + i));
item.setRefund_recv_accout(dataMap.get("refund_recv_accout_" + i)); // 新增
// 新增 item.setRefund_success_time(dataMap.get("refund_success_time_" + i));
item.setRefund_success_time(dataMap.get("refund_success_time_" + i)); item.setN(i);
item.setN(i); if (item.getCoupon_refund_count() != null) {
if (item.getCoupon_refund_count() != null) { couponList = new ArrayList<>();
couponList = new ArrayList<>();
for (int j = 0; j < item.getCoupon_refund_count(); ++j) {
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);
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);
couponList.add(coupon); }
} item.setCoupons(couponList);
item.setCoupons(couponList); }
} list.add(item);
list.add(item); }
} this.items = list;
this.items = list; }
} }
}
}
} }
}

@ -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([^;]*);", "<span class='emoji emoji$1'></span>") : 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;
}
}
}

@ -0,0 +1,8 @@
package com.ynxbd.wx.wxfactory.utils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WechatPayHelper {
}

@ -1,58 +1,60 @@
package com.ynxbd.wx.wxfactory.utils; package com.ynxbd.wx.wxfactory.utils;
import com.ynxbd.wx.wxfactory.bean.event.WxEvent; import com.ynxbd.wx.wxfactory.base.passivemsg.event.WxEvent;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.util.Arrays; import java.util.Arrays;
@Slf4j @Slf4j
public class WxEventHelper { public class WxEventHelper {
/** private static final String TEMPLATE_SEND_JOB_FINISH = "TEMPLATESENDJOBFINISH";
* 过滤内容可以直接返回
* /**
* @param wxEvent 事件 * 过滤内容可以直接返回
*/ *
public static boolean filter(WxEvent wxEvent) { * @param wxEvent 事件
String event = wxEvent.getEvent(); */
if (event != null) { public static boolean filter(WxEvent wxEvent) {
event = event.toUpperCase(); String event = wxEvent.getEvent();
} if (event != null) {
String msgType = wxEvent.getMsgType(); event = event.toUpperCase();
if (msgType != null) { }
msgType = msgType.toUpperCase(); String msgType = wxEvent.getMsgType();
} if (msgType != null) {
if ("VIEW".equals(event) && "EVENT".equals(msgType)) { // 点击菜单 msgType = msgType.toUpperCase();
return true; }
} 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; if (TEMPLATE_SEND_JOB_FINISH.equals(event)) { // 模板发送作业完成-->直接返回success
} log.warn("[公众号]模板消息推送 fromUserName={}, msgType={}, eventKey={}, event={}", wxEvent.getFromUserName(), msgType, wxEvent.getEventKey(), event);
return false; return true;
} }
return false;
}
/**
* 消息验签
* /**
* @param request request * 消息验签
* @param wxToken wxToken *
*/ * @param request request
public static boolean verifyEventSign(HttpServletRequest request, String wxToken) { * @param wxToken wxToken
String nonce = request.getParameter("nonce"); */
String timestamp = request.getParameter("timestamp"); public static boolean verifyEventSign(HttpServletRequest request, String wxToken) {
String nonce = request.getParameter("nonce");
String[] array = new String[]{wxToken, timestamp, nonce}; String timestamp = request.getParameter("timestamp");
Arrays.sort(array);
String[] array = new String[]{wxToken, timestamp, nonce};
StringBuilder sb = new StringBuilder(); Arrays.sort(array);
for (String s : array) {
sb.append(s); StringBuilder sb = new StringBuilder();
} for (String s : array) {
return DigestUtils.sha1Hex(sb.toString()).equals(request.getParameter("signature")); sb.append(s);
} }
} return DigestUtils.sha1Hex(sb.toString()).equals(request.getParameter("signature"));
}
}

@ -1,7 +1,8 @@
package com.ynxbd.wx.wxfactory; package com.ynxbd.wx.wxfactory.utils;
import com.ynxbd.common.result.JsonResult; import com.ynxbd.common.result.JsonResult;
import com.ynxbd.wx.config.WeChatConfig; import com.ynxbd.wx.config.WeChatConfig;
import com.ynxbd.wx.wxfactory.WxCacheHelper;
import com.ynxbd.wx.wxfactory.medical.WxMedConfig; import com.ynxbd.wx.wxfactory.medical.WxMedConfig;
import com.ynxbd.wx.wxfactory.message.MdClient; import com.ynxbd.wx.wxfactory.message.MdClient;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -10,7 +11,7 @@ import lombok.extern.slf4j.Slf4j;
* 就医助手 * 就医助手
*/ */
@Slf4j @Slf4j
public class WxMessageHelper { public class WxMedAssistantHelper {
/** /**
* 就医助手授权 * 就医助手授权

@ -5,17 +5,27 @@ import com.ynxbd.common.helper.common.JsonHelper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import org.apache.commons.codec.digest.DigestUtils; 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.Mac;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.StringReader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@Slf4j @Slf4j
@ -46,7 +56,7 @@ public class WxSignHelper {
if (signType == null) { if (signType == null) {
signType = SIGN_TYPE_MD5; signType = SIGN_TYPE_MD5;
} }
log.info("[医保]签名前参数:paramsStr-{}",paramsStr + "&key=" + key); log.info("[医保]签名前参数:paramsStr-{} key-{}", paramsStr, key);
if (SIGN_TYPE_HMAC_SHA256.equalsIgnoreCase(signType)) { if (SIGN_TYPE_HMAC_SHA256.equalsIgnoreCase(signType)) {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); SecretKeySpec secret_key = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
@ -80,8 +90,8 @@ public class WxSignHelper {
* @param key 密钥 * @param key 密钥
* @return t | f * @return t | f
*/ */
public static boolean validateSign(Map<String, Object> map, String sign_type, String key) { public static boolean validateSign(Map<String, Object> map, String signType, String key) {
return map.get("sign") != null && map.get("sign").equals(generateSign(map, sign_type, 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); sb.append(buffer, 0, len);
} }
String respData = sb.toString(); String respData = sb.toString();
if ("".equals(respData)) { if (ObjectUtils.isEmpty(respData)) {
return null; return null;
} }
return respData; return respData;
@ -117,7 +127,7 @@ public class WxSignHelper {
* @param request 请求 * @param request 请求
* @return map * @return map
*/ */
public static Map<String, Object> getReqXmlParamsMap(HttpServletRequest request) { public static Map<String, Object> reqXmlParamsMap(HttpServletRequest request) {
String reqXml = getReqData(request); String reqXml = getReqData(request);
if (reqXml == null) { if (reqXml == null) {
return null; return null;
@ -131,8 +141,8 @@ public class WxSignHelper {
* @param request 请求 * @param request 请求
* @return 对象 * @return 对象
*/ */
public static <T> T getReqXmlToBean(HttpServletRequest request ,Class<T> clazz) { public static <T> T reqXmlToBean(HttpServletRequest request, Class<T> clazz) {
Map<String, Object> paramsMap = getReqXmlParamsMap(request); Map<String, Object> paramsMap = reqXmlParamsMap(request);
if (paramsMap == null) { if (paramsMap == null) {
return null; return null;
} }
@ -178,4 +188,41 @@ public class WxSignHelper {
return info.toString(); return info.toString();
} }
public static Map<String, Object> reqXmlToMapByNativePay(HttpServletRequest request) {
String xml = getReqData(request);
if (xml == null) {
return null;
}
Map<String, Object> 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;
}
} }

@ -1,7 +1,7 @@
package com.ynxbd.wx.wxfactory.utils; package com.ynxbd.wx.wxfactory.utils;
import com.alibaba.fastjson.JSON; 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 lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.dom4j.*; import org.dom4j.*;

Loading…
Cancel
Save