欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

java微信公众号开发案例

程序员文章站 2024-03-12 08:25:26
微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤: 1、首先你需要一个邮箱在微信公众号平台进...

微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤

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微信开发教程汇总》欢迎大家学习阅读。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇: PHP图片水印类的封装

下一篇: