大家好,又见面了,我是你们的朋友全栈君。
笔者最近在为一个艺考服务团队开发手机端的服务,由于开发app需要的时间较长,所以选择开发微信公众号。本人比较擅长Java开发,所以本文是基于Java语言的公众号开发。话不多说,直接进入正题。
准备工作:
一、在微信公众平台申请账号。
百度搜索微信公众平台,点击注册,通过邮箱注册成功后会看到如下画面。
在这里,选择类型时要注意下。如果你是个人开发的话只能选择订阅号,订阅号没有自定义菜单等接口,具体接口权限你可以登录公众平台后在开发—>接口权限中看到。如果你想拥有自定义菜单等接口,需要注册服务号,但是服务号只能企业、组织等注册。本人想做的公众号是要求有自定义菜单的,并且委托我开发的团队是一家公司,所以注册的服务号。无论你是订阅号还是服务号都不影响本文的阅读。
注册完登录进入公众平台,微信会给你分配属于你的AppID和AppSecret,在开发—>基本配置中可以看到。有了这两个ID和密钥你就可以开发你的公众号了。以上为准备工作。
代码编写
一、创建自定义菜单(不需要自定义菜单的读者可以跳过该节)
本文中没有使用Java框架,采用的是原生jdbc和servlet,这样可以确保在云服务器配置有限的情况下提升公众号的响应速度。
新建CreateMenuServlet,该servlet用于创建自定义菜单。doGet方法中的代码如下:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 第三方用户唯一凭证 String appId = “你的APPID”; // 第三方用户唯一凭证密钥 String appSecret = “你的appSecret”; // 调用接口获取access_token AccessToken at = WeixinUtil.getAccessToken(appId, appSecret); if (null != at) { // 调用接口创建菜单 int result = WeixinUtil.createMenu(getMenu(), at.getToken()); // 判断菜单创建结果 if (0 == result){ response.setContentType(“text/html;charset=UTF-8”); PrintWriter pw = response.getWriter(); pw.println(“菜单创建成功!”); pw.flush(); }else{ response.setContentType(“text/html;charset=UTF-8”); PrintWriter pw = response.getWriter(); pw.println(“菜单创建失败,错误码:” result); pw.flush(); } } }
AccessToken类代码如下:
public class AccessToken { // 获取到的凭证 private String token; // 凭证有效时间,单位:秒 private int expiresIn; public String getToken() { return token; } public void setToken(String token) { this.token = token; } public int getExpiresIn() { return expiresIn; } public void setExpiresIn(int expiresIn) { this.expiresIn = expiresIn; } }
WeixinUtil类主要功能是用于调用微信提供的接口来创建菜单,因全部代码过长,不便贴出,会在后面的源码中给出。
getMenu方法代码如下,其中Menu、CommonButton等是我自定义的类,它可以实现一级菜单、二级菜单等效果。每一个按钮都有它自己的Type和key,type用于说明该按钮的类型,即点击之后回复消息还是跳转网页;key用于唯一定义该按钮,后面会通过这个key来判断哪个按钮被点击了。
private static Menu getMenu() { CommonButton btn11 = new CommonButton(); btn11.setName(“个人信息查看”); btn11.setType(“click”); btn11.setKey(“stuInfoView”); CommonButton btn12 = new CommonButton(); btn12.setName(“个人信息修改”); btn12.setType(“click”); btn12.setKey(“stuInfoEdit”); CommonButton btn21 = new CommonButton(); btn21.setName(“行程查看”); btn21.setType(“click”); btn21.setKey(“stuTravelView”); CommonButton btn22 = new CommonButton(); btn22.setName(“行程添加”); btn22.setType(“click”); btn22.setKey(“stuTravelAdd”); CommonButton btn23 = new CommonButton(); btn23.setName(“行程修改”); btn23.setType(“click”); btn23.setKey(“stuTravelEdit”); ComplexButton mainBtn1 = new ComplexButton(); mainBtn1.setName(“个人信息”); mainBtn1.setSub_button(new Button[] { btn11, btn12}); Menu menu = new Menu(); menu.setButton(new Button[] { mainBtn1, mainBtn2, mainBtn3 }); return menu; }
在浏览器中运行localhost:8080/WechatDemo/CreateMenuServlet,如果页面显示“菜单创建成功!”说明菜单已创建,在公众号中效果如下图:
二、接收消息并作出响应
新建EastnetServlet,该Servlet用于公众号接收用户的消息并作出响应返回给用户。
doGet方法代码如下:
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; }
SignUtil类中checkSignature方法代码如下:
private static String token = “你的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; }
token设置在开发—>基本配置中有Token(令牌),上面的token要和公众号中设置的token一致。
以上doGet方法中的代码是用于确认请求来源于微信服务器,满足微信API。
doPost方法中代码如下:
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //消息的接受、处理、响应 request.setCharacterEncoding(“utf-8”); response.setCharacterEncoding(“utf-8”); //调用核心业务类型接受消息、处理消息 String respMessage = EastnetService.processRequest(request);
//响应消息 PrintWriter out = response.getWriter(); out.print(respMessage); out.close(); }
doPost中用于处理接收到的消息,其中EastnetService为业务层,专门用于处理消息并作出响应。
EastnetService中processRequest方法部分代码如下:
public static String processRequest(HttpServletRequest request) { String respMessage = null; //默认返回的文本消息类容 String respContent = “请求处理异常,请稍后尝试!”; String fromUserName=””; String toUserName =””; String msgType =””; try { //xml请求解析 Map<String,String> requestMap = MessageUtil.pareXml(request);
//发送方账号(open_id) fromUserName = requestMap.get(“FromUserName”); //公众账号 toUserName = requestMap.get(“ToUserName”); //消息类型 msgType = requestMap.get(“MsgType”); // String eventType = requestMap.get(“Event”); String fromContent=requestMap.get(“Content”); String userName=””; if((MessageUtil.REQ_MESSSAGE_TYPE_EVENT).equals(msgType)){ // 事件类型 String eventType = requestMap.get(“Event”); if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) { // 事件KEY值,与创建自定义菜单时指定的KEY值对应 String eventKey = requestMap.get(“EventKey”); if (“stuInfoEdit”.equals(eventKey)) {//个人信息修改 respContent=new OperatorUtil().editStuInfo(fromUserName); }else if(“stuInfoView”.equals(eventKey)){ respContent=new OperatorUtil().viewStuInfo(fromUserName); }else if(“stuTravelView”.equals(eventKey)){//行程查看 respContent=new OperatorUtil().viewTravel(fromUserName); }else if(“stuTravelAdd”.equals(eventKey)){//行程添加 respContent=new OperatorUtil().addTravel(fromUserName); }else if(“stuTravelEdit”.equals(eventKey)){//行程修改 respContent=new OperatorUtil().editTravel(fromUserName); }else{ respContent=”请求失败”; } } } //订阅 String eventTypeSub = requestMap.get(“Event”); if((MessageUtil.EVENT_TYPE_SUBSCRIBE).equals(eventTypeSub)){ respContent = “景程教育欢迎您的到来! n 回复”用户名绑定” 登录用户名 如:用户名绑定fangw 可完成账号绑定!n 只有绑定账号后才可以实现接下来的操作”; } //回复文本消息 TextMessage textMessage = new TextMessage(); textMessage.setToUserName(toUserName); textMessage.setFromUserName(fromUserName); textMessage.setCreateTime(new Date().getTime()); textMessage.setMsgType(MessageUtil.RESP_MESSSAGE_TYPE_TEXT); textMessage.setFuncFlag(0); StringBuffer sb=new StringBuffer(); respMessage=(“<xml><ToUserName><![CDATA[“ requestMap.get(“FromUserName”) “]]></ToUserName>” ”<FromUserName><![CDATA[“ requestMap.get(“ToUserName”) ”]]></FromUserName><CreateTime>” System.currentTimeMillis() ”</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[“ respContent ”]]></Content></xml>”); } catch (Exception e) { respMessage=(“<xml><ToUserName><![CDATA[“ fromUserName “]]></ToUserName>” ”<FromUserName><![CDATA[“ toUserName ”]]></FromUserName><CreateTime>” System.currentTimeMillis() ”</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[“ respContent ”]]></Content></xml>”); } return respMessage; }
上面代码中MessageUtil.pareXml用于解析request中携带的内容,将fromUserName、toUserName、msgType等内容解析出来,用于公众号对消息作出响应。OperatorUtil类用于操作数据库,暂且不用管。respMessage是公众号发送给用户的响应消息,要满足微信api要求的xml格式。
以上就是基于Java的微信公众号开发实例,具体效果如下:
源码地址:http://download.csdn.net/detail/fanguoddd/9746510
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/146088.html原文链接:https://javaforall.cn