zoukankan      html  css  js  c++  java
  • 微信公众号开发(一)

    微信公众号开发

     

     第一章 公众号基本配置

    1. 微信公众号与Java后台的基本连接配置

    1.1 步骤

    1.1.1、填写服务器配置

    1.1.2、验证服务器地址的有效性

    1.1.3、依据接口文档实现业务逻辑

        微信后台与Java后台的初始连接:

         

        

            URL是Java后台服务器的url地址;

            Token令牌是自己定义的,和Java后台获取连接是需要验证的。

        1.2验证消息的确来自微信服务器

            需验证参数如下:

            

        1.2.1、Java后台需要通过get请求与微信服务器验证上述参数

            1)将token、timestamp、nonce三个参数进行字典序排序

            2)将三个参数字符串拼接成一个字符串进行sha1加密

            3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

            Java后台完成初始连接校验:

    CheckUtil:

    import java.security.MessageDigest;
    import java.util.Arrays;
    
    /**
     * 校验工具类
     * @author li_hao
     *
     */
    public class CheckUitl {
        private static final String token = "centit";//定义一个token,用来和微信端校验
        /**
         * 校验方法
         */
        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]);
            }
            
            String temp = getSha1(content.toString());//调用sha1加密
            
            return temp.equals(signature);
        }
        
        /**
         * sha1加密
         */
        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) {
                return null;
            }
        }
        
    }

    WeixinServlet:

    import java.io.IOException;
    import java.io.PrintWriter;
    import java.util.Date;
    import java.util.Map;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.dom4j.DocumentException;
    
    import com.centit.cmip.weixin.po.TextMessage;
    import com.centit.cmip.weixin.util.CheckUitl;
    import com.centit.cmip.weixin.util.MessageUtil;
    
    public class WeixinServlet extends HttpServlet {
    
        /**
         * 初始连接微信的信息校验
         */
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //获取四个参数,进行验证
            String signature = req.getParameter("signature");//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            String timestamp = req.getParameter("timestamp");//时间戳
            String nonce = req.getParameter("nonce");//随机数
            String echostr = req.getParameter("echostr");//随机字符串
            
            //调用校验方法进行校验,如果校验成功,就把随机字符串(echostr)返回
            PrintWriter out = resp.getWriter();
            if(CheckUitl.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.xmlToMap(req);//获取消息到集合中
                //获取参数
                String toUserName = map.get("ToUserName");
                String fromUserName = map.get("FromUserName");
                String msgType = map.get("MsgType");
                String content = map.get("Content");
                
                String message = null;
                //根据msgType判断消息类型    
                if(MessageUtil.MESSAGE_EVENT.equals(msgType)){  //事件推送
                    String eventType = map.get("Event");//获取事件推送中的具体事件类型
                    if(MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)){   //关注
                        message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());//关注推送
                    }else if(MessageUtil.MESSAGE_CLICK.equals(eventType)){  //click按钮点击回复
                        message = MessageUtil.initNewsMessage(toUserName, fromUserName);
                    }else if(MessageUtil.MESSAGE_VIEW.equals(eventType)){  //view类型按钮
                        String url = map.get("EventKey");//得到url
                        //message = MessageUtil.initText(toUserName, fromUserName, url);//回复一个url
                    }else if(MessageUtil.MESSAGE_SCANCODE.equals(eventType)){  //扫码类型按钮
                        String key = map.get("EventKey");
                        //message = MessageUtil.initText(toUserName, fromUserName, key);//回复一个key值
                    }
                    
                    System.out.println(message);
                    out.print(message);
                }else if(MessageUtil.MESSAGE_LOCATION.equals(msgType)){ //地理位置回复
                    String label = map.get("Label");
                    message = MessageUtil.initText(toUserName, fromUserName, label);//回复一个地理位置
                    
                    System.out.println(message);
                    out.print(message);
                }
            } catch (DocumentException e) {
                e.printStackTrace();
            }finally{
                out.close();
            }
         }
    
    }

    2. 获取access_token

      access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

      接口调用说明:

      

      

    备注(个人理解):

      如果说初始连接是设置的Token令牌是我们自己设置的初始连接秘钥,那么access_token则是我们在Java后台与微信后台的交互中微信返回的唯一凭证,几乎Java后台所有的操作(如:设置菜单按钮,设置回复,上传媒体消息,上传图文消息体,以及推送等等)都需要access_token来进行与微信服务器的验证,才能成功。

      access_token有效期:7200秒;

      access_token每天只能获取2000次;

      (所以在Java后台需要把access_token获取保存,1:定时器;2:保存数据库)

      

      /**
         * 获取Access_Token
         * @return
         */
        public static AccessToken getAccessToken(String appid,String appsecret){
            AccessToken token = new AccessToken();
            String url = ACCESS_TOKEN_URL.replace("APPID", appid).replace("APPSECRET", appsecret);//替换原url中的APPID和APPSECRIPT
            JSONObject jsonObject = doGetStr(url);//通过get方法获取结果
            if(jsonObject != null){
                try {
                    token.setToken(jsonObject.getString("access_token"));//放入access_token
                    token.setExpiresIn(jsonObject.getInt("expires_in"));//放入有效时间
                } catch (JSONException e) {
                    token = null;
                    // 获取token失败
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return token;
        }

    3. 常用接口地址(部分)

      //Access_Token 接口调用请求地址(请求方式:get)
        private static final String ACCESS_TOKEN_URL= "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        //上传媒体接口
        private static final String UPLOAD_URL= "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
        //自定义菜单创建(修改)接口 ,添加菜单接口(POST)
        private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";
        //自定义菜单查询接口  (get)
        private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN";
        //自定义菜单删除接口(get)
        private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN";
        
        
        //消息推送相关接口(以下)
        //上传图文消息内的图片获取URL 接口  (post)
        private static final String UPLOAD_SEND_IMAGE = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN";
        //上传图文消息素材 接口  (post)
        private static final String UPLOAD_SEND_NEWS = "https://api.weixin.qq.com/cgi-bin/media/uploadnews?access_token=ACCESS_TOKEN";
        //根据分组进行群发推送接口 (post)
        private static final String SEND_NEWS = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token=ACCESS_TOKEN";
        
        //微信预览接口(post)
        private static final String PREVIEW_NEWS = "https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token=ACCESS_TOKEN";
        
        
        //分组相关接口
        //创建分组 (post)
        private static final String CREATE_GROUP = "https://api.weixin.qq.com/cgi-bin/groups/create?access_token=ACCESS_TOKEN";
        
        //获取关注用户列表
        private static final String GET_USER_LIST = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
        
        //获取用户信息接口 (get)
        private static final String GET_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
        

     (下一章:微信公众号-创建菜单)

  • 相关阅读:
    HAVING 和 WHERE 的使用
    Input and Output
    python数据分析知识点
    正则化
    ol 接入百度地图
    高德室内地图解析
    mapbox 接入高德矢量地图实战
    4、微信小程序和weui
    3、YishaAdmin开源框架搭建
    2、微信小程序开发注册、配置介绍说明
  • 原文地址:https://www.cnblogs.com/hooly/p/8039258.html
Copyright © 2011-2022 走看看