瀏覽代碼

新增项目

zhoufan 7 年之前
當前提交
50ce7c1801

+ 84 - 0
DingDingDemo.Common/AjaxResult.cs

@@ -0,0 +1,84 @@
1
+using System;
2
+
3
+namespace DingDingDemo.Common
4
+{
5
+    public class AjaxResult
6
+    {
7
+        /// <summary>
8
+        /// 操作结果类型
9
+        /// </summary>
10
+        public object state { get; set; }
11
+        /// <summary>
12
+        /// 获取 消息内容
13
+        /// </summary>
14
+        public string message { get; set; }
15
+        /// <summary>
16
+        /// 获取 返回数据
17
+        /// </summary>
18
+        public object data { get; set; }
19
+    }
20
+    /// <summary>
21
+    /// 表示 ajax 操作结果类型的枚举
22
+    /// </summary>
23
+    public enum ResultTypes
24
+    {
25
+        /// <summary>
26
+        /// 成功结果类型
27
+        /// </summary>
28
+        success = 200, //请求(或处理)成功,
29
+
30
+        /// <summary>
31
+        /// 成功结果类型
32
+        /// </summary>
33
+        redirect = 302, //跳转,
34
+
35
+        /// <summary>
36
+        /// 警告结果类型
37
+        /// </summary>
38
+        warning = 402,//警告
39
+
40
+        /// <summary>
41
+        /// 未授权
42
+        /// </summary>
43
+        unauthorized = 401,
44
+
45
+
46
+        /// <summary>
47
+        /// 请求参数不完整或不正确
48
+        /// </summary>
49
+        parameterError = 400,
50
+
51
+        /// <summary>
52
+        /// 请求TOKEN失效
53
+        /// </summary>
54
+        tokenInvalid = 403,
55
+
56
+        /// <summary>
57
+        /// HTTP请求类型不合法
58
+        /// </summary>
59
+        httpMehtodError = 405,
60
+
61
+
62
+        /// <summary>
63
+        /// HTTP请求类型不合法
64
+        /// </summary>
65
+        httpRequestError = 406,
66
+
67
+
68
+        /// <summary>
69
+        /// 该URL已经失效
70
+        /// </summary>
71
+        yrlExpireError = 407,
72
+
73
+        /// <summary>
74
+        /// 未登录或登录已过期
75
+        /// </summary>
76
+        notoken = 499,
77
+
78
+        /// <summary>
79
+        /// 异常结果类型
80
+        /// </summary>
81
+        error = 500
82
+
83
+    }
84
+}

+ 77 - 0
DingDingDemo.Common/BaseController.cs

@@ -0,0 +1,77 @@
1
+using Microsoft.AspNetCore.Mvc;
2
+using System;
3
+using System.Collections.Generic;
4
+using System.Text;
5
+
6
+namespace DingDingDemo.Common
7
+{
8
+    public class BaseController : Controller
9
+    {
10
+        /// <summary>
11
+        /// 成功的消息格式化
12
+        /// </summary>
13
+        /// <param name="message"></param>
14
+        /// <returns></returns>
15
+        protected virtual ActionResult Success(string message)
16
+        {
17
+            var jsonMsg = new AjaxResult { state = ResultTypes.success.ToString(), message = message }.ToJson();
18
+            return Content(jsonMsg);
19
+        }
20
+
21
+        /// <summary>
22
+        /// 成功的消息格式化
23
+        /// </summary>
24
+        /// <param name="message"></param>
25
+        /// <param name="data"></param>
26
+        /// <returns></returns>
27
+        protected virtual IActionResult Success(string message, object data)
28
+        {
29
+            var jsonMsg = new AjaxResult { state = ResultTypes.success.ToString(), message = message, data = data }.ToJson();
30
+            return Content(jsonMsg);
31
+        }
32
+
33
+        /// <summary>
34
+        /// 跳转的消息格式化
35
+        /// </summary>
36
+        /// <param name="message"></param>
37
+        /// <param name="data"></param>
38
+        /// <returns></returns>
39
+        protected virtual IActionResult Redirect(string message, object data)
40
+        {
41
+            return Content(new AjaxResult { state = ResultTypes.redirect.ToString(), message = message, data = data }.ToJson());
42
+        }
43
+
44
+        /// <summary>
45
+        /// 错误的消息格式化
46
+        /// </summary>
47
+        /// <param name="message"></param>
48
+        /// <returns></returns>
49
+        protected virtual IActionResult Error(string message)
50
+        {
51
+            var jsonMsg = new AjaxResult { state = ResultTypes.error.ToString(), message = message }.ToJson();
52
+            return Content(jsonMsg);
53
+        }
54
+
55
+        /// <summary>
56
+        /// 未登录或者登录已过期
57
+        /// </summary>
58
+        /// <param name="message"></param>
59
+        /// <returns></returns>
60
+        protected virtual IActionResult NoToken(string message)
61
+        {
62
+            var jsonMsg = new AjaxResult { state = ResultTypes.notoken.ToString(), message = message }.ToJson();
63
+            return Content(jsonMsg);
64
+        }
65
+
66
+        /// <summary>
67
+        /// 未授权
68
+        /// </summary>
69
+        /// <param name="message"></param>
70
+        /// <returns></returns>
71
+        protected virtual IActionResult UnAuthorized(string message)
72
+        {
73
+            var jsonMsg = new AjaxResult { state = ResultTypes.unauthorized.ToString(), message = message }.ToJson();
74
+            return Content(jsonMsg);
75
+        }
76
+    }
77
+}

+ 42 - 0
DingDingDemo.Common/Common.cs

@@ -0,0 +1,42 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Text;
4
+
5
+namespace DingDingDemo.Common
6
+{
7
+    public static class Common
8
+    {
9
+        /// <summary>
10
+        /// 获取时间戳
11
+        /// </summary>
12
+        /// <returns></returns>
13
+        public static string GetTimeStamp(System.DateTime time)
14
+        {
15
+            long ts = ConvertDateTimeToInt(time);
16
+            return ts.ToString();
17
+        }
18
+        /// <summary>  
19
+        /// 将c# DateTime时间格式转换为Unix时间戳格式  
20
+        /// </summary>  
21
+        /// <param name="time">时间</param>  
22
+        /// <returns>long</returns>  
23
+        public static long ConvertDateTimeToInt(System.DateTime time)
24
+        {
25
+            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1, 0, 0, 0, 0));
26
+            long t = (time.Ticks - startTime.Ticks) / 10000;   //除10000调整为13位      
27
+            return t;
28
+        }
29
+        /// <summary>        
30
+        /// 时间戳转为C#格式时间        
31
+        /// </summary>        
32
+        /// <param name=”timeStamp”></param>        
33
+        /// <returns></returns>        
34
+        private static DateTime ConvertStringToDateTime(string timeStamp)
35
+        {
36
+            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
37
+            long lTime = long.Parse(timeStamp + "0000");
38
+            TimeSpan toNow = new TimeSpan(lTime);
39
+            return dtStart.Add(toNow);
40
+        }
41
+    }
42
+}

+ 238 - 0
DingDingDemo.Common/Cryptography.cs

@@ -0,0 +1,238 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.IO;
4
+using System.Net;
5
+using System.Security.Cryptography;
6
+using System.Text;
7
+
8
+namespace DingDingDemo.Common
9
+{
10
+    class Cryptography
11
+    {
12
+        public static UInt32 HostToNetworkOrder(UInt32 inval)
13
+        {
14
+            UInt32 outval = 0;
15
+            for (int i = 0; i < 4; i++)
16
+                outval = (outval << 8) + ((inval >> (i * 8)) & 255);
17
+            return outval;
18
+        }
19
+
20
+        public static Int32 HostToNetworkOrder(Int32 inval)
21
+        {
22
+            Int32 outval = 0;
23
+            for (int i = 0; i < 4; i++)
24
+                outval = (outval << 8) + ((inval >> (i * 8)) & 255);
25
+            return outval;
26
+        }
27
+        /// <summary>
28
+        /// 解密方法
29
+        /// </summary>
30
+        /// <param name="Input">密文</param>
31
+        /// <param name="EncodingAESKey"></param>
32
+        /// <returns></returns>
33
+        /// 
34
+        public static string AES_decrypt(String Input, string EncodingAESKey, ref string corpid)
35
+        {
36
+            byte[] Key;
37
+            Key = Convert.FromBase64String(EncodingAESKey + "=");
38
+            byte[] Iv = new byte[16];
39
+            Array.Copy(Key, Iv, 16);
40
+            byte[] btmpMsg = AES_decrypt(Input, Iv, Key);
41
+
42
+            int len = BitConverter.ToInt32(btmpMsg, 16);
43
+            len = IPAddress.NetworkToHostOrder(len);
44
+
45
+
46
+            byte[] bMsg = new byte[len];
47
+            byte[] bCorpid = new byte[btmpMsg.Length - 20 - len];
48
+            Array.Copy(btmpMsg, 20, bMsg, 0, len);
49
+            Array.Copy(btmpMsg, 20 + len, bCorpid, 0, btmpMsg.Length - 20 - len);
50
+            string oriMsg = Encoding.UTF8.GetString(bMsg);
51
+            corpid = Encoding.UTF8.GetString(bCorpid);
52
+
53
+
54
+            return oriMsg;
55
+        }
56
+        /// <summary>
57
+        /// 加密方法
58
+        /// </summary>
59
+        /// <param name="Input"></param>
60
+        /// <param name="EncodingAESKey"></param>
61
+        /// <param name="corpid"></param>
62
+        /// <returns></returns>
63
+        public static String AES_encrypt(String Input, string EncodingAESKey, string corpid)
64
+        {
65
+            byte[] Key;
66
+            Key = Convert.FromBase64String(EncodingAESKey + "=");
67
+            byte[] Iv = new byte[16];
68
+            Array.Copy(Key, Iv, 16);
69
+            string Randcode = CreateRandCode(16);
70
+            byte[] bRand = Encoding.UTF8.GetBytes(Randcode);
71
+            byte[] bCorpid = Encoding.UTF8.GetBytes(corpid);
72
+            byte[] btmpMsg = Encoding.UTF8.GetBytes(Input);
73
+            byte[] bMsgLen = BitConverter.GetBytes(HostToNetworkOrder(btmpMsg.Length));
74
+            byte[] bMsg = new byte[bRand.Length + bMsgLen.Length + bCorpid.Length + btmpMsg.Length];
75
+
76
+            Array.Copy(bRand, bMsg, bRand.Length);
77
+            Array.Copy(bMsgLen, 0, bMsg, bRand.Length, bMsgLen.Length);
78
+            Array.Copy(btmpMsg, 0, bMsg, bRand.Length + bMsgLen.Length, btmpMsg.Length);
79
+            Array.Copy(bCorpid, 0, bMsg, bRand.Length + bMsgLen.Length + btmpMsg.Length, bCorpid.Length);
80
+
81
+            return AES_encrypt(bMsg, Iv, Key);
82
+
83
+        }
84
+        private static string CreateRandCode(int codeLen)
85
+        {
86
+            string codeSerial = "2,3,4,5,6,7,a,c,d,e,f,h,i,j,k,m,n,p,r,s,t,A,C,D,E,F,G,H,J,K,M,N,P,Q,R,S,U,V,W,X,Y,Z";
87
+            if (codeLen == 0)
88
+            {
89
+                codeLen = 16;
90
+            }
91
+            string[] arr = codeSerial.Split(',');
92
+            string code = "";
93
+            int randValue = -1;
94
+            Random rand = new Random(unchecked((int)DateTime.Now.Ticks));
95
+            for (int i = 0; i < codeLen; i++)
96
+            {
97
+                randValue = rand.Next(0, arr.Length - 1);
98
+                code += arr[randValue];
99
+            }
100
+            return code;
101
+        }
102
+
103
+        private static String AES_encrypt(String Input, byte[] Iv, byte[] Key)
104
+        {
105
+            var aes = new RijndaelManaged();
106
+            //秘钥的大小,以位为单位
107
+            aes.KeySize = 256;
108
+            //支持的块大小
109
+            aes.BlockSize = 128;
110
+            //填充模式
111
+            aes.Padding = PaddingMode.PKCS7;
112
+            aes.Mode = CipherMode.CBC;
113
+            aes.Key = Key;
114
+            aes.IV = Iv;
115
+            var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
116
+            byte[] xBuff = null;
117
+
118
+            using (var ms = new MemoryStream())
119
+            {
120
+                using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
121
+                {
122
+                    byte[] xXml = Encoding.UTF8.GetBytes(Input);
123
+                    cs.Write(xXml, 0, xXml.Length);
124
+                }
125
+                xBuff = ms.ToArray();
126
+            }
127
+            String Output = Convert.ToBase64String(xBuff);
128
+            return Output;
129
+        }
130
+
131
+        private static String AES_encrypt(byte[] Input, byte[] Iv, byte[] Key)
132
+        {
133
+            var aes = new RijndaelManaged();
134
+            //秘钥的大小,以位为单位
135
+            aes.KeySize = 256;
136
+            //支持的块大小
137
+            aes.BlockSize = 128;
138
+            //填充模式
139
+            //aes.Padding = PaddingMode.PKCS7;
140
+            aes.Padding = PaddingMode.None;
141
+            aes.Mode = CipherMode.CBC;
142
+            aes.Key = Key;
143
+            aes.IV = Iv;
144
+            var encrypt = aes.CreateEncryptor(aes.Key, aes.IV);
145
+            byte[] xBuff = null;
146
+
147
+            #region 自己进行PKCS7补位,用系统自己带的不行
148
+            byte[] msg = new byte[Input.Length + 32 - Input.Length % 32];
149
+            Array.Copy(Input, msg, Input.Length);
150
+            byte[] pad = KCS7Encoder(Input.Length);
151
+            Array.Copy(pad, 0, msg, Input.Length, pad.Length);
152
+            #endregion
153
+
154
+            #region 注释的也是一种方法,效果一样
155
+            //ICryptoTransform transform = aes.CreateEncryptor();
156
+            //byte[] xBuff = transform.TransformFinalBlock(msg, 0, msg.Length);
157
+            #endregion
158
+
159
+            using (var ms = new MemoryStream())
160
+            {
161
+                using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write))
162
+                {
163
+                    cs.Write(msg, 0, msg.Length);
164
+                }
165
+                xBuff = ms.ToArray();
166
+            }
167
+
168
+            String Output = Convert.ToBase64String(xBuff);
169
+            return Output;
170
+        }
171
+
172
+        private static byte[] KCS7Encoder(int text_length)
173
+        {
174
+            int block_size = 32;
175
+            // 计算需要填充的位数
176
+            int amount_to_pad = block_size - (text_length % block_size);
177
+            if (amount_to_pad == 0)
178
+            {
179
+                amount_to_pad = block_size;
180
+            }
181
+            // 获得补位所用的字符
182
+            char pad_chr = chr(amount_to_pad);
183
+            string tmp = "";
184
+            for (int index = 0; index < amount_to_pad; index++)
185
+            {
186
+                tmp += pad_chr;
187
+            }
188
+            return Encoding.UTF8.GetBytes(tmp);
189
+        }
190
+        /**
191
+         * 将数字转化成ASCII码对应的字符,用于对明文进行补码
192
+         * 
193
+         * @param a 需要转化的数字
194
+         * @return 转化得到的字符
195
+         */
196
+        static char chr(int a)
197
+        {
198
+
199
+            byte target = (byte)(a & 0xFF);
200
+            return (char)target;
201
+        }
202
+        private static byte[] AES_decrypt(String Input, byte[] Iv, byte[] Key)
203
+        {
204
+            RijndaelManaged aes = new RijndaelManaged();
205
+            aes.KeySize = 256;
206
+            aes.BlockSize = 128;
207
+            aes.Mode = CipherMode.CBC;
208
+            aes.Padding = PaddingMode.None;
209
+            aes.Key = Key;
210
+            aes.IV = Iv;
211
+            var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
212
+            byte[] xBuff = null;
213
+            using (var ms = new MemoryStream())
214
+            {
215
+                using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
216
+                {
217
+                    byte[] xXml = Convert.FromBase64String(Input);
218
+                    byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
219
+                    Array.Copy(xXml, msg, xXml.Length);
220
+                    cs.Write(xXml, 0, xXml.Length);
221
+                }
222
+                xBuff = decode2(ms.ToArray());
223
+            }
224
+            return xBuff;
225
+        }
226
+        private static byte[] decode2(byte[] decrypted)
227
+        {
228
+            int pad = (int)decrypted[decrypted.Length - 1];
229
+            if (pad < 1 || pad > 32)
230
+            {
231
+                pad = 0;
232
+            }
233
+            byte[] res = new byte[decrypted.Length - pad];
234
+            Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
235
+            return res;
236
+        }
237
+    }
238
+}

+ 21 - 0
DingDingDemo.Common/DingDingDemo.Common.csproj

@@ -0,0 +1,21 @@
1
+<Project Sdk="Microsoft.NET.Sdk">
2
+
3
+  <PropertyGroup>
4
+    <TargetFramework>netstandard2.0</TargetFramework>
5
+  </PropertyGroup>
6
+
7
+  <ItemGroup>
8
+    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
9
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
10
+  </ItemGroup>
11
+
12
+  <ItemGroup>
13
+    <Reference Include="Microsoft.AspNetCore.Mvc.ViewFeatures">
14
+      <HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.mvc.viewfeatures\2.0.4\lib\netstandard2.0\Microsoft.AspNetCore.Mvc.ViewFeatures.dll</HintPath>
15
+    </Reference>
16
+    <Reference Include="Microsoft.Extensions.Configuration.Json">
17
+      <HintPath>C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.extensions.configuration.json\2.0.2\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll</HintPath>
18
+    </Reference>
19
+  </ItemGroup>
20
+
21
+</Project>

+ 263 - 0
DingDingDemo.Common/DingTalkCrypt.cs

@@ -0,0 +1,263 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.Security.Cryptography;
5
+using System.Text;
6
+
7
+namespace DingDingDemo.Common
8
+{
9
+    public class DingTalkCrypt
10
+    {
11
+        private string m_sEncodingAESKey;
12
+        private string m_sToken;
13
+        private string m_sSuiteKey;
14
+        /**ask getPaddingBytes key固定长度**/
15
+        private static int AES_ENCODE_KEY_LENGTH = 43;
16
+        /**加密随机字符串字节长度**/
17
+        private static int RANDOM_LENGTH = 16;
18
+
19
+        enum DingTalkCryptErrorCode
20
+        {
21
+            /**成功**/
22
+            SUCCESS = 0,
23
+            /**加密明文文本非法**/
24
+            ENCRYPTION_PLAINTEXT_ILLEGAL = 900001,
25
+            /**加密时间戳参数非法**/
26
+            ENCRYPTION_TIMESTAMP_ILLEGAL = 900002,
27
+            /**加密随机字符串参数非法**/
28
+            ENCRYPTION_NONCE_ILLEGAL = 900003,
29
+            /**不合法的aeskey**/
30
+            AES_KEY_ILLEGAL = 900004,
31
+            /**签名不匹配**/
32
+            SIGNATURE_NOT_MATCH = 900005,
33
+            /**计算签名错误**/
34
+            COMPUTE_SIGNATURE_ERROR = 900006,
35
+            /**计算加密文字错误**/
36
+            COMPUTE_ENCRYPT_TEXT_ERROR = 900007,
37
+            /**计算解密文字错误**/
38
+            COMPUTE_DECRYPT_TEXT_ERROR = 900008,
39
+            /**计算解密文字长度不匹配**/
40
+            COMPUTE_DECRYPT_TEXT_LENGTH_ERROR = 900009,
41
+            /**计算解密文字suiteKey不匹配**/
42
+            COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR = 900010,
43
+        };
44
+
45
+        /// <summary>
46
+        /// 构造函数
47
+        /// </summary>
48
+        /// <param name="token">钉钉开放平台上,开发者设置的token</param>
49
+        /// <param name="encodingAesKey">钉钉开放台上,开发者设置的EncodingAESKey</param>
50
+        /// <param name="suiteKey">钉钉开放平台上,开发者设置的suiteKey</param>
51
+        public DingTalkCrypt(string token, string encodingAesKey, string suiteKey)
52
+        {
53
+            m_sToken = token;
54
+            m_sSuiteKey = suiteKey;
55
+            m_sEncodingAESKey = encodingAesKey;
56
+        }
57
+
58
+        /// <summary>
59
+        /// 将消息加密,返回加密后字符串
60
+        /// </summary>
61
+        /// <param name="sReplyMsg">传递的消息体明文</param>
62
+        /// <param name="sTimeStamp">时间戳</param>
63
+        /// <param name="sNonce">随机字符串</param>
64
+        /// <param name="sEncryptMsg">加密后的消息信息</param>
65
+        /// <param name="signature">解密用的签名串</param>
66
+        /// <returns>成功0,失败返回对应的错误码</returns>
67
+        public int EncryptMsg(string sReplyMsg, string sTimeStamp, string sNonce, ref string sEncryptMsg, ref string signature)
68
+        {
69
+            if (string.IsNullOrEmpty(sReplyMsg))
70
+                return (int)DingTalkCryptErrorCode.ENCRYPTION_PLAINTEXT_ILLEGAL;
71
+            if (string.IsNullOrEmpty(sTimeStamp))
72
+                return (int)DingTalkCryptErrorCode.ENCRYPTION_TIMESTAMP_ILLEGAL;
73
+            if (string.IsNullOrEmpty(sNonce))
74
+                return (int)DingTalkCryptErrorCode.ENCRYPTION_NONCE_ILLEGAL;
75
+
76
+            if (m_sEncodingAESKey.Length != AES_ENCODE_KEY_LENGTH)
77
+                return (int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL;
78
+
79
+            string raw = "";
80
+            try
81
+            {
82
+                raw = Cryptography.AES_encrypt(sReplyMsg, m_sEncodingAESKey, m_sSuiteKey);
83
+            }
84
+            catch (Exception)
85
+            {
86
+                return (int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL;
87
+            }
88
+
89
+            string msgSigature = "";
90
+            int ret = GenerateSignature(m_sToken, sTimeStamp, sNonce, raw, ref msgSigature);
91
+            sEncryptMsg = raw;
92
+            signature = msgSigature;
93
+            return ret;
94
+        }
95
+        /// <summary>
96
+        /// 密文解密
97
+        /// </summary>
98
+        /// <param name="sMsgSignature">签名串</param>
99
+        /// <param name="sTimeStamp">时间戳</param>
100
+        /// <param name="sNonce">随机串</param>
101
+        /// <param name="sPostData">密文</param>
102
+        /// <param name="sMsg">解密后的原文,当return返回0时有效</param>
103
+        /// <returns>成功0,失败返回对应的错误码</returns>
104
+        public int DecryptMsg(string sMsgSignature, string sTimeStamp, string sNonce, string sPostData, ref string sMsg)
105
+        {
106
+            if (m_sEncodingAESKey.Length != AES_ENCODE_KEY_LENGTH)
107
+                return (int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL;
108
+
109
+            string sEncryptMsg = sPostData;
110
+
111
+            int ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEncryptMsg, sMsgSignature);
112
+
113
+            string cpid = "";
114
+            try
115
+            {
116
+                sMsg = Cryptography.AES_decrypt(sEncryptMsg, m_sEncodingAESKey, ref cpid);
117
+            }
118
+            catch (FormatException)
119
+            {
120
+                sMsg = "";
121
+                return (int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR;
122
+
123
+            }
124
+            catch (Exception)
125
+            {
126
+                sMsg = "";
127
+                return (int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR;
128
+            }
129
+
130
+            if (cpid != m_sSuiteKey)
131
+                return (int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR;
132
+
133
+            return ret;
134
+        }
135
+
136
+        /// <summary>
137
+        /// 生成签名
138
+        /// </summary>
139
+        /// <param name="sToken"></param>
140
+        /// <param name="sTimeStamp"></param>
141
+        /// <param name="sNonce"></param>
142
+        /// <param name="sMsgEncrypt"></param>
143
+        /// <param name="sMsgSignature"></param>
144
+        /// <returns></returns>
145
+        public static int GenerateSignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, ref string sMsgSignature)
146
+        {
147
+            ArrayList AL = new ArrayList();
148
+            AL.Add(sToken);
149
+            AL.Add(sTimeStamp);
150
+            AL.Add(sNonce);
151
+            AL.Add(sMsgEncrypt);
152
+            AL.Sort(new DictionarySort());
153
+            string raw = "";
154
+            for (int i = 0; i < AL.Count; ++i)
155
+            {
156
+                raw += AL[i];
157
+            }
158
+
159
+            SHA1 sha;
160
+            ASCIIEncoding enc;
161
+            string hash = "";
162
+            try
163
+            {
164
+                sha = new SHA1CryptoServiceProvider();
165
+                enc = new ASCIIEncoding();
166
+                byte[] dataToHash = enc.GetBytes(raw);
167
+                byte[] dataHashed = sha.ComputeHash(dataToHash);
168
+                hash = BitConverter.ToString(dataHashed).Replace("-", "");
169
+                hash = hash.ToLower();
170
+            }
171
+            catch (Exception)
172
+            {
173
+                return (int)DingTalkCryptErrorCode.COMPUTE_SIGNATURE_ERROR;
174
+            }
175
+            sMsgSignature = hash;
176
+            return 0;
177
+        }
178
+        /// <summary>
179
+        /// 验证签名
180
+        /// </summary>
181
+        /// <param name="sToken"></param>
182
+        /// <param name="sTimeStamp"></param>
183
+        /// <param name="sNonce"></param>
184
+        /// <param name="sMsgEncrypt"></param>
185
+        /// <param name="sSigture"></param>
186
+        /// <returns></returns>
187
+        private static int VerifySignature(string sToken, string sTimeStamp, string sNonce, string sMsgEncrypt, string sSigture)
188
+        {
189
+            string hash = "";
190
+            int ret = 0;
191
+            ret = GenerateSignature(sToken, sTimeStamp, sNonce, sMsgEncrypt, ref hash);
192
+            if (ret != 0)
193
+                return ret;
194
+            if (hash == sSigture)
195
+                return 0;
196
+            else
197
+            {
198
+                return (int)DingTalkCryptErrorCode.SIGNATURE_NOT_MATCH;
199
+            }
200
+        }
201
+
202
+        /// <summary>
203
+        /// 验证URL
204
+        /// </summary>
205
+        /// <param name="sMsgSignature">签名串,对应URL参数的msg_signature</param>
206
+        /// <param name="sTimeStamp">时间戳,对应URL参数的timestamp</param>
207
+        /// <param name="sNonce">随机串,对应URL参数的nonce</param>
208
+        /// <param name="sEchoStr">经过加密的消息体,对应URL参数的encrypt</param>
209
+        /// <param name="sReplyEchoStr"></param>
210
+        /// <returns></returns>
211
+        public int VerifyURL(string sMsgSignature, string sTimeStamp, string sNonce, string sEchoStr, ref string sReplyEchoStr)
212
+        {
213
+            int ret = 0;
214
+            if (m_sEncodingAESKey.Length != 43)
215
+            {
216
+                return (int)DingTalkCryptErrorCode.AES_KEY_ILLEGAL;
217
+            }
218
+            ret = VerifySignature(m_sToken, sTimeStamp, sNonce, sEchoStr, sMsgSignature);
219
+            sReplyEchoStr = "";
220
+            string cpid = "";
221
+            try
222
+            {
223
+                sReplyEchoStr = Cryptography.AES_decrypt(sEchoStr, m_sEncodingAESKey, ref cpid); //m_sCorpID);
224
+            }
225
+            catch (Exception)
226
+            {
227
+                sReplyEchoStr = "";
228
+                return (int)DingTalkCryptErrorCode.COMPUTE_SIGNATURE_ERROR;
229
+            }
230
+            if (cpid != m_sSuiteKey)
231
+            {
232
+                sReplyEchoStr = "";
233
+                return (int)DingTalkCryptErrorCode.COMPUTE_DECRYPT_TEXT_SuiteKey_ERROR;
234
+            }
235
+            return ret;
236
+        }
237
+        /// <summary>
238
+        /// 字典排序
239
+        /// </summary>
240
+        public class DictionarySort : System.Collections.IComparer
241
+        {
242
+            public int Compare(object oLeft, object oRight)
243
+            {
244
+                string sLeft = oLeft as string;
245
+                string sRight = oRight as string;
246
+                int iLeftLength = sLeft.Length;
247
+                int iRightLength = sRight.Length;
248
+                int index = 0;
249
+                while (index < iLeftLength && index < iRightLength)
250
+                {
251
+                    if (sLeft[index] < sRight[index])
252
+                        return -1;
253
+                    else if (sLeft[index] > sRight[index])
254
+                        return 1;
255
+                    else
256
+                        index++;
257
+                }
258
+                return iLeftLength - iRightLength;
259
+
260
+            }
261
+        }
262
+    }
263
+}

+ 146 - 0
DingDingDemo.Common/HttpHelper.cs

@@ -0,0 +1,146 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Net.Http;
4
+using System.Text;
5
+using System.Threading.Tasks;
6
+
7
+namespace DingDingDemo.Common
8
+{
9
+    public class HttpHelper
10
+    {
11
+        /// <summary>
12
+        /// 同步GET请求
13
+        /// </summary>
14
+        /// <param name="url"></param>
15
+        /// <param name="headers"></param>
16
+        /// <param name="timeout">请求响应超时时间,单位/s(默认100秒)</param>
17
+        /// <returns></returns>
18
+        public static string HttpGet(string url, Dictionary<string, string> headers = null, int timeout = 0)
19
+        {
20
+            using (HttpClient client = new HttpClient())
21
+            {
22
+                if (headers != null)
23
+                {
24
+                    foreach (KeyValuePair<string, string> header in headers)
25
+                    {
26
+                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
27
+                    }
28
+                }
29
+                if (timeout > 0)
30
+                {
31
+                    client.Timeout = new TimeSpan(0, 0, timeout);
32
+                }
33
+                Byte[] resultBytes = client.GetByteArrayAsync(url).Result;
34
+                return Encoding.UTF8.GetString(resultBytes);
35
+            }
36
+        }
37
+
38
+        /// <summary>
39
+        /// 异步GET请求
40
+        /// </summary>
41
+        /// <param name="url"></param>
42
+        /// <param name="headers"></param>
43
+        /// <param name="timeout">请求响应超时时间,单位/s(默认100秒)</param>
44
+        /// <returns></returns>
45
+        public static async Task<string> HttpGetAsync(string url, Dictionary<string, string> headers = null, int timeout = 0)
46
+        {
47
+            using (HttpClient client = new HttpClient())
48
+            {
49
+                if (headers != null)
50
+                {
51
+                    foreach (KeyValuePair<string, string> header in headers)
52
+                    {
53
+                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
54
+                    }
55
+                }
56
+                if (timeout > 0)
57
+                {
58
+                    client.Timeout = new TimeSpan(0, 0, timeout);
59
+                }
60
+                Byte[] resultBytes = await client.GetByteArrayAsync(url);
61
+                return Encoding.Default.GetString(resultBytes);
62
+            }
63
+        }
64
+
65
+
66
+        /// <summary>
67
+        /// 同步POST请求
68
+        /// </summary>
69
+        /// <param name="url"></param>
70
+        /// <param name="postData"></param>
71
+        /// <param name="headers"></param>
72
+        /// <param name="contentType"></param>
73
+        /// <param name="timeout">请求响应超时时间,单位/s(默认100秒)</param>
74
+        /// <param name="encoding">默认UTF8</param>
75
+        /// <returns></returns>
76
+        public static string HttpPost(string url, string postData, Dictionary<string, string> headers = null, string contentType = null, int timeout = 0, Encoding encoding = null)
77
+        {
78
+            using (HttpClient client = new HttpClient())
79
+            {
80
+                if (headers != null)
81
+                {
82
+                    foreach (KeyValuePair<string, string> header in headers)
83
+                    {
84
+                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
85
+                    }
86
+                }
87
+                if (timeout > 0)
88
+                {
89
+                    client.Timeout = new TimeSpan(0, 0, timeout);
90
+                }
91
+                using (HttpContent content = new StringContent(postData ?? "", encoding ?? Encoding.UTF8))
92
+                {
93
+                    if (contentType != null)
94
+                    {
95
+                        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
96
+                    }
97
+                    using (HttpResponseMessage responseMessage = client.PostAsync(url, content).Result)
98
+                    {
99
+                        Byte[] resultBytes = responseMessage.Content.ReadAsByteArrayAsync().Result;
100
+                        return Encoding.UTF8.GetString(resultBytes);
101
+                    }
102
+                }
103
+            }
104
+        }
105
+
106
+        /// <summary>
107
+        /// 异步POST请求
108
+        /// </summary>
109
+        /// <param name="url"></param>
110
+        /// <param name="postData"></param>
111
+        /// <param name="headers"></param>
112
+        /// <param name="contentType"></param>
113
+        /// <param name="timeout">请求响应超时时间,单位/s(默认100秒)</param>
114
+        /// <param name="encoding">默认UTF8</param>
115
+        /// <returns></returns>
116
+        public static async Task<string> HttpPostAsync(string url, string postData, Dictionary<string, string> headers = null, string contentType = null, int timeout = 0, Encoding encoding = null)
117
+        {
118
+            using (HttpClient client = new HttpClient())
119
+            {
120
+                if (headers != null)
121
+                {
122
+                    foreach (KeyValuePair<string, string> header in headers)
123
+                    {
124
+                        client.DefaultRequestHeaders.Add(header.Key, header.Value);
125
+                    }
126
+                }
127
+                if (timeout > 0)
128
+                {
129
+                    client.Timeout = new TimeSpan(0, 0, timeout);
130
+                }
131
+                using (HttpContent content = new StringContent(postData ?? "", encoding ?? Encoding.UTF8))
132
+                {
133
+                    if (contentType != null)
134
+                    {
135
+                        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
136
+                    }
137
+                    using (HttpResponseMessage responseMessage = await client.PostAsync(url, content))
138
+                    {
139
+                        Byte[] resultBytes = await responseMessage.Content.ReadAsByteArrayAsync();
140
+                        return Encoding.UTF8.GetString(resultBytes);
141
+                    }
142
+                }
143
+            }
144
+        }
145
+    }
146
+}

+ 44 - 0
DingDingDemo.Common/JsonHelper.cs

@@ -0,0 +1,44 @@
1
+using Newtonsoft.Json;
2
+using Newtonsoft.Json.Converters;
3
+using Newtonsoft.Json.Linq;
4
+using System;
5
+using System.Collections.Generic;
6
+using System.Data;
7
+using System.Text;
8
+
9
+namespace DingDingDemo.Common
10
+{
11
+    public static class JsonHelper
12
+    {
13
+        public static object ToJson(this string Json)
14
+        {
15
+            return Json == null ? null : JsonConvert.DeserializeObject(Json);
16
+        }
17
+        public static string ToJson(this object obj)
18
+        {
19
+            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
20
+            return JsonConvert.SerializeObject(obj, timeConverter);
21
+        }
22
+        public static string ToJson(this object obj, string datetimeformats)
23
+        {
24
+            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = datetimeformats };
25
+            return JsonConvert.SerializeObject(obj, timeConverter);
26
+        }
27
+        public static T ToObject<T>(this string Json)
28
+        {
29
+            return Json == null ? default(T) : JsonConvert.DeserializeObject<T>(Json);
30
+        }
31
+        public static List<T> ToList<T>(this string Json)
32
+        {
33
+            return Json == null ? null : JsonConvert.DeserializeObject<List<T>>(Json);
34
+        }
35
+        public static DataTable ToTable(this string Json)
36
+        {
37
+            return Json == null ? null : JsonConvert.DeserializeObject<DataTable>(Json);
38
+        }
39
+        public static JObject ToJObject(this string Json)
40
+        {
41
+            return Json == null ? JObject.Parse("{}") : JObject.Parse(Json.Replace("&nbsp;", ""));
42
+        }
43
+    }
44
+}

+ 43 - 0
DingDingDemo.Common/TokenHelper.cs

@@ -0,0 +1,43 @@
1
+using Microsoft.Extensions.Caching.Distributed;
2
+using Microsoft.Extensions.Configuration;
3
+using System;
4
+using System.Collections.Generic;
5
+using System.Text;
6
+
7
+namespace DingDingDemo.Common
8
+{
9
+    public class TokenHelper
10
+    {
11
+        private readonly IDistributedCache _cache;
12
+        private readonly IConfiguration _configuration;
13
+        public TokenHelper(IDistributedCache cache, IConfiguration configuration)
14
+        {
15
+            _cache = cache;
16
+            _configuration = configuration;
17
+        }
18
+
19
+        /// <summary>
20
+        /// 获取AccessToken
21
+        /// </summary>
22
+        /// <returns></returns>
23
+        public string GetAccessToken()
24
+        {
25
+            var accesstoken = _cache.GetString(_configuration["DingTalkSettings:AppKey"] +"accesstoken");
26
+            if (string.IsNullOrEmpty(accesstoken))
27
+            {
28
+                string result = HttpHelper.HttpGet(string.Format(_configuration["DingTalkSettings:TokenUrl"], _configuration["DingTalkSettings:AppKey"], _configuration["DingTalkSettings:AppSecret"]));
29
+                var resultobj = result.ToJObject();
30
+                if (resultobj["errcode"].ToString() == "0")
31
+                {
32
+                    accesstoken = resultobj["access_token"].ToString();
33
+                    string cachetime = _configuration["DingTalkSettings:TokenCacheTime"];
34
+                    DistributedCacheEntryOptions options = new DistributedCacheEntryOptions();
35
+                    options.AbsoluteExpiration = DateTime.Now.AddSeconds(long.Parse(cachetime));
36
+                    _cache.SetString(_configuration["DingTalkSettings:AppKey"] + "accesstoken", accesstoken, options);
37
+                }
38
+            }
39
+
40
+            return accesstoken;
41
+        }
42
+    }
43
+}

+ 31 - 0
DingDingDemo.sln

@@ -0,0 +1,31 @@
1
+
2
+Microsoft Visual Studio Solution File, Format Version 12.00
3
+# Visual Studio 15
4
+VisualStudioVersion = 15.0.27703.1
5
+MinimumVisualStudioVersion = 10.0.40219.1
6
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DingDingDemo", "DingDingDemo\DingDingDemo.csproj", "{BDA65DB7-984F-4CAB-9237-671307B00B2B}"
7
+EndProject
8
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DingDingDemo.Common", "DingDingDemo.Common\DingDingDemo.Common.csproj", "{97374216-953D-44DF-94A3-3D932D0085CE}"
9
+EndProject
10
+Global
11
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
12
+		Debug|Any CPU = Debug|Any CPU
13
+		Release|Any CPU = Release|Any CPU
14
+	EndGlobalSection
15
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
16
+		{BDA65DB7-984F-4CAB-9237-671307B00B2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17
+		{BDA65DB7-984F-4CAB-9237-671307B00B2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
18
+		{BDA65DB7-984F-4CAB-9237-671307B00B2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
19
+		{BDA65DB7-984F-4CAB-9237-671307B00B2B}.Release|Any CPU.Build.0 = Release|Any CPU
20
+		{97374216-953D-44DF-94A3-3D932D0085CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21
+		{97374216-953D-44DF-94A3-3D932D0085CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
22
+		{97374216-953D-44DF-94A3-3D932D0085CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
23
+		{97374216-953D-44DF-94A3-3D932D0085CE}.Release|Any CPU.Build.0 = Release|Any CPU
24
+	EndGlobalSection
25
+	GlobalSection(SolutionProperties) = preSolution
26
+		HideSolutionNode = FALSE
27
+	EndGlobalSection
28
+	GlobalSection(ExtensibilityGlobals) = postSolution
29
+		SolutionGuid = {9863934D-1195-451D-B701-D8A9D6CCC5BC}
30
+	EndGlobalSection
31
+EndGlobal

+ 347 - 0
DingDingDemo/Controllers/AttendanceController.cs

@@ -0,0 +1,347 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.Linq;
5
+using System.Threading.Tasks;
6
+using DingDingDemo.Common;
7
+using Microsoft.AspNetCore.Mvc;
8
+using Microsoft.Extensions.Caching.Distributed;
9
+using Microsoft.Extensions.Configuration;
10
+using Microsoft.Extensions.Logging;
11
+
12
+namespace DingDingDemo.Controllers
13
+{
14
+    /// <summary>
15
+    /// 考勤
16
+    /// </summary>
17
+    [Produces("application/json")]
18
+    [Route("api/[controller]")]
19
+    public class AttendanceController : BaseController
20
+    {
21
+        private readonly ILogger<AttendanceController> _logger;
22
+        private readonly IDistributedCache _cache;
23
+        private readonly IConfiguration _configuration;
24
+        public AttendanceController(IDistributedCache cache, IConfiguration configuration, ILogger<AttendanceController> logger)
25
+        {
26
+            _cache = cache;
27
+            _logger = logger;
28
+            _configuration = configuration;
29
+        }
30
+
31
+        /// <summary>
32
+        /// 获取排班列表
33
+        /// </summary>
34
+        /// <param name="date"></param>
35
+        /// <returns></returns>
36
+        [HttpGet("getschedulelist")]
37
+        public async Task<IActionResult> GetScheduleList(DateTime? date)
38
+        {
39
+            string strdate = date == null ? DateTime.Now.ToString("yyyy-MM-dd") : date.Value.ToString("yyyy-MM-dd");
40
+            TokenHelper th = new TokenHelper(_cache, _configuration);
41
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetSchedule"], th.GetAccessToken()) + "&workDate=" + strdate);
42
+            var result = strresult.ToJObject();
43
+            if (result["errcode"].ToString() == "0")
44
+            {
45
+                var rt = result["result"].ToString().ToJObject();
46
+                return Success("成功", rt["schedules"]);
47
+            }
48
+            else
49
+            {
50
+                return Error(result["errmsg"].ToString());
51
+            }
52
+        }
53
+
54
+        /// <summary>
55
+        /// 获取考勤组列表
56
+        /// </summary>
57
+        /// <returns></returns>
58
+        [HttpGet("getgrouplist")]
59
+        public IActionResult GetGroupList()
60
+        {
61
+            TokenHelper th = new TokenHelper(_cache, _configuration);
62
+
63
+            return Success("成功", GetGroups(th.GetAccessToken(), 0, 10));
64
+        }
65
+
66
+        /// <summary>
67
+        /// 获取列表
68
+        /// </summary>
69
+        /// <param name="token"></param>
70
+        /// <param name="offset"></param>
71
+        /// <param name="size"></param>
72
+        /// <returns></returns>
73
+        [ApiExplorerSettings(IgnoreApi = true)]
74
+        public ArrayList GetGroups(string token, int offset = 0, int size = 10)
75
+        {
76
+            ArrayList arrresult = new ArrayList();
77
+
78
+            string url = string.Format(_configuration["DingTalkSettings:GetGroupList"], token);
79
+            //url += "&offset=" + index + "&size=" + size;
80
+            var param = new
81
+            {
82
+                offset,
83
+                size
84
+            };
85
+            var strresult = HttpHelper.HttpPost(url, param.ToJson());
86
+            var result = strresult.ToJObject();
87
+            if (result["errcode"].ToString() == "0")
88
+            {
89
+                var rt = result["result"].ToString().ToJObject();
90
+                var rtlist = rt["groups"].ToJson().ToList<Dictionary<string, object>>();
91
+                arrresult.AddRange(rtlist);
92
+                if (rt["has_more"].ToString().ToLower() == "true")
93
+                {
94
+                    arrresult.AddRange(GetGroups(token, offset + size, size));
95
+                }
96
+            }
97
+            return arrresult;
98
+        }
99
+
100
+        /// <summary>
101
+        /// 获取打卡列表
102
+        /// </summary>
103
+        /// <param name="userids"></param>
104
+        /// <param name="start"></param>
105
+        /// <param name="end"></param>
106
+        /// <returns></returns>
107
+        [HttpGet("getrecordlist")]
108
+        public async Task<IActionResult> GetRecordList(string[] userids, DateTime? start, DateTime? end)
109
+        {
110
+            if (userids.Length==0)
111
+            {
112
+                return Error("员工id不能为空");
113
+            }
114
+            if (end != null && start != null && end.Value.Subtract(start.Value).TotalDays > 7)
115
+            {
116
+                return Error("时间区间不能超过7天");
117
+            }
118
+            if (start == null && end == null)
119
+            {
120
+                end = DateTime.Now;
121
+                start = end.Value.AddDays(-7);
122
+            }
123
+
124
+            TokenHelper th = new TokenHelper(_cache, _configuration);
125
+            string url = string.Format(_configuration["DingTalkSettings:GetRecordList"], th.GetAccessToken());
126
+            //string param = "userIds=" + userid + "&checkDateFrom=" + start.Value.ToString("yyyy-MM-dd HH:mm:ss") + "&checkDateTo=" + end.Value.ToString("yyyy-MM-dd HH:mm:ss");
127
+            var param = new
128
+            {
129
+                userIds = userids,
130
+                checkDateFrom = start.Value.ToString("yyyy-MM-dd HH:mm:ss"),
131
+                checkDateTo = end.Value.ToString("yyyy-MM-dd HH:mm:ss")
132
+            };
133
+            var strresult = await HttpHelper.HttpPostAsync(url, param.ToJson());
134
+            var result = strresult.ToJObject();
135
+            if (result["errcode"].ToString() == "0")
136
+            {
137
+                return Success("成功", result["recordresult"]);
138
+            }
139
+            else
140
+            {
141
+                return Error(result["errmsg"].ToString());
142
+            }
143
+        }
144
+
145
+        /// <summary>
146
+        /// 获取打卡结果列表
147
+        /// </summary>
148
+        /// <param name="userids"></param>
149
+        /// <param name="start"></param>
150
+        /// <param name="end"></param>
151
+        /// <returns></returns>
152
+        [HttpGet("getresultlist")]
153
+        public IActionResult GetResultList(string[] userids, DateTime? start, DateTime? end)
154
+        {
155
+            if (userids.Length==0)
156
+            {
157
+                return Error("员工id不能为空");
158
+            }
159
+            if (end != null && start != null && end.Value.Subtract(start.Value).TotalDays > 7)
160
+            {
161
+                return Error("时间区间不能超过7天");
162
+            }
163
+            if (start == null && end == null)
164
+            {
165
+                end = DateTime.Now;
166
+                start = end.Value.AddDays(-7);
167
+            }
168
+
169
+            TokenHelper th = new TokenHelper(_cache, _configuration);
170
+
171
+            return Success("成功", GetResults(th.GetAccessToken(), userids, start.Value, end.Value, 0, 50));
172
+        }
173
+
174
+        /// <summary>
175
+        /// 获取列表
176
+        /// </summary>
177
+        /// <param name="token"></param>
178
+        /// <param name="userids"></param>
179
+        /// <param name="start"></param>
180
+        /// <param name="end"></param>
181
+        /// <param name="offset"></param>
182
+        /// <param name="size"></param>
183
+        /// <returns></returns>
184
+        [ApiExplorerSettings(IgnoreApi = true)]
185
+        public ArrayList GetResults(string token, string[] userids, DateTime start, DateTime end, int offset = 0, int size = 10)
186
+        {
187
+            ArrayList arrresult = new ArrayList();
188
+
189
+            string url = string.Format(_configuration["DingTalkSettings:GetRecordResult"], token);
190
+            //url += "&userIdList=" + userid + "&workDateFrom=" + start.ToString("yyyy-MM-dd HH:mm:ss") + "&workDateTo=" + end.ToString("yyyy-MM-dd HH:mm:ss");
191
+            //url += "&offset=" + index + "&limit=" + size;
192
+            var param = new
193
+            {
194
+                userIdList= userids,
195
+                workDateFrom= start.ToString("yyyy-MM-dd HH:mm:ss"),
196
+                workDateTo= end.ToString("yyyy-MM-dd HH:mm:ss"),
197
+                offset,
198
+                limit= size
199
+            };
200
+            var strresult = HttpHelper.HttpPost(url, param.ToJson());
201
+            var result = strresult.ToJObject();
202
+            if (result["errcode"].ToString() == "0")
203
+            {
204
+                var rtlist = result["recordresult"].ToJson().ToList<Dictionary<string, object>>();
205
+                arrresult.AddRange(rtlist);
206
+                if (result["hasMore"].ToString().ToLower() == "true")
207
+                {
208
+                    arrresult.AddRange(GetResults(token, userids, start, end, offset + size, size));
209
+                }
210
+            }
211
+            return arrresult;
212
+        }
213
+
214
+        /// <summary>
215
+        /// 查询请假状态
216
+        /// </summary>
217
+        /// <returns></returns>
218
+        [HttpGet("getleavestatuslist")]
219
+        public IActionResult GetLeaveStatusList(string[] userids, DateTime? start, DateTime? end)
220
+        {
221
+            if (userids.Length == 0)
222
+            {
223
+                return Error("员工id不能为空");
224
+            }
225
+            if (end != null && start != null && end.Value.Subtract(start.Value).TotalDays > 180)
226
+            {
227
+                return Error("时间区间不能超过180天");
228
+            }
229
+            if (start == null && end == null)
230
+            {
231
+                end = DateTime.Now;
232
+                start = DateTime.Parse(end.Value.ToString("yyyy-MM") + "-01");
233
+            }
234
+            TokenHelper th = new TokenHelper(_cache, _configuration);
235
+
236
+            return Success("成功", GetLeaveStatus(th.GetAccessToken(), userids, start.Value, end.Value, 0, 20));
237
+        }
238
+
239
+        /// <summary>
240
+        /// 获取列表
241
+        /// </summary>
242
+        /// <param name="token"></param>
243
+        /// <param name="userids"></param>
244
+        /// <param name="start"></param>
245
+        /// <param name="end"></param>
246
+        /// <param name="offset"></param>
247
+        /// <param name="size"></param>
248
+        /// <returns></returns>
249
+        [ApiExplorerSettings(IgnoreApi = true)]
250
+        public ArrayList GetLeaveStatus(string token, string[] userids, DateTime start, DateTime end, int offset = 0, int size = 10)
251
+        {
252
+            ArrayList arrresult = new ArrayList();
253
+
254
+            string url = string.Format(_configuration["DingTalkSettings:GetLeaveStatus"], token);
255
+            var param = new
256
+            {
257
+                userid_list = userids,
258
+                start_time = Common.Common.GetTimeStamp(start),
259
+                end_time = Common.Common.GetTimeStamp(end),
260
+                offset,
261
+                size
262
+            };
263
+            var strresult = HttpHelper.HttpPost(url, param.ToJson());
264
+            var result = strresult.ToJObject();
265
+            if (result["errcode"].ToString() == "0")
266
+            {
267
+                var rt = result["result"].ToString().ToJObject();
268
+                var rtlist = rt["leave_status"].ToJson().ToList<Dictionary<string, object>>();
269
+                arrresult.AddRange(rtlist);
270
+                if (rt["has_more"].ToString().ToLower() == "true")
271
+                {
272
+                    arrresult.AddRange(GetGroups(token, offset + size, size));
273
+                }
274
+            }
275
+            return arrresult;
276
+        }
277
+
278
+        /// <summary>
279
+        /// 获取请假时长
280
+        /// </summary>
281
+        /// <returns></returns>
282
+        [HttpGet("getleaveapproveduration")]
283
+        public IActionResult GetLeaveApproveDuration(string userid, DateTime? start, DateTime? end)
284
+        {
285
+            if (string.IsNullOrEmpty(userid))
286
+            {
287
+                return Error("员工id不能为空");
288
+            }
289
+            //if (end != null && start != null && end.Value.Subtract(start.Value).TotalDays > 180)
290
+            //{
291
+            //    return Error("时间区间不能超过180天");
292
+            //}
293
+            if (start == null && end == null)
294
+            {
295
+                end = DateTime.Now;
296
+                start = DateTime.Parse(end.Value.ToString("yyyy-MM") + "-01");
297
+            }
298
+            TokenHelper th = new TokenHelper(_cache, _configuration);
299
+
300
+            string url = string.Format(_configuration["DingTalkSettings:GetLeaveApproveDuration"], th.GetAccessToken());
301
+            var param = new
302
+            {
303
+                userid ,
304
+                from_date = start,
305
+                to_date = end
306
+            };
307
+            var strresult = HttpHelper.HttpPost(url, param.ToJson());
308
+            var result = strresult.ToJObject();
309
+            if (result["errcode"].ToString() == "0")
310
+            {
311
+                var rt = result["result"].ToString().ToJObject();
312
+                return Success("成功", rt["duration_in_minutes"]);
313
+            }
314
+            else
315
+            {
316
+                return Error(result["errmsg"].ToString());
317
+            }
318
+        }
319
+
320
+
321
+        /// <summary>
322
+        /// 获取用户考勤组
323
+        /// </summary>
324
+        /// <param name="userid"></param>
325
+        /// <returns></returns>
326
+        [HttpGet("getusergroup")]
327
+        public async Task<IActionResult> GetUserGroup(string userid)
328
+        {
329
+            if (string.IsNullOrEmpty(userid))
330
+            {
331
+                return Error("员工id不能为空");
332
+            }
333
+            TokenHelper th = new TokenHelper(_cache, _configuration);
334
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetUserGroup"], th.GetAccessToken()) + "&userid=" + userid);
335
+            var result = strresult.ToJObject();
336
+            if (result["errcode"].ToString() == "0")
337
+            {
338
+                return Success("成功", result["result"]);
339
+            }
340
+            else
341
+            {
342
+                return Error(result["errmsg"].ToString());
343
+            }
344
+        }
345
+
346
+    }
347
+}

+ 52 - 0
DingDingDemo/Controllers/BlackBoardController.cs

@@ -0,0 +1,52 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Linq;
4
+using System.Threading.Tasks;
5
+using DingDingDemo.Common;
6
+using Microsoft.AspNetCore.Mvc;
7
+using Microsoft.Extensions.Caching.Distributed;
8
+using Microsoft.Extensions.Configuration;
9
+using Microsoft.Extensions.Logging;
10
+
11
+namespace DingDingDemo.Controllers
12
+{
13
+    /// <summary>
14
+    /// 公告
15
+    /// </summary>
16
+    public class BlackBoardController : BaseController
17
+    {
18
+        private readonly ILogger<BlackBoardController> _logger;
19
+        private readonly IDistributedCache _cache;
20
+        private readonly IConfiguration _configuration;
21
+        public BlackBoardController(IDistributedCache cache, IConfiguration configuration, ILogger<BlackBoardController> logger)
22
+        {
23
+            _cache = cache;
24
+            _logger = logger;
25
+            _configuration = configuration;
26
+        }
27
+
28
+        /// <summary>
29
+        /// 获取公告列表
30
+        /// </summary>
31
+        /// <returns></returns>
32
+        [HttpGet("getblackboardlist")]
33
+        public async Task<IActionResult> GetBlackBoardList(string userid)
34
+        {
35
+            if (string.IsNullOrEmpty(userid))
36
+            {
37
+                return Error("员工id不能为空");
38
+            }
39
+            TokenHelper th = new TokenHelper(_cache, _configuration);
40
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetBlackBoard"], th.GetAccessToken()) + "&userid=" + userid);
41
+            var result = strresult.ToJObject();
42
+            if (result["errcode"].ToString() == "0")
43
+            {
44
+                return Success("成功", result["blackboard_list"]);
45
+            }
46
+            else
47
+            {
48
+                return Error(result["errmsg"].ToString());
49
+            }
50
+        }
51
+    }
52
+}

+ 214 - 0
DingDingDemo/Controllers/DepartmentController.cs

@@ -0,0 +1,214 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.Linq;
5
+using System.Threading.Tasks;
6
+using DingDingDemo.Common;
7
+using Microsoft.AspNetCore.Mvc;
8
+using Microsoft.Extensions.Caching.Distributed;
9
+using Microsoft.Extensions.Configuration;
10
+using Microsoft.Extensions.Logging;
11
+
12
+namespace DingDingDemo.Controllers
13
+{
14
+    /// <summary>
15
+    /// 部门
16
+    /// </summary>
17
+    [Produces("application/json")]
18
+    [Route("api/[controller]")]
19
+    public class DepartmentController : BaseController
20
+    {
21
+        private readonly ILogger<DepartmentController> _logger;
22
+        private readonly IDistributedCache _cache;
23
+        private readonly IConfiguration _configuration;
24
+        public DepartmentController(IDistributedCache cache, IConfiguration configuration, ILogger<DepartmentController> logger)
25
+        {
26
+            _cache = cache;
27
+            _logger = logger;
28
+            _configuration = configuration;
29
+        }
30
+
31
+        /// <summary>
32
+        /// 获取权限
33
+        /// </summary>
34
+        /// <returns></returns>
35
+        [HttpGet("getauthscopes")]
36
+        public async Task<IActionResult> GetAuthScopes()
37
+        {
38
+            TokenHelper th = new TokenHelper(_cache, _configuration);
39
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetAuthScopes"], th.GetAccessToken()) );
40
+            var result = strresult.ToJObject();
41
+            if (result["errcode"].ToString() == "0")
42
+            {
43
+                return Success("成功", result);
44
+            }
45
+            else
46
+            {
47
+                return Error(result["errmsg"].ToString());
48
+            }
49
+        }
50
+
51
+        /// <summary>
52
+        /// 获取列表
53
+        /// </summary>
54
+        /// <returns></returns>
55
+        [HttpGet("getlist")]
56
+        public async Task<IActionResult> GetList(int id = 1)
57
+        {
58
+            TokenHelper th = new TokenHelper(_cache, _configuration);
59
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetDepartmentList"], th.GetAccessToken()) + "&id=" + id);
60
+            var result = strresult.ToJObject();
61
+            if (result["errcode"].ToString() == "0")
62
+            {
63
+                return Success("成功", result["department"]);
64
+            }
65
+            else
66
+            {
67
+                return Error(result["errmsg"].ToString());
68
+            }
69
+        }
70
+
71
+        /// <summary>
72
+        /// 获取详情
73
+        /// </summary>
74
+        /// <returns></returns>
75
+        [HttpGet("getsingle")]
76
+        public async Task<IActionResult> GetSingle(int id = 1)
77
+        {
78
+            TokenHelper th = new TokenHelper(_cache, _configuration);
79
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetDepartment"], th.GetAccessToken(), id));
80
+            var result = strresult.ToJObject();
81
+            if (result["errcode"].ToString() == "0")
82
+            {
83
+                return Success("成功", result);
84
+            }
85
+            else
86
+            {
87
+                return Error(result["errmsg"].ToString());
88
+            }
89
+        }
90
+
91
+        /// <summary>
92
+        /// 获取部门用户列表
93
+        /// </summary>
94
+        /// <returns></returns>
95
+        [HttpGet("getdeptuserlist")]
96
+        public IActionResult GetDeptUserList(int deptid = 1)
97
+        {
98
+            TokenHelper th = new TokenHelper(_cache, _configuration);
99
+
100
+            return Success("成功", GetDeptUsers(th.GetAccessToken(), deptid, 0, 50));
101
+        }
102
+
103
+        /// <summary>
104
+        /// 获取部门用户列表
105
+        /// </summary>
106
+        /// <param name="token"></param>
107
+        /// <param name="deptid"></param>
108
+        /// <param name="index"></param>
109
+        /// <param name="size"></param>
110
+        /// <returns></returns>
111
+        [HttpGet]
112
+        [ApiExplorerSettings(IgnoreApi = true)]
113
+        public ArrayList GetDeptUsers(string token, int deptid = 1, int index = 0, int size = 10)
114
+        {
115
+            ArrayList arrresult = new ArrayList();
116
+
117
+            string url = string.Format(_configuration["DingTalkSettings:GetEmployeeListByDepartmentId"], token, deptid);
118
+            url += "&offset=" + index + "&size=" + size;
119
+            var strresult = HttpHelper.HttpGet(url);
120
+            var result = strresult.ToJObject();
121
+            if (result["errcode"].ToString() == "0")
122
+            {
123
+                var rtlist = result["userlist"].ToJson().ToList<Dictionary<string, object>>();
124
+                arrresult.AddRange(rtlist);
125
+                if (result["hasMore"].ToString().ToLower() == "true")
126
+                {
127
+                    arrresult.AddRange(GetDeptUsers(token, deptid, index + size, size));
128
+                }
129
+            }
130
+            return arrresult;
131
+        }
132
+
133
+        /// <summary>
134
+        /// 查询部门的所有上级父部门路径
135
+        /// </summary>
136
+        /// <returns></returns>
137
+        [HttpGet("getdeptparents")]
138
+        public async Task<IActionResult> GetDeptParents(int id = 1)
139
+        {
140
+            TokenHelper th = new TokenHelper(_cache, _configuration);
141
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetDepartmentParents"], th.GetAccessToken(), id));
142
+            var result = strresult.ToJObject();
143
+            if (result["errcode"].ToString() == "0")
144
+            {
145
+                return Success("成功", result["parentIds"]);
146
+            }
147
+            else
148
+            {
149
+                return Error(result["errmsg"].ToString());
150
+            }
151
+        }
152
+
153
+        /// <summary>
154
+        /// 获取子部门ID列表
155
+        /// </summary>
156
+        /// <returns></returns>
157
+        [HttpGet("getdeptchildren")]
158
+        public async Task<IActionResult> GetDeptChildren(int id = 1)
159
+        {
160
+            TokenHelper th = new TokenHelper(_cache, _configuration);
161
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetDepartmentChildren"], th.GetAccessToken(), id));
162
+            var result = strresult.ToJObject();
163
+            if (result["errcode"].ToString() == "0")
164
+            {
165
+                return Success("成功", result["sub_dept_id_list"]);
166
+            }
167
+            else
168
+            {
169
+                return Error(result["errmsg"].ToString());
170
+            }
171
+        }
172
+
173
+        /// <summary>
174
+        /// 查询指定用户的所有上级父部门路径
175
+        /// </summary>
176
+        /// <returns></returns>
177
+        [HttpGet("getuserdeptparents")]
178
+        public async Task<IActionResult> GetUserDeptParents(string userid)
179
+        {
180
+            TokenHelper th = new TokenHelper(_cache, _configuration);
181
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetEmployeeDepartmentParents"], th.GetAccessToken(), userid));
182
+            var result = strresult.ToJObject();
183
+            if (result["errcode"].ToString() == "0")
184
+            {
185
+                return Success("成功", result["department"]);
186
+            }
187
+            else
188
+            {
189
+                return Error(result["errmsg"].ToString());
190
+            }
191
+        }
192
+
193
+        /// <summary>
194
+        /// 查询指定用户的所有上级父部门路径
195
+        /// </summary>
196
+        /// <returns></returns>
197
+        [HttpGet("getusercount")]
198
+        public async Task<IActionResult> GetUserCount(int isactive = 1)
199
+        {
200
+            TokenHelper th = new TokenHelper(_cache, _configuration);
201
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetEmployeeCount"], th.GetAccessToken()) + "&onlyActive=" + isactive);
202
+            var result = strresult.ToJObject();
203
+            if (result["errcode"].ToString() == "0")
204
+            {
205
+                return Success("成功", result["count"]);
206
+            }
207
+            else
208
+            {
209
+                return Error(result["errmsg"].ToString());
210
+            }
211
+        }
212
+
213
+    }
214
+}

+ 23 - 0
DingDingDemo/Controllers/InfoController.cs

@@ -0,0 +1,23 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.Linq;
4
+using System.Threading.Tasks;
5
+using DingDingDemo.Common;
6
+using Microsoft.AspNetCore.Mvc;
7
+
8
+namespace DingDingDemo.Controllers
9
+{
10
+    /// <summary>
11
+    /// 信息
12
+    /// </summary>
13
+    [Produces("application/json")]
14
+    [Route("api/Info")]
15
+    public class InfoController : BaseController
16
+    {
17
+        [HttpGet]
18
+        public IEnumerable<string> Get()
19
+        {
20
+            return new string[] { "Hello World !" };
21
+        }
22
+    }
23
+}

+ 161 - 0
DingDingDemo/Controllers/RoleController.cs

@@ -0,0 +1,161 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.Linq;
5
+using System.Threading.Tasks;
6
+using DingDingDemo.Common;
7
+using Microsoft.AspNetCore.Mvc;
8
+using Microsoft.Extensions.Caching.Distributed;
9
+using Microsoft.Extensions.Configuration;
10
+using Microsoft.Extensions.Logging;
11
+
12
+namespace DingDingDemo.Controllers
13
+{
14
+    /// <summary>
15
+    /// 角色
16
+    /// </summary>
17
+    [Produces("application/json")]
18
+    [Route("api/[controller]")]
19
+    public class RoleController : BaseController
20
+    {
21
+        private readonly ILogger<RoleController> _logger;
22
+        private readonly IDistributedCache _cache;
23
+        private readonly IConfiguration _configuration;
24
+        public RoleController(IDistributedCache cache, IConfiguration configuration, ILogger<RoleController> logger)
25
+        {
26
+            _cache = cache;
27
+            _logger = logger;
28
+            _configuration = configuration;
29
+        }
30
+
31
+        /// <summary>
32
+        /// 获取列表
33
+        /// </summary>
34
+        /// <returns></returns>
35
+        [HttpGet("getlist")]
36
+        public IActionResult GetList()
37
+        {
38
+            TokenHelper th = new TokenHelper(_cache, _configuration);
39
+
40
+            return Success("成功", GetRoleList(th.GetAccessToken(), 0, 100));
41
+        }
42
+
43
+
44
+        /// <summary>
45
+        /// 获取列表
46
+        /// </summary>
47
+        /// <param name="token"></param>
48
+        /// <param name="index"></param>
49
+        /// <param name="size"></param>
50
+        /// <returns></returns>
51
+        [HttpGet]
52
+        [ApiExplorerSettings(IgnoreApi = true)]
53
+        public ArrayList GetRoleList(string token, int index = 0, int size = 10)
54
+        {
55
+            ArrayList arrresult = new ArrayList();
56
+
57
+            string url = string.Format(_configuration["DingTalkSettings:GetRoleList"], token);
58
+            url += "&offset=" + index + "&size=" + size;
59
+            var strresult = HttpHelper.HttpGet(url);
60
+            var result = strresult.ToJObject();
61
+            if (result["errcode"].ToString() == "0")
62
+            {
63
+                var rt = result["result"].ToString().ToJObject();
64
+                var rtlist = rt["list"].ToJson().ToList<Dictionary<string, object>>();
65
+                arrresult.AddRange(rtlist);
66
+                if (rt["hasMore"].ToString().ToLower() == "true")
67
+                {
68
+                    arrresult.AddRange(GetRoleList(token, index + size, size));
69
+                }
70
+            }
71
+            return arrresult;
72
+        }
73
+
74
+        /// <summary>
75
+        /// 获取详情
76
+        /// </summary>
77
+        /// <param name="id"></param>
78
+        /// <returns></returns>
79
+        [HttpGet("getsingle")]
80
+        public async Task<IActionResult> GetSingle(int id = 1)
81
+        {
82
+            TokenHelper th = new TokenHelper(_cache, _configuration);
83
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetRole"], th.GetAccessToken(), id));
84
+            var result = strresult.ToJObject();
85
+            if (result["errcode"].ToString() == "0")
86
+            {
87
+                return Success("成功", result);
88
+            }
89
+            else
90
+            {
91
+                return Error(result["errmsg"].ToString());
92
+            }
93
+        }
94
+
95
+        /// <summary>
96
+        /// 获取角色用户列表
97
+        /// </summary>
98
+        /// <param name="roleid"></param>
99
+        /// <returns></returns>
100
+        [HttpGet("getroleuserlist")]
101
+        public IActionResult GetRoleUserList(int roleid = 1)
102
+        {
103
+            TokenHelper th = new TokenHelper(_cache, _configuration);
104
+
105
+            return Success("成功", GetRoleUsers(th.GetAccessToken(), roleid, 0, 200));
106
+        }
107
+
108
+        /// <summary>
109
+        /// 获取角色用户列表
110
+        /// </summary>
111
+        /// <param name="token"></param>
112
+        /// <param name="roleid"></param>
113
+        /// <param name="index"></param>
114
+        /// <param name="size"></param>
115
+        /// <returns></returns>
116
+        [HttpGet]
117
+        [ApiExplorerSettings(IgnoreApi = true)]
118
+        public ArrayList GetRoleUsers(string token, int roleid = 1, int index = 0, int size = 10)
119
+        {
120
+            ArrayList arrresult = new ArrayList();
121
+
122
+            string url = string.Format(_configuration["DingTalkSettings:GetEmployeeListByRoleId"], token, roleid);
123
+            url += "&offset=" + index + "&size=" + size;
124
+            var strresult = HttpHelper.HttpGet(url);
125
+            var result = strresult.ToJObject();
126
+            if (result["errcode"].ToString() == "0")
127
+            {
128
+                var rt = result["result"].ToString().ToJObject();
129
+                var rtlist = rt["list"].ToJson().ToList<Dictionary<string, object>>();
130
+                arrresult.AddRange(rtlist);
131
+                if (rt["hasMore"].ToString().ToLower() == "true")
132
+                {
133
+                    arrresult.AddRange(GetRoleUsers(token, roleid, index + size, size));
134
+                }
135
+            }
136
+            return arrresult;
137
+        }
138
+
139
+        /// <summary>
140
+        /// 获取角色组
141
+        /// </summary>
142
+        /// <param name="groupid"></param>
143
+        /// <returns></returns>
144
+        [HttpGet("getrolegroup")]
145
+        public async Task<IActionResult> GetRoleGroup(int groupid = 1)
146
+        {
147
+            TokenHelper th = new TokenHelper(_cache, _configuration);
148
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetRoleGroup"], th.GetAccessToken(), groupid));
149
+            var result = strresult.ToJObject();
150
+            if (result["errcode"].ToString() == "0")
151
+            {
152
+                return Success("成功", result["role_group"]);
153
+            }
154
+            else
155
+            {
156
+                return Error(result["errmsg"].ToString());
157
+            }
158
+        }
159
+
160
+    }
161
+}

+ 117 - 0
DingDingDemo/Controllers/UserController.cs

@@ -0,0 +1,117 @@
1
+using System;
2
+using System.Collections;
3
+using System.Collections.Generic;
4
+using System.Linq;
5
+using System.Threading.Tasks;
6
+using DingDingDemo.Common;
7
+using Microsoft.AspNetCore.Mvc;
8
+using Microsoft.Extensions.Caching.Distributed;
9
+using Microsoft.Extensions.Configuration;
10
+using Microsoft.Extensions.Logging;
11
+
12
+namespace DingDingDemo.Controllers
13
+{
14
+    /// <summary>
15
+    /// 用户
16
+    /// </summary>
17
+    [Produces("application/json")]
18
+    [Route("api/[controller]")]
19
+    public class UserController : BaseController
20
+    {
21
+        
22
+        private readonly ILogger<UserController> _logger;
23
+        private readonly IDistributedCache _cache;
24
+        private readonly IConfiguration _configuration;
25
+        public UserController(IDistributedCache cache, IConfiguration configuration, ILogger<UserController> logger)
26
+        {
27
+            _cache = cache;
28
+            _logger = logger;
29
+            _configuration = configuration;
30
+        }
31
+
32
+        /// <summary>
33
+        /// 获取列表
34
+        /// </summary>
35
+        /// <param name="deptid"></param>
36
+        /// <returns></returns>
37
+        [HttpGet("getlist")]
38
+        public async Task<IActionResult> GetList(int deptid = 0)
39
+        {
40
+            ArrayList arrresult = new ArrayList();
41
+
42
+            TokenHelper th = new TokenHelper(_cache, _configuration);
43
+
44
+            if (deptid == 0 )
45
+            {
46
+                var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetDepartmentList"], th.GetAccessToken()));
47
+                var result = strresult.ToJObject();
48
+                if (result["errcode"].ToString() == "0")
49
+                {
50
+                    var rtlist = result["department"].ToJson().ToList<Dictionary<string, object>>();
51
+                    foreach (var rt in rtlist)
52
+                    {
53
+                        arrresult.AddRange(GetDeptUserList(th.GetAccessToken(), Int32.Parse(rt["id"].ToString()), 0, 100));
54
+                    }
55
+                }
56
+            }
57
+            else
58
+            {
59
+                arrresult.AddRange(GetDeptUserList(th.GetAccessToken(), deptid, 0, 100));
60
+            }
61
+
62
+            return Success("成功", arrresult);
63
+        }
64
+
65
+
66
+        /// <summary>
67
+        /// 获取部门用户列表
68
+        /// </summary>
69
+        /// <param name="token"></param>
70
+        /// <param name="deptid"></param>
71
+        /// <param name="index"></param>
72
+        /// <param name="size"></param>
73
+        /// <returns></returns>
74
+        [ApiExplorerSettings(IgnoreApi = true)]
75
+        public ArrayList GetDeptUserList(string token, int deptid = 1, int index = 0, int size = 10)
76
+        {
77
+            ArrayList arrresult = new ArrayList();
78
+
79
+            string url = string.Format(_configuration["DingTalkSettings:GetEmployeeListByDepartmentId"], token, deptid);
80
+            url += "&offset=" + index + "&size=" + size;
81
+            var strresult = HttpHelper.HttpGet(url);
82
+            var result = strresult.ToJObject();
83
+            if (result["errcode"].ToString() == "0")
84
+            {
85
+                var rtlist = result["userlist"].ToJson().ToList<Dictionary<string, object>>();
86
+                arrresult.AddRange(rtlist);
87
+                if (result["hasMore"].ToString().ToLower() == "true")
88
+                {
89
+                    arrresult.AddRange(GetDeptUserList(token, deptid, index + size, size));
90
+                }
91
+            }
92
+            return arrresult;
93
+        }
94
+
95
+
96
+        /// <summary>
97
+        /// 获取详情
98
+        /// </summary>
99
+        /// <param name="id"></param>
100
+        /// <returns></returns>
101
+        [HttpGet("getsingle")]
102
+        public async Task<IActionResult> GetSingle(string id)
103
+        {
104
+            TokenHelper th = new TokenHelper(_cache, _configuration);
105
+            var strresult = await HttpHelper.HttpGetAsync(string.Format(_configuration["DingTalkSettings:GetEmployee"], th.GetAccessToken(), id));
106
+            var result = strresult.ToJObject();
107
+            if (result["errcode"].ToString() == "0")
108
+            {
109
+                return Success("成功", result);
110
+            }
111
+            else
112
+            {
113
+                return Error(result["errmsg"].ToString());
114
+            }
115
+        }
116
+    }
117
+}

+ 29 - 0
DingDingDemo/DingDingDemo.csproj

@@ -0,0 +1,29 @@
1
+<Project Sdk="Microsoft.NET.Sdk.Web">
2
+
3
+  <PropertyGroup>
4
+    <TargetFramework>netcoreapp2.0</TargetFramework>
5
+  </PropertyGroup>
6
+
7
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
8
+    <DocumentationFile>bin\Debug\netcoreapp2.0\DingDingDemo.xml</DocumentationFile>
9
+    <NoWarn>1701;1702;1591</NoWarn>
10
+  </PropertyGroup>
11
+
12
+  <ItemGroup>
13
+    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
14
+    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" />
15
+    <PackageReference Include="NLog.Web.AspNetCore" Version="4.4.1" />
16
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />
17
+  </ItemGroup>
18
+
19
+  <ItemGroup>
20
+    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />
21
+  </ItemGroup>
22
+
23
+  <ItemGroup>
24
+    <ProjectReference Include="..\DingDingDemo.Common\DingDingDemo.Common.csproj" />
25
+  </ItemGroup>
26
+
27
+  <ProjectExtensions><VisualStudio><UserProperties /></VisualStudio></ProjectExtensions>
28
+
29
+</Project>

+ 19 - 0
DingDingDemo/DingDingDemo.csproj.user

@@ -0,0 +1,19 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+  <PropertyGroup>
4
+    <ShowAllFiles>true</ShowAllFiles>
5
+    <Controller_SelectedScaffolderID>MvcControllerEmptyScaffolder</Controller_SelectedScaffolderID>
6
+    <Controller_SelectedScaffolderCategoryPath>root/Controller</Controller_SelectedScaffolderCategoryPath>
7
+    <WebStackScaffolding_ControllerDialogWidth>600</WebStackScaffolding_ControllerDialogWidth>
8
+    <WebStackScaffolding_IsLayoutPageSelected>True</WebStackScaffolding_IsLayoutPageSelected>
9
+    <WebStackScaffolding_IsPartialViewSelected>False</WebStackScaffolding_IsPartialViewSelected>
10
+    <WebStackScaffolding_IsReferencingScriptLibrariesSelected>True</WebStackScaffolding_IsReferencingScriptLibrariesSelected>
11
+    <WebStackScaffolding_LayoutPageFile />
12
+    <WebStackScaffolding_IsAsyncSelected>False</WebStackScaffolding_IsAsyncSelected>
13
+    <ActiveDebugProfile>IIS Express</ActiveDebugProfile>
14
+    <NameOfLastUsedPublishProfile>FolderProfile</NameOfLastUsedPublishProfile>
15
+  </PropertyGroup>
16
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
17
+    <DebuggerFlavor>ProjectDebugger</DebuggerFlavor>
18
+  </PropertyGroup>
19
+</Project>

+ 25 - 0
DingDingDemo/Program.cs

@@ -0,0 +1,25 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.IO;
4
+using System.Linq;
5
+using System.Threading.Tasks;
6
+using Microsoft.AspNetCore;
7
+using Microsoft.AspNetCore.Hosting;
8
+using Microsoft.Extensions.Configuration;
9
+using Microsoft.Extensions.Logging;
10
+
11
+namespace DingDingDemo
12
+{
13
+    public class Program
14
+    {
15
+        public static void Main(string[] args)
16
+        {
17
+            BuildWebHost(args).Run();
18
+        }
19
+
20
+        public static IWebHost BuildWebHost(string[] args) =>
21
+            WebHost.CreateDefaultBuilder(args)
22
+                .UseStartup<Startup>()
23
+                .Build();
24
+    }
25
+}

+ 39 - 0
DingDingDemo/Properties/launchSettings.json

@@ -0,0 +1,39 @@
1
+{
2
+  "iisSettings": {
3
+    "windowsAuthentication": false,
4
+    "anonymousAuthentication": true,
5
+    "iisExpress": {
6
+      "applicationUrl": "http://localhost:58409/",
7
+      "sslPort": 0
8
+    }
9
+  },
10
+  "profiles": {
11
+    "IIS Express": {
12
+      "commandName": "IISExpress",
13
+      "launchBrowser": true,
14
+      //"launchUrl": "api/info",
15
+      "launchUrl": "swagger",
16
+      "environmentVariables": {
17
+        "ASPNETCORE_ENVIRONMENT": "Development"
18
+      }
19
+    },
20
+    "DingDingDemo(Dev)": {
21
+      "commandName": "Project",
22
+      "launchBrowser": false,
23
+      "launchUrl": "api/info",
24
+      "environmentVariables": {
25
+        "ASPNETCORE_ENVIRONMENT": "Development"
26
+      },
27
+      "applicationUrl": "http://localhost:58410/"
28
+    },
29
+    "DingDingDemo(Prod)": {
30
+      "commandName": "Project",
31
+      "launchBrowser": false,
32
+      "launchUrl": "api/info",
33
+      "environmentVariables": {
34
+        "ASPNETCORE_ENVIRONMENT": "Production"
35
+      },
36
+      "applicationUrl": "http://localhost:58410/"
37
+    }
38
+  }
39
+}

+ 111 - 0
DingDingDemo/Startup.cs

@@ -0,0 +1,111 @@
1
+using System;
2
+using System.Collections.Generic;
3
+using System.IO;
4
+using System.Linq;
5
+using System.Reflection;
6
+using System.Threading.Tasks;
7
+using Microsoft.AspNetCore.Builder;
8
+using Microsoft.AspNetCore.Hosting;
9
+using Microsoft.Extensions.Configuration;
10
+using Microsoft.Extensions.DependencyInjection;
11
+using Microsoft.Extensions.Logging;
12
+using Microsoft.Extensions.Options;
13
+using NLog.Extensions.Logging;
14
+using NLog.Web;
15
+using Swashbuckle.AspNetCore.Swagger;
16
+
17
+namespace DingDingDemo
18
+{
19
+    public class Startup
20
+    {
21
+        public Startup(IHostingEnvironment env)
22
+        {
23
+            Configuration = new ConfigurationBuilder()
24
+                            .SetBasePath(env.ContentRootPath)
25
+                            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
26
+                            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
27
+                            .AddEnvironmentVariables()
28
+                            .Build();
29
+        }
30
+
31
+        public IConfiguration Configuration { get; }
32
+
33
+        // This method gets called by the runtime. Use this method to add services to the container.
34
+        public void ConfigureServices(IServiceCollection services)
35
+        {
36
+            #region Cors 配置
37
+            //生产环境 的cors
38
+            services.AddCors(options =>
39
+            {
40
+                options.AddPolicy("CorsProd",
41
+                 builder => builder.AllowAnyOrigin()
42
+                //builder => builder.WithOrigins(Configuration["Cors"].Split(','))
43
+                .AllowAnyMethod()
44
+                .AllowAnyHeader()
45
+                .AllowCredentials().SetPreflightMaxAge(TimeSpan.FromMinutes(30)));
46
+            });
47
+            //开发环境的cors
48
+            services.AddCors(options =>
49
+            {
50
+                options.AddPolicy("CorsDev",
51
+                builder => builder.AllowAnyOrigin()
52
+                .AllowAnyMethod()
53
+                .AllowAnyHeader()
54
+                .AllowCredentials().SetPreflightMaxAge(TimeSpan.FromMinutes(30)));
55
+            });
56
+            #endregion
57
+
58
+            #region redis配置
59
+            services.AddDistributedRedisCache(options =>
60
+            {
61
+                options.InstanceName = Configuration["Redis:InstanceName"].ToString();
62
+                options.Configuration = $"{Configuration["Redis:HostName"].ToString()}:{Configuration["Redis:Port"].ToString()},allowAdmin=true,password={Configuration["Redis:Password"].ToString()},defaultdatabase={Configuration["Redis:Defaultdatabase"].ToString()}";
63
+            });
64
+            #endregion
65
+
66
+            //注册Swagger生成器,定义一个和多个Swagger 文档
67
+            services.AddSwaggerGen(c =>
68
+            {
69
+                c.SwaggerDoc("v1", new Info { Title = "DingTalk", Version = "v1" });
70
+                // 设置SWAGER JSON和UI的注释路径。
71
+                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
72
+                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
73
+                c.IncludeXmlComments(xmlPath);
74
+            });
75
+
76
+            services.AddMvc();
77
+        }
78
+
79
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
80
+        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
81
+        {
82
+            if (env.IsProduction())
83
+            {
84
+                app.UseCors("CorsProd");
85
+            }
86
+            else
87
+            {
88
+                app.UseCors("CorsDev");
89
+                app.UseDeveloperExceptionPage();
90
+                app.UseDatabaseErrorPage();
91
+                app.UseBrowserLink();
92
+            }
93
+
94
+            app.UseMvc();
95
+
96
+            loggerFactory.AddNLog();//添加NLog
97
+            env.ConfigureNLog("nlog.config");//读取Nlog配置文件
98
+            app.AddNLogWeb();
99
+
100
+            //启用中间件服务生成Swagger作为JSON终结点
101
+            app.UseSwagger();
102
+            //启用中间件服务对swagger-ui,指定Swagger JSON终结点
103
+            app.UseSwaggerUI(c =>
104
+            {
105
+                c.SwaggerEndpoint("/swagger/v1/swagger.json", "DingTalk V1");
106
+                // 要在应用程序的根处提供Swagger UI ,请将该RoutePrefix属性设置为空字符串
107
+                c.RoutePrefix = string.Empty;
108
+            });
109
+        }
110
+    }
111
+}

+ 34 - 0
DingDingDemo/appsettings.Development.json

@@ -0,0 +1,34 @@
1
+{
2
+  "Logging": {
3
+    "IncludeScopes": false,
4
+    "LogLevel": {
5
+      "Default": "Information",
6
+      "System": "Information",
7
+      "Microsoft": "Information"
8
+    }
9
+  },
10
+  "Redis": {
11
+    "HostName": "139.224.236.21",
12
+    "Port": "4000",
13
+    "Password": "sms+800100",
14
+    "Defaultdatabase": "14",
15
+    "InstanceName": "dingtalk"
16
+  },
17
+  "DingTalkSettings": {
18
+    "AppKey": "ding77tk1okpuoxhitxs",
19
+    "AppSecret": "lrV9pt51pjxUY00qCkPdoZ-393can29IujDFdlR9SZnechH_pSG1Tl1maWocWrDB",
20
+    "TokenCacheTime": "7000",
21
+    "TokenUrl": "https://oapi.dingtalk.com/gettoken?appkey={0}&appsecret={1}",
22
+    "GetAuthScopes": "https://oapi.dingtalk.com/auth/scopes?access_token={0}",
23
+    "GetDepartmentList": "https://oapi.dingtalk.com/department/list?access_token={0}",
24
+    "GetDepartment": "https://oapi.dingtalk.com/department/get?access_token={0}&id={1}",
25
+    "GetEmployeeListByPage": "https://oapi.dingtalk.com/user/listbypage?access_token={0}&department_id={1}",
26
+    "GetEmployee": "https://oapi.dingtalk.com/user/get?access_token={0}&userid={1}",
27
+    "GetRoleList": "https://oapi.dingtalk.com/topapi/role/list?access_token={0}",
28
+    "GetRole": "https://oapi.dingtalk.com/topapi/role/getrole?access_token={0}&roleId={1}",
29
+    "GetSchedule": "https://oapi.dingtalk.com/topapi/attendance/listschedule?access_token={0}",
30
+    "GetGroupList": "https://oapi.dingtalk.com/topapi/attendance/getsimplegroups?access_token={0}",
31
+    "GetRecordList": "https://oapi.dingtalk.com/attendance/listRecord?access_token={0}",
32
+    "GetRecordResult": "https://oapi.dingtalk.com/attendance/list?access_token={0}"
33
+  }
34
+}

+ 44 - 0
DingDingDemo/appsettings.Production.json

@@ -0,0 +1,44 @@
1
+{
2
+  "Logging": {
3
+    "IncludeScopes": false,
4
+    "LogLevel": {
5
+      "Default": "Information",
6
+      "System": "Information",
7
+      "Microsoft": "Information"
8
+    }
9
+  },
10
+  "Redis": {
11
+    "HostName": "139.224.236.21",
12
+    "Port": "4000",
13
+    "Password": "sms+800100",
14
+    "Defaultdatabase": "14",
15
+    "InstanceName": "dingtalk"
16
+  },
17
+  "DingTalkSettings": {
18
+    "AppKey": "ding77tk1okpuoxhitxs",
19
+    "AppSecret": "lrV9pt51pjxUY00qCkPdoZ-393can29IujDFdlR9SZnechH_pSG1Tl1maWocWrDB",
20
+    "TokenCacheTime": "7000",
21
+    "TokenUrl": "https://oapi.dingtalk.com/gettoken?appkey={0}&appsecret={1}",
22
+    "GetAuthScopes": "https://oapi.dingtalk.com/auth/scopes?access_token={0}",
23
+    "GetDepartmentList": "https://oapi.dingtalk.com/department/list?access_token={0}",
24
+    "GetDepartment": "https://oapi.dingtalk.com/department/get?access_token={0}&id={1}",
25
+    "GetDepartmentParents": "https://oapi.dingtalk.com/department/list_parent_depts_by_dept?access_token={0}&id={1}",
26
+    "GetDepartmentChildren": "https://oapi.dingtalk.com/department/list_ids?access_token={0}&id={1}",
27
+    "GetEmployeeDepartmentParents": "https://oapi.dingtalk.com/department/list_parent_depts?access_token={0}&userid={1}",
28
+    "GetEmployeeCount": "https://oapi.dingtalk.com/user/get_org_user_count?access_token={0}",
29
+    "GetEmployeeListByDepartmentId": "https://oapi.dingtalk.com/user/listbypage?access_token={0}&department_id={1}",
30
+    "GetEmployee": "https://oapi.dingtalk.com/user/get?access_token={0}&userid={1}",
31
+    "GetRoleList": "https://oapi.dingtalk.com/topapi/role/list?access_token={0}",
32
+    "GetRole": "https://oapi.dingtalk.com/topapi/role/getrole?access_token={0}&roleId={1}",
33
+    "GetEmployeeListByRoleId": "https://oapi.dingtalk.com/user/listbypage?access_token={0}&role_id={1}",
34
+    "GetRoleGroup": "https://oapi.dingtalk.com/topapi/role/getrolegroup?access_token={0}&group_id={1}",
35
+    "GetSchedule": "https://oapi.dingtalk.com/topapi/attendance/listschedule?access_token={0}",
36
+    "GetGroupList": "https://oapi.dingtalk.com/topapi/attendance/getsimplegroups?access_token={0}",
37
+    "GetRecordList": "https://oapi.dingtalk.com/attendance/listRecord?access_token={0}",
38
+    "GetRecordResult": "https://oapi.dingtalk.com/attendance/list?access_token={0}",
39
+    "GetUserGroup": "https://oapi.dingtalk.com/topapi/attendance/getusergroup?access_token={0}",
40
+    "GetLeaveStatus": "https://oapi.dingtalk.com/topapi/attendance/getleavestatus?access_token={0}",
41
+    "GetLeaveApproveDuration": "https://oapi.dingtalk.com/topapi/attendance/getleaveapproveduration?access_token={0}",
42
+    "GetBlackBoard": "https://oapi.dingtalk.com/topapi/blackboard/listtopten?access_token={0}"
43
+  }
44
+}

+ 15 - 0
DingDingDemo/appsettings.json

@@ -0,0 +1,15 @@
1
+{
2
+  "Logging": {
3
+    "IncludeScopes": false,
4
+    "Debug": {
5
+      "LogLevel": {
6
+        "Default": "Warning"
7
+      }
8
+    },
9
+    "Console": {
10
+      "LogLevel": {
11
+        "Default": "Warning"
12
+      }
13
+    }
14
+  }
15
+}

+ 71 - 0
DingDingDemo/nlog.config

@@ -0,0 +1,71 @@
1
+<?xml version="1.0" encoding="utf-8" ?>
2
+<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
3
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+      autoReload="true"
5
+      internalLogLevel="Error"
6
+      internalLogFile="nlogtemp\internal-nlog.txt">
7
+
8
+ <!-- 加载ASP.NET Core插件 -->
9
+  <extensions>
10
+    <add assembly="NLog.Web.AspNetCore"/>
11
+  </extensions>
12
+
13
+  <!-- 输出目的地 -->
14
+  <targets>
15
+    <!-- 输出到文件,这个文件记录所有日志 -->
16
+    <!--<target xsi:type="File" name="allfile" fileName="\nlogtemp\${shortdate}\nlog-all-${shortdate}.log"
17
+                layout="记录时间:${longdate}|控制器:${logger}|消息:${message} 异常:${exception}" />-->
18
+
19
+    <!-- 另外一个日志记录文件,户口也跳过Microsoft开头相关日志信息 -->
20
+    <!--archiveFileName表示滚动日志存放路径,log.{#####}.txt是滚动日志文件名-->
21
+    <!--archiveAboveSize每个日志文件大小的最大值(单位:字节)20(mb)=20971520(b),主日志文件超过大小超过该值时会将文件内容写入滚动日志并清空主日志文件内容-->
22
+    <!--maxArchiveFiles滚动日志文件上限数,滚动日志文件数达到上限新的文件内容会覆盖旧文件内容 -->
23
+
24
+    <target xsi:type="File" name="own_file" fileName="log/${shortdate}/own_${shortdate}.log"
25
+            archiveFileName="log/${shortdate}/own_${shortdate}.{#####}.log"
26
+            archiveAboveSize="20971520" archiveNumbering="Rolling" concurrentWrites="true" maxArchiveFiles="-1" keepFileOpen="false" 
27
+            layout="${level}|记录时间:${longdate}|${event-properties:item=EventId.Id}|控制器:${logger}|action: ${aspnet-mvc-action}|${newline}消息:${message}|${newline}异常:${exception}|${newline}url: ${aspnet-request-url}|${newline}" />
28
+    <!--layout="记录时间:${longdate}|控制器:${logger}|  action: ${aspnet-mvc-action}|  消息:${message} 异常:${exception}" />-->
29
+    <!--错误提示-->
30
+    
31
+
32
+    <target name="error_file" xsi:type="File" fileName="log/${shortdate}/error-${shortdate}.log"
33
+            archiveFileName="log/${shortdate}/own-${shortdate}.{#####}.log"
34
+            archiveAboveSize="20971520" archiveNumbering="Rolling" concurrentWrites="true" maxArchiveFiles="-1" keepFileOpen="false" 
35
+            layout="${level}|记录时间:${longdate}|控制器:${logger}|action: ${aspnet-mvc-action}|${newline}消息:${message}|${newline}异常:${onexception:${exception:format=tostring} ${newline} ${stacktrace}|${newline}" />
36
+    <target name="debugger_file" xsi:type="File" fileName="log/${shortdate}/debugger-${shortdate}.log"
37
+            archiveFileName="log/${shortdate}/debugger-${shortdate}.{#####}.log"
38
+            archiveAboveSize="20971520" archiveNumbering="Rolling" concurrentWrites="true" maxArchiveFiles="-1" keepFileOpen="false"
39
+            layout="${level}|记录时间:${date:format=HH/:mm/:ss}|控制器:${logger}|action: ${aspnet-mvc-action}|消息:${message}|${newline}" />
40
+     <target name="warn_file" xsi:type="File" fileName="log/${shortdate}/warn-${shortdate}.log"
41
+            archiveFileName="log/${shortdate}/warn-${shortdate}.{#####}.log"
42
+            archiveAboveSize="20971520" archiveNumbering="Rolling" concurrentWrites="true" maxArchiveFiles="-1" keepFileOpen="false" 
43
+            layout="${level}|记录时间:${date:format=HH/:mm/:ss}|控制器:${logger}|action: ${aspnet-mvc-action}|消息:${message}|${newline}" />
44
+    <!-- write to the void aka just remove -->
45
+    <target xsi:type="Null" name="blackhole" />
46
+  </targets>
47
+
48
+  <!-- 写入目的地的规则 -->
49
+  <rules>
50
+    <!--全部记录,包括Microsoft开头的相关日志信息-->
51
+    <!--<logger name="*" minlevel="Trace" writeTo="allfile" />-->
52
+
53
+    <!--name - 记录者的名字 (允许使用通配符*)
54
+        minlevel - 匹配日志范围的最低级别
55
+        maxlevel - 匹配日志范围的最高级别
56
+        level - 匹配的单一日志级别 :::::NLog 用于输出日志的级别包括:Trace,Debug,Info,Warn,Error,Fatal
57
+        levels - 匹配的一系列日志级别,由逗号分隔。
58
+        writeTo - 规则匹配时日志应该被写入的一系列目标,由逗号分隔。-->
59
+
60
+    <!--跳过Microsoft开头的相关日志信息-->
61
+    <!--<logger name="Microsoft.*" minlevel="Trace" writeTo="blackhole" final="true" />-->
62
+
63
+    <!--错误提示-->
64
+    <logger name="*" minlevel="Trace" writeTo="own_file" />
65
+    <logger name="*" level="Debug" writeTo="debugger_file" />
66
+    <logger name="*" minlevel="Error" writeTo="error_file" />
67
+    <logger name="*" level="Warn" writeTo="warn_file" />
68
+ 
69
+
70
+  </rules>
71
+</nlog>