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>

猜你喜欢

转载自blog.csdn.net/Vincent_yuan1991/article/details/82223135