企業微信的接入和開發(配置回撥和獲得userId)
阿新 • • 發佈:2018-12-29
企業微信的網址: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;
}
}