c#實現釘釘免登功能
阿新 • • 發佈:2018-11-21
釘釘提供的免登功能
如下
- 企業應用免登
- ISV應用免登
- 微應用後臺管理員免登
- 第三方WEB網站免登
- 第三方WEB網站掃碼登入
這裡要講解的是4,5;即第三方Web網站免登:點選網站上登入頁面的釘釘圖示,顯示二維碼,然後掃碼登入功能;
釘釘Web網站掃碼登入文件
一.前期準備
- 第三方網站的網址
- 第三方網站logo的網址
- 操作:
建立要填寫的一些相關資訊。授權LOGO地址,建議就放你網站的logo好啦。
確定之後就會生成APPID和appSecret,先放著。appSecret後面拿取釘釘的使用者資訊會用到。
通過以上步驟得到:appId,appSecret ,後面會用到(必須值)
二.流程說明
1.流程圖
2.流程文字說明
- 使用者點選Web網站上釘釘圖示,展示二維碼
- 使用者使用釘釘app,掃碼授權
- 釘釘伺服器往回調地址傳送code和state
- 在回撥地址的action中,由appid,appSecret獲取accessToken
- 由3中的code和4中的accessToken獲取持久授權碼persistent_code
- 由accessToken和5中得到的persistent_code和openid獲取使用者授權的sns_token
- 再由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>