From 5c23b5d88d50b07f45c19a7781ed262658567512 Mon Sep 17 00:00:00 2001
From: jyx <1584081113@qq.com>
Date: Mon, 25 Feb 2019 23:51:51 +0800
Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E6=B5=8B=E8=AF=95=E5=8F=B7?=
=?UTF-8?q?=E6=8E=A5=E5=8F=A3=E9=85=8D=E7=BD=AE=EF=BC=8C=E5=85=AC=E4=BC=97?=
=?UTF-8?q?=E5=8F=B7=E8=87=AA=E5=8A=A8=E5=9B=9E=E5=A4=8D=EF=BC=8C=E5=85=B3?=
=?UTF-8?q?=E6=B3=A8/=E5=8F=96=E6=B6=88=E5=85=B3=E6=B3=A8=E5=9B=9E?=
=?UTF-8?q?=E5=A4=8D=EF=BC=8C=E8=87=AA=E5=AE=9A=E4=B9=89=E8=8F=9C=E5=8D=95?=
=?UTF-8?q?https?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
demo/pom.xml | 54 +++-
.../com/example/demo/DemoApplication.java | 3 +-
.../demo/loginService/SessionFilter.java | 3 +-
.../demo/weixin/bean/WeixinMessageInfo.java | 32 +++
.../demo/weixin/bean/menu/AccessToken.java | 11 +
.../example/demo/weixin/bean/menu/Button.java | 17 ++
.../demo/weixin/bean/menu/ClickButton.java | 17 ++
.../demo/weixin/bean/menu/ComplexButton.java | 17 ++
.../example/demo/weixin/bean/menu/Menu.java | 16 ++
.../demo/weixin/bean/menu/ViewButton.java | 17 ++
.../demo/weixin/bean/message/Article.java | 18 ++
.../demo/weixin/bean/message/Image.java | 11 +
.../demo/weixin/bean/message/Music.java | 19 ++
.../demo/weixin/bean/message/Video.java | 13 +
.../demo/weixin/bean/message/Voice.java | 11 +
.../weixin/bean/response/BaseMessage.java | 20 ++
.../weixin/bean/response/ImageMessage.java | 12 +
.../weixin/bean/response/MusicMessage.java | 11 +
.../weixin/bean/response/NewsMessage.java | 16 ++
.../weixin/bean/response/TextMessage.java | 11 +
.../weixin/bean/response/VideoMessage.java | 12 +
.../weixin/bean/response/VoiceMessage.java | 11 +
.../controller/WeixinCoreController.java | 72 +++++
.../demo/weixin/service/DataProcess.java | 14 +
.../weixin/service/WeixinCoreService.java | 8 +
.../weixin/service/WeixinCoreServiceImpl.java | 165 +++++++++++
.../weixin/service/https/HttpRequestUtil.java | 87 ++++++
.../service/https/MyX509TrustManager.java | 42 +++
.../demo/weixin/util/WeixinSignUtil.java | 70 +++++
.../weixin/util/menu/WechatCommonUtil.java | 52 ++++
.../weixin/util/menu/WechatConstants.java | 8 +
.../util/menu/WechatCreatDefaultMenu.java | 35 +++
.../util/menu/WechatMenuManagerUtil.java | 55 ++++
.../demo/weixin/util/menu/WechatMenuUtil.java | 89 ++++++
.../util/message/WeixinMessageModelUtil.java | 113 ++++++++
.../util/message/WeixinMessageUtil.java | 263 ++++++++++++++++++
36 files changed, 1417 insertions(+), 8 deletions(-)
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/WeixinMessageInfo.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/AccessToken.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/Button.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/ClickButton.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/ComplexButton.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/Menu.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/menu/ViewButton.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/message/Article.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/message/Image.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/message/Music.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/message/Video.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/message/Voice.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/BaseMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/ImageMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/MusicMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/NewsMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/TextMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/VideoMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/bean/response/VoiceMessage.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/controller/WeixinCoreController.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/service/DataProcess.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/service/WeixinCoreService.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/service/WeixinCoreServiceImpl.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/service/https/HttpRequestUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/service/https/MyX509TrustManager.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/WeixinSignUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/menu/WechatCommonUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/menu/WechatConstants.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/menu/WechatCreatDefaultMenu.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuManagerUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageModelUtil.java
create mode 100644 demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageUtil.java
diff --git a/demo/pom.xml b/demo/pom.xml
index f71e8f5..899cb2c 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -55,6 +55,40 @@
1.2.37
+
+
+ commons-beanutils
+ commons-beanutils
+ 1.9.3
+
+
+ commons-collections
+ commons-collections
+ 3.2.1
+
+
+ commons-lang
+ commons-lang
+ 2.6
+
+
+ commons-logging
+ commons-logging
+ 1.1.1
+
+
+ net.sf.ezmorph
+ ezmorph
+ 1.0.6
+
+
+ net.sf.json-lib
+ json-lib
+ 2.2.3
+ jdk15
+
+
+
@@ -89,11 +123,11 @@
true
-
-
-
-
-
+
+
+
+
+
@@ -114,6 +148,16 @@
spring-session
+
+
+
+ com.thoughtworks.xstream
+ xstream
+ 1.4.9
+
+
+
+
diff --git a/demo/src/main/java/com/example/demo/DemoApplication.java b/demo/src/main/java/com/example/demo/DemoApplication.java
index d95cf7a..c82d15a 100644
--- a/demo/src/main/java/com/example/demo/DemoApplication.java
+++ b/demo/src/main/java/com/example/demo/DemoApplication.java
@@ -2,10 +2,9 @@ package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
-@ServletComponentScan("com.example.demo")
+//@ServletComponentScan("com.example.demo")
//@MapperScan("com.example.demo.Dao")
public class DemoApplication {
public static void main(String[] args) {
diff --git a/demo/src/main/java/com/example/demo/loginService/SessionFilter.java b/demo/src/main/java/com/example/demo/loginService/SessionFilter.java
index dafd5a3..ff1ad50 100644
--- a/demo/src/main/java/com/example/demo/loginService/SessionFilter.java
+++ b/demo/src/main/java/com/example/demo/loginService/SessionFilter.java
@@ -11,7 +11,8 @@ import java.io.IOException;
@WebFilter(filterName = "sessionFilter",urlPatterns = {"/*"})
public class SessionFilter implements Filter {
String NO_LOGIN="/Login.html";
- String[] includeUrls=new String[]{"/Login.html","/Register.html","/login","/register","/userExisted.html","/userPwdError.html","/userNotExist.html","/userPwdNotSame.html"};
+ String[] includeUrls=new String[]{"/Login.html","/Register.html","/login","/register","/userExisted.html","/userPwdError.html","/userNotExist.html","/userPwdNotSame.html",
+ "/wechat","/access","/wechat/access"};
// @Override
// public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws ServletException,IOException{
// HttpServletRequest request=(HttpServletRequest) servletRequest;
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/WeixinMessageInfo.java b/demo/src/main/java/com/example/demo/weixin/bean/WeixinMessageInfo.java
new file mode 100644
index 0000000..125fdc6
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/WeixinMessageInfo.java
@@ -0,0 +1,32 @@
+package com.example.demo.weixin.bean;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.stereotype.Component;
+
+import java.io.Serializable;
+
+@Component
+@Getter
+@Setter
+public class WeixinMessageInfo implements Serializable {
+
+ //序列化版本号
+ //默认会根据对象结构自动生成。
+ //如果对象结构发生变化,序列号就会变化,导致不能正常调用。
+ //这样直接声明出来,就是一个定值了,即使构造方法发生了变化,仍然可以调用,只不过发生改动的属性会变成null
+ private static final long serialVersionUID = 1L;
+
+ private String fromUserName; //发送方微信账号
+ private String toUserName; //接收方微信账号
+ private String weixinUserName; //微信用户名
+ private String messageType; //消息类型
+
+ @Override
+ public String toString(){
+ return "WeixinMessageInfo [fromUserName=" + fromUserName
+ + ", toUserName=" + toUserName +", weixinUserName="
+ + weixinUserName + ", messageType=" + messageType + "]";
+
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/AccessToken.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/AccessToken.java
new file mode 100644
index 0000000..411d160
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/AccessToken.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.menu;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class AccessToken {
+ private String Access_token;
+ private int Expires_in;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/Button.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/Button.java
new file mode 100644
index 0000000..69faf77
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/Button.java
@@ -0,0 +1,17 @@
+package com.example.demo.weixin.bean.menu;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description: 按钮的基类(每个按钮对象都有一个共同的name属性,
+ * 因此需要定义一个按钮对象的基类,所有按钮对象都需要继承该类)
+ * @Parameters:
+ * @Return:
+*/
+
+@Setter
+@Getter
+public class Button {
+ private String name;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/ClickButton.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/ClickButton.java
new file mode 100644
index 0000000..36d6658
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/ClickButton.java
@@ -0,0 +1,17 @@
+package com.example.demo.weixin.bean.menu;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description: click类型的按钮(有type、name和key3个属性)
+ * @Parameters:
+ * @Return:
+ */
+
+@Setter
+@Getter
+public class ClickButton extends Button{
+ private String type;
+ private String key;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/ComplexButton.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/ComplexButton.java
new file mode 100644
index 0000000..84cba66
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/ComplexButton.java
@@ -0,0 +1,17 @@
+package com.example.demo.weixin.bean.menu;
+
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description: 复合类型的按钮(也就是含有子菜单的一级菜单)
+ * @Parameters:
+ * @Return:
+ */
+
+@Getter
+@Setter
+public class ComplexButton extends Button {
+ private Button[] sub_button;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/Menu.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/Menu.java
new file mode 100644
index 0000000..1ba74e0
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/Menu.java
@@ -0,0 +1,16 @@
+package com.example.demo.weixin.bean.menu;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description: 菜单
+ * @Parameters:
+ * @Return:
+ */
+
+@Setter
+@Getter
+public class Menu {
+ private Button[] button;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/menu/ViewButton.java b/demo/src/main/java/com/example/demo/weixin/bean/menu/ViewButton.java
new file mode 100644
index 0000000..029fe89
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/menu/ViewButton.java
@@ -0,0 +1,17 @@
+package com.example.demo.weixin.bean.menu;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @Description: view类型的按钮(有type、name、url三个属性)
+ * @Parameters:
+ * @Return:
+*/
+
+@Getter
+@Setter
+public class ViewButton extends Button {
+ public String type;
+ public String url;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/message/Article.java b/demo/src/main/java/com/example/demo/weixin/bean/message/Article.java
new file mode 100644
index 0000000..0b82e0b
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/message/Article.java
@@ -0,0 +1,18 @@
+package com.example.demo.weixin.bean.message;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class Article {
+ //图文消息名称
+ private String Title;
+ //图文消息描述
+ private String Description;
+ //图片链接,支持JPG、PNG格式,较好的效果为大图640像素*320像素,小图80像素*80像素
+ private String PicUrl;
+ //点击图文消息跳转链接
+ private String Url;
+
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/message/Image.java b/demo/src/main/java/com/example/demo/weixin/bean/message/Image.java
new file mode 100644
index 0000000..43a4a33
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/message/Image.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.message;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class Image {
+ //媒体文件ID
+ private String MediaId;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/message/Music.java b/demo/src/main/java/com/example/demo/weixin/bean/message/Music.java
new file mode 100644
index 0000000..0294564
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/message/Music.java
@@ -0,0 +1,19 @@
+package com.example.demo.weixin.bean.message;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class Music {
+ private String Title;
+ //音乐描述
+ private String Description;
+ //音乐链接
+ private String MusicUrl;
+ //高品质音乐链接,Wi-Fi环境优先使用该链接播放音乐
+ private String HQMusicUrl;
+ //缩略图的媒体ID,通过上传多媒体文件得到的ID
+ private String ThumbMediaId;
+
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/message/Video.java b/demo/src/main/java/com/example/demo/weixin/bean/message/Video.java
new file mode 100644
index 0000000..a100d70
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/message/Video.java
@@ -0,0 +1,13 @@
+package com.example.demo.weixin.bean.message;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class Video {
+ //媒体文件ID
+ private String MediaId;
+ //视频消息缩略图的媒体ID
+ private String ThumbMediaId;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/message/Voice.java b/demo/src/main/java/com/example/demo/weixin/bean/message/Voice.java
new file mode 100644
index 0000000..eb55ac1
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/message/Voice.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.message;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class Voice {
+ //语音消息媒体ID
+ private String mediaId;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/BaseMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/BaseMessage.java
new file mode 100644
index 0000000..e468607
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/BaseMessage.java
@@ -0,0 +1,20 @@
+package com.example.demo.weixin.bean.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+public class BaseMessage {
+ //接收方账号(收到的OpenID)
+ private String ToUserName;
+ //开发者微信号
+ private String FromUserName;
+ //消息创建时间(整型)
+ private long CreateTime;
+ //消息类型(text/music/news)
+ private String MsgType;
+ //星标刚收到的消息
+ private int FuncFlag;
+
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/ImageMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/ImageMessage.java
new file mode 100644
index 0000000..44db7ac
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/ImageMessage.java
@@ -0,0 +1,12 @@
+package com.example.demo.weixin.bean.response;
+
+
+import com.example.demo.weixin.bean.message.Image;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class ImageMessage extends BaseMessage {
+ private Image image;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/MusicMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/MusicMessage.java
new file mode 100644
index 0000000..d89e186
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/MusicMessage.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.response;
+
+import com.example.demo.weixin.bean.message.Music;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class MusicMessage extends BaseMessage {
+ private Music music;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/NewsMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/NewsMessage.java
new file mode 100644
index 0000000..57ba879
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/NewsMessage.java
@@ -0,0 +1,16 @@
+package com.example.demo.weixin.bean.response;
+
+import com.example.demo.weixin.bean.message.Article;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class NewsMessage extends BaseMessage {
+ //图文消息个数,限制为10条以内
+ private int ArticleCount;
+ //多条图文消息信息,默认第一个item为大图
+ private List Articles;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/TextMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/TextMessage.java
new file mode 100644
index 0000000..7b7da3d
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/TextMessage.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class TextMessage extends BaseMessage {
+ //回复的消息内容
+ private String Content;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/VideoMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/VideoMessage.java
new file mode 100644
index 0000000..6f60692
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/VideoMessage.java
@@ -0,0 +1,12 @@
+package com.example.demo.weixin.bean.response;
+
+import com.example.demo.weixin.bean.message.Video;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class VideoMessage extends BaseMessage {
+ private Video video;
+
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/bean/response/VoiceMessage.java b/demo/src/main/java/com/example/demo/weixin/bean/response/VoiceMessage.java
new file mode 100644
index 0000000..68b6d86
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/bean/response/VoiceMessage.java
@@ -0,0 +1,11 @@
+package com.example.demo.weixin.bean.response;
+
+import com.example.demo.weixin.bean.message.Voice;
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class VoiceMessage extends BaseMessage{
+ private Voice voice;
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/controller/WeixinCoreController.java b/demo/src/main/java/com/example/demo/weixin/controller/WeixinCoreController.java
new file mode 100644
index 0000000..6097fcf
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/controller/WeixinCoreController.java
@@ -0,0 +1,72 @@
+package com.example.demo.weixin.controller;
+
+import com.example.demo.weixin.service.DataProcess;
+import com.example.demo.weixin.service.WeixinCoreService;
+import com.example.demo.weixin.util.WeixinSignUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@RestController
+@RequestMapping(value = "/wechat")
+public class WeixinCoreController {
+
+ //控制台输出日志信息所在的类
+ private static Logger logger = LoggerFactory.getLogger(WeixinCoreController.class);
+
+ @Autowired
+ private WeixinSignUtil weixinSignUtil;
+ @Autowired
+ private DataProcess dataProcess;
+ @Autowired
+ private WeixinCoreService weixinCoreService;
+
+ @RequestMapping(value = "/access",method = RequestMethod.GET)
+ public String WeChatInterface(HttpServletRequest request)/*throws Exception*/{
+ System.out.println("-----验证微信服务号开始-----");
+ //微信加密签名
+ String signature = request.getParameter("signature");
+ //时间戳
+ String timestamp = request.getParameter("timestamp");
+ //随机数
+ String nonce = request.getParameter("nonce");
+ //随机字符串
+ String echostr = request.getParameter("echostr");
+
+ logger.info("signature is :"+signature+" timestamp is :"+timestamp+" nonce is :"+nonce);
+ if(weixinSignUtil.checkSignature(signature,timestamp,nonce)){
+ System.out.println("------验证微信服务号结束-------");
+ return echostr;
+ }else{
+
+ //此处可以实现其他逻辑
+ logger.warn("不是微信服务器的请求,小心!!");
+ return null;
+ }
+ }
+
+
+ @RequestMapping(value="/access", method=RequestMethod.POST)
+ public String getWeiXinMessage(HttpServletRequest request, HttpServletResponse response)throws Exception{
+ logger.info("----------------开始处理微信发过来的消息------------------");
+ // 微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;
+ request.setCharacterEncoding("UTF-8");
+ // 在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;
+ response.setCharacterEncoding("UTF-8");
+ String respXml = weixinCoreService.weixinMessageHandelCoreService(request, response);
+ if (dataProcess.dataIsNull(respXml)){
+ logger.error("-------------处理微信消息失败-----------------------");
+ return null;
+ }else {
+ logger.info("----------返回微信消息处理结果-----------------------:"+respXml);
+ return respXml;
+ }
+ }
+
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/service/DataProcess.java b/demo/src/main/java/com/example/demo/weixin/service/DataProcess.java
new file mode 100644
index 0000000..7afcfc0
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/service/DataProcess.java
@@ -0,0 +1,14 @@
+package com.example.demo.weixin.service;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class DataProcess {
+ public boolean dataIsNull(String respXml){
+ if(respXml.isEmpty()){
+ return true;
+ }else{
+ return false;
+ }
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreService.java b/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreService.java
new file mode 100644
index 0000000..5dab8cd
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreService.java
@@ -0,0 +1,8 @@
+package com.example.demo.weixin.service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface WeixinCoreService {
+ public abstract String weixinMessageHandelCoreService(HttpServletRequest request,HttpServletResponse response);
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreServiceImpl.java b/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreServiceImpl.java
new file mode 100644
index 0000000..7402bc2
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/service/WeixinCoreServiceImpl.java
@@ -0,0 +1,165 @@
+package com.example.demo.weixin.service;
+
+import com.example.demo.weixin.bean.WeixinMessageInfo;
+import com.example.demo.weixin.bean.response.TextMessage;
+import com.example.demo.weixin.util.message.WeixinMessageModelUtil;
+import com.example.demo.weixin.util.message.WeixinMessageUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+import java.util.Map;
+
+@Service("weixinCoreService")
+public class WeixinCoreServiceImpl implements WeixinCoreService {
+
+ private static Logger logger = LoggerFactory.getLogger(WeixinCoreServiceImpl.class);
+
+ @Autowired
+ private WeixinMessageUtil weixinMessageUtil;
+ @Autowired
+ private WeixinMessageInfo weixinMessageInfo;
+ @Autowired
+ private WeixinMessageModelUtil weixinMessageModelUtil;
+// @Autowired
+// private UserDao userDao;
+// @Autowired
+// private DataProcess dataProcess;
+
+ @Override
+ public String weixinMessageHandelCoreService(HttpServletRequest request,
+ HttpServletResponse response) {
+
+ logger.info("------------微信消息开始处理-------------");
+ // 返回给微信服务器的消息,默认为null
+
+ String respMessage = null;
+
+ try {
+
+ // 默认返回的文本消息内容
+ String respContent = null;
+ // xml分析
+ // 调用消息工具类MessageUtil解析微信发来的xml格式的消息,解析的结果放在HashMap里;
+ Map map = weixinMessageUtil.parseXml(request);
+ // 发送方账号
+ String fromUserName = map.get("FromUserName");
+ weixinMessageInfo.setFromUserName(fromUserName);
+ System.out.println("fromUserName--->"+fromUserName);
+ // 接受方账号(公众号)
+ String toUserName = map.get("ToUserName");
+ weixinMessageInfo.setToUserName(toUserName);
+ System.out.println("toUserName----->"+toUserName);
+ // 消息类型
+ String msgType = map.get("MsgType");
+ weixinMessageInfo.setMessageType(msgType);
+ logger.info("fromUserName is:" +fromUserName+" toUserName is:" +toUserName+" msgType is:" +msgType);
+
+ // 默认回复文本消息
+ TextMessage textMessage = new TextMessage();
+ textMessage.setToUserName(fromUserName);
+ textMessage.setFromUserName(toUserName);
+ textMessage.setCreateTime(new Date().getTime());
+ textMessage.setMsgType(weixinMessageUtil.RESP_MESSAGE_TYPE_TEXT);
+ textMessage.setFuncFlag(0);
+
+ // 分析用户发送的消息类型,并作出相应的处理
+
+ // 文本消息
+ if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_TEXT)){
+ respContent = "亲,这是文本消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 图片消息
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
+ respContent = "您发送的是图片消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 语音消息
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
+ respContent = "您发送的是语音消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 视频消息
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
+ respContent = "您发送的是视频消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 地理位置消息
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
+ respContent = "您发送的是地理位置消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 链接消息
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_LINK)) {
+ respContent = "您发送的是链接消息!";
+ textMessage.setContent(respContent);
+ respMessage = weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+ // 事件推送(当用户主动点击菜单,或者扫面二维码等事件)
+ else if (msgType.equals(weixinMessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
+
+ // 事件类型
+ String eventType =map.get("Event");
+ System.out.println("eventType------>"+eventType);
+ // 关注
+ if (eventType.equals(weixinMessageUtil.EVENT_TYPE_SUBSCRIBE)){
+ respMessage = weixinMessageModelUtil.followResponseMessageModel(weixinMessageInfo);
+ }
+ // 取消关注
+ else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
+ System.out.println("取消关注");
+ //weixinMessageModelUtil.cancelAttention(fromUserName);
+ }
+ // 扫描带参数二维码
+ else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_SCAN)) {
+ System.out.println("扫描带参数二维码");
+ }
+ // 上报地理位置
+ else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_LOCATION)) {
+ System.out.println("上报地理位置");
+ }
+ // 自定义菜单(点击菜单拉取消息)
+ else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_CLICK)) {
+
+ // 事件KEY值,与创建自定义菜单时指定的KEY值对应
+ String eventKey=map.get("EventKey");
+ System.out.println("eventKey------->"+eventKey);
+
+ }
+ // 自定义菜单((自定义菜单URl视图))
+ else if (eventType.equals(weixinMessageUtil.EVENT_TYPE_VIEW)) {
+ System.out.println("处理自定义菜单URI视图");
+ }
+
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ logger.error("系统出错");
+ System.err.println("系统出错");
+ respMessage = null;
+ } finally{
+ if (null == respMessage) {
+ respMessage = weixinMessageModelUtil.systemErrorResponseMessageModel(weixinMessageInfo);
+ }
+ }
+
+ return respMessage;
+ }
+
+}
\ No newline at end of file
diff --git a/demo/src/main/java/com/example/demo/weixin/service/https/HttpRequestUtil.java b/demo/src/main/java/com/example/demo/weixin/service/https/HttpRequestUtil.java
new file mode 100644
index 0000000..bc3f925
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/service/https/HttpRequestUtil.java
@@ -0,0 +1,87 @@
+package com.example.demo.weixin.service.https;
+
+import net.sf.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.URL;
+
+/**
+ *
+ * @Description: 发起https请求并获取结果
+ * @Parameters: requestUrl 请求地址。 需要写全地址,即前边的http必须写上,不能只写www.baidu.com这样的。
+ * requestMethod 请求方式(GET、POST)
+ * outputStr 我们在发起请求的时候传递参数到所要请求的服务器,
+ * 要传递的参数也要看接口文档确定格式,一般是封装成json或xml.
+ * @Return: JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
+ */
+@Component
+public class HttpRequestUtil {
+ Logger logger = LoggerFactory.getLogger(HttpRequestUtil.class);
+ public JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr){
+ //初始化一个json对象
+ JSONObject jsonObject = null;
+ try {
+ //创建SSLContext对象,并使用我们指定的信任管理器初始化
+ TrustManager[] tmManagers = {new MyX509TrustManager()};
+ SSLContext sslContext = SSLContext.getInstance("SSL","SunJSSE");
+ sslContext.init(null, tmManagers, new java.security.SecureRandom());
+ //从上述SSLContext对象中得到SSLSocketFactory对象
+ SSLSocketFactory sslSocket = sslContext.getSocketFactory();
+
+ URL url = new URL(requestUrl);
+ HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url.openConnection();
+ httpsURLConnection.setSSLSocketFactory(sslSocket);
+
+ httpsURLConnection.setDoOutput(true); /*httpUrlConnection.setDoOutput(true);以后就可以使用conn.getOutputStream().write() httpUrlConnection.setDoInput(true);以后就可以使用conn.getInputStream().read(); get请求用不到conn.getOutputStream(),因为参数直接追加在地址后面,因此默认是false。 post请求(比如:文件上传)需要往服务区传输大量的数据,这些数据是放在http的body里面的,因此需要在建立连接以后,往服务端写数据。 因为总是使用conn.getInputStream()获取服务端的响应,因此默认值是true。 */
+ httpsURLConnection.setDoInput(true);
+ httpsURLConnection.setUseCaches(false);
+ //设置请求方式 GET/POST
+ httpsURLConnection.setRequestMethod(requestMethod);
+ if ("GET".equalsIgnoreCase(requestMethod)) { //不考虑大小写。如果两个字符串的长度相等,并且两个字符串中的相应字符都相等(忽略大小写),则认为这两个字符串是相等的。
+ httpsURLConnection.connect();
+ }
+ //当有数据需要提交时,往服务器端写内容 也就是发起http请求需要带的参数
+ if (null != outputStr) {
+ OutputStream outputStream = httpsURLConnection.getOutputStream();
+ //注意编码格式,防止中文乱码
+ outputStream.write(outputStr.getBytes("UTF-8"));
+ outputStream.close();
+ }
+
+ //获得输入流 读取服务器端返回的内容
+ InputStream inputStream = httpsURLConnection.getInputStream();
+ InputStreamReader inputStreamReader = new InputStreamReader(inputStream,"utf-8");
+ BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
+ String str = null;
+ StringBuffer stringBuffer = new StringBuffer();
+ while((str = bufferedReader.readLine()) != null){
+ stringBuffer.append(str);
+ }
+ //释放资源
+ bufferedReader.close();
+ inputStreamReader.close();
+ inputStream.close();
+ inputStream = null;
+ httpsURLConnection.disconnect();
+ //将字符串转换为json对象
+ jsonObject = JSONObject.fromObject(stringBuffer.toString());
+ System.out.println("JSONObject---------------------->"+jsonObject);
+ } catch (ConnectException ce) {
+ logger.error("Weixin server connection timed out.");
+ } catch(Exception e){
+ logger.error("https request error:{}",e);
+ }
+ return jsonObject;
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/service/https/MyX509TrustManager.java b/demo/src/main/java/com/example/demo/weixin/service/https/MyX509TrustManager.java
new file mode 100644
index 0000000..965ea59
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/service/https/MyX509TrustManager.java
@@ -0,0 +1,42 @@
+/**
+ * 对于https请求,我们需要一个证书信任管理器, 这个管理器类需要自己定义,需要实现X509TrustManager接口代码
+ */
+
+package com.example.demo.weixin.service.https;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+
+public class MyX509TrustManager implements X509TrustManager {
+ /**
+ * 该方法用于检查客户端的证书,若不信则抛出异常
+ * 由于我们不需要对客户端进行认证,可以不做任何处理
+ */
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateEncodingException {
+
+ }
+
+ /**
+ * 该方法用于检验服务器端的证书,若不信任则抛出异常
+ * 通过自己实现该方法,可以使之信任我们指定的任何证书
+ * 在实现该方法时,也可以不做任何处理,即一个空的方法实现
+ * 由于不会抛出异常,它就会信任任何证书
+ */
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateEncodingException {
+
+ }
+
+ /**
+ * 返回收信任的X509证书数组
+ */
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/demo/src/main/java/com/example/demo/weixin/util/WeixinSignUtil.java b/demo/src/main/java/com/example/demo/weixin/util/WeixinSignUtil.java
new file mode 100644
index 0000000..ae73ef4
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/WeixinSignUtil.java
@@ -0,0 +1,70 @@
+/**
+ * 检测signature,标识该请求来自于微信
+ */
+
+package com.example.demo.weixin.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+@Component
+public class WeixinSignUtil {
+
+ //控制台输出日志信息所在的类
+ public static Logger logger = LoggerFactory.getLogger(WeixinSignUtil.class);
+ //与微信公众号号中配置的token相同
+ public static String token = "weixin";
+
+ public boolean checkSignature(String signature,String timestamp,String nonce){
+ String[] arr = new String[]{token,timestamp,nonce};
+ //将tokec,timestamp,nonce三个参数进行字典序排序
+ Arrays.sort(arr);
+ StringBuilder content = new StringBuilder();
+ for(int i = 0 ; i>> 4) & 0X0F];
+ tempArr[1] = Digit[c & 0X0F];
+
+ String s = new String(tempArr);
+ return s;
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCommonUtil.java b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCommonUtil.java
new file mode 100644
index 0000000..3caba1f
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCommonUtil.java
@@ -0,0 +1,52 @@
+package com.example.demo.weixin.util.menu;
+
+import com.example.demo.weixin.bean.menu.AccessToken;
+import com.example.demo.weixin.service.https.HttpRequestUtil;
+import net.sf.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 编写获取access_token的工具类
+ */
+
+
+@Component
+public class WechatCommonUtil {
+ Logger logger = LoggerFactory.getLogger(WechatCommonUtil.class);
+
+ //获取access_token接口
+ private static String token_url = WechatConstants.ACCESS_TOKEN_URL;
+ //@Autowired
+ HttpRequestUtil httpRequestUtil = new HttpRequestUtil();
+
+ /**
+ * @Description: 获取微信调用高级接口的凭证(access_token)
+ * @Parameters:
+ * @Return:
+ */
+ public AccessToken getAccessToken(String appid,String appsecret){
+ //将公众号的appid和appsecret替换进url
+ //String.replace()替换原字符串中的子串
+ String url = token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
+ AccessToken accessToken = new AccessToken();
+ //发起get请求获取凭证
+ JSONObject jsonObject = httpRequestUtil.httpsRequest(url,"GET",null);
+ logger.info("获取到的json格式的Token为:"+jsonObject);
+ if (jsonObject!=null) {
+ try {
+ accessToken.setAccess_token(jsonObject.getString("access_token"));
+ accessToken.setExpires_in(jsonObject.getInt("expires_in"));
+ } catch (Exception e) {
+ accessToken = null;
+ //获取token失败
+ logger.error("获取token失败 errcode:{} errmsg:{}",
+ jsonObject.getInt("errcode"),
+ jsonObject.getString("errmsg"));
+ }
+ }
+ return accessToken;
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/util/menu/WechatConstants.java b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatConstants.java
new file mode 100644
index 0000000..d0fa716
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatConstants.java
@@ -0,0 +1,8 @@
+package com.example.demo.weixin.util.menu;
+
+public class WechatConstants {
+ public static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
+ public static String MENU_CREATE_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
+ public static String MENU_GET_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
+ public static String MENU_DELETE_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCreatDefaultMenu.java b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCreatDefaultMenu.java
new file mode 100644
index 0000000..1c63afa
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatCreatDefaultMenu.java
@@ -0,0 +1,35 @@
+package com.example.demo.weixin.util.menu;
+
+
+import com.example.demo.weixin.bean.menu.Menu;
+
+/**
+ * @Description: 创建自定义菜单主方法
+ * @Parameters:
+ * @Return:
+ */
+public class WechatCreatDefaultMenu {
+ public static void main(String[] args){
+ WechatCommonUtil wechatCommonUtil = new WechatCommonUtil();
+ WechatMenuUtil wechatMenuUtil = new WechatMenuUtil();
+ WechatMenuManagerUtil wechatMenuManagerUtil = new WechatMenuManagerUtil();
+ String appid = "wx473235c6be5c945a";
+ String appsecret = "69a0c7bcccf20833fd549ae9a530d299";
+
+ //获取access_token
+ String accessToken = wechatCommonUtil.getAccessToken(appid, appsecret).getAccess_token();
+ //获取菜单结构
+ Menu menu = wechatMenuManagerUtil.getMenu();
+ if (accessToken!=null) {
+ //生成菜单
+ boolean result = wechatMenuUtil.creatMenu(menu, accessToken);
+ if (result) {
+ System.out.println("菜单创建成功");
+ }else {
+ System.out.println("菜单创建失败");
+ }
+ }else {
+ System.out.println("token为空");
+ }
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuManagerUtil.java b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuManagerUtil.java
new file mode 100644
index 0000000..16324b8
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuManagerUtil.java
@@ -0,0 +1,55 @@
+package com.example.demo.weixin.util.menu;
+
+import com.example.demo.weixin.bean.menu.*;
+
+
+/**
+ * @Description: 菜单管理器类
+ * @Parameters:
+ * @Return:
+ */
+public class WechatMenuManagerUtil {
+ /**
+ * @Description: 定义菜单结构
+ * @Parameters:
+ * @Return:
+ */
+ public Menu getMenu(){
+// ClickButton firstClickButton = new ClickButton();
+// firstClickButton.setName("功能图文");
+// firstClickButton.setKey("function");
+// firstClickButton.setType("click");
+
+ ViewButton firstViewButton = new ViewButton();
+ firstViewButton.setName("业务介绍");
+ firstViewButton.setType("view");
+ firstViewButton.setUrl("http://loan.ngrok.xiaomiqiu.cn/personalCenter.html");
+
+ ViewButton secondViewButton = new ViewButton();
+ secondViewButton.setName("我要贷款");
+ secondViewButton.setType("view");
+ secondViewButton.setUrl("http://loan.ngrok.xiaomiqiu.cn/personalCenter.html");
+
+ ComplexButton complexButton = new ComplexButton();
+
+ ViewButton viewButton1 = new ViewButton();
+ viewButton1.setType("view");
+ viewButton1.setName("个人中心");
+ viewButton1.setUrl("http://loan.ngrok.xiaomiqiu.cn/personalCenter.html");
+
+ ViewButton viewButton2 = new ViewButton();
+ viewButton2.setType("view");
+ viewButton2.setName("网页授权");
+ viewButton2.setUrl("http://loan.ngrok.xiaomiqiu.cn/personalCenter.html"); //http://loan.ngrok.xiaomiqiu.cn/WeChat/login.php
+ ViewButton[] viewButton = {viewButton1,viewButton2};
+ complexButton.setSub_button(viewButton);
+ complexButton.setName("我的服务");
+
+ Menu menu = new Menu();
+ Button[] boButtons = {firstViewButton,secondViewButton,complexButton};
+ menu.setButton(boButtons);
+
+ return menu;
+ }
+}
+
diff --git a/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuUtil.java b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuUtil.java
new file mode 100644
index 0000000..0d23295
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/menu/WechatMenuUtil.java
@@ -0,0 +1,89 @@
+package com.example.demo.weixin.util.menu;
+
+import com.example.demo.weixin.bean.menu.Menu;
+import com.example.demo.weixin.service.https.HttpRequestUtil;
+import net.sf.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+
+/**
+ * @Description: 自定义菜单工具类,包括菜单的创建、查询、删除
+ * @Parameters:
+ * @Return:
+ */
+
+public class WechatMenuUtil {
+ Logger logger = LoggerFactory.getLogger(WechatMenuUtil.class);
+ //@Autowired
+ private HttpRequestUtil httpRequestUtil = new HttpRequestUtil();
+
+ /**
+ * @Parameters: menu 菜单实例
+ * accessToken 凭证
+ * @Return: true false
+ * @Return:
+ */
+ public boolean creatMenu(Menu menu, String accessToken){
+ boolean result = false;
+ String url = WechatConstants.MENU_CREATE_URL.replace("ACCESS_TOKEN", accessToken);
+ //将菜单对象转换成JSON字符串
+ String jsonMenu = JSONObject.fromObject(menu).toString();
+ //发起POST请求创建菜单
+ JSONObject jsonObject = httpRequestUtil.httpsRequest(url, "POST", jsonMenu);
+
+ if (null != jsonObject) {
+ int errorCode = jsonObject.getInt("errcode");
+ String errorMsg = jsonObject.getString("errmsg");
+ if (0== errorCode) {
+ result = true;
+ } else {
+ result = false;
+ logger.error("创建菜单失败 errcode:{} errmsg:{} ",errorCode,errorMsg);
+ }
+ }
+ return result;
+ }
+ /**
+ *
+ * @Description: 查询菜单
+ * @Parameters:
+ * @Return:
+ */
+ public String getMenu(String accessToken){
+ String result = null;
+ String requestUrl = WechatConstants.MENU_GET_URL.replace("ACCESS_TOKEN", accessToken);
+ //发起GET请求查询菜单
+ JSONObject jsonObject = httpRequestUtil.httpsRequest(requestUrl, "GET", null);
+
+ if (null != jsonObject) {
+ result = jsonObject.toString();
+ }
+ return result;
+ }
+ /**
+ *
+ * @Description: 删除菜单
+ * @Parameters:
+ * @Return:
+ */
+ public boolean deleteMenu(String accessToken){
+ boolean result = false;
+ String requestUrl = WechatConstants.MENU_DELETE_URL.replace("ACCESS_TOKEN", accessToken);
+ //发起GET请求删除菜单
+ JSONObject jsonObject = httpRequestUtil.httpsRequest(requestUrl, "GET", null);
+
+ if (null != jsonObject) {
+ int errorCode = jsonObject.getInt("errcode");
+ String errorMsg = jsonObject.getString("errmsg");
+ if (0== errorCode) {
+ result = true;
+ } else {
+ result = false;
+ logger.error("创建菜单失败 errcode:{} errmsg:{} ",errorCode,errorMsg);
+ }
+ }
+ return result;
+ }
+}
diff --git a/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageModelUtil.java b/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageModelUtil.java
new file mode 100644
index 0000000..6792e88
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageModelUtil.java
@@ -0,0 +1,113 @@
+/**
+ * 微信消息处理,将关注回复消息等写成方法
+ */
+
+package com.example.demo.weixin.util.message;
+
+import com.example.demo.loginService.API.impl.UserService;
+import com.example.demo.weixin.bean.WeixinMessageInfo;
+import com.example.demo.weixin.bean.response.TextMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+
+@Component
+public class WeixinMessageModelUtil {
+ /**
+ * @Description: 封装微信回复消息,各种回复消息对应不同的方法
+ */
+ @Autowired
+ private WeixinMessageUtil weixinMessageUtil;
+// @Autowired
+// private WebConfigBean webConfigBean;
+ @Autowired
+ private UserService userService;
+// @Autowired
+// private EncodeUTF8 encodeUT8;
+
+ /**
+ * @Description: 当系统出错时,默认回复的文本消息
+ * @Parameters: WeixinMessageModelUtil
+ * @Return: 系统出错回复的消息
+ */
+ public String systemErrorResponseMessageModel(WeixinMessageInfo weixinMessageInfo ){
+
+ // 回复文本消息
+ TextMessage textMessage = new TextMessage();
+ textMessage.setToUserName(weixinMessageInfo.getFromUserName());
+ textMessage.setFromUserName(weixinMessageInfo.getToUserName());
+ textMessage.setCreateTime(new Date().getTime());
+ textMessage.setMsgType(weixinMessageUtil.RESP_MESSAGE_TYPE_TEXT);
+ textMessage.setFuncFlag(0);
+ textMessage.setContent("系统出错啦,请稍后再试");
+ return weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+// /**
+// * @Description: 用户关注时发送的图文消息
+// * @Parameters: WeixinMessageModelUtil
+// * @Return: 用户关注后发送的提示绑定用户的图文消息
+// */
+// public String followResponseMessageModel(WeixinMessageInfo weixinMessageInfo){
+//
+// // 关注时发送图文消息
+// NewsMessage newsMessage = new NewsMessage();
+// newsMessage.setToUserName(weixinMessageInfo.getFromUserName());
+// newsMessage.setFromUserName(weixinMessageInfo.getToUserName());
+// newsMessage.setCreateTime(new Date().getTime());
+// newsMessage.setMsgType(weixinMessageUtil.RESP_MESSAGE_TYPE_NEWS);
+// newsMessage.setFuncFlag(0);
+//
+// // 图文消息
+// List articleList=new ArrayList();
+// Article article = new Article();
+// // 设置图文消息的标题
+// String string = "欢迎关注借贷平台";
+// article.setTitle(string);
+// article.setPicUrl(webConfigBean.getWeixinPicture()+"meetingLogo2.png");
+// article.setUrl(webConfigBean.getDoMainNameurl()+"/WeixinParticipantFouce");
+// articleList.add(article);
+// newsMessage.setArticleCount(articleList.size());
+// newsMessage.setArticles(articleList);
+// return weixinMessageUtil.newsMessageToXml(newsMessage);
+// }
+
+
+ /**
+ * @Description: 用户关注时发送的文本消息
+ * @Parameters: WeixinMessageModelUtil
+ * @Return: 用户关注后发送的提示绑定用户的文本消息
+ */
+ public String followResponseMessageModel(WeixinMessageInfo weixinMessageInfo){
+
+ // 关注时发送文本消息
+ TextMessage textMessage = new TextMessage();
+ textMessage.setFromUserName(weixinMessageInfo.getToUserName());
+ textMessage.setToUserName(weixinMessageInfo.getFromUserName());
+ textMessage.setCreateTime(new Date().getTime());
+ textMessage.setMsgType(weixinMessageUtil.REQ_MESSAGE_TYPE_TEXT);
+ textMessage.setFuncFlag(0);
+
+ // 设置文本内容
+ String string = "欢迎关注借贷平台";
+ textMessage.setContent(string);
+ return weixinMessageUtil.textMessageToXml(textMessage);
+ }
+
+
+// /**
+// * @Description: 用户取消关注,先判断用户是否绑定,如果已经绑定则解除绑定
+// * @Parameters: WeixinMessageModelUtil
+// * @Return: void
+// */
+// public void cancelAttention(String fromUserName){
+//
+// if (userService.isAlreadyBinding(fromUserName)) {
+// userService.userUnbinding(fromUserName);
+// }else {
+// System.out.println("取消关注用户{}"+fromUserName+"还未绑定");
+// }
+// }
+}
+
diff --git a/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageUtil.java b/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageUtil.java
new file mode 100644
index 0000000..6888ebd
--- /dev/null
+++ b/demo/src/main/java/com/example/demo/weixin/util/message/WeixinMessageUtil.java
@@ -0,0 +1,263 @@
+/**
+ *封装微信消息类型,有一个解析微信发过的xml消息的工具
+ */
+package com.example.demo.weixin.util.message;
+
+import com.example.demo.weixin.bean.message.Article;
+import com.example.demo.weixin.bean.response.*;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.core.util.QuickWriter;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
+import com.thoughtworks.xstream.io.xml.XppDriver;
+import org.dom4j.Document;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.InputStream;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+@Component
+public class WeixinMessageUtil {
+ /**
+ * 请求消息类型:文本
+ */
+ public final String REQ_MESSAGE_TYPE_TEXT = "text";
+
+ /**
+ * 请求消息类型:图片
+ */
+ public final String REQ_MESSAGE_TYPE_IMAGE="image";
+
+ /**
+ * 请求消息类型:语音
+ */
+ public final String REQ_MESSAGE_TYPE_VOICE="voice";
+
+ /**
+ * 请求消息类型:视频
+ */
+ public final String REQ_MESSAGE_TYPE_VIDEO="video";
+
+ /**
+ * 请求消息类型:链接
+ */
+ public final String REQ_MESSAGE_TYPE_LINK = "link";
+
+ /**
+ * 请求消息类型:地理位置
+ */
+ public final String REQ_MESSAGE_TYPE_LOCATION="location";
+
+ /**
+ * 请求消息类型:小视频
+ */
+ public final String REQ_MESSAGE_TYPE_SHORTVIDEO="shortvideo";
+
+ /**
+ *请求消息类型:事件推送
+ */
+ public final String REQ_MESSAGE_TYPE_EVENT = "event";
+
+ /**
+ * 返回消息类型:文本
+ */
+ public final String RESP_MESSAGE_TYPE_TEXT = "text";
+
+ /**
+ * 消息返回类型:图片
+ */
+ public final String RESP_MESSAGE_TYPE_IMAGE="image";
+
+ /**
+ * 消息返回类型:语音
+ */
+ public final String RESP_MESSAGE_TYPE_VOICE = "voice";
+
+ /**
+ * 消息返回类型:音乐
+ */
+ public final String RESP_MESSAGE_TYPE_MUSIC = "music";
+
+ /**
+ * 消息返回类型:图文
+ */
+ public final String RESP_MESSAGE_TYPE_NEWS = "news";
+
+ /**
+ * 消息返回类型:视频
+ */
+ public final String RESP_MESSAGE_TYPE_VIDEO="video";
+
+ /**
+ * 事件类型:订阅
+ */
+ public final String EVENT_TYPE_SUBSCRIBE = "subscribe";
+
+ /**
+ * 事件类型:取消订阅
+ */
+ public final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
+
+ /**
+ * 事件类型:scan(关注用户扫描带参二维码)
+ */
+ public final String EVENT_TYPE_SCAN = "scan";
+
+ /**
+ * 事件类型:location(上报地理位置)
+ */
+ public final String EVENT_TYPE_LOCATION = "location";
+
+ /**
+ * 事件类型:CLICK(点击菜单拉取消息)
+ */
+ public final String EVENT_TYPE_CLICK ="CLICK";
+
+ /**
+ * 事件类型:VIEW(自定义菜单URl视图)
+ */
+ public final String EVENT_TYPE_VIEW ="VIEW";
+
+ /**
+ * 事件类型:TEMPLATESENDJOBFINISH(模板消息送达情况提醒)
+ */
+ public final String EVENT_TYPE_TEMPLATESENDJOBFINISH="TEMPLATESENDJOBFINISH";
+
+
+ /**
+ * @Description: 解析微信服务器发过来的xml格式的消息将其转换为map
+ * @Parameters: WeixinMessageUtil
+ * @Return: Map
+ */
+ public Map parseXml(HttpServletRequest request)throws Exception{
+
+ // 将解析结果存储在HashMap中
+ Mapmap =new HashMap();
+ // 从request中得到输入流
+ InputStream inputStream=request.getInputStream();
+
+ //用SAXReader解析xml文档
+ SAXReader reader = new SAXReader();
+ // 读取输入流
+ Document document = reader.read(inputStream);
+ // 得到XML的根元素
+ Element root = document.getRootElement();
+ // 得到根元素的所有子节点
+ @SuppressWarnings("unchecked") //忽略黄色警告
+ List elementList = root.elements();
+ // 判断有没有子元素列表
+ if (elementList.size()==0){
+ map.put(root.getName(), root.getText());
+ }else {
+ for (Element e : elementList)
+ map.put(e.getName(), e.getText());
+ }
+ // 释放资源
+ inputStream.close();
+ inputStream = null;
+ System.out.println("---------xml转换为map-----:"+map);
+ return map;
+ }
+
+ /**
+ * @Description: 文本消息对象转换成xml
+ * @param textMessage
+ * @return xml
+ */
+ public String textMessageToXml(TextMessage textMessage) {
+ xstream.alias("xml", textMessage.getClass());
+ return xstream.toXML(textMessage);
+ }
+
+ /**
+ * @Description: 图文消息对象转换成xml
+ * @param newsMessage
+ * @return xml
+ */
+
+ public String newsMessageToXml(NewsMessage newsMessage) {
+ xstream.alias("xml", newsMessage.getClass());
+ xstream.alias("item", new Article().getClass());
+ return xstream.toXML(newsMessage);
+ }
+
+ /**
+ * @Description: 图片消息对象转换成xml
+ * @param imageMessage
+ * @return xml
+ */
+ public String imageMessageToXml(ImageMessage imageMessage) {
+ xstream.alias("xml", imageMessage.getClass());
+ return xstream.toXML(imageMessage);
+ }
+
+
+ /**
+ * @Description: 语音消息对象转换成xml
+ * @param voiceMessage
+ * @return xml
+ */
+ public String voiceMessageToXml(VoiceMessage voiceMessage) {
+ xstream.alias("xml", voiceMessage.getClass());
+ return xstream.toXML(voiceMessage);
+ }
+
+ /**
+ * @Description: 视频消息对象转换成xml
+ * @param videoMessage
+ * @return xml
+ */
+ public String videoMessageToXml(VideoMessage videoMessage) {
+ xstream.alias("xml", videoMessage.getClass());
+ return xstream.toXML(videoMessage);
+ }
+
+ /**
+ * @Description: 音乐消息对象转换成xml
+ * @param musicMessage
+ * @return xml
+ */
+ public String musicMessageToXml(MusicMessage musicMessage) {
+ xstream.alias("xml", musicMessage.getClass());
+ return xstream.toXML(musicMessage);
+ }
+
+ /**
+ * 对象到xml的处理
+ * 扩展xstream,使其支持CDATA块
+ */
+ private XStream xstream = new XStream(new XppDriver() {
+ @Override
+ public HierarchicalStreamWriter createWriter(Writer out) {
+ return new PrettyPrintWriter(out) {
+ // 对所有xml节点的转换都增加CDATA标记
+ boolean cdata = true;
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public void startNode(String name, Class clazz) {
+ super.startNode(name, clazz);
+ }
+
+ @Override
+ protected void writeText(QuickWriter writer, String text) {
+ if (cdata) {
+ writer.write("");
+ } else {
+ writer.write(text);
+ }
+ }
+ };
+ }
+ });
+
+}