• 钉钉开发系列(二)结构封装


    钉钉的每个API接口返回的数据都包含有ErrCode和ErrMsg,由此我们想到可以使用基类来定义,之后的其他数据以继承的方式来达成。所以我们定义一个结果基类。

    namespace DDSDK
    {
        public class ResultPackage
        {
            /// <summary>
            /// 错误码
            /// </summary>
            public ErrCodeEnum ErrCode { get; set; } = ErrCodeEnum.Unknown;
    
            /// <summary>
            /// 错误消息
            /// </summary>
            public string ErrMsg { get; set; }
    
            /// <summary>
            /// 结果的json形式
            /// </summary>
            public String Json { get; set; }
    
    
            #region IsOK Function              
            public bool IsOK()
            {
                return ErrCode == ErrCodeEnum.OK;
            }
            #endregion
    
            #region ToString
            public override string ToString()
            {
                String info = $"{nameof(ErrCode)}:{ErrCode},{nameof(ErrMsg)}:{ErrMsg}";
    
                return info;
            }
            #endregion
        }
    }
    
    为了便于查验返回的结果,我们又定义了一个Json来保存取回的数据。为了能更好的判断数据包是否正确,增加了IsOK函数。为了更好的查看错误码和错误信息,我们重载了ToString的方法。

    有了结果的基类,那么我们就可以将前一篇的获取access_token的结果类重新定义,代码如下

    public class TokenResult:ResultPackage
            {
                public string Access_token { get; set; }
            }
    由于我们每次发起的都是网络请求,而网络请求主要是以GET和POST的方式发起的,所以我们可以定义一个分析器,在分析器中封装GET和POST的请求方法,之后将相应的结果以泛型的形式返回。代码如下。

    namespace DDSDK
    {
        /// <summary>
        /// 分析器
        /// </summary>
        public class Analyze
        {
            #region Get Function  
            /// <summary>
            /// 发起GET请求
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="requestUrl"></param>
            /// <returns></returns>
            public static T Get<T>(String requestUrl) where T : ResultPackage, new()
            {
                String resultJson = RequestHelper.Get(requestUrl);
                return AnalyzeResult<T>(resultJson);
            }
            #endregion
    
            #region Post Function
            /// <summary>
            /// 发起POST请求
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="requestUrl"></param>
            /// <param name="requestParamOfJsonStr"></param>
            /// <returns></returns>
            public static T Post<T>(String requestUrl, String requestParamOfJsonStr) where T : ResultPackage, new()
            {
                String resultJson = RequestHelper.Post(requestUrl, requestParamOfJsonStr);
                return AnalyzeResult<T>(resultJson);
            }
            #endregion
    
            #region AnalyzeResult
            /// <summary>
            /// 分析结果
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="resultJson"></param>
            /// <returns></returns>
            private static T AnalyzeResult<T>(string resultJson) where T : ResultPackage, new()
            {
                ResultPackage tempResult = null;
                if (!String.IsNullOrEmpty(resultJson))
                {
                    tempResult = JsonConvert.DeserializeObject<ResultPackage>(resultJson);
                }
                T result = null;
                if (tempResult != null && tempResult.IsOK())
                {
                    result = JsonConvert.DeserializeObject<T>(resultJson);
                }
                else if (tempResult != null)
                {
                    result = tempResult as T;
                }
                else if (tempResult == null)
                {
                    result = new T();
                }
                result.Json = resultJson;
                return result;
            }
            #endregion      
        }
    }
    为了能让泛型类保持结果的基本一致性,我们将泛型类作了限定,即where T : ResultPackage, new(),这句话的意思是说泛型T必须源于ResultPackage,且要实现无参的构造方法。为了保证结果的正确返回,我们在得到返回的json数据串时,先序列化基本类,判断结果是否OK,然后再二次序列化成最终的结果类。

    下面是RequestHelper类

    namespace DDSDK
    {
        /// <summary>
        /// 请求协助类
        /// </summary>
        public class RequestHelper
        {
            #region Get
            /// <summary>
            /// 执行基本的命令方法,以Get方式
            /// </summary>
            /// <param name="apiurl"></param>
            /// <returns></returns>
            public static String Get(string apiurl)
            {
                WebRequest request = WebRequest.Create(@apiurl);
                request.Method = "GET";
                WebResponse response = request.GetResponse();
                Stream stream = response.GetResponseStream();
                Encoding encode = Encoding.UTF8;
                StreamReader reader = new StreamReader(stream, encode);
                string resultJson = reader.ReadToEnd();
                return resultJson;
            }
            #endregion
    
            #region Post
            /// <summary>
            /// 以Post方式提交命令
            /// </summary>
            public static String Post(string apiurl, string jsonString)
            {
                WebRequest request = WebRequest.Create(@apiurl);
                request.Method = "POST";
                request.ContentType = "application/json";
    
                byte[] bs = Encoding.UTF8.GetBytes(jsonString);
                request.ContentLength = bs.Length;
                Stream newStream = request.GetRequestStream();
                newStream.Write(bs, 0, bs.Length);
                newStream.Close();
    
                WebResponse response = request.GetResponse();
                Stream stream = response.GetResponseStream();
                Encoding encode = Encoding.UTF8;
                StreamReader reader = new StreamReader(stream, encode);
                string resultJson = reader.ReadToEnd();
                return resultJson;
            }
            #endregion
        }
    }
    有了这些封装后,我们前一篇中获取access_token的方法就可进一步简化,简化代码如下

     #region UpdateAccessToken
            /// <summary>
            ///更新票据
            /// </summary>
            /// <param name="forced">true:强制更新.false:按缓存是否到期来更新</param>
            public static void UpdateAccessToken(bool forced = false)
            {         
                if (!forced && AccessToken.Begin.AddSeconds(ConstVars.CACHE_TIME) >= DateTime.Now)
                {//没有强制更新,并且没有超过缓存时间
                    return;
                }
                string CorpID = ConfigHelper.FetchCorpID();
                string CorpSecret = ConfigHelper.FetchCorpSecret();
                string TokenUrl = Urls.gettoken;
                string apiurl = $"{TokenUrl}?{Keys.corpid}={CorpID}&{Keys.corpsecret}={CorpSecret}";
                TokenResult tokenResult = Analyze.Get<TokenResult>(apiurl);
                if (tokenResult.ErrCode== ErrCodeEnum.OK)
                {
                    AccessToken.Value = tokenResult.Access_token;
                    AccessToken.Begin = DateTime.Now;
                }
            }
            #endregion
    在发起请求的过程中,会用到很多的常量和KEY,这里专门定义了相关的类来保存,以方便需要的地方调用。

    namespace DDSDK
    {
        public class ConstVars
        {
            /// <summary>
            /// 缓存的JS票据的KEY
            /// </summary>
            public const string CACHE_JS_TICKET_KEY = "CACHE_JS_TICKET_KEY";
    
            /// <summary>
            /// 缓存时间
            /// </summary>
            public const int CACHE_TIME = 5000;
        }
    }


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DDSDK
    {
        /// <summary>
        /// Url的Key
        /// </summary>
        public sealed class Keys
        {
            public const string corpid = "corpid";
    
            public const string corpsecret = "corpsecret";
    
            public const string department_id = "department_id";
    
            public const string userid = "userid";
    
            public const string chatid = "chatid";
    
            public const string access_token = "access_token";
    
            public const string jsapi_ticket = "jsapi_ticket";
    
            public const string noncestr = "noncestr";
    
            public const string timestamp = "timestamp";
    
            public const string url = "url";
        }
    }
    


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace DDSDK
    {
        /// <summary>
        /// SDK使用的URL
        /// </summary>
        public sealed class Urls
        {
            /// <summary>
            /// 创建会话
            /// </summary>
            public const string chat_create = "https://oapi.dingtalk.com/chat/create";
            /// <summary>
            /// 获取会话信息
            /// </summary>
            public const string chat_get = "https://oapi.dingtalk.com/chat/get";
            /// <summary>
            /// 发送会话消息
            /// </summary>
            public const string chat_send = "https://oapi.dingtalk.com/chat/send";
            /// <summary>
            /// 更新会话信息
            /// </summary>
            public const string chat_update = "https://oapi.dingtalk.com/chat/update";
    
            /// <summary>
            /// 获取部门列表
            /// </summary>
            public const string department_list = "https://oapi.dingtalk.com/department/list";
    
            /// <summary>
            /// 获取访问票记
            /// </summary>
            public const string gettoken = "https://oapi.dingtalk.com/gettoken";
    
            /// <summary>
            /// 发送消息
            /// </summary>
            public const string message_send = "https://oapi.dingtalk.com/message/send";
    
            /// <summary>
            /// 用户列表
            /// </summary>
            public const string user_list = "https://oapi.dingtalk.com/user/list";
            /// <summary>
            /// 用户详情
            /// </summary>
            public const string user_get = "https://oapi.dingtalk.com/user/get";
    
            /// <summary>
            /// 获取JSAPI的票据
            /// </summary>
            public const string get_jsapi_ticket = "https://oapi.dingtalk.com/get_jsapi_ticket";
        }
    }
    

    至此,基本的结构封装已经完成。

    欢迎打描左侧二维码打赏。

    转载请注明出处。







  • 相关阅读:
    Centos8.2安装Mongodb4.4.2(社区版)
    Spirng 循环依赖报错:Requested bean is currently in creation: Is there an unresolvable circular reference?
    SpringBoot Test 多线程报错:dataSource already closed
    SpringCloud Stream整合RabbitMQ3.5.0
    SpringBoot2.2.5整合ElasticSearch7.9.2
    ElasticSearch7.9.2设置密码
    CentOS7安装Kibana7.9.2
    张家界国庆6天行
    安装tomcat时,SYSTEM进程(PID=4)占用80端口的几种情况及解决方法(window7系统)
    竞品分析的目的是什么?如何筛选竞品?竞品分析资料来源?
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604933.html
Copyright © 2020-2023  润新知