1. 程式人生 > >c#實現釘釘免登功能

c#實現釘釘免登功能

釘釘提供的免登功能

如下

  1. 企業應用免登
  2. ISV應用免登
  3. 微應用後臺管理員免登
  4. 第三方WEB網站免登
  5. 第三方WEB網站掃碼登入

這裡要講解的是4,5;即第三方Web網站免登:點選網站上登入頁面的釘釘圖示,顯示二維碼,然後掃碼登入功能;
釘釘Web網站掃碼登入文件

一.前期準備
  1. 第三方網站的網址
  2. 第三方網站logo的網址
  3. 操作:
    這裡寫圖片描述
    建立要填寫的一些相關資訊。授權LOGO地址,建議就放你網站的logo好啦。
    這裡寫圖片描述
    確定之後就會生成APPID和appSecret,先放著。appSecret後面拿取釘釘的使用者資訊會用到。

通過以上步驟得到:appId,appSecret ,後面會用到(必須值)

二.流程說明

1.流程圖
這裡寫圖片描述
2.流程文字說明

  1. 使用者點選Web網站上釘釘圖示,展示二維碼
  2. 使用者使用釘釘app,掃碼授權
  3. 釘釘伺服器往回調地址傳送code和state
  4. 在回撥地址的action中,由appid,appSecret獲取accessToken
  5. 由3中的code和4中的accessToken獲取持久授權碼persistent_code
  6. 由accessToken和5中得到的persistent_code和openid獲取使用者授權的sns_token
  7. 再由6中的sns_token獲取釘釘使用者資訊

詳情請參考官方文件

三.編碼實現

下面的程式碼因為專案需要除了免登以外,還有一些通訊錄的操作,使用者自行選取
注:免登(appid,appsecret)獲取的AccessToken與用CorpID和CorpSecret來換取AccessToken不同

1.後臺操作程式碼
using EClaim.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using
System.Text; using System.Threading.Tasks; namespace EClaim.Service.DingDingHelper { public class DingDingHelper { //免登必需引數 private static string appid = ""; //免登必需引數 private static string appsecret = ""; //其他操作必需引數(例如:通訊錄) private static string corpid = ""; //其他操作必需引數(例如:通訊錄) private static string corpsecret = ""; //由corpid和corpsecret獲取accessToken public static AccessTokenResult GetAccessToken0() { string url = "https://oapi.dingtalk.com/gettoken?corpid="+corpid+"&corpsecret="+corpsecret; try { var response = HttpGet(url); //Log.LogMsg("DingDing_GetAccessToken0", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetAccessToken0_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 獲取釘釘開放應用的ACCESS_TOKEN(免登功能使用) /// </summary> /// <returns></returns> public static AccessTokenResult GetAccessToken() { string url = "https://oapi.dingtalk.com/sns/gettoken?appid=" + appid + "&appsecret=" + appsecret; try { var response = HttpGet(url); //Log.LogMsg("DingDing_GetAccessToken", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<AccessTokenResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetAccessToken_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 獲取使用者授權的持久授權碼(免登功能使用) /// </summary> /// <param name="accessToken"></param> /// <param name="code"></param> /// <returns></returns> public static PersistentCodeResult GetPersistentCode(string accessToken, string code) { string url = "https://oapi.dingtalk.com/sns/get_persistent_code?access_token=" + accessToken; string param = "{ \"tmp_auth_code\": \""+code+"\"}"; try { //Log.LogMsg("進入HttpPost之前", DateTime.Now, "[url:"+url+"]--[param:"+param+"]"); var response = HttpPost(url, param); //var response = PostHttp(url, param, Encoding.GetEncoding("utf-8")); //Log.LogMsg("DingDing_GetPersistentCode", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<PersistentCodeResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetPersistentCode_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 獲取使用者授權的SNS_TOKEN(免登功能使用) /// </summary> /// <param name="accessToken"></param> /// <param name="openId"></param> /// <param name="persistentCode"></param> /// <returns></returns> public static Sns_tokenResult GetSnsToken(string accessToken, string openId, string persistentCode) { string url = "https://oapi.dingtalk.com/sns/get_sns_token?access_token=" + accessToken; string param = "{\"openid\": \""+openId+"\",\"persistent_code\": \""+persistentCode+"\"}"; try { var response = HttpPost(url, param); //Log.LogMsg("DingDing_GetSnsToken", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Sns_tokenResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetSnsToken_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 獲取使用者授權的個人資訊(免登功能使用) /// </summary> /// <param name="sns_token"></param> /// <returns></returns> public static UserInfoResult GetUserInfo(string sns_token) { string url = "https://oapi.dingtalk.com/sns/getuserinfo?sns_token=" + sns_token; try { var response = HttpGet(url); //Log.LogMsg("DingDing_GetUserInfo", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfoResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetUserInfo_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 根據unionid獲取userId /// </summary> /// <param name="accessToken"></param> /// <param name="unionid"></param> /// <returns></returns> public static UserIdResult GetUserIdByUnionId(string unionid) { var accessToken = GetAccessToken0(); string url = "https://oapi.dingtalk.com/user/getUseridByUnionid?access_token=" + accessToken.access_token + "&unionid=" + unionid; try { var response = HttpGet(url); //Log.LogMsg("DingDing_GetUserId", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserIdResult>(response); return result; } catch (Exception ex) { //Log.LogMsg("DingDing_GetUserId_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } /// <summary> /// 獲取成員詳情 /// </summary> /// <param name="accessToken"></param> /// <param name="userid"></param> /// <returns></returns> public static UserDetailResult GetUserDetail(string userid) { var accessToken = GetAccessToken0(); string url = "https://oapi.dingtalk.com/user/get?access_token="+ accessToken.access_token + "&userid="+userid; try { var response = HttpGet(url); //Log.LogMsg("DingDing_GetUserDetail", DateTime.Now, response); var result = Newtonsoft.Json.JsonConvert.DeserializeObject<UserDetailResult>(response); return result; } catch(Exception ex) { //Log.LogMsg("DingDing_GetUserDetail_Exception", DateTime.Now, ex.Message); throw new Exception(ex.Message); } } #region 傳送請求方法 /// <summary> /// get方式傳送請求 /// </summary> /// <param name="url"></param> /// <returns></returns> public static string HttpGet(string url) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.ContentType = "text/html;charset=UTF-8"; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream myResponseStream = response.GetResponseStream(); StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8")); string retString = myStreamReader.ReadToEnd(); myStreamReader.Close(); myResponseStream.Close(); return retString; } public static string HttpPost(string url, string body) { //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); Encoding encoding = Encoding.UTF8; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "POST"; request.Accept = "text/html, application/xhtml+xml, */*"; request.ContentType = "application/json"; byte[] buffer = encoding.GetBytes(body); request.ContentLength = buffer.Length; request.GetRequestStream().Write(buffer, 0, buffer.Length); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) { return reader.ReadToEnd(); } } #endregion } public class AccessTokenResult { public string access_token { get; set; } public int errcode { get; set; } public string errmsg { get; set; } } public class PersistentCodeResult { public int errcode { get; set; } public string errmsg { get; set; } public string openid { get; set; } public string persistent_code { get; set; } public string unionid { get; set; } } public class Sns_tokenResult { public int errcode { get; set; } public string errmsg { get; set; } public int expires_in { get; set; } public string sns_token { get; set; } } public class UserInfoResult { public int errcode { get; set; } public string errmsg { get; set; } public UserInfo user_info { get; set; } } public class UserInfo { public string maskedMobile { get; set; } public string nick { get; set; } public string openid { get; set; } public string unionid { get; set; } } public class UserIdResult { public int errcode { get; set; } public string errmsg { get; set; } public int contactType { get; set; } public string userid { get; set; } } public class UserDetailResult { public int errcode { get; set; } public string unionid { get; set; } public string openId { get; set; } public string roles { get; set; } public string remark { get; set; } public string userid { get; set; } public string isLeaderInDepts { get; set; } public bool isBoss { get; set; } public string hiredDate { get; set; } public bool isSenior { get; set; } public string tel { get; set; } public int[] department { get; set; } public string workPlace { get; set; } public string email { get; set; } public string orderInDepts { get; set; } public string mobile { get; set; } public string errmsg { get; set; } public bool active { get; set; } public string avatar { get; set; } public bool isAdmin { get; set; } public bool isHide { get; set; } public string jobnumber { get; set; } public string name { get; set; } public object extattr { get; set; } public string stateCode { get; set; } public string position { get; set; } } }
2.前臺程式碼實現
<p class="dingdinglogin" onclick="dingdingLogin();">釘釘掃碼登入</p>



 <script src="//g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>
    <script>
        var appid = "必填值";
        var redirect_uri = "必填值";
        var dingurl="https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid="+appid+"&response_type=code&scope=snsapi_login&state=STATE&redirect_uri="+redirect_uri;

        function dingdingLogin() {
            debugger;
            //$(".login-content-2").hide();
            //$("#login_container").show();
            var obj = DDLogin({
                id: "login_container",//這裡需要你在自己的頁面定義一個HTML標籤並設定id,例如<div id="login_container"></div>或<span id="login_container"></span>
                goto: encodeURIComponent(dingurl),
                width: "365",
                height: "400",
            });

            var hanndleMessage = function (event) {
                var origin = event.origin;
                console.log("origin", event.origin);
                if (origin == "https://login.dingtalk.com") { //判斷是否來自ddLogin掃碼事件。
                    var loginTmpCode = event.data; //拿到loginTmpCode後就可以在這裡構造跳轉連結進行跳轉了
                    console.log("loginTmpCode", loginTmpCode);

                    window.location.href = dingurl+"&loginTmpCode=" + loginTmpCode;
                }

            };

            if (typeof window.addEventListener != 'undefined') {
                window.addEventListener('message', hanndleMessage, false);
            } else if (typeof window.attachEvent != 'undefined') {
                window.attachEvent('onmessage', hanndleMessage);
            }
        }

    </script>