【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接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...
随机推荐
- DEDE标签综合
dede: sql标签: sql标签可以称得上是个万能标签了,查询数据库将其输出,这里介绍一些关于这个标签的用法: 1.用来输出统计内容,这个是不错的,举个例子,我们来统计下总共发了多少的文章,思路就 ...
- C#.NET常见问题(FAQ)-abstract抽象类如何理解
例如有太多相似,但是不一样的类,他们都继承自同一个基类(比如大型游戏有各个种族,每个种族有各种人物,加起来几百种类型,然后基本上他们都是一个角色,都有基本相同的属性和方法,比如都会走,只是速度不同,都 ...
- php 内置函数JSON处理
一:生成json数据 <?php $arr = array ('a'=>1,'b'=>2,'c'=>3,'d'=>4,'e'=>5); echo json_enco ...
- itext Protecting your PDF
/* * This class is part of the book "iText in Action - 2nd Edition" * written by Bruno Low ...
- sqlserver 创建对某个存储过程执行情况的跟踪
有时候需要抓取执行存储过程时某个参数的值,有时候程序调用存储过程执行后结果不太对,不确定是程序的问题还是存储过程的问题,需要单独执行存储过程看结果 即可用下面的方法 --=============== ...
- HTTP协议详解之User Agent篇
•User Agent:用户代理 指浏览器他的信息包括硬件平台.系统软件.应用软件和用户个人偏好.用户代理不仅仅指浏览器,还包括搜索引擎. •为什么所有浏览器的User Agent都带有Mozilla ...
- set 容器 的全解(转)
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- tkinter Canvas画图片大坑总结
一.ImportError: cannot import name '_imagingtk' 问题描述 使用tkinter画pillow生成的图片时,在tkinter中抛出此异常. 解决方案 pip ...
- HighCharts: 设置时间图x轴的宽度
这个x轴宽度的设置整了好久,被老板催的要死 highcharts的api文档很难找,找了半天也没找到,网上资料少,说的试了下,也没有,我用的图里api文档里没有介绍,这个属性不知道的话,根本不好找.为 ...
- C# 打开钱箱支持北洋、佳博、爱普生
/// <summary> /// 执行开钱箱操作 /// 没钱箱或打印机原功能都可以正常使用 /// </summary> public void ExecuteOpenCa ...