一、开发前准备
1)微信公众平台账号
订阅号:个人版用户,每天可以群发一条消息
服务号:企业版用户,每天可以群发四条消息
2)在线虚拟主机或服务器(SAE云引擎、BAE云引擎、阿里云引擎)
3)TortoiseSVN(SVN客户端软件)
4)外网映射工具—花生壳
与微信对接的url要具备以下条件:
下面是用花生壳做映射:
访问外网地址,可见就可以访问自己主机上的网站:
开发模式:
二、服务器验证
在eclipse+tomcat上开发
微信服务器的验证要求(详见微信平台的开发者文档):
微信通过通过get请求传进四个参数
signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。timestamp 时间戳nonce 随机数echostr 随机字符串
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
其中 token是自定的。
这其中最重要的是对消息的处理,当普通微信用户向公众账号发消息时,微信服务器将POST消息的
首先将
不同消息类型的推送
关于消息管理,详见文档。
注意导包:
dom4j包 用来解析
WeixinServlet.java
public class WeixinServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String signature=req.getParameter("signature"); String timestamp=req.getParameter("timestamp"); String nonce=req.getParameter("nonce"); String echostr=req.getParameter("echostr"); PrintWriter out = resp.getWriter(); if(CheckUtil.checkSignature(signature, timestamp, nonce)){ out.print(echostr); } } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); PrintWriter out = resp.getWriter(); try { Map<String,String> map = MessageUtil.= map.get("ToUserName"); String fromUserName = map.get("FromUserName"); String msgType = map.get("MsgType"); String content = map.get("Content"); String message = null; //文本类型 if("text".equals(msgType)) { //按关键字进行判断 if("喜欢你".equals(content)){ message=MessageUtil.initText(toUserName, fromUserName,MessageUtil.firstMenu());; }else if("很喜欢你".equals(content)){ message=MessageUtil.initText(toUserName, fromUserName,MessageUtil.secondMenu()); }else if("?".equals(content)||"?".equals(content)){ message=MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText()); } System.out.println(message); } //关注事件 else if(MessageUtil.MESSAGE_EVENT.equals(msgType)){ String eventType = map.get("Event"); if(MessageUtil.EVENT_SUB.equals(eventType)){ String mycontent = MessageUtil.menuText(); message = MessageUtil.initText(toUserName, fromUserName, mycontent); } } out.print(message); } catch (Exception e) { e.printStackTrace(); }finally{ out.close(); } }}
校验:
public class CheckUtil { private static final String token="huaweiclub"; 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=getSha1(content.toString()); return temp.equals(signature); } public static String getSha1(String str){ if(str==null||str.length()==0){ return null; } char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9', 'a','b','c','d','e','f'}; try { MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); mdTemp.update(str.getBytes("UTF-8")); byte[] md = mdTemp.digest(); int j = md.length; char buf[] = new char[j*2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (Exception e) { // TODO: handle exception return null; } }}
消息的格式转化:
/* * */ public class MessageUtil { /* * 定义不同的消息类型 */ public static final String MESSAGE_TEXT = "text"; public static final String MESSAGE_IMAGE = "image"; public static final String MESSAGE_VOICE = "voice"; public static final String MESSAGE_VIDEO = "video"; public static final String MESSAGE_LINK = "link"; public static final String MESSAGE_LOCATION = "location"; public static final String MESSAGE_EVENT = "event"; public static final String EVENT_SUB = "subscribe"; public static final String EVENT_UNSUB = "unsubscribe"; public static final String EVENT_CLICK = "CLICK"; public static final String EVENT_VIEW = "VIEW"; /** * @param request * @return * @throws DocumentException * @throws IOException */ public static Map<String, String> throws DocumentException, IOException { Map<String,String> map = new HashMap<String, String>(); //SAXreader用于解析 SAXReader reader = new SAXReader(); InputStream ins = request.getInputStream(); //从输入流中读取 Document doc = reader.read(ins); //取得root节点 Element root = doc.getRootElement(); List<Element> list = root.elements(); for (Element e : list) { map.put(e.getName(), e.getText()); } ins.close(); return map; } /* * 将文本消息转换为*/ public static String textMessageTo= new XStream(); //将序列化中的类全量名称,用别名替换 xstream.alias(", textMessage.getClass()); return xstream.topublic static String initText(String toUserName, String fromUserName, String content){ TextMessage text = new TextMessage(); text.setFromUserName(toUserName); text.setToUserName(fromUserName); text.setMsgType(MESSAGE_TEXT); text.setCreateTime(new Date().getTime()); text.setContent(content); return textMessageTo/* * 根据关键字回复内容 */ public static String menuText(){ StringBuffer sb = new StringBuffer(); sb.append("谢谢关注"); return sb.toString(); } public static String firstMenu(){ StringBuffer sb = new StringBuffer(); sb.append("好感+1"); return sb.toString(); } public static String secondMenu(){ StringBuffer sb = new StringBuffer(); sb.append("好感+2"); return sb.toString(); } }
package com.xidian.bean;/**微信通信用的是*/public class TextMessage { private String ToUserName; private String FromUserName; private long CreateTime; private String MsgType; private String Content; private long 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 l) { CreateTime = l; } public String getMsgType() { return MsgType; } public void setMsgType(String msgType) { MsgType = msgType; } public String getContent() { return Content; } public void setContent(String content) { Content = content; } public long getMsgId() { return MsgId; } public void setMsgId(long msgId) { MsgId = msgId; }}
原标题:微信开发入门(一)
关键词: