你的位置:首页 > Java教程

[Java教程]微信开发入门(一)

一、开发前准备

1)微信公众平台账号

订阅号:个人版用户,每天可以群发一条消息

服务号:企业版用户,每天可以群发四条消息

2)在线虚拟主机或服务器(SAE云引擎、BAE云引擎、阿里云引擎)

3)TortoiseSVN(SVN客户端软件)

4)外网映射工具—花生壳

与微信对接的url要具备以下条件:

  • 在公网上能够访问
  • 端口只支持80端口

下面是用花生壳做映射:

访问外网地址,可见就可以访问自己主机上的网站:

 

开发模式:

 

二、服务器验证

在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;    }}