微信开发
2016-04-16 15:31
543 查看
初识Java微信公众号开发
开发环境搭建
开发环境准备
一个微信公众号外网映射工具(开发调试。与微信对接需满足两个条件。一:公网能访问该地址。二:端口只支持80端口。)
如何准备外网映射工具。
在ngrok国内服务器下载ngrok,下载好后里面有说明,按照说明启动ngrok。
开发模式接入
开发者文档地址
接入指南创建WeixinServlet
package com.imooc.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.imooc.po.TextMessage; import com.imooc.util.CheckUtil; import com.imooc.util.MessageUtil; import com.sun.xml.internal.ws.util.xml.XmlUtil; /** * Servlet implementation class WeixinServlet */ public class WeixinServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public WeixinServlet() { super(); // TODO Auto-generated constructor stub } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
修改web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Weixin</display-name> <servlet> <description></description> <display-name>WeixinServlet</display-name> <servlet-name>WeixinServlet</servlet-name> <servlet-class>com.imooc.servlet.WeixinServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>WeixinServlet</servlet-name> <url-pattern>/wx.do</url-pattern> </servlet-mapping> </web-app>
添加工具类写校验逻辑
package com.imooc.util; import java.util.Arrays; public class CheckUtil { private static final String token = "imooc"; public static boolean checkSignature(String signature , String timestamp ,String nonce) { String[] arr = new String[]{token,timestamp,nonce}; //排序 Arrays.sort(arr); //拼接字符 StringBuffer content = new StringBuffer(); for(int i = 0 ; i < arr.length ; i++){ content.append(arr[i]); } //sha1算法加密 String temp = null; if(content != null) { temp = new SHA1Util().getDigestOfString(content.toString().getBytes()); temp = temp.toLowerCase(); } return temp.equals(signature); } }
测试公网映射地址
先在浏览器通过本地访问http://localhost:8080/Weixin/wx.do可访问,只是报空指针错误,因为没传参
再通过公网访问地址http://alexnest.ittun.com/Weixin/wx.do
一样可访问
填写服务器配置
左侧菜单栏“基本配置”右侧页面点击修改配置
修改配置信息
点击提交
提交成功的话表示微信后台与微信公众平台的对接已经成功。
文本消息
所需jar包
dom4j-1.6.1.jar(解析xml,把xml放进map类型中,方便以后操作)xstream-1.3.1.jar(把对象转成xml String类型)
添加文本对象
package com.imooc.po; public class TextMessage { public final static String MESSAGE_ToUserName = "ToUserName"; public final static String MESSAGE_FromUserName = "FromUserName"; public final static String MESSAGE_CreateTime = "CreateTime"; public final static String MESSAGE_MsgType = "MsgType"; public final static String MESSAGE_Content = "Content"; public final static String MESSAGE_MsgId = "MsgId"; public final static String ME 13a4f SSAGE_MsgType_TEXT = "text"; private String ToUserName; private String FromUserName; private long CreateTime; private String MsgType; private String Content; private String MsgId; public String getToUserName() { return ToUserName; } public void setToUserName(String toUserName) { ToUserName = toUserName; } public String getFromUserName() { return FromUserName; } public void setFromUserName(String fromUserName) { this.FromUserName = fromUserName; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { this.MsgType = msgType; } public String getContent() { return Content; } public void setContent(String content) { this.Content = content; } public String getMsgId() { return MsgId; } public void setMsgId(String msgId) { this.MsgId = msgId; } public long getCreateTime() { return CreateTime; } public void setCreateTime(long createTime) { this.CreateTime = createTime; } }
添加工具类
添加工具类,在工具类中增加方法xml2Map,把微信公众平台传过来的xml解析放进map中,增加方法textMessage2XML把文本对象转成xml String类型。package com.imooc.util; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import com.imooc.po.TextMessage; import com.thoughtworks.xstream.XStream; public class MessageUtil { public final static String MESSAGE_TEXT = "text"; public final static String MESSAGE_IMAGE = "image"; public final static String MESSAGE_VOICE = "voice"; public final static String MESSAGE_VEDIO = "vedio"; public final static String MESSAGE_NEWS = "news"; public final static String MESSAGE_LINK = "link"; public final static String MESSAGE_LOCATION = "location"; public final static String MESSAGE_EVENT = "event"; public final static String MESSAGE_SUBSCRIBE = "subscribe"; public final static String MESSAGE_UNSUBSCRIBE = "unsubscribe"; public final static String MESSAGE_CLICK = "CLICK"; public final static String MESSAGE_VIEW = "VIEW"; /** * xml转成map * @param request * @return * @throws Exception */ public static Map<String, String> xml2Map(HttpServletRequest request) throws Exception { Map<String, String> map = new HashMap<String,String>(); InputStream inputStream = request.getInputStream(); SAXReader reader = new SAXReader(); Document document = reader.read(inputStream); Element root = document.getRootElement(); List<Element> elements = root.elements(); for(Element element : elements){ map.put(element.getName(), element.getText()); } return map; } /** * 将文本消息对象转成XML * @param textMessage * @return */ public static String textMessage2XML(TextMessage textMessage) { XStream xStream = new XStream(); xStream.alias("xml", textMessage.getClass()); return xStream.toXML(textMessage); } }
在servlet中重写post方法
package com.imooc.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.imooc.po.TextMessage; import com.imooc.util.CheckUtil; import com.imooc.util.MessageUtil; import com.sun.xml.internal.ws.util.xml.XmlUtil; /** * Servlet implementation class WeixinServlet */ public class WeixinServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public WeixinServlet() { super(); // TODO Auto-generated constructor stub } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); PrintWriter out = response.getWriter(); if(CheckUtil.checkSignature(signature, timestamp, nonce)){ out.write(echostr); } } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Map<String, String> map = MessageUtil.xml2Map(request); String content = map.get(TextMessage.MESSAGE_Content); String toUserName = map.get(TextMessage.MESSAGE_ToUserName); String fromUserName = map.get(TextMessage.MESSAGE_FromUserName); String msgType = map.get(TextMessage.MESSAGE_MsgType); String message = null; if(MessageUtil.MESSAGE_TEXT.equals(msgType)){ TextMessage textMessage = new TextMessage(); textMessage.setContent("您发送的内容是" + content); textMessage.setToUserName(fromUserName); textMessage.setFromUserName(toUserName); textMessage.setMsgType(TextMessage.MESSAGE_MsgType_TEXT); textMessage.setCreateTime(new Date().getTime()); message = MessageUtil.textMessage2XML(textMessage); } System.out.println(message); out.write(message); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { out.close(); } } }
测试
在微信客户端输入内容,可以看到后台也显示出一样的内容。测试通过。微信开发进阶
使用公众测试号
根据开发者文档,个人订阅号开发的开发接口很少,而认证又需要公司资质,开发初期使用公众测试号。如何开通公众测试号?
进入微信公众号后台 -> 左侧菜单“开发者工具”-> 右侧内容页选择“公众平台测试账号”接下来操作根据页面提示,即可申请测试账号。
消息回复接口
图文消息
图文消息回复的XML结构
<xml> <ToUserName> <![CDATA[toUser]]> </ToUserName> <FromUserName> <![CDATA[fromUser]]> </FromUserName> <CreateTime>12345678</CreateTime> <MsgType> <![CDATA[news]]> </MsgType> <ArticleCount>2</ArticleCount> <Articles> <item> <Title> <![CDATA[title1]]> </Title> <Description> <![CDATA[description1]]> </Description> <PicUrl> <![CDATA[picurl]]> </PicUrl> <Url> <![CDATA创建图文消息的组装方法
/** * 图文消息的组装 * @param toUserName * @param fromUserName * @return */ public static String initNewsMessage(String toUserName , String fromUserName) { String message = null; NewsMessage newsMessage = new NewsMessage(); List<News> newsList = new ArrayList<News>(); News news1 = new News(); news1.setTitle("title1"); news1.setDescription("description1"); news1.setPicUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"); news1.setUrl("www.baidu.com"); newsList.add(news1); newsMessage.setFromUserName(toUserName); newsMessage.setToUserName(fromUserName); newsMessage.setCreateTime(new Date().getTime()); newsMessage.setMsgType("news"); newsMessage.setArticles(newsList); newsMessage.setArticleCount(newsList.size()); message = newsMessageToXML(newsMessage); return message; }测试方法
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Map<String, String> map = MessageUtil.xml2Map(request); String content = map.get(TextMessage.MESSAGE_Content); String toUserName = map.get(TextMessage.MESSAGE_ToUserName); String fromUserName = map.get(TextMessage.MESSAGE_FromUserName); String msgType = map.get(TextMessage.MESSAGE_MsgType); String message = null; if(MessageUtil.MESSAGE_TEXT.equals(msgType)){ if(content.equals("2")){ message = MessageUtil.initNewsMessage(toUserName, fromUserName); } } else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) { String eventType = map.get("Event"); if(MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)){ message = MessageUtil.initText(MessageUtil.menuText(), fromUserName, toUserName); } } System.out.println(message); out.write(message); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { out.close(); } }access_token获取(上)
什么是access_token?
access_token是公众号的全局唯一票据,所有接口都需要用access_token。access_token特点
access_token有效时间为2个小时,过了时间会失效
重复获取access_token,上次获取的access_token会失效。获取access_token
http请求方式: GET
[url=https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET]https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET" target=_blank>]>
</Url>
</item>
<item>
<Title>
<![CDATA[title]]>
</Title>
<Description>
<![CDATA[description]]>
</Description>
<PicUrl>
<![CDATA[picurl]]>
</PicUrl>
<Url>
<![CDATA[url]]>
</Url>
</item>
</Articles>
</xml>[/code]创建实体类映射xml
创建 BaseMessage.javapackage com.imooc.po; public class BaseMessage { private String ToUserName; private String FromUserName; private String 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 String getCreateTime() { return CreateTime; } public void setCreateTime(String createTime) { CreateTime = createTime; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { MsgType = msgType; } }
创建 News.javapackage com.imooc.po; public class News { private String Title; private String Description; private String PicUrl; private String Url; public String getTitle() { return Title; } public void setTitle(String title) { Title = title; } public String getDescription() { return Description; } public void setDescription(String description) { Description = description; } public String getPicUrl() { return PicUrl; } public void setPicUrl(String picUrl) { PicUrl = picUrl; } public String getUrl() { return Url; } public void setUrl(String url) { Url = url; } }
创建 NewsMessage.javapackage com.imooc.po; import java.util.List; public class NewsMessage extends BaseMessage { private int ArticleCount; private List<News> Articles; public int getArticleCount() { return ArticleCount; } public void setArticleCount(int articleCount) { ArticleCount = articleCount; } public List<News> getArticles() { return Articles; } public void setArticles(List<News> articles) { Articles = articles; } }创建方法把实体对象转xml
因微信后台只接收xml格式,我们需要把实体类转成xml格式/*** * 图文消息转XML * @param newsMessage * @return */ 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; NewsMessage newsMessage = new NewsMessage(); List<News> newsList = new ArrayList<News>(); News news1 = new News(); news1.setTitle("title1"); news1.setDescription("description1"); news1.setPicUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png"); news1.setUrl("www.baidu.com"); newsList.add(news1); newsMessage.setFromUserName(toUserName); newsMessage.setToUserName(fromUserName); newsMessage.setCreateTime(new Date().getTime()); newsMessage.setMsgType("news"); newsMessage.setArticles(newsList); newsMessage.setArticleCount(newsList.size()); message = newsMessageToXML(newsMessage); return message; }测试方法
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); try { Map<String, String> map = MessageUtil.xml2Map(request); String content = map.get(TextMessage.MESSAGE_Content); String toUserName = map.get(TextMessage.MESSAGE_ToUserName); String fromUserName = map.get(TextMessage.MESSAGE_FromUserName); String msgType = map.get(TextMessage.MESSAGE_MsgType); String message = null; if(MessageUtil.MESSAGE_TEXT.equals(msgType)){ if(content.equals("2")){ message = MessageUtil.initNewsMessage(toUserName, fromUserName); } } else if (MessageUtil.MESSAGE_EVENT.equals(msgType)) { String eventType = map.get("Event"); if(MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)){ message = MessageUtil.initText(MessageUtil.menuText(), fromUserName, toUserName); } } System.out.println(message); out.write(message); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { out.close(); } }access_token获取(上)
什么是access_token?
access_token是公众号的全局唯一票据,所有接口都需要用access_token。access_token特点
access_token有效时间为2个小时,过了时间会失效
重复获取access_token,上次获取的access_token会失效。获取access_token
http请求方式: GET
[url=https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET]https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数说明
参数 是否必须 说明
grant_type 是 获取access_token填写client_credential
appid 是 第三方用户唯一凭证
secret 是 第三方用户唯一凭证密钥,即appsecret创建WeixinUtil.class
因希望把get请求获取到的结果转为JSON格式,所以需要导入json-lib-2.3-jdk15.jar,这个包又依赖于commons-beanutils-1.7.0.jar,commons-collections-3.2.1.jar,commons-lang-2.5.jar,commons-logging-1.0.4.jar,ezmorph-1.0.6.jar。所以一共要导入6个包。
在服务器端用get请求获取数据,需要调用DefaultHttpClient类中的execute方法,此类在httpclient-4.2.5.jar,httpcore-4.2.4.jar这两个包里面,所以我们需要把这两个包导进来。
代码package com.imooc.util; import java.io.IOException; import net.sf.json.JSONObject; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; /** * 微信工具类 * @author Stephen * */ public class WeixinUtil { private static final String APPID = "wxdd76438574cc239e"; private static final String APPSECRET = "8fb4f41bd36156e171631d371750b519"; /** * get请求 * @param url * @return * @throws ParseException * @throws IOException */ public static JSONObject doGetStr(String url) throws ParseException, IOException{ DefaultHttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet(url); JSONObject jsonObject = null; HttpResponse httpResponse = client.execute(httpGet); HttpEntity entity = httpResponse.getEntity(); if(entity != null){ String result = EntityUtils.toString(entity,"UTF-8"); jsonObject = JSONObject.fromObject(result); } return jsonObject; } /** * POST请求 * @param url * @param outStr * @return * @throws ParseException * @throws IOException */ public static JSONObject doPostStr(String url,String outStr) throws ParseException, IOException{ DefaultHttpClient client = new DefaultHttpClient(); HttpPost httpost = new HttpPost(url); JSONObject jsonObject = null; httpost.setEntity(new StringEntity(outStr,"UTF-8")); HttpResponse response = client.execute(httpost); String result = EntityUtils.toString(response.getEntity(),"UTF-8"); jsonObject = JSONObject.fromObject(result); return jsonObject; } }素材管理接口
自定义菜单接口
百度翻译API
课程总结
相关文章推荐
- 人人,金山西山居,腾讯互娱,微信,网易游戏offer及面经
- VS 星期作业 if else的应用 做一个受不受异性欢迎的小程序
- 高仿微信新消息提示音功能
- 使用cookie实现记录浏览商品的过程并能够清空浏览记录(简单的小程序不涉及到数据库的调取)
- 使用JSSDK集成微信分享遇到的一些坑
- 【转】微信扫描二维码登录网页是什么原理?
- 微信抽奖类游戏设计
- Django:之中间件、微信接口和单元测试
- 微信公众号如何取名好?
- 微信公众号欢迎语怎么设置才有吸引力?
- ***微信LBS地理位置开发+百度地图API(地理位置和坐标转换)
- showPopupWindow 类似微信+
- Android学习之Android 5.0分享动画实现微信点击全屏效果
- 微信移动客户端内部浏览器分享到朋友圈,QQ空间代码
- 微信开放平台开发(3) 移动应用微信登录
- 微信开放平台开发(3) 移动应用微信登录
- 微信开放平台开发(3) 移动应用微信登录
- 微信硬件蓝牙开发各种坑不完全开发指南
- iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客
- iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客