【JavaWeb】(10)微信公众号开发进阶
因为普通开发会有很多的权限限制,所以我们能够申请一个測试账号来开发体验一下微信公众号的其它接口功能。
申请測试号我就不介绍了。非常easy。申请成功后,还须要配置Url地址和token,和我们普通公众账号填写的一致就能够了。
1. 图文消息
这里因为我们图文消息用到很多上一篇TextMessage中的一些属性。所以我们须要重构一下我们的代码,创建基类BaseMessage:
public class BaseMessage { private String ToUserName;
private String FromUserName;
private long CreateTime;
private String MsgType;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
}
然后将我们的TextMessage和NewsMessage都继承这个基类。
在创建图文消息中的一条项目类News:
public class News { private String Title;
private String Description;
private String PicUrl;
private String Url;
}
最后创建图文消息类:
public class NewsMessage extends BaseMessage { private int ArticleCount;
private List<News> Articles;
}
每个类都生成set和get方法。
增添我们的工具类MessageUtil:
/**
* 将图文消息转换成xml
*
* @param newsMessage
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
XStream xStream = new XStream();
xStream.alias("xml", newsMessage.getClass());
xStream.alias("item", new News().getClass());
return xStream.toXML(newsMessage);
} /**
* 图文消息的组装
*
* @param toUserName
* @param fromUserName
* @return
*/
public static String initNewsMessage(String toUserName, String fromUserName) {
String message = null;
List<News> newsList = new ArrayList<News>();
NewsMessage newsMessage = new NewsMessage();
News news = new News();
News news2 = new News(); news.setTitle("克里斯托弗诺兰");
news.setDescription("美国当代伟大的导演");
news.setPicUrl("http://wechat.tunnel.mobi/WeChat/image/p1659233202.jpg");
news.setUrl("http://movie.duuban.com");
newsList.add(news); news2.setTitle("克里斯托弗诺兰");
news2.setDescription("美国当代伟大的导演");
news2.setPicUrl("http://wechat.tunnel.mobi/WeChat/image/p1659233202.jpg");
news2.setUrl("http://movie.duuban.com");
newsList.add(news2); newsMessage.setToUserName(fromUserName);
newsMessage.setFromUserName(toUserName);
newsMessage.setCreateTime(new Date().getTime());
newsMessage.setMsgType(MESSAGE_NEWS);
newsMessage.setArticles(newsList);
newsMessage.setArticleCount(newsList.size());
message = newsMessageToXml(newsMessage);
return message;
}
这里须要新增一个常量:
public static final String MESSAGE_NEWS = "news";
最后在改动一下WeChatServlet类測试就能够了。
2. access_token的获取
access_token是公众号的全局唯一票据,公众号调用各接口时都须要使用access_token。
开发人员须要进行妥善保存。
access_token的存储至少要保留512个字符空间。access_token的有效期眼下为2个小时,续订是刷新,反复获取将导致上次获取的access_token失效。
创建我们的工具类:
public class WeChatUtil { private static final String APPID = "wx893f724e92d10f25";
private static final String APP_SECRET = "b2ba8f4bcceb544798ce25509910555f"; private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET"; /**
* 使用get方式获得Json对象
*
* @param url
* @return
*/
public static JSONObject doGetString(String url) {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
JSONObject jsonObject = null; try {
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity, "UTF-8");
jsonObject = JSONObject.fromObject(result);
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return jsonObject;
} /**
* 使用post方式获得Json对象
*
* @param url
* @return
*/
public static JSONObject doPostString(String url, String outString) { DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
JSONObject jsonObject = null; try { httpPost.setEntity(new StringEntity(outString, "UTF-8"));
HttpResponse response = httpClient.execute(httpPost);
String result = EntityUtils.toString(response.getEntity(), "UTF-8");
jsonObject = JSONObject.fromObject(result);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} return null;
} /**
* 获取access_token
*
* @return
*/
public static AccessToken getAccessToken() {
AccessToken token = new AccessToken();
String url = ACCESS_TOKEN_URL.replace("APPID", APPID).replace(
"APPSECRET", APP_SECRET);
JSONObject jsonObject = doGetString(url);
if (jsonObject != null) {
token.setToken(jsonObject.getString("access_token"));
token.setExpiresIn(jsonObject.getInt("expires_in"));
}
return token;
}
}
里面有get和post两种方式获取access_token的方法,这里须要导入几个jar包。后面的项目源代码里面会有,能够下载。
3. 图片消息自己主动回复
这里我们首先须要获得一个OpenId,新增我们的工具类方法,使用上传图片的一个方法来获得一个media_id。上传文件的类比較长。这里就不贴出来了。上传的Url地址文档里面也有介绍,这个是上传地址:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
继续扩充我们的工具类MessageUtil:
/**
* 将图片消息转换成xml
*
* @param newsMessage
*/
public static String imageMessageToXml(ImageMessage imageMessage) {
XStream xStream = new XStream();
xStream.alias("xml", imageMessage.getClass());
return xStream.toXML(imageMessage);
} /**
* 组装图片消息
*
* @param toUserName
* @param fromUserName
* @return
*/
public static String initImageMessage(String toUserName, String fromUserName) {
String message = null; Image image = new Image(); image.setMediaId("kk5p2z-NaHhQs1X6oZsMgWKzz4p8xWW1nVJAG4jx1NGM1mWAypJZ6gHlJPTLw243");
ImageMessage imageMessage = new ImageMessage();
imageMessage.setImage(image);
imageMessage.setToUserName(fromUserName);
imageMessage.setFromUserName(toUserName);
imageMessage.setMsgType(MESSAGE_IMAGE);
imageMessage.setCreateTime(new Date().getTime());
message = imageMessageToXml(imageMessage);
return message;
}
当中的MediaId就是我们再上传的时候取得的。每一次上传取得的MediaId都是不同的,这里须要注意一下。
4. 音乐消息的回复
音乐消息的回复和图片消息的回复大体上一直,我们须要加入一首歌到项目中。
这里我们要发的音乐消息须要一个缩略图,和上传图片的方式基本一样,仅仅只是在类型上改动为“thumb__media_id”,其他操作基本一样。
5. 自己定义菜单
接下来我们看一下怎样创建自己定义菜单。
对比文档首先创建基类button:
public class Button { private String name;
private String type;
private Button[] sub_button;
}
然后创建ClickButton、ViewButton,ClickButton自己独有的属性:key、ViewButton独有的属性:url,最后创建Menu实体类,仅仅有一个成员变量Button集合。
创建主菜单:
/**
* 创建组装主菜单
*
* @return
*/
public static Menu initMenu() {
Menu menu = new Menu(); // 主菜单一
ClickButton button11 = new ClickButton();
button11.setName("Click菜单");
button11.setType("click");
button11.setKey("11"); // 主菜单二
ViewButton button21 = new ViewButton();
button21.setName("view菜单");
button21.setType("view");
button21.setUrl("http://movie.douban.com"); // 菜单三子菜单一
ClickButton button31 = new ClickButton();
button31.setName("扫码事件");
button31.setType("scancode_push");
button31.setKey("31"); // 菜单三子菜单二
ClickButton button32 = new ClickButton();
button32.setName("地理位置");
button32.setType("location_select");
button32.setKey("32"); // 主菜单三
Button button = new Button();
button.setName("菜单");
button.setSub_button(new Button[] { button31, button32 }); menu.setButton(new Button[] { button11, button21, button });
return menu;
}
然后编写创建菜单的方法:
/**
* 创建菜单
* @param token
* @param menu
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static int createMenu(String token, String menu)
throws ClientProtocolException, IOException {
int result = 0;
String url = CREATE_MENU_URL.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = doPostString(url, menu);
if (jsonObject != null) {
result = jsonObject.getInt("errcode");
}
return result;
}
这里须要加入一个URL的常量:
private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create? access_token=ACCESS_TOKEN";
编写測试代码:
String menu = JSONObject.fromObject(WeChatUtil.initMenu())
.toString();
int result = WeChatUtil.createMenu(token.getToken(), menu);
if (result == 0) {
System.out.println("创建菜单成功");
} else { System.out.println("创建菜单失败,错误码" + result);
}
运行。 创建菜单成功。
6. 菜单的事件推送
改动我们的WeChatServlet类:
} else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) {
String eventType = map.get("Event");
if (MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)) { // 首次关注事件
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.menuText());
} else if (MessageUtil.MESSAGE_CLICK.equals(eventType)) { // 菜单一的点击事件
message = MessageUtil.initText(toUserName, fromUserName,
MessageUtil.menuText());
} else if (MessageUtil.MESSAGE_VIEW.equals(eventType)) { // 菜单二的点击事件
String url = map.get("EventKey");
message = MessageUtil.initText(toUserName, fromUserName,
url);
} else if (MessageUtil.MESSAGE_SCANCODE.equals(eventType)) { // 菜单三的扫码事件
String key = map.get("EventKey");
message = MessageUtil.initText(toUserName, fromUserName,
key);
}
} else if (MessageUtil.MESSAGE_LOCATION.equals(msgType)) { // 地理位置
String label = map.get("Label");
message = MessageUtil.initText(toUserName, fromUserName, label);
}
当中,假设当前页面要跳转到还有一个页面的时候,那么公众号是不会给我们在返回来的时候输出信息的。
7. 自己定义菜单的查询与删除
/**
* 菜单的查询
*
* @param token
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static JSONObject queryMenu(String token)
throws ClientProtocolException, IOException {
String url = QUERY_MENU_URL.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = doGetString(url);
return jsonObject;
} /**
* 菜单的删除
*
* @param token
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static int deleteMenu(String token)
throws ClientProtocolException, IOException {
String url = DELETE_MENU_URL.replace("ACCESS_TOKEN", token);
JSONObject jsonObject = doGetString(url);
int result = 0;
if (jsonObject != null) {
result = jsonObject.getInt("errcode");
}
return result;
}
须要加入两个常量:
private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
编写測试类就可以。
8. 百度翻译
接下来添加一个翻译的应用。做这个功能首先须要在百度开发平台申请一个账号。并加入一个应用,记住自己的API Key和Secret Key,后面我们将用到。
翻译的工具方法非常easy:
public static String translate(String source)
throws ClientProtocolException, IOException {
String url = TRANS_URL.replace("KEYWORD",
URLEncoder.encode(source, "UTF-8"));
JSONObject jsonObject = doGetString(url);
StringBuffer dst = new StringBuffer();
List<Map> list = (List<Map>) jsonObject.get("trans_result");
for (Map map : list) {
dst.append(map.get("dst"));
}
return dst.toString();
}
TRANS_URL是这个样子的:
private static final String TRANS_URL = "http://openapi.baidu.com/public/2.0/bmt/translate?client_id=bqnAaRDLL6KGVjZByGeO8Ycq&q=KEYWORD&from=auto&to=auto";
client_id后面跟的是我们申请的API Key。from和to设置成auto能够让工具自己推断翻译中文或者英文。
然后在Servlet中调用就可以:
message = MessageUtil.initText(toUserName, fromUserName,
WeChatUtil.translate(content));
大功告成!
【JavaWeb】(10)微信公众号开发进阶的更多相关文章
- 微信公众号开发系统入门教程(公众号注册、开发环境搭建、access_token管理、Demo实现、natapp外网穿透)
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/a1786223749/article/ ...
- C#微信公众号开发系列教程三(消息体签名及加解密)
http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...
- NET微信公众号开发-5.0微信支付(待测试)
开发前准备. 1.0微信支付官方开发者文档 2.0官方demo下载 我们用c#所以选择.net版本 不过这个官方的demo根本跑步起来 3.0官方demo运行起来解决方案 4.0微信支付官方.net版 ...
- 微信公众号开发之被逼学web服务端1-----使用SecureCRT连接Linux服务器
做Android的进新公司后安排做微信公众号开发,这基本是后台和前端的活都要由小白的我来做,这两天基本成鸭子了,被填的满满的,却还是不够,博文仅作记录,希望能给后来的小白一点参考吧 今天做的是如何配置 ...
- 利用OpenShift托管Node.js Web服务进行微信公众号开发
最近写了一个微信的翻译机器人.用户只要关注该公众号,发送英文的消息,就能收到中文翻译的回复.有兴趣的读者可以扫描下面的二维码关注该公众号,尝试发送英文单词试试看.(有时候第一次发送单词会收到“该公众号 ...
- .NET微信公众号开发-5.0微信支付
一.前言 在开始做这个功能之前,我们要做的第一件事情就是思考,如何做这个微信支付,从哪里开始,从哪里入手,官方的sdk说明什么的,有没有什么官方的demo,还有就是老板给我的一些资料齐全不,那些要申请 ...
- 微信公众号开发笔记1(nodejs开发的)
本篇记录了微信公众号开发的一些笔记 一.微信服务器与我们服务器的交流 微信开发者拥有自己的服务器,在我们服务器上可以与微信服务器进行交流.既然可以交流,那就必定需要前提条件(微信认证),也就是说,只有 ...
- VopSdk一个高逼格微信公众号开发SDK:自动化生产(装逼模式开启)
VopSdk一个高逼格微信公众号开发SDK(源码下载) VopSdk一个高逼格微信公众号开发SDK:自动化生产(装逼模式开启) 针对第一版,我们搞了第二版本,老规矩先定个目标. 一 我们的目标 a.移 ...
- 微信公众号开发《三》微信JS-SDK之地理位置的获取,集成百度地图实现在线地图搜索
本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...
随机推荐
- [Python] 错误“IndentationError: unindent does not match any outer indentation level”是什么意思?
文本没有对齐,建议打开文本编辑器的Tab显示(我用的Editplus是视图->空白->制表符),看缩进是否合理,调整一致就好了.
- STL - 容器 - Array
Array是C++ 11给STL新增加的容器 ArrayTest.cpp #include <array> #include <algorithm> #include < ...
- JavaScript 之 uploadify 或 SWFUpload上传问题
1.uploadify 或 SWFUpload在Chrome.Firefox浏览器下session找不到的问题 问题如下:为了安全起见,程序开发中往往通过Session设置权限控制,只有登录用户才能进 ...
- 去除icon图标特效,阴影,反光
在icon默认情况: 程序的图标会被apple进行美化, 自动圆角, 加上阴影和反光效果:如果不想要这种效果:在Info.plist中 添加一个Icon already includes gloss ...
- B/S与C/S的差别
前一段时间已经结束了C/S的学习,開始了B/S的旅程,那么为什么我们要学习这两个,这两个有什么差别呢?这些差别你知道多少呢? B/S结构.即Browser/Server(浏览器/server)结构.是 ...
- vb sendmessage 详解1
SendMessage函数的常用消息及其应用(有点长,希望能对大家有所帮助)函数原型: Declare Function SendMessage Lib "user32" Alia ...
- code[VS] 1048 石子归并
题目描写叙述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次合并可以合并相邻的两堆石子.一次合并的代价为两堆石子的重量和w[i]+w[i+1]. 问安排如何的合并顺序, ...
- 在Tomcat下指定Jsp生成的Java文件路径
在tomcat的配置文件server.xml(路径:tomcat路径\conf下面)里,找到:<Context docBase="D:/workspace/icinfo/trunk/w ...
- 引入css的几种方式
使用CSS样式的几种方式 CreateTime--2017年10月11日16:45:26 Author:Marydon a.外部样式 a1.链接式(推荐使用) <link href=&quo ...
- Codeforces554C:Kyoya and Colored Balls(组合数学+费马小定理)
Kyoya Ootori has a bag with n colored balls that are colored with k different colors. The colors are ...