java微信公众号开发案例
微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤:
1、首先你需要一个邮箱在微信公众号平台进行注册;
注册的方式有订阅号、公众号、小程序和企业号,个人我们这里只能选择订阅号
2、注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写URL和token,URL就是我们使用服务器的接口;
3、JavaWeb服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试:
1)、选择合适的接口
2)、系统会生成该接口的参数表,您可以直接在文本框内填入对应的参数值(红色星号表示该字段必填)
3)、点击检查问题按钮,即可得到相应的调试信息
eg:获取access_token的步骤:
1)、接口类型:基础支持
2)、接口列表:获取access_token接口/token
3)、填写相应的参数:grant_type、appid、secret
4)、点击检查问题
5)、验证成功会返回结果和提示,结果为:200ok,提示:Requestsuccessful即表示验证成功
我们这里验证比较多的是消息接口调试:文本消息、图片消息、语音消息、视频消息、etc
4、接口有不理解的地方,可进入开发-->开发者工具-->开发者文档进行查询
5、接口权限:订阅号主要有基础支持、接收消息及网页服务里面的一些接口
下面我们主要讲订阅号怎么样接收消息的案例:
1、需要申请一个个人微信订阅号
2、url服务器和服务器端代码部署(可以用腾讯云or阿里云服务器)
1)、AccountsServlet.java类,验证来自微信服务器和微信服务器的消息处理
packagecn.jon.wechat.servlet;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcn.jon.wechat.service.AccountsService;
importcn.jon.wechat.utils.SignUtil;
publicclassAccountsServletextendsHttpServlet{
publicAccountsServlet(){
super();
}
publicvoiddestroy(){
super.destroy();
//Putyourcodehere
}
/**
*确认请求来自于微信服务器
*/
publicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
System.out.println("接口测试开始!!!");
//微信加密签名
Stringsignature=request.getParameter("signature");
//时间戳
Stringtimestamp=request.getParameter("timestamp");
//随机数
Stringnonce=request.getParameter("nonce");
//随机字符串
Stringechostr=request.getParameter("echostr");
PrintWriterout=response.getWriter();
//通过校验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if(SignUtil.checkSignature(signature,timestamp,nonce)){
out.print(echostr);
}
out.close();
out=null;
//response.encodeRedirectURL("success.jsp");
}
/**
*处理微信服务器发来的消息
*/
publicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException{
//消息的接受、处理、响应
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
//调用核心业务类型接受消息、处理消息
StringrespMessage=AccountsService.processRequest(request);
//响应消息
PrintWriterout=response.getWriter();
out.print(respMessage);
out.close();
}
publicvoidinit()throwsServletException{
//Putyourcodehere
}
}
2)、SignUtil.java类,请求校验工具类,token需要和微信中填写的token一致
packagecn.jon.wechat.utils;
importjava.security.MessageDigest;
importjava.security.NoSuchAlgorithmException;
importjava.util.Arrays;
importjava.util.Iterator;
importjava.util.Map;
importjava.util.Set;
importjava.util.concurrent.ConcurrentHashMap;
/**
*请求校验工具类
*@authorjon
*/
publicclassSignUtil{
//与微信配置中的的Token一致
privatestaticStringtoken="";
publicstaticbooleancheckSignature(Stringsignature,Stringtimestamp,
Stringnonce){
String[]arra=newString[]{token,timestamp,nonce};
//将signature,timestamp,nonce组成数组进行字典排序
Arrays.sort(arra);
StringBuildersb=newStringBuilder();
for(inti=0;i<arra.length;i++){
sb.append(arra[i]);
}
MessageDigestmd=null;
StringstnStr=null;
try{
md=MessageDigest.getInstance("SHA-1");
byte[]digest=md.digest(sb.toString().getBytes());
stnStr=byteToStr(digest);
}catch(NoSuchAlgorithmExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
//释放内存
sb=null;
//将sha1加密后的字符串与signature对比,标识该请求来源于微信
returnstnStr!=null?stnStr.equals(signature.toUpperCase()):false;
}
/**
*将字节数组转换成十六进制字符串
*@paramdigestArra
*@return
*/
privatestaticStringbyteToStr(byte[]digestArra){
//TODOAuto-generatedmethodstub
StringdigestStr="";
for(inti=0;i<digestArra.length;i++){
digestStr+=byteToHexStr(digestArra[i]);
}
returndigestStr;
}
/**
*将字节转换成为十六进制字符串
*/
privatestaticStringbyteToHexStr(bytedByte){
//TODOAuto-generatedmethodstub
char[]Digit={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
char[]tmpArr=newchar[2];
tmpArr[0]=Digit[(dByte>>>4)&0X0F];
tmpArr[1]=Digit[dByte&0X0F];
Strings=newString(tmpArr);
returns;
}
publicstaticvoidmain(String[]args){
/*bytedByte='A';
System.out.println(byteToHexStr(dByte));*/
Map<String,String>map=newConcurrentHashMap<String,String>();
map.put("4","zhangsan");
map.put("100","lisi");
Setset=map.keySet();
Iteratoriter=set.iterator();
while(iter.hasNext()){
//StringkeyV=(String)iter.next();
Stringkey=(String)iter.next();
System.out.println(map.get(key));
//System.out.println(map.get(iter.next()));
}
/*for(inti=0;i<map.size();i++){
}*/
}
}
3)、AccountsService.java服务类,主要是消息的请求和响应处理,并且当用户关注你的公众号的时候,可以设置默认推送消息
packagecn.jon.wechat.service;
importjava.util.Date;
importjava.util.Map;
importjavax.servlet.http.HttpServletRequest;
importcn.jon.wechat.message.req.ImageMessage;
importcn.jon.wechat.message.req.LinkMessage;
importcn.jon.wechat.message.req.LocationMessage;
importcn.jon.wechat.message.req.VideoMessage;
importcn.jon.wechat.message.req.VoiceMessage;
importcn.jon.wechat.message.resp.TextMessage;
importcn.jon.wechat.utils.MessageUtil;
/**
*解耦,使控制层与业务逻辑层分离开来,主要处理请求,响应
*@authorjon
*/
publicclassAccountsService{
publicstaticStringprocessRequest(HttpServletRequestrequest){
StringrespMessage=null;
//默认返回的文本消息内容
StringrespContent="请求处理异常,请稍后尝试!";
try{
//xml请求解析
Map<String,String>requestMap=MessageUtil.pareXml(request);
//发送方账号(open_id)
StringfromUserName=requestMap.get("FromUserName");
//公众账号
StringtoUserName=requestMap.get("ToUserName");
//消息类型
StringmsgType=requestMap.get("MsgType");
//默认回复此文本消息
TextMessagedefaultTextMessage=newTextMessage();
defaultTextMessage.setToUserName(fromUserName);
defaultTextMessage.setFromUserName(toUserName);
defaultTextMessage.setCreateTime(newDate().getTime());
defaultTextMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT);
defaultTextMessage.setFuncFlag(0);
//由于href属性值必须用双引号引起,这与字符串本身的双引号冲突,所以要转义
defaultTextMessage.setContent("欢迎访问<ahref=\"http://blog.csdn.net/j086924\">jon的博客</a>!");
//defaultTextMessage.setContent(getMainMenu());
//将文本消息对象转换成xml字符串
respMessage=MessageUtil.textMessageToXml(defaultTextMessage);
//文本消息
if(msgType.equals(MessageUtil.MESSSAGE_TYPE_TEXT)){
//respContent="Hi,您发送的是文本消息!";
//回复文本消息
TextMessagetextMessage=newTextMessage();
//textMessage.setToUserName(toUserName);
//textMessage.setFromUserName(fromUserName);
//这里需要注意,否则无法回复消息给用户了
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(newDate().getTime());
textMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_TEXT);
textMessage.setFuncFlag(0);
respContent="Hi,你发的消息是:"+requestMap.get("Content");
textMessage.setContent(respContent);
respMessage=MessageUtil.textMessageToXml(textMessage);
}
//图片消息
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_IMAGE)){
ImageMessageimageMessage=newImageMessage();
imageMessage.setToUserName(fromUserName);
imageMessage.setFromUserName(toUserName);
imageMessage.setCreateTime(newDate().getTime());
imageMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_IMAGE);
//respContent=requestMap.get("PicUrl");
imageMessage.setPicUrl("http://img24.pplive.cn//2013//07//24//12103112092_230X306.jpg");
respMessage=MessageUtil.imageMessageToXml(imageMessage);
}
//地理位置
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_LOCATION)){
LocationMessagelocationMessage=newLocationMessage();
locationMessage.setToUserName(fromUserName);
locationMessage.setFromUserName(toUserName);
locationMessage.setCreateTime(newDate().getTime());
locationMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LOCATION);
locationMessage.setLocation_X(requestMap.get("Location_X"));
locationMessage.setLocation_Y(requestMap.get("Location_Y"));
locationMessage.setScale(requestMap.get("Scale"));
locationMessage.setLabel(requestMap.get("Label"));
respMessage=MessageUtil.locationMessageToXml(locationMessage);
}
//视频消息
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_VIDEO)){
VideoMessagevideoMessage=newVideoMessage();
videoMessage.setToUserName(fromUserName);
videoMessage.setFromUserName(toUserName);
videoMessage.setCreateTime(newDate().getTime());
videoMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VIDEO);
videoMessage.setMediaId(requestMap.get("MediaId"));
videoMessage.setThumbMediaId(requestMap.get("ThumbMediaId"));
respMessage=MessageUtil.videoMessageToXml(videoMessage);
}
//链接消息
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_LINK)){
LinkMessagelinkMessage=newLinkMessage();
linkMessage.setToUserName(fromUserName);
linkMessage.setFromUserName(toUserName);
linkMessage.setCreateTime(newDate().getTime());
linkMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_LINK);
linkMessage.setTitle(requestMap.get("Title"));
linkMessage.setDescription(requestMap.get("Description"));
linkMessage.setUrl(requestMap.get("Url"));
respMessage=MessageUtil.linkMessageToXml(linkMessage);
}
//语音消息
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_VOICE)){
VoiceMessagevoiceMessage=newVoiceMessage();
voiceMessage.setToUserName(fromUserName);
voiceMessage.setFromUserName(toUserName);
voiceMessage.setCreateTime(newDate().getTime());
voiceMessage.setMsgType(MessageUtil.MESSSAGE_TYPE_VOICE);
voiceMessage.setMediaId(requestMap.get("MediaId"));
voiceMessage.setFormat(requestMap.get("Format"));
respMessage=MessageUtil.voiceMessageToXml(voiceMessage);
}
//事件推送
elseif(msgType.equals(MessageUtil.MESSSAGE_TYPE_EVENT)){
//事件类型
StringeventType=requestMap.get("Event");
//订阅
if(eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)){
respContent="谢谢关注!";
}
//取消订阅
elseif(eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)){
//
System.out.println("取消订阅");
}
elseif(eventType.equals(MessageUtil.EVENT_TYPE_CLICK)){
//自定义菜单消息处理
System.out.println("自定义菜单消息处理");
}
}
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnrespMessage;
}
publicstaticStringgetMainMenu()
{
StringBufferbuffer=newStringBuffer();
buffer.append("您好,我是jon,请回复数字选择服务:").append("\n");
buffer.append("1、我的博客").append("\n");
buffer.append("2、歌曲点播").append("\n");
buffer.append("3、经典游戏").append("\n");
buffer.append("4、聊天打牌").append("\n\n");
buffer.append("回复"+"0"+"显示帮助菜单");
returnbuffer.toString();
}
}
4)、MessageUtil.java帮助类,包括常量的定义和xml消息转换和处理
packagecn.jon.wechat.utils;
importjava.io.InputStream;
importjava.io.Writer;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjavax.servlet.http.HttpServletRequest;
importorg.dom4j.Document;
importorg.dom4j.Element;
importorg.dom4j.io.SAXReader;
importcn.jon.wechat.message.req.ImageMessage;
importcn.jon.wechat.message.req.LinkMessage;
importcn.jon.wechat.message.req.LocationMessage;
importcn.jon.wechat.message.req.VideoMessage;
importcn.jon.wechat.message.req.VoiceMessage;
importcn.jon.wechat.message.resp.Article;
importcn.jon.wechat.message.resp.MusicMessage;
importcn.jon.wechat.message.resp.NewsMessage;
importcn.jon.wechat.message.resp.TextMessage;
importcom.thoughtworks.xstream.XStream;
importcom.thoughtworks.xstream.core.util.QuickWriter;
importcom.thoughtworks.xstream.io.HierarchicalStreamWriter;
importcom.thoughtworks.xstream.io.xml.PrettyPrintWriter;
importcom.thoughtworks.xstream.io.xml.XppDriver;
/**
*各种消息的处理类
*@authorjon
*/
publicclassMessageUtil{
/**
*文本类型
*/
publicstaticfinalStringMESSSAGE_TYPE_TEXT="text";
/**
*音乐类型
*/
publicstaticfinalStringMESSSAGE_TYPE_MUSIC="music";
/**
*图文类型
*/
publicstaticfinalStringMESSSAGE_TYPE_NEWS="news";
/**
*视频类型
*/
publicstaticfinalStringMESSSAGE_TYPE_VIDEO="video";
/**
*图片类型
*/
publicstaticfinalStringMESSSAGE_TYPE_IMAGE="image";
/**
*链接类型
*/
publicstaticfinalStringMESSSAGE_TYPE_LINK="link";
/**
*地理位置类型
*/
publicstaticfinalStringMESSSAGE_TYPE_LOCATION="location";
/**
*音频类型
*/
publicstaticfinalStringMESSSAGE_TYPE_VOICE="voice";
/**
*推送类型
*/
publicstaticfinalStringMESSSAGE_TYPE_EVENT="event";
/**
*事件类型:subscribe(订阅)
*/
publicstaticfinalStringEVENT_TYPE_SUBSCRIBE="subscribe";
/**
*事件类型:unsubscribe(取消订阅)
*/
publicstaticfinalStringEVENT_TYPE_UNSUBSCRIBE="unsubscribe";
/**
*事件类型:click(自定义菜单点击事件)
*/
publicstaticfinalStringEVENT_TYPE_CLICK="CLICK";
/**
*解析微信发来的请求XML
*/
@SuppressWarnings("unchecked")
publicstaticMap<String,String>pareXml(HttpServletRequestrequest)throwsException{
//将解析的结果存储在HashMap中
Map<String,String>reqMap=newHashMap<String,String>();
//从request中取得输入流
InputStreaminputStream=request.getInputStream();
//读取输入流
SAXReaderreader=newSAXReader();
Documentdocument=reader.read(inputStream);
//得到xml根元素
Elementroot=document.getRootElement();
//得到根元素的所有子节点
List<Element>elementList=root.elements();
//遍历所有的子节点取得信息类容
for(Elementelem:elementList){
reqMap.put(elem.getName(),elem.getText());
}
//释放资源
inputStream.close();
inputStream=null;
returnreqMap;
}
/**
*响应消息转换成xml返回
*文本对象转换成xml
*/
publicstaticStringtextMessageToXml(TextMessagetextMessage){
xstream.alias("xml",textMessage.getClass());
returnxstream.toXML(textMessage);
}
/**
*语音对象的转换成xml
*
*/
publicstaticStringvoiceMessageToXml(VoiceMessagevoiceMessage){
xstream.alias("xml",voiceMessage.getClass());
returnxstream.toXML(voiceMessage);
}
/**
*视频对象的转换成xml
*
*/
publicstaticStringvideoMessageToXml(VideoMessagevideoMessage){
xstream.alias("xml",videoMessage.getClass());
returnxstream.toXML(videoMessage);
}
/**
*音乐对象的转换成xml
*
*/
publicstaticStringmusicMessageToXml(MusicMessagemusicMessage){
xstream.alias("xml",musicMessage.getClass());
returnxstream.toXML(musicMessage);
}
/**
*图文对象转换成xml
*
*/
publicstaticStringnewsMessageToXml(NewsMessagenewsMessage){
xstream.alias("xml",newsMessage.getClass());
xstream.alias("item",newArticle().getClass());
returnxstream.toXML(newsMessage);
}
/**
*图片对象转换成xml
*
*/
publicstaticStringimageMessageToXml(ImageMessageimageMessage)
{
xstream.alias("xml",imageMessage.getClass());
returnxstream.toXML(imageMessage);
}
/**
*链接对象转换成xml
*
*/
publicstaticStringlinkMessageToXml(LinkMessagelinkMessage)
{
xstream.alias("xml",linkMessage.getClass());
returnxstream.toXML(linkMessage);
}
/**
*地理位置对象转换成xml
*
*/
publicstaticStringlocationMessageToXml(LocationMessagelocationMessage)
{
xstream.alias("xml",locationMessage.getClass());
returnxstream.toXML(locationMessage);
}
/**
*拓展xstream,使得支持CDATA块
*
*/
privatestaticXStreamxstream=newXStream(newXppDriver(){
publicHierarchicalStreamWritercreateWriter(Writerout){
returnnewPrettyPrintWriter(out){
//对所有的xml节点的转换都增加CDATA标记
booleancdata=true;
@SuppressWarnings("unchecked")
publicvoidstartNode(Stringname,Classclazz){
super.startNode(name,clazz);
}
protectedvoidwriteText(QuickWriterwriter,Stringtext){
if(cdata){
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
}else{
writer.write(text);
}
}
};
}
});
}
5)、BaseMessage.java消息基类(包括:开发者微信号、用户账户、创建时间、消息类型、消息ID变量),文本、视频、图片消息都会继承此基类,在此基础上扩展自己的变量,可根据开发者文档中的各种消息属性进行定义
packagecn.jon.wechat.message.req;
/**
*消息基类(普通用户-公众号)
*@authorjon
*/
publicclassBaseMessage{
//开发者微信号
privateStringToUserName;
//发送方账号(一个openId)
privateStringFromUserName;
//消息创建时间(整型)
privatelongCreateTime;
//消息类型(text/image/location/link...)
privateStringMsgType;
//消息id64位整型
privateStringMsgId;
publicBaseMessage(){
super();
//TODOAuto-generatedconstructorstub
}
publicBaseMessage(StringtoUserName,StringfromUserName,longcreateTime,
StringmsgType,StringmsgId){
super();
ToUserName=toUserName;
FromUserName=fromUserName;
CreateTime=createTime;
MsgType=msgType;
MsgId=msgId;
}
publicStringgetToUserName(){
returnToUserName;
}
publicvoidsetToUserName(StringtoUserName){
ToUserName=toUserName;
}
publicStringgetFromUserName(){
returnFromUserName;
}
publicvoidsetFromUserName(StringfromUserName){
FromUserName=fromUserName;
}
publiclonggetCreateTime(){
returnCreateTime;
}
publicvoidsetCreateTime(longcreateTime){
CreateTime=createTime;
}
publicStringgetMsgType(){
returnMsgType;
}
publicvoidsetMsgType(StringmsgType){
MsgType=msgType;
}
publicStringgetMsgId(){
returnMsgId;
}
publicvoidsetMsgId(StringmsgId){
MsgId=msgId;
}
}
6)、TextMessage.java文本消息,继承自5中基类,扩展内容属性
packagecn.jon.wechat.message.req;
/**
*文本消息
*@authorjon
*/
publicclassTextMessageextendsBaseMessage{
//消息内容
privateStringcontent;
publicStringgetContent(){
returncontent;
}
publicvoidsetContent(Stringcontent){
this.content=content;
}
}
7)、ImageMessage.java图片消息
packagecn.jon.wechat.message.req;
/**
*图片消息
*@authorjon
*/
publicclassImageMessageextendsBaseMessage{
//图片链接
privateStringPicUrl;
publicStringgetPicUrl(){
returnPicUrl;
}
publicvoidsetPicUrl(StringpicUrl){
PicUrl=picUrl;
}
}
8)、VideoMessage.java视频消息
packagecn.jon.wechat.message.req;
publicclassVideoMessageextendsBaseMessage{
privateStringmediaId;
privateStringthumbMediaId;
publicStringgetMediaId(){
returnmediaId;
}
publicvoidsetMediaId(StringmediaId){
this.mediaId=mediaId;
}
publicStringgetThumbMediaId(){
returnthumbMediaId;
}
publicvoidsetThumbMediaId(StringthumbMediaId){
this.thumbMediaId=thumbMediaId;
}
}
其他消息类可根据开发者文档自行进行完成,另外,开发者也可以申请公众平台测试账号,对开发的相关内容进行测试。
本文已被整理到了《Android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。