1.应用的相关配置

应用相关的信息在这里,后台需要配置 网页授权及JS-SDK、接收消息

网页授权及JS-SDK的URL是后台的回调地址,具体怎么实现后面讲

接收消息里面设置 Token和 EncodingAESKey ,这2参数需要在URL中用到

2.回调配置

首先看一遍官方文档,然后操作。

配置回调服务,需要有三个配置项,分别是:URL, Token, EncodingAESKey 就是上面配置的

这三个应用的具体介绍见文档 https://work.weixin.qq.com/api/doc#90000/90135/90930

在验证回调地址的时候,微信服务器会根据我们之前写的URL地址生成url请求

我们的后台需要根据请求地址传过来的数据,解密后,获得echostr 并返回,同时微信后台会显示配置完成

具体代码如下,当然还要在文档里下载demo  simple才行

/**
     * 企业微信号验证回调URL
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value = "/workWxCallback")
    public void workWxcheck(HttpServletRequest request, HttpServletResponse response) throws IOException, AesException {
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        PrintWriter print;

        WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(WxApiUtil.TOKEN, WxApiUtil.EncodingAESKey, WxApiUtil.CORPID);

        if(isGet){
            // 微信加密签名
            String sVerifyMsgSig = request.getParameter("msg_signature");
            // 时间戳
            String sVerifyTimeStamp = request.getParameter("timestamp");
            // 随机数
            String sVerifyNonce = request.getParameter("nonce");
            // 随机字符串
            String sVerifyEchoStr = request.getParameter("echostr");
            String sEchoStr; //需要返回的明文

            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            try {
                sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig, sVerifyTimeStamp,
                        sVerifyNonce, sVerifyEchoStr);
                System.out.println("verifyurl echostr: " + sEchoStr);
                // 验证URL成功,将sEchoStr返回
                print = response.getWriter();
                print.write(sEchoStr);
                print.flush();
            } catch (Exception e) {
                //验证URL失败,错误原因请查看异常
                e.printStackTrace();
            }
        }
    }

3.获得登录用户的userId

/**
     * 获得登录者的userId( 在这个应用中userId 等于 staffId )
     * 1.取得请求过来的地址中的code
     * 2.向微信服务器 获得 accessToken
     * 3.通过WxApiUtil.getUserId(accessToken, code) 获得userId
     * @param request
     * @param response
     * @param session
     */
    @RequestMapping(value = "/checkUser")
    @ResponseBody
    public void checkUser(HttpServletRequest request, HttpServletResponse response, HttpSession session){
        //获得code
        String code = request.getParameter("code");
        AccessToken accessTokenBean = null;
        try {
            if (session.getAttribute("accessToken") == null) {
                //获得access_token
                accessTokenBean = WxApiUtil.getAccessToken();
                session.setAttribute("accessToken", accessTokenBean.getAccess_token());
            }
            String accessToken = session.getAttribute("accessToken").toString();
            //获得userId
            String userId = WxApiUtil.getUserId(accessToken, code);
            //打印log
            logger.info(">>>>>>>>>>>>>>accessToken: {}",accessToken);
            logger.info(">>>>>>>>>>>>>>userId: {}",userId);

            Integer status = projectStatusService.getNowProjectStatus("xxx");
            //如果在维护中
            if (status == 0){
                //userId是否在白名单里
                Integer integer = projectWhitelistService.checkUserId(userId);
                if (integer != null){
                    //将userId作为staffId存进session
                    session.setAttribute("staffId", userId);
                    //进入测试页面
                    response.sendRedirect("http://xxx");
                }
            }else {
                //将userId作为staffId存进session
                session.setAttribute("staffId", userId);
                response.sendRedirect("http://xxx");
            }
        } catch (IOException e) {
            e.getMessage();
        }
    }

这里的userId作为员工工号,存进session,这么一来,后续就水到渠成了

需要注意的几个点是:

在上面的代码里我加入了项目状态和白名单的业务判断

有一个地方需要注意的是 WxApiUtil 这个工具类

类源码:

public class WxApiUtil {

    private final static Logger logger = LoggerFactory.getLogger(WxApiUtil.class);

    /**
     * 企业ID
     */
    public static String CORPID = "xxx";
    /**
     * 应用ID
     */
    public static Integer AGENTID = xxx;
    /**
     * 应用密码
     */
    public static String SECRET = "xxx";
    /**
     *  //后台应用配置的API接收Token
     */
    public static String TOKEN = "xxx";
    /**
     *  //后台应用配置的API接收EncodingAESKey
     */
    public static String EncodingAESKey = "xxx";
    /**
     * 获得ACCESS_TOKEN的请求地址
     */
    public static String GET_ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET";
    //js api
//    public static String JS_API = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=%s";

    public static String GET_USERID_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE";

    /**
     * 获取access token
     * @return
     */
    public static AccessToken getAccessToken(){
        // 拼接请求地址
        String requestUrl = WxApiUtil.GET_ACCESS_TOKEN_URL;
        requestUrl = requestUrl.replace("ID", CORPID);
        requestUrl = requestUrl.replace("SECRET", SECRET);
        // 获取传回的信息
        JSONObject jsonObject = HttpCommonUtil.httpsRequest(requestUrl, "GET", null);
        if (jsonObject == null){
            new Exception("token内容为空");
        }
        AccessToken accessToken = new AccessToken();
        if (jsonObject.getInteger("errcode") ==  0) {
            logger.info("accessToken {}",jsonObject);
            logger.debug("accessToken {}",jsonObject);

            accessToken.setErrcode(jsonObject.getInteger("errcode"));
            accessToken.setAccess_token(jsonObject.getString("access_token"));
            accessToken.setErrmsg(jsonObject.getString("errmsg"));
            accessToken.setExpires_in(jsonObject.getInteger("expires_in"));
            return  accessToken;
        } else {
            logger.error("{} get access error,msg:{}", jsonObject.toString());
        }
        return null;
    }

    /**
     * 获取userId
     * @return
     */
    public static String getUserId(String accessToken,String code){
        String requestUrl = GET_USERID_URL;
        // 拼接请求地址
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken);
        requestUrl = requestUrl.replace("CODE", code);
        // 获取传回的信息
        JSONObject jsonObject = HttpCommonUtil.httpsRequest(requestUrl, "GET", null);
        if (jsonObject.getInteger("errcode") ==  0){
            //企业成员授权时返回 userId 非企业成员openId
            String userId = jsonObject.getString("UserId");
            return  userId;
        }
        if ( jsonObject.getInteger("errcode") == 42001){
            String newAccessToken = getAccessToken().getAccess_token();
            getUserId(newAccessToken,code);
        } else {
            logger.error("{} get userId error,msg:{}", jsonObject.toString());
        }
        return null;
    }

}

这里面的属性都是根据自己企业微信填写的,这个类比较重要,有2个核心方法 getAccessToken和getUserId

在方法里有个工具类比较重要 就是HttpCommonUtil,这是一个http请求统一处理的工具类

代码:

public class HttpCommonUtil {

    /**
     * 发送https请求
     *
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);

            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject  = JSONObject.parseObject(buffer.toString());
        } catch (ConnectException ce) {
//            log.error("连接超时:{}", ce);
        } catch (Exception e) {
//            log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
}