因为普通开发会有很多的权限限制,所以我们能够申请一个測试账号来开发体验一下微信公众号的其它接口功能。

申请測试号我就不介绍了。非常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)微信公众号开发进阶的更多相关文章

  1. 微信公众号开发系统入门教程(公众号注册、开发环境搭建、access_token管理、Demo实现、natapp外网穿透)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/a1786223749/article/ ...

  2. C#微信公众号开发系列教程三(消息体签名及加解密)

    http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...

  3. NET微信公众号开发-5.0微信支付(待测试)

    开发前准备. 1.0微信支付官方开发者文档 2.0官方demo下载 我们用c#所以选择.net版本 不过这个官方的demo根本跑步起来 3.0官方demo运行起来解决方案 4.0微信支付官方.net版 ...

  4. 微信公众号开发之被逼学web服务端1-----使用SecureCRT连接Linux服务器

    做Android的进新公司后安排做微信公众号开发,这基本是后台和前端的活都要由小白的我来做,这两天基本成鸭子了,被填的满满的,却还是不够,博文仅作记录,希望能给后来的小白一点参考吧 今天做的是如何配置 ...

  5. 利用OpenShift托管Node.js Web服务进行微信公众号开发

    最近写了一个微信的翻译机器人.用户只要关注该公众号,发送英文的消息,就能收到中文翻译的回复.有兴趣的读者可以扫描下面的二维码关注该公众号,尝试发送英文单词试试看.(有时候第一次发送单词会收到“该公众号 ...

  6. .NET微信公众号开发-5.0微信支付

    一.前言 在开始做这个功能之前,我们要做的第一件事情就是思考,如何做这个微信支付,从哪里开始,从哪里入手,官方的sdk说明什么的,有没有什么官方的demo,还有就是老板给我的一些资料齐全不,那些要申请 ...

  7. 微信公众号开发笔记1(nodejs开发的)

    本篇记录了微信公众号开发的一些笔记 一.微信服务器与我们服务器的交流 微信开发者拥有自己的服务器,在我们服务器上可以与微信服务器进行交流.既然可以交流,那就必定需要前提条件(微信认证),也就是说,只有 ...

  8. VopSdk一个高逼格微信公众号开发SDK:自动化生产(装逼模式开启)

    VopSdk一个高逼格微信公众号开发SDK(源码下载) VopSdk一个高逼格微信公众号开发SDK:自动化生产(装逼模式开启) 针对第一版,我们搞了第二版本,老规矩先定个目标. 一 我们的目标 a.移 ...

  9. 微信公众号开发《三》微信JS-SDK之地理位置的获取,集成百度地图实现在线地图搜索

    本次讲解微信开发第三篇:获取用户地址位置信息,是非常常用的功能,特别是服务行业公众号,尤为需要该功能,本次讲解的就是如何调用微信JS-SDK接口,获取用户位置信息,并结合百度地铁,实现在线地图搜索,与 ...

随机推荐

  1. Node FS 读取文件中文乱码解决

    1:首先保证源文件编码方式为UTF-8 2:读取代码,设置编码方式rs.setEncoding('utf8') var fs = require('fs'); var rs = fs.createRe ...

  2. 输出python的help结果到文件中

    1.命令行方式: python -c "import sys; help(sys.exit)" > help.txt 2.函数代码的方式输出 def help_output( ...

  3. js replace 如何替换字符串中的最后一个匹配项

    1.正则表达时,贪婪模式,.*会一直匹配到最后一个 // 验证 let str = "123[空]345[空]789[空]0"; let res = str.replace(/(. ...

  4. android 上线流程

    1.首先打开安卓市场官网,在右上角找到注册按钮,先注册成为开发者. 2.而后点击“开发者”进入“开发者中心”页面(也可从网页下方的“开发者入口”进入). 3.选择“发布软件”选项,依次上传创建的APP ...

  5. CSS实现水平垂直居中方式

    1.定位 核心代码实现请看示例代码中的注释: <!DOCTYPE html> <html lang="zh"> <head> <meta ...

  6. ideaIU-15.0.2 注册码

    注册时选择 License server ,填 http://idea.lanyus.com ,然后点击 OK

  7. load()和get()的区别

    区别1:如果数据库中,没有userId的对象.如果通过get方法加载,则返回的是一个null:如果通过load加载,则返回一个代理对象,如果后面代码如果调用user对象的某个属性(比如user.get ...

  8. jquery获取td所在的行和列

    今天在做项目时.遇到一个须要获取第几行第几列的问题. 后来.网上找了找资料,整理了此文.(使用jquery的preAll()获取列) 代码例如以下: <!DOCTYPE html PUBLIC ...

  9. python之函数用法isinstance()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法isinstance() #isinstance() #说明:返回一个布尔值,判断数据 ...

  10. 全面提升WordPress前台和后台的 打开速度的方案

    装好WordPress之后,准备想访问自己的网站,或是登入后台的时候,却发现,这个速度不敢恭维,即使是本地话的程序,也是慢慢的.操作起来也要挺久.那下面我们来解决一下这个问题,提升WordPress的 ...