1. 程式人生 > >企業微信的接入和開發(配置回撥和獲得userId)

企業微信的接入和開發(配置回撥和獲得userId)

企業微信的網址:https://work.weixin.qq.com

我們開發的程式在這裡,企業微信裡自建一個應用,相當於在微信裡新建一個微信公眾號

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