您的位置:首页 > 移动开发 > 微信开发

微信开发

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.java

package 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.java

package 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.java

package 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

课程总结

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: