微信公众号开发的时候大多数人都是看官方文档,但是这样很耗费时间,下面是一个Demo的讲解,可以让初次开发者快速的搭建好开发环境。
首先在公众号开发之前我们要做一个重要准备,那就是把我们本地的项目部署起来并将端口映射到外网,让外网也可以访问我们的项目,请看我之前转载的一片文章。
开发准备工作:点击打开链接http://blog.csdn.net/qq962464qq/article/details/79296319
Demo:Demo下载,Demo中采用简单的Spring MVC+mybaitis进行开发,Demo结构如下
我们用到的文件讲解
controller:接收请求
dao:和mapper中的sql对应,用于操作数据库
entity:实体
mapper:mybaitis的操作数据库的.xml文件,编写的sql
util:工具类
weixin:微信开发用到的一些代码(下面会详细讲解)
配置文件:applicationContext.xml和Spring-MVC.xml是spring的一些配置language.....文件是用来做页面中英文切换的(可以不要)system.properties文件配置了全局的一些变量,如Token等
这个准备工作的作用:
在公众号开发之前我们需要在微信官网平台的公众号(测试号也可以)填写一个url和Token,token可以自己命名,但是必须和你的项目中的Token一致,在你点击确 定的时候微信将访问你的url,加密你填写的token和你本地设置的token(本地需要加密,加密代码后面讲解)进行对比,对比成功则完成设置。
Demo讲解
1.绑定URL和Token
URL是微信平台访问的链接,用来校验Token的请求地址(DoMessageController中)
2.接收请求
接收关注,消息等请求,绑定了图灵机器人,实现智能问答。关注时进行消息推送(DoMessageController中)
/**
* 处理微信发来的请求
* @param request
* @return xml
*/
public String processRequest(HttpServletRequest request) {
// xml格式的消息数据
String respXml = null;
// 默认返回的文本消息内容
String respContent = "未知的消息类型!";
try {
// 调用parseXml方法解析请求消息
Map requestMap = MessageUtil.parseXml(request);
// 发送方帐号
String fromUserName = requestMap.get("FromUserName");
// 开发者微信号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 回复文本消息
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
//消息内容
String content = requestMap.get("Content");
Robot robot = new Robot();
//调用机器人对话
respContent = robot.dialogue(content, fromUserName);
}
// 图片消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
respContent = "您发送的图片我没见过!";
}
// 语音消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
respContent = "我听不见您说的什么,还是打字吧!";
}
// 视频消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
respContent = "您发送视频我没看过!";
}
// 视频消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
respContent = "您发送的是小视频消息!";
}
// 地理位置消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
respContent = "这个地方我没去过!";
}
// 链接消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
respContent = "您发送的是链接消息!但是我不认识!";
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 关注
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
respContent = "欢迎关注上海质子重离子医院设备设施综合运行管理微信平台!";
//拉取用户数据
String url = "https://api.weixin.qq.com/cgi-bin/user/info";
String param = "access_token="+accessTokenService.getAccessToken().getAccesstoken()+"&openid="+fromUserName+"&lang=zh_CN";
JSONObject followPersonJson = HttpUtil.sendGetOfJson(url, param);
followPersonJson.remove("tagid_list");
FollowPerson followPerson = (FollowPerson)JSONObject.toBean(followPersonJson,FollowPerson.class);
if(followPersonService.listFollowPerson(followPerson).size()==0){
followPersonService.saveFollowPerson(followPerson);
//tempMsgPushService.pushAllUser();
}
}
// 取消关注
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
//取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
FollowPerson followPerson = new FollowPerson();
followPerson.setOpenid(fromUserName);
followPersonService.delFollowPerson(followPerson);
}
// 扫描带参数二维码
else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
// 处理扫描带参数二维码事件
}
// 上报地理位置
else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
//处理上报地理位置事件
}
// 自定义菜单
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
//处理菜单点击事件
}
}
// 设置文本消息的内容
textMessage.setContent(respContent);
// 将文本消息对象转换成xml
respXml = MessageUtil.messageToXml(textMessage);
} catch (Exception e) {
e.printStackTrace();
}
return respXml;
}
3
.自定义菜单
weixin/InitMenu.java
//使用线程初始化access_Token
public void init() throws ServletException {
try {
ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext());
AccessTokenService accessTokenService = (AccessTokenService) applicationContext.getBean("accessTokenService");
//获取access_token
String aturl = "https://api.weixin.qq.com/cgi-bin/token";
//参数配置在system.properties中
String param = "grant_type=client_credential&appid="+Common.getSystemProperty("appID")+"&secret="+Common.getSystemProperty("appsecret");
JSONObject jsonObj = HttpUtil.sendGetOfJson(aturl, param);
String access_token = jsonObj.getString("access_token");
int expires_in= jsonObj.getInt("expires_in");
AccessToken accessToken = new AccessToken();
if(StringUtils.isNotBlank(access_token) && expires_in>0){
accessToken.setAccesstoken(access_token);
accessToken.setExpires(expires_in);
//保存access_Token到数据库
accessTokenService.delAccessToken();
accessTokenService.saveAccessToken(accessToken);;
}
if(Common.isnull(accessToken)){
System.out.println("access_Token错误");
}
String url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="+accessToken.getAccesstoken();
//json参数
JSONObject jsonParam = new JSONObject();
JSONArray jsonArr1 = new JSONArray();
JSONArray jsonArr2 = new JSONArray();
//一级菜单项
JSONObject jsonParam1 = new JSONObject();
//二级菜单项
JSONObject jsonParam2 = new JSONObject();
//第一组
jsonParam1.put("name", "首页");
//添加二级
jsonParam2.put("type", "view");
jsonParam2.put("appid", Common.getSystemProperty("appID"));
jsonParam2.put("name", "登陆");
jsonParam2.put("url", "http://e23c7752.ngrok.io");
jsonArr2.add(jsonParam2);
jsonParam2.clear();
//继续添加二级
//将二级添加到1级下
jsonParam1.put("sub_button", jsonArr2);
jsonArr1.add(jsonParam1);
jsonParam2.clear();
jsonParam1.clear();
/*//第二组
jsonParam1.put("name", "首页");
jsonParam1.put("type", "view");
jsonParam1.put("url", "www.baidu.com");
jsonParam.put("button", jsonParam1);
jsonParam2.clear();
jsonParam1.clear();
//第二组
jsonParam1.put("name", "首页");
jsonParam1.put("type", "view");
jsonParam1.put("url", "www.baidu.com");
jsonParam.put("button", jsonParam1);
jsonParam2.clear();
jsonParam1.clear();*/
jsonParam.put("button", jsonArr1);
System.out.println(jsonParam);
//初始化返回
//JSONObject rsJson = HttpUtil.sendPost(url, jsonParam);
JSONObject rsJson = HttpUtil.sendPostOfJson(url, jsonParam);
String errmsg= rsJson.getString("errmsg");
int errcode= rsJson.getInt("errcode");
if(errcode==0 && errmsg.equals("ok")){
System.out.println(DateTimeUtil.formatDate(new Date(), DateTimeUtil.yyyy_MM_dd_HH_mm_ss)+" success:初始化菜单成功");
}else{
System.out.println(DateTimeUtil.formatDate(new Date(), DateTimeUtil.yyyy_MM_dd_HH_mm_ss)+": error:初始化菜单失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
其余核心代码中都有注释