java微信公众号开发案例
微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤:
1、首先你需要一个邮箱在微信公众号平台进行注册;
注册的方式有订阅号、公众号、小程序和企业号,个人我们这里只能选择订阅号
2、注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写url和token,url就是我们使用服务器的接口;
3、java web服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试:
1)、选择合适的接口
2)、系统会生成该接口的参数表,您可以直接在文本框内填入对应的参数值(红色星号表示该字段必填)
3)、点击检查问题按钮,即可得到相应的调试信息
eg:获取access_token的步骤:
1)、接口类型:基础支持
2)、接口列表:获取access_token接口/token
3)、填写相应的参数:grant_type、appid、secret
4)、点击检查问题
5)、验证成功会返回结果和提示,结果为:200 ok,提示:request successful即表示验证成功
我们这里验证比较多的是消息接口调试:文本消息、图片消息、语音消息、视频消息、etc
4、接口有不理解的地方,可进入开发-->开发者工具-->开发者文档进行查询
5、接口权限:订阅号主要有基础支持、接收消息及网页服务里面的一些接口
下面我们主要讲订阅号怎么样接收消息的案例:
1、需要申请一个个人微信订阅号
2、url服务器和服务器端代码部署(可以用腾讯云or阿里云服务器)
1)、accountsservlet.java类,验证来自微信服务器和微信服务器的消息处理
package cn.jon.wechat.servlet; import java.io.ioexception; import java.io.printwriter; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import cn.jon.wechat.service.accountsservice; import cn.jon.wechat.utils.signutil; public class accountsservlet extends httpservlet { public accountsservlet() { super(); } public void destroy() { super.destroy(); // put your code here } /** * 确认请求来自于微信服务器 */ public void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { system.out.println("接口测试开始!!!"); //微信加密签名 string signature = request.getparameter("signature"); //时间戳 string timestamp = request.getparameter("timestamp"); //随机数 string nonce = request.getparameter("nonce"); //随机字符串 string echostr = request.getparameter("echostr"); printwriter out = response.getwriter(); //通过校验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败 if(signutil.checksignature(signature,timestamp,nonce)){ out.print(echostr); } out.close(); out = null; // response.encoderedirecturl("success.jsp"); } /** * 处理微信服务器发来的消息 */ public void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { //消息的接受、处理、响应 request.setcharacterencoding("utf-8"); response.setcharacterencoding("utf-8"); //调用核心业务类型接受消息、处理消息 string respmessage = accountsservice.processrequest(request); //响应消息 printwriter out = response.getwriter(); out.print(respmessage); out.close(); } public void init() throws servletexception { // put your code here } }
2)、signutil.java类,请求校验工具类,token需要和微信中填写的token一致
package cn.jon.wechat.utils; import java.security.messagedigest; import java.security.nosuchalgorithmexception; import java.util.arrays; import java.util.iterator; import java.util.map; import java.util.set; import java.util.concurrent.concurrenthashmap; /** * 请求校验工具类 * @author jon */ public class signutil { //与微信配置中的的token一致 private static string token = ""; public static boolean checksignature(string signature, string timestamp, string nonce) { string[] arra = new string[]{token,timestamp,nonce}; //将signature,timestamp,nonce组成数组进行字典排序 arrays.sort(arra); stringbuilder sb = new stringbuilder(); for(int i=0;i<arra.length;i++){ sb.append(arra[i]); } messagedigest md = null; string stnstr = null; try { md = messagedigest.getinstance("sha-1"); byte[] digest = md.digest(sb.tostring().getbytes()); stnstr = bytetostr(digest); } catch (nosuchalgorithmexception e) { // todo auto-generated catch block e.printstacktrace(); } //释放内存 sb = null; //将sha1加密后的字符串与signature对比,标识该请求来源于微信 return stnstr!=null?stnstr.equals(signature.touppercase()):false; } /** * 将字节数组转换成十六进制字符串 * @param digestarra * @return */ private static string bytetostr(byte[] digestarra) { // todo auto-generated method stub string digeststr = ""; for(int i=0;i<digestarra.length;i++){ digeststr += bytetohexstr(digestarra[i]); } return digeststr; } /** * 将字节转换成为十六进制字符串 */ private static string bytetohexstr(byte dbyte) { // todo auto-generated method stub char[] digit = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; char[] tmparr = new char[2]; tmparr[0] = digit[(dbyte>>>4)&0x0f]; tmparr[1] = digit[dbyte&0x0f]; string s = new string(tmparr); return s; } public static void main(string[] args) { /*byte dbyte = 'a'; system.out.println(bytetohexstr(dbyte));*/ map<string,string> map = new concurrenthashmap<string, string>(); map.put("4", "zhangsan"); map.put("100", "lisi"); set set = map.keyset(); iterator iter = set.iterator(); while(iter.hasnext()){ // string keyv = (string) iter.next(); string key =(string)iter.next(); system.out.println(map.get(key)); // system.out.println(map.get(iter.next())); } /*for(int i=0;i<map.size();i++){ }*/ } }
3)、accountsservice.java服务类,主要是消息的请求和响应处理,并且当用户关注你的公众号的时候,可以设置默认推送消息
package cn.jon.wechat.service; import java.util.date; import java.util.map; import javax.servlet.http.httpservletrequest; import cn.jon.wechat.message.req.imagemessage; import cn.jon.wechat.message.req.linkmessage; import cn.jon.wechat.message.req.locationmessage; import cn.jon.wechat.message.req.videomessage; import cn.jon.wechat.message.req.voicemessage; import cn.jon.wechat.message.resp.textmessage; import cn.jon.wechat.utils.messageutil; /** * 解耦,使控制层与业务逻辑层分离开来,主要处理请求,响应 * @author jon */ public class accountsservice { public static string processrequest(httpservletrequest request) { string respmessage = null; //默认返回的文本消息内容 string respcontent = "请求处理异常,请稍后尝试!"; try { //xml请求解析 map<string,string> requestmap = messageutil.parexml(request); //发送方账号(open_id) string fromusername = requestmap.get("fromusername"); //公众账号 string tousername = requestmap.get("tousername"); //消息类型 string msgtype = requestmap.get("msgtype"); //默认回复此文本消息 textmessage defaulttextmessage = new textmessage(); defaulttextmessage.settousername(fromusername); defaulttextmessage.setfromusername(tousername); defaulttextmessage.setcreatetime(new date().gettime()); defaulttextmessage.setmsgtype(messageutil.messsage_type_text); defaulttextmessage.setfuncflag(0); // 由于href属性值必须用双引号引起,这与字符串本身的双引号冲突,所以要转义 defaulttextmessage.setcontent("欢迎访问<a href=\"http://blog.csdn.net/j086924\">jon的博客</a>!"); // defaulttextmessage.setcontent(getmainmenu()); // 将文本消息对象转换成xml字符串 respmessage = messageutil.textmessagetoxml(defaulttextmessage); //文本消息 if(msgtype.equals(messageutil.messsage_type_text)){ //respcontent = "hi,您发送的是文本消息!"; //回复文本消息 textmessage textmessage = new textmessage(); // textmessage.settousername(tousername); // textmessage.setfromusername(fromusername); //这里需要注意,否则无法回复消息给用户了 textmessage.settousername(fromusername); textmessage.setfromusername(tousername); textmessage.setcreatetime(new date().gettime()); textmessage.setmsgtype(messageutil.messsage_type_text); textmessage.setfuncflag(0); respcontent = "hi,你发的消息是:"+requestmap.get("content"); textmessage.setcontent(respcontent); respmessage = messageutil.textmessagetoxml(textmessage); } //图片消息 else if(msgtype.equals(messageutil.messsage_type_image)){ imagemessage imagemessage=new imagemessage(); imagemessage.settousername(fromusername); imagemessage.setfromusername(tousername); imagemessage.setcreatetime(new date().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); } //地理位置 else if(msgtype.equals(messageutil.messsage_type_location)){ locationmessage locationmessage=new locationmessage(); locationmessage.settousername(fromusername); locationmessage.setfromusername(tousername); locationmessage.setcreatetime(new date().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); } //视频消息 else if(msgtype.equals(messageutil.messsage_type_video)){ videomessage videomessage=new videomessage(); videomessage.settousername(fromusername); videomessage.setfromusername(tousername); videomessage.setcreatetime(new date().gettime()); videomessage.setmsgtype(messageutil.messsage_type_video); videomessage.setmediaid(requestmap.get("mediaid")); videomessage.setthumbmediaid(requestmap.get("thumbmediaid")); respmessage = messageutil.videomessagetoxml(videomessage); } //链接消息 else if(msgtype.equals(messageutil.messsage_type_link)){ linkmessage linkmessage=new linkmessage(); linkmessage.settousername(fromusername); linkmessage.setfromusername(tousername); linkmessage.setcreatetime(new date().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); } //语音消息 else if(msgtype.equals(messageutil.messsage_type_voice)){ voicemessage voicemessage=new voicemessage(); voicemessage.settousername(fromusername); voicemessage.setfromusername(tousername); voicemessage.setcreatetime(new date().gettime()); voicemessage.setmsgtype(messageutil.messsage_type_voice); voicemessage.setmediaid(requestmap.get("mediaid")); voicemessage.setformat(requestmap.get("format")); respmessage = messageutil.voicemessagetoxml(voicemessage); } //事件推送 else if(msgtype.equals(messageutil.messsage_type_event)){ //事件类型 string eventtype = requestmap.get("event"); //订阅 if(eventtype.equals(messageutil.event_type_subscribe)){ respcontent = "谢谢关注!"; } //取消订阅 else if(eventtype.equals(messageutil.event_type_unsubscribe)){ // system.out.println("取消订阅"); } else if(eventtype.equals(messageutil.event_type_click)){ //自定义菜单消息处理 system.out.println("自定义菜单消息处理"); } } } catch (exception e) { // todo auto-generated catch block e.printstacktrace(); } return respmessage; } public static string getmainmenu() { stringbuffer buffer =new stringbuffer(); 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"+"显示帮助菜单"); return buffer.tostring(); } }
4)、messageutil.java帮助类,包括常量的定义和xml消息转换和处理
package cn.jon.wechat.utils; import java.io.inputstream; import java.io.writer; 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 cn.jon.wechat.message.req.imagemessage; import cn.jon.wechat.message.req.linkmessage; import cn.jon.wechat.message.req.locationmessage; import cn.jon.wechat.message.req.videomessage; import cn.jon.wechat.message.req.voicemessage; import cn.jon.wechat.message.resp.article; import cn.jon.wechat.message.resp.musicmessage; import cn.jon.wechat.message.resp.newsmessage; import cn.jon.wechat.message.resp.textmessage; import com.thoughtworks.xstream.xstream; import com.thoughtworks.xstream.core.util.quickwriter; import com.thoughtworks.xstream.io.hierarchicalstreamwriter; import com.thoughtworks.xstream.io.xml.prettyprintwriter; import com.thoughtworks.xstream.io.xml.xppdriver; /** * 各种消息的处理类 * @author jon */ public class messageutil { /** * 文本类型 */ public static final string messsage_type_text = "text"; /** * 音乐类型 */ public static final string messsage_type_music = "music"; /** * 图文类型 */ public static final string messsage_type_news = "news"; /** * 视频类型 */ public static final string messsage_type_video = "video"; /** * 图片类型 */ public static final string messsage_type_image = "image"; /** * 链接类型 */ public static final string messsage_type_link = "link"; /** * 地理位置类型 */ public static final string messsage_type_location = "location"; /** * 音频类型 */ public static final string messsage_type_voice = "voice"; /** * 推送类型 */ public static final string messsage_type_event = "event"; /** * 事件类型:subscribe(订阅) */ public static final string event_type_subscribe = "subscribe"; /** * 事件类型:unsubscribe(取消订阅) */ public static final string event_type_unsubscribe = "unsubscribe"; /** * 事件类型:click(自定义菜单点击事件) */ public static final string event_type_click= "click"; /** * 解析微信发来的请求 xml */ @suppresswarnings("unchecked") public static map<string,string> parexml(httpservletrequest request) throws exception { //将解析的结果存储在hashmap中 map<string,string> reqmap = new hashmap<string, string>(); //从request中取得输入流 inputstream inputstream = request.getinputstream(); //读取输入流 saxreader reader = new saxreader(); document document = reader.read(inputstream); //得到xml根元素 element root = document.getrootelement(); //得到根元素的所有子节点 list<element> elementlist = root.elements(); //遍历所有的子节点取得信息类容 for(element elem:elementlist){ reqmap.put(elem.getname(),elem.gettext()); } //释放资源 inputstream.close(); inputstream = null; return reqmap; } /** * 响应消息转换成xml返回 * 文本对象转换成xml */ public static string textmessagetoxml(textmessage textmessage) { xstream.alias("xml", textmessage.getclass()); return xstream.toxml(textmessage); } /** * 语音对象的转换成xml * */ public static string voicemessagetoxml(voicemessage voicemessage) { xstream.alias("xml", voicemessage.getclass()); return xstream.toxml(voicemessage); } /** * 视频对象的转换成xml * */ public static string videomessagetoxml(videomessage videomessage) { xstream.alias("xml", videomessage.getclass()); return xstream.toxml(videomessage); } /** * 音乐对象的转换成xml * */ public static string musicmessagetoxml(musicmessage musicmessage) { xstream.alias("xml", musicmessage.getclass()); return xstream.toxml(musicmessage); } /** * 图文对象转换成xml * */ public static string newsmessagetoxml(newsmessage newsmessage) { xstream.alias("xml", newsmessage.getclass()); xstream.alias("item", new article().getclass()); return xstream.toxml(newsmessage); } /** * 图片对象转换成xml * */ public static string imagemessagetoxml(imagemessage imagemessage) { xstream.alias("xml",imagemessage.getclass()); return xstream.toxml(imagemessage); } /** * 链接对象转换成xml * */ public static string linkmessagetoxml(linkmessage linkmessage) { xstream.alias("xml",linkmessage.getclass()); return xstream.toxml(linkmessage); } /** * 地理位置对象转换成xml * */ public static string locationmessagetoxml(locationmessage locationmessage) { xstream.alias("xml",locationmessage.getclass()); return xstream.toxml(locationmessage); } /** * 拓展xstream,使得支持cdata块 * */ private static xstream xstream = new xstream(new xppdriver(){ public hierarchicalstreamwriter createwriter(writer out){ return new prettyprintwriter(out){ //对所有的xml节点的转换都增加cdata标记 boolean cdata = true; @suppresswarnings("unchecked") public void startnode(string name,class clazz){ super.startnode(name,clazz); } protected void writetext(quickwriter writer,string text){ if(cdata){ writer.write("<![cdata["); writer.write(text); writer.write("]]>"); }else{ writer.write(text); } } }; } }); }
5)、basemessage.java消息基类(包括:开发者微信号、用户账户、创建时间、消息类型、消息id变量),文本、视频、图片消息都会继承此基类,在此基础上扩展自己的变量,可根据开发者文档中的各种消息属性进行定义
package cn.jon.wechat.message.req; /** * 消息基类 (普通用户-公众号) * @author jon */ public class basemessage { //开发者微信号 private string tousername; //发送方账号(一个openid) private string fromusername; //消息创建时间(整型) private long createtime; //消息类型(text/image/location/link...) private string msgtype; //消息id 64位整型 private string msgid; public basemessage() { super(); // todo auto-generated constructor stub } public basemessage(string tousername, string fromusername, long createtime, string msgtype, string msgid) { super(); tousername = tousername; fromusername = fromusername; createtime = createtime; msgtype = msgtype; msgid = msgid; } 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; } public string getmsgid() { return msgid; } public void setmsgid(string msgid) { msgid = msgid; } }
6)、textmessage.java文本消息,继承自5中基类,扩展内容属性
package cn.jon.wechat.message.req; /** * 文本消息 * @author jon */ public class textmessage extends basemessage{ //消息内容 private string content; public string getcontent() { return content; } public void setcontent(string content) { this.content = content; } }
7)、imagemessage.java图片消息
package cn.jon.wechat.message.req; /** * 图片消息 * @author jon */ public class imagemessage extends basemessage{ //图片链接 private string picurl; public string getpicurl() { return picurl; } public void setpicurl(string picurl) { picurl = picurl; } }
8)、videomessage.java视频消息
package cn.jon.wechat.message.req; public class videomessage extends basemessage { private string mediaid; private string thumbmediaid; public string getmediaid() { return mediaid; } public void setmediaid(string mediaid) { this.mediaid = mediaid; } public string getthumbmediaid() { return thumbmediaid; } public void setthumbmediaid(string thumbmediaid) { this.thumbmediaid = thumbmediaid; } }
其他消息类可根据开发者文档自行进行完成,另外,开发者也可以申请公众平台测试账号,对开发的相关内容进行测试。
本文已被整理到了《android微信开发教程汇总》,《java微信开发教程汇总》欢迎大家学习阅读。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: Simple JSON开发指南