钉钉工作台单点登录金蝶云星空原创
金蝶云社区-the_Old_Zhang
the_Old_Zhang
6人赞赏了该文章 453次浏览 未经作者许可,禁止转载编辑于2024年09月06日 16:54:50
summary-icon摘要由AI智能服务提供

本文介绍了如何通过钉钉的免登授权码和API接口,实现钉钉微应用与金蝶云星空系统的单点登录功能。首先,通过中转页面获取钉钉的免登授权码,并重定向到服务端代码文件。该文件中的JavaScript代码调用钉钉JS API获取授权码,并通过该码请求用户身份信息。随后,在C#后端代码中,使用钉钉的API接口和授权码及App密钥获取accessToken,并结合accessToken和授权码调用用户信息API,最终获取并打印用户名称。过程中还涉及了HTTP POST请求的发送和JSON数据的处理。此外,还提醒了在内网使用时避免使用HTTPS以及如何通过URL传递参数等问题。


    1.首先是一个中转页,用来获取钉钉的免登授权码,打开一个新窗口重定向到第二部分写的代码文件,这样写点击钉钉工作台应用后,可以直接在电脑的默认浏览器打开页面,这个文件存放路径我是放在了服务器的html5路径下。注意一下,钉钉微应用的pc端首页地址应该是这个形式http://你的服务器ip/k3cloud/html5/你的第一部分代码文件名称.html?corpId=$CORPID$还有一点就是,如果你是在内网使用,并且不做穿透的话,不要用https,钉钉会直接无法访问。


<!DOCTYPE html>

<html>

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=devicewidth, initialscale=1.0">

    <script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.11.1/dingtalk.open.js" charset="UTF-8"></script>

    <title>示例</title>

</head>

<body>

    <script>

        window.onload = function() {

                dd.ready(function() {

                         dd.runtime.permission.requestAuthCode({

                             corpId: getURLParameter('corpId'), // 企业id

                             onSuccess: function (info) {

                                       code = info.code // 通过该免登授权码可以获取用户身份

                                            window.close();

                                            window.open('http://你的服务器ip/k3cloud/SSTO.DTalk.SYS.GetLogUrl.ExecuteService,SSTO.DTalk.SYS.common.kdsvc?code='+code);        

                             }

                         });                    

                });

                function getURLParameter(name) {

                         name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");

                         var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),

                         results = regex.exec(document.location.href);

                         return results[1];

                };

        };

        

    </script>


</body>

</html>



 2.获取钉钉的accessToken,并且和第一部分获取的免登授权码code组合,获取钉钉的用户名称。



using Kingdee.BOS.ServiceFacade.KDServiceFx;

using Kingdee.BOS.Util;

using Kingdee.BOS.WebApi.ServicesStub;

using Newtonsoft.Json;

using Newtonsoft.Json.Linq;

using System;

using System.ComponentModel;

using System.IO;

using System.Net;






namespace SSTO.DTalk.SYS

{

    [Kingdee.BOS.Util.HotUpdate]


    [Description("钉钉单点登陆金蝶云星空")]


    public class GetLogUrl : AbstractWebApiBusinessService

    {

        //定义一些必要变量


        static string accessToken;

        static string name;

        static string userName; //实际为code,此处暂为这样

        public GetLogUrl(KDServiceContext context) : base(context)

        {

        }




        public JObject ExecuteService(JObject parameter)

        {


            JObject messages = new JObject();

            userName = this.KDContext.WebContext.Context.Request["code"];


            if (!string.IsNullOrEmpty(userName))

            {

                try

                {

                    // 钉钉API的URL  

                    string url = "https://api.dingtalk.com/v1.0/oauth2/accessToken";

                    var postData = new

                    {

                        appKey = "你的钉钉微应用appkey",

                        appSecret = "你的钉钉微应用appSecret "


                    };


                    // 将对象序列化为JSON字符串

                    string json = JsonConvert.SerializeObject(postData);


                    // 发送HTTP POST请求并等待结果  

                    var responseBody = JObject.Parse(SendPostRequest(url, json));

                    accessToken = (string)responseBody["accessToken"];

                    Console.WriteLine(accessToken);

                }

                catch (AggregateException ex)

                {

                    // 捕获由于等待Task时发生的异常  

                    foreach (var innerEx in ex.InnerExceptions)

                    {

                        Console.WriteLine($"Inner Exception: {innerEx.Message}");

                        

                    }

                }

                catch (Exception e)

                {

                    // 捕获其他类型的异常  

                    Console.WriteLine($"Exception: {e.Message}");

                    

                }

            }


            if (!string.IsNullOrEmpty(accessToken))

            {

                try

                {

                    // API的URL,利用了上方接口返回值,需要code和accessToken才可调用此接口返回信息

                    string userurl = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo?access_token=" + accessToken;

                    var postData = new

                    {

                        code = userName 

                        //上方提到过,此处userName实际为获取的免登授权码code

                    };


                    // 将对象序列化为JSON字符串

                    string json = JsonConvert.SerializeObject(postData);


                    // 发送HTTP POST请求并等待结果  

                    JObject responseBody = JObject.Parse(SendPostRequest(userurl, json));

                    

                    JObject resObject = (JObject)responseBody["result"];

                    

                    name = (string)resObject["name"];


                    Console.WriteLine(name);

                }

                catch (AggregateException ex)

                {

                    // 捕获由于等待Task时发生的异常  

                    foreach (var innerEx in ex.InnerExceptions)

                    {

                        Console.WriteLine($"Inner Exception: {innerEx.Message}");

                        

                    }

                }

                catch (Exception e)

                {

                    // 捕获其他类型的异常  

                    

                    Console.WriteLine($"Exception: {e.Message}");

                }

            }



             //此处获取钉钉用户名后,调用第三部分单点登录的api,不做在一起,是方便后续单独使用此api,钉钉这傻东西获取用户名太麻烦了

            string html = "http://你的服务器ip/k3cloud/SSTO.K3Cloud.SYS.GetLogUrl.ExecuteService,SSTO.K3Cloud.SYS.common.kdsvc?code=" + name;


            this.KDContext.WebContext.Context.Response.Redirect(html);


            messages.Add("issuccess", "true");

            return messages;

        }

        static string SendPostRequest(string url, string json)

        {

            WebRequest request = WebRequest.Create(url);

            request.Method = "POST";

            request.ContentType = "application/json; charset=utf-8";


            using (var streamWriter = new StreamWriter(request.GetRequestStream()))

            {

                streamWriter.Write(json);

            }


            var httpResponse = (HttpWebResponse)request.GetResponse();

            using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))

            {

                return streamReader.ReadToEnd();

            }

        }




    }


}



3.适用于传统oa单点登录的api,有用户名拼接后可以直接登录到erp,第二部分代码重定向的时候就是调用的这个,这块可以直接参考社区内一个大佬的代码,是用于和泛微的单点登录集成的。

    星空第三方单点登录开发方案




图标赞 6
6人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!