企業微信接入自有應用實現免登陸

公司要將移動端審批流程接入企業微信,員工經過企業微信的自建審批應用就能夠在微信端審批單據,要審批單據就先得讓企業微信跟用戶綁定起來,實現無感自動登陸系統內。因爲企業的員工已經被手動的從微信拉入企業微信內,這樣就不能夠經過企業微信的建立人員接口將人員推到微信內。只能在用戶第一次登陸審批系統的時候去微信獲取用戶ID(userId)並與審批系統的人員關聯起來。綁定好後就能夠實現自動登陸。html

企業微信API:https://work.weixin.qq.com/api/doc#90001/90143/91201java

員工點擊應用後自動登陸步驟以下:sql

1.攔截用戶是否登陸數據庫

在過濾器或者攔截器內檢查用戶是否登陸,若是沒有登陸跳轉到微信獲取用戶的身份信息apache

企業微信API地址:https://work.weixin.qq.com/api/doc#90001/90143/91120json

獲取企業微信受權信息URL:c#

https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&agentid=AGENTID&state=STATE#wechat_redirec

頁面跳轉到企業微信後企業微信處理完成後,頁面將從新跳轉至 redirect_uri參數指定的回調地址並帶上參數code=CODE&state=STATE,企業可根據code參數得到員工的userid。code長度最大爲512字節。api

public static final String OAUTH_CODE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_base&state=%s#wechat_redirect";
Integer serverPort = request.getServerPort();
String port = (null != serverPort && serverPort == 80) ? "" : ":" + serverPort.toString();
String url = "http://" + request.getServerName() // 服務器地址
            + port // 端口號
            + request.getContextPath(); // 項目名稱
url = url + "/weixin/auth/weixinLogin/oauthLogin.html";
try{
    url = URLEncoder.encode(url, "utf-8");
}catch (UnsupportedEncodingException e){
    e.printStackTrace();
}
String weixinUrl = String.format(OAUTH_CODE_URL, "企業ID", url, "state""); 
response.sendRedirect(weixinUrl);

2.獲取用戶信息並登陸緩存

微信回調接收到CODE值並用CODE去交換真實的用戶信息,若是用戶與系統綁定就表示登陸成功,登陸成功後將用戶信息放入SESSION中。這樣就能夠實現自動登陸審批系統了。服務器

/**
     * 微信回調接口
     * @return
     */
    public String oauthLogin(){
        try{
            
            Map<String, Object> returnMap = WeixinUtil.getUserInfo(code, Constants.APPROVAL);
            if (null != returnMap){
                //獲得微信用戶ID
                String userid = MapUtils.getString(returnMap, "UserId");
                if (!StringUtil.isRealEmpty(userid)){
                    //用戶與微信ID綁定實體
                    UserWx userWx = userWxManager.findByWXID(userid);
                    if (userWx != null){
                        if (StringUtil.isRealEmpty(userWx.getAvatar())){
                            WxUser wxUser = WeixinUtil.getWxUser(userid, Constants.APPROVAL);
                            if (null != wxUser && !StringUtil.isRealEmpty(wxUser.getAvatar())){
                                // +64取小頭像 ;+0取大頭像
                                userWx.setAvatar(wxUser.getAvatar());
                                userWxManager.save(userWx);
                            }
                        }
                            
                         //登陸成功,將用戶信息放入SESSION等後續操做
                        ....... 
                        return null;
                    }else{
                        //顯示未綁定的邏輯
                        return customMethod("unbind");
                    } 
                }else{
                    return customMethod("error");
                }
            }else{
                return customMethod("error");
            }
        }catch (Exception e){
            return customMethod("error");
        } 
    }

WeixinUtil的代碼以下:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.alibaba.fastjson.JSON;
import cn.boxbank.WxUser;

public class WeixinUtil
{
    
    private static Log log = LogFactory.getLog(WeixinUtil.class);
    
    /**
     * 發起https請求並獲取結果
     * 
     * @param requestUrl 請求地址
     * @param requestMethod 請求方式(GET、POST)
     * @param outputStr 提交的數據
     * @return JSONObject(經過JSONObject.get(key)的方式獲取json對象的屬性值)
     */
    public static Map<String, Object> HttpRequest(String requestUrl, String requestMethod, String outputStr)
    {
        // log.error("發起https請求並獲取結果 :"+requestUrl+","+requestMethod+","+outputStr);
        Map<String, Object> map = new HashMap<String, Object>();
        StringBuffer buffer = new StringBuffer();
        try
        {
            // 建立SSLContext對象,並使用咱們指定的信任管理器初始化
            TrustManager[] tm = { new EwX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 從上述SSLContext對象中獲得SSLSocketFactory對象
            SSLSocketFactory ssf = sslContext.getSocketFactory();
            
            URL url = new URL(requestUrl);
            HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
            httpUrlConn.setSSLSocketFactory(ssf);
            
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setDoInput(true);
            httpUrlConn.setUseCaches(false);
            httpUrlConn.setConnectTimeout(60 * 1000);
            httpUrlConn.setReadTimeout(60 * 1000);
            // 設置請求方式(GET/POST)
            httpUrlConn.setRequestMethod(requestMethod);
            
            httpUrlConn.connect();
            // if ("GET".equalsIgnoreCase(requestMethod))
            
            // 當有數據須要提交時
            if (null != outputStr)
            {
                OutputStream outputStream = httpUrlConn.getOutputStream();
                // 注意編碼格式,防止中文亂碼
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            
            // 將返回的輸入流轉換成字符串
            InputStream inputStream = httpUrlConn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            
            String str = null;
            while ((str = bufferedReader.readLine()) != null)
            {
                buffer.append(str);
            }
            bufferedReader.close();
            inputStreamReader.close();
            // 釋放資源
            inputStream.close();
            inputStream = null;
            httpUrlConn.disconnect();
            
            // 返回map
            // map = JsonUtil.json2Map(buffer.toString(), Map.class, String.class, Object.class);
            
            map = (Map<String, Object>) JSON.parseObject(buffer.toString(), Map.class);
            
        }
        catch (ConnectException ce)
        {
            System.out.println("Connection Timed Out......");
        }
        catch (Exception e)
        {
            String result = String.format("Https Request Error:%s", e);
            System.out.println(result);
        }
        return map;
    }
    
    /**
     * 根據code調微信接口獲取USERID
     * 
     * @param code
     * @return
     */
    public static Map<String, Object> getUserInfo(String code, String agentFlag)
    {
        String OAUTH_GETUSERINFO_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s";
        String url = String.format(OAUTH_GETUSERINFO_URL, getAccessToken(agentFlag), code);
        Map<String, Object> result = HttpRequest(url, "GET", null);
        return result;
    }
    
    /**
     * 從配置參數中獲取
     * @param agentFlag
     * @return
     */
    public static String getAccessToken(String agentFlag)
    {
        //這裏是獲取應用的ACCESS_TOKEN,能夠將獲取ACCESS_TOKEN放到定時線程內,每2個小時去從新獲取一次。
        //從數據庫或者緩存中拿出應用的ACCESS_TOKEN
        ......
    }
    
    /**
     * 經過userid 從微信獲取用戶
     * 
     * @param userid
     * @return
     */
    public static WxUser getWxUser(String userid, String agentFlag)
    {
        String GET_USER_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=%s&userid=%s";
        WxUser user = null;
        String url = String.format(Constants.GET_USER_URL, getAccessToken(agentFlag), userid);
        Map<String, Object> returnMap = HttpRequest(url, "GET", null);
        int errcode = MapUtils.getIntValue(returnMap, "errcode");
        if (errcode == 0)
        {
            user = JSON.toJavaObject((JSON) JSON.toJSON(returnMap), WxUser.class);
        }
        return user;
    }
    
    /**
     * 調用微信接口獲取accessToken
     * 
     * @param cropid 企業號ID
     * @param cropsecret 企業號管理組對應的secret
     * @return AccessToken
     */
    public static void getAccessToken(String cropid, String cropsecret)
    {
        String ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
        // 添加URL中的cropid和cropsecret的值
        String url = String.format(ACCESS_TOKEN_URL, cropid, cropsecret);
        // 根據url經過https請求獲取accesstoken
        Map<String, Object> returnMap = WeixinUtil.HttpRequest(url, "GET", null);
        
        if (null != returnMap && returnMap.size() > 0)
        {
            // access_token
            String access_token = MapUtils.getString(returnMap, "access_token");
            // accessToken有效時間expires_in:7200秒
            Integer expires_in = MapUtils.getInteger(returnMap, "expires_in");
            //可將取到的ACCESS_TOKEN存入數據庫或者緩存中。每2個小時更新一次
            ........
        }
        else
        {
            log.info("accesstoken獲取失敗");
        }
        
    }
    
    /**
     * 微信接口返回代碼轉換信息
     * 
     * @param errorcode
     * @return
     */
    public static String convertErrorCode2Msg(int errorcode)
    {
        String errmsg = "";
        switch (errorcode)
        {
            case -1:
                errmsg = "系統繁忙 ";
                break;
            case 0:
                errmsg = "請求成功 ";
                break;
            case 40001:
                errmsg = "獲取access_token時Secret錯誤,或者access_token無效 ";
                break;
            case 40002:
                errmsg = "不合法的憑證類型";
                break;
            case 40003:
                errmsg = "不合法的UserID";
                break;
            case 40004:
                errmsg = "不合法的媒體文件類型 ";
                break;
            case 40005:
                errmsg = "不合法的文件類型 ";
                break;
            case 40006:
                errmsg = "不合法的文件大小";
                break;
            case 40007:
                errmsg = "不合法的媒體文件id";
                break;
            case 40008:
                errmsg = "不合法的消息類型 ";
                break;
            case 40013:
                errmsg = "不合法的corpid ";
                break;
            case 40014:
                errmsg = "不合法的access_token";
                break;
            case 40015:
                errmsg = "不合法的菜單類型";
                break;
            case 40016:
                errmsg = "不合法的按鈕個數";
                break;
            case 40017:
                errmsg = "不合法的按鈕類型";
                break;
            case 40018:
                errmsg = "不合法的按鈕名字長度";
                break;
            case 40019:
                errmsg = "不合法的按鈕KEY長度";
                break;
            case 40020:
                errmsg = "不合法的按鈕URL長度 ";
                break;
            case 40021:
                errmsg = "不合法的菜單版本號 ";
                break;
            case 40022:
                errmsg = "不合法的子菜單級數";
                break;
            case 40023:
                errmsg = "不合法的子菜單按鈕個數";
                break;
            case 40024:
                errmsg = "不合法的子菜單按鈕類型";
                break;
            case 40025:
                errmsg = "不合法的子菜單按鈕名字長度";
                break;
            case 40026:
                errmsg = "不合法的子菜單按鈕KEY長度";
                break;
            case 40027:
                errmsg = "不合法的子菜單按鈕URL長度";
                break;
            case 40028:
                errmsg = "不合法的自定義菜單使用員工";
                break;
            case 40029:
                errmsg = "不合法的oauth_code";
                break;
            case 40031:
                errmsg = "不合法的UserID列表";
                break;
            case 40032:
                errmsg = "不合法的UserID列表長度";
                break;
            case 40033:
                errmsg = "不合法的請求字符,不能包含\\uxxxx格式的字符 ";
                break;
            case 40035:
                errmsg = "不合法的參數 ";
                break;
            case 40038:
                errmsg = "不合法的請求格式 ";
                break;
            case 40039:
                errmsg = "不合法的URL長度";
                break;
            case 40040:
                errmsg = "不合法的插件token";
                break;
            case 40041:
                errmsg = "不合法的插件id";
                break;
            case 40042:
                errmsg = "不合法的插件會話";
                break;
            case 40048:
                errmsg = "url中包含不合法domain";
                break;
            case 40054:
                errmsg = "不合法的子菜單url域名";
                break;
            case 40055:
                errmsg = "不合法的按鈕url域名 ";
                break;
            case 40056:
                errmsg = "不合法的agentid";
                break;
            case 40057:
                errmsg = "不合法的callbackurl";
                break;
            case 40058:
                errmsg = "不合法的紅包參數 ";
                break;
            case 40059:
                errmsg = "不合法的上報地理位置標誌位 ";
                break;
            case 40060:
                errmsg = "設置上報地理位置標誌位時沒有設置callbackurl";
                break;
            case 40061:
                errmsg = "設置應用頭像失敗";
                break;
            case 40062:
                errmsg = "不合法的應用模式";
                break;
            case 40063:
                errmsg = "紅包參數爲空";
                break;
            case 40064:
                errmsg = "管理組名字已存在";
                break;
            case 40065:
                errmsg = "不合法的管理組名字長度";
                break;
            case 40066:
                errmsg = "不合法的部門列表";
                break;
            case 40067:
                errmsg = "標題長度不合法 ";
                break;
            case 40068:
                errmsg = "不合法的標籤ID";
                break;
            case 40069:
                errmsg = "不合法的標籤ID列表";
                break;
            case 40070:
                errmsg = "列表中全部標籤(用戶)ID都不合法  ";
                break;
            case 40071:
                errmsg = "不合法的標籤名字,標籤名字已經存在 ";
                break;
            case 40072:
                errmsg = "不合法的標籤名字長度";
                break;
            case 40073:
                errmsg = "不合法的openid";
                break;
            case 40074:
                errmsg = "news消息不支持指定爲高保密消息";
                break;
            case 41001:
                errmsg = "缺乏access_token參數 ";
                break;
            case 41002:
                errmsg = "缺乏corpid參數";
                break;
            case 41003:
                errmsg = "缺乏refresh_token參數";
                break;
            case 41004:
                errmsg = "缺乏secret參數";
                break;
            case 41005:
                errmsg = "缺乏多媒體文件數據";
                break;
            case 41006:
                errmsg = "缺乏media_id參數";
                break;
            case 41007:
                errmsg = "缺乏子菜單數據";
                break;
            case 41008:
                errmsg = "缺乏oauth code";
                break;
            case 41009:
                errmsg = "缺乏UserID";
                break;
            case 41010:
                errmsg = "缺乏url";
                break;
            case 41011:
                errmsg = "缺乏agentid";
                break;
            case 41012:
                errmsg = "缺乏應用頭像mediaid";
                break;
            case 41013:
                errmsg = "缺乏應用名字";
                break;
            case 41014:
                errmsg = "缺乏應用描述";
                break;
            case 41015:
                errmsg = "缺乏Content";
                break;
            case 41016:
                errmsg = "缺乏標題";
                break;
            case 41017:
                errmsg = "缺乏標籤ID";
                break;
            case 41018:
                errmsg = "缺乏標籤名字 ";
                break;
            case 42001:
                errmsg = "access_token超時 ";
                break;
            case 42002:
                errmsg = "refresh_token超時";
                break;
            case 42003:
                errmsg = "oauth_code超時 ";
                break;
            case 42004:
                errmsg = "插件token超時";
                break;
            case 43001:
                errmsg = "須要GET請求";
                break;
            case 43002:
                errmsg = "須要POST請求";
                break;
            case 43003:
                errmsg = "須要HTTPS";
                break;
            case 43004:
                errmsg = "須要接收者關注";
                break;
            case 43005:
                errmsg = "須要好友關係";
                break;
            case 43006:
                errmsg = "須要訂閱";
                break;
            case 43007:
                errmsg = "須要受權";
                break;
            case 43008:
                errmsg = "須要支付受權";
                break;
            case 43009:
                errmsg = "須要員工已關注";
                break;
            case 43010:
                errmsg = "須要處於回調模式";
                break;
            case 43011:
                errmsg = "須要企業受權";
                break;
            case 44001:
                errmsg = "多媒體文件爲空";
                break;
            case 44002:
                errmsg = "POST的數據包爲空";
                break;
            case 44003:
                errmsg = "圖文消息內容爲空";
                break;
            case 44004:
                errmsg = "文本消息內容爲空";
                break;
            case 45001:
                errmsg = "多媒體文件大小超過限制";
                break;
            case 45002:
                errmsg = "消息內容超過限制";
                break;
            case 45003:
                errmsg = "標題字段超過限制";
                break;
            case 45004:
                errmsg = "描述字段超過限制";
                break;
            case 45005:
                errmsg = "連接字段超過限制";
                break;
            case 45006:
                errmsg = "圖片連接字段超過限制";
                break;
            case 45007:
                errmsg = "語音播放時間超過限制";
                break;
            case 45008:
                errmsg = "圖文消息超過限制";
                break;
            case 45009:
                errmsg = "接口調用超過限制";
                break;
            case 45010:
                errmsg = "建立菜單個數超過限制";
                break;
            case 45015:
                errmsg = "回覆時間超過限制";
                break;
            case 45016:
                errmsg = "系統分組,不容許修改";
                break;
            case 45017:
                errmsg = "分組名字過長";
                break;
            case 45018:
                errmsg = "分組數量超過上限";
                break;
            case 45024:
                errmsg = "帳號數量超過上限";
                break;
            case 46001:
                errmsg = "不存在媒體數據";
                break;
            case 46002:
                errmsg = "不存在的菜單版本";
                break;
            case 46003:
                errmsg = "不存在的菜單數據";
                break;
            case 46004:
                errmsg = "不存在的員工";
                break;
            case 47001:
                errmsg = "解析JSON/XML內容錯誤";
                break;
            case 48002:
                errmsg = "Api禁用";
                break;
            case 50001:
                errmsg = "redirect_uri未受權";
                break;
            case 50002:
                errmsg = "員工不在權限範圍";
                break;
            case 50003:
                errmsg = "應用已停用";
                break;
            case 50004:
                errmsg = "員工狀態不正確(未關注狀態) ";
                break;
            case 50005:
                errmsg = "企業已禁用";
                break;
            case 60001:
                errmsg = "部門長度不符合限制";
                break;
            case 60002:
                errmsg = "部門層級深度超過限制";
                break;
            case 60003:
                errmsg = "部門不存在";
                break;
            case 60004:
                errmsg = "父親部門不存在";
                break;
            case 60005:
                errmsg = "不容許刪除有成員的部門";
                break;
            case 60006:
                errmsg = "不容許刪除有子部門的部門";
                break;
            case 60007:
                errmsg = "不容許刪除根部門";
                break;
            case 60008:
                errmsg = "部門名稱已存在";
                break;
            case 60009:
                errmsg = "部門名稱含有非法字符";
                break;
            case 60010:
                errmsg = "部門存在循環關係";
                break;
            case 60011:
                errmsg = "管理員權限不足,(user/department/agent)無權限";
                break;
            case 60012:
                errmsg = "不容許刪除默認應用";
                break;
            case 60013:
                errmsg = "不容許關閉應用";
                break;
            case 60014:
                errmsg = "不容許開啓應用";
                break;
            case 60015:
                errmsg = "不容許修改默認應用可見範圍";
                break;
            case 60016:
                errmsg = "不容許刪除存在成員的標籤";
                break;
            case 60017:
                errmsg = "不容許設置企業";
                break;
            case 60102:
                errmsg = "UserID已存在";
                break;
            case 60103:
                errmsg = "手機號碼不合法";
                break;
            case 60104:
                errmsg = "手機號碼已存在";
                break;
            case 60105:
                errmsg = "郵箱不合法";
                break;
            case 60106:
                errmsg = "郵箱已存在";
                break;
            case 60107:
                errmsg = "微信號不合法";
                break;
            case 60108:
                errmsg = "微信號已存在";
                break;
            case 60109:
                errmsg = "QQ號已存在";
                break;
            case 60110:
                errmsg = "部門個數超出限制";
                break;
            case 60111:
                errmsg = "UserID不存在";
                break;
            case 60112:
                errmsg = "成員姓名不合法";
                break;
            case 60113:
                errmsg = "身份認證信息(微信號/手機/郵箱)不能同時爲空 ";
                break;
            case 60114:
                errmsg = "性別不合法";
                break;
            default:
                errmsg = "沒有此錯誤碼! ";
                break;
        }
        return errmsg;
    }
}

WxUser類的結構以下,省get\set

public class WxUser
{
    
    // 必填, 成員UserID。對應管理端的賬號,企業內必須惟一。不區分大小寫,長度爲1~64個字節
    private String userid;
    
    // 必填,成員名稱。長度爲1~64個字節
    private String name;
    
    // 必填,成員所屬部門id列表,不超過20個
    private String[] department;
    
    private String deptId;
    
    // 職位信息。長度爲0~64個字節
    private String position;
    
    // 手機號碼。企業內必須惟一,mobile/weixinid/email三者不能同時爲空
    private String mobile;
    
    // 性別。1表示男性,2表示女性
    private String gender;
    
    // 郵箱。長度爲0~64個字節。企業內必須惟一
    private String email;
    
    // 微信號。企業內必須惟一。(注意:是微信號,不是微信的名字)
    private String weixinid;
    
    // 成員頭像的mediaid,經過多媒體接口上傳圖片得到的mediaid
    private String avatar_mediaid;
    
    private String avatar;
    
    private String status;
}
相關文章
相關標籤/搜索