漂流的老妖怪

导航

 

微信公众号开发

 

 第一章 公众号基本配置

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";
    

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

posted on 2017-12-14 18:49  漂流的老妖怪  阅读(534)  评论(2编辑  收藏  举报