CrazyIter_Bin 3 年之前
父节点
当前提交
0f90df0b62

+ 59 - 1
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageTableExtensions.cs

@@ -402,7 +402,51 @@ namespace TEAMModelOS.SDK.DI
             }
             return entitys;
         }
+        public static   List<T>  FindListByDictSync<T>(this CloudTable table, Dictionary<string, object> dict) where T : TableEntity, new()
+        {
+            var exQuery = new TableQuery<T>();
+            StringBuilder builder = new();
+            if (null != dict && dict.Count > 0)
+            {
+                var keys = dict.Keys;
+                int index = 1;
+                foreach (string key in keys)
+                {
+                    if (dict[key] != null && !string.IsNullOrEmpty(dict[key].ToString()))
+                    {
+                        string typeStr = SwitchType<T>(dict[key], key);
+                        if (string.IsNullOrEmpty(typeStr))
+                        {
+                            continue;
+                        }
+                        if (index == 1)
+                        {
+                            //builder.Append(TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
+                            builder.Append(typeStr);
+
+                        }
+                        else
+                        {
+                            //builder.Append("  " + TableOperators.And + "  " + TableQuery.GenerateFilterCondition(key, QueryComparisons.Equal, dict[key].ToString()));
+                            builder.Append("  " + TableOperators.And + "  " + typeStr);
+
+                        }
+                        index++;
+                    }
+                    else
+                    {
+                        throw new Exception("The parameter must have value!");
+                    }
+                }
 
+                exQuery.Where(builder.ToString());
+                return   QueryListSync<T>(exQuery, table);
+            }
+            else
+            {
+                return null;
+            }
+        }
         public static async Task<List<T>> FindListByDict<T>(this CloudTable table, Dictionary<string, object> dict) where T : TableEntity, new()
         {            
             var exQuery = new TableQuery<T>();
@@ -449,7 +493,21 @@ namespace TEAMModelOS.SDK.DI
             }
         }
 
-
+        private static List<T> QueryListSync<T>(TableQuery<T> exQuery, CloudTable TableName) where T : TableEntity, new()
+        {
+            TableContinuationToken continuationToken = null;
+            List<T> entitys = new();
+            do
+            {
+                var result =   TableName.ExecuteQuerySegmented(exQuery, continuationToken);
+                if (result.Results.Count > 0)
+                {
+                    entitys.AddRange(result.ToList());
+                }
+                continuationToken = result.ContinuationToken;
+            } while (continuationToken != null);
+            return entitys;
+        }
 
         private static async Task<List<T>> QueryList<T>(TableQuery<T> exQuery, CloudTable TableName  ) where T : TableEntity, new()
         {

+ 33 - 0
TEAMModelOS/Controllers/Third/Xkw/Hmac/HmacConst.cs

@@ -0,0 +1,33 @@
+using System;
+
+namespace TEAMModelOS.Controllers.Third.Xkw
+{
+    public class HmacConst
+    {
+
+        /// <summary>
+        ///  分隔符
+        /// </summary>
+        public static char SEPARATOR = '/';
+
+        /// <summary>
+        /// 允许的最大时间间隔
+        /// </summary>
+        public static long MAX_TIMESTAMP_GAP = 5 * 60L;
+
+        public static String KEY_TIMESTAMP = "Xop-Timestamp";
+
+        public static String KEY_SIGN = "Xop-Sign";
+
+        public static String KEY_APP_ID = "Xop-App-Id";
+        /// <summary>
+        /// 每次请求的防止重放攻击的随机串
+        /// </summary>
+        public static String KEY_NONCE = "Xop-Nonce";
+   
+
+        public static String KEY_URL = "xop_url";
+
+        public static String REQUEST_BODY = "xop_body";
+    }
+}

+ 19 - 0
TEAMModelOS/Controllers/Third/Xkw/Hmac/HmacResult.cs

@@ -0,0 +1,19 @@
+using System;
+
+namespace TEAMModelOS.Controllers.Third.Xkw
+{
+    public class HmacResult
+    {
+        public long TimeStamp { get; set; }
+        public String Sign { get; set; }
+        public String Nonce { get; set; }
+
+        public HmacResult(long timeStamp, String sign, String nonce)
+        {
+            this.TimeStamp = timeStamp;
+            this.Sign = sign;
+            this.Nonce = nonce;
+        }
+
+    }
+}

+ 288 - 0
TEAMModelOS/Controllers/Third/Xkw/Hmac/HmacUtils.cs

@@ -0,0 +1,288 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace TEAMModelOS.Controllers.Third.Xkw
+{
+    public class HmacUtils
+    {
+        /// <summary>
+        /// Java的System.currentTimeMillis()转成C#的
+        /// </summary>
+        /// <returns></returns>
+        public static long GetCurrentTimeMillis()
+        {
+            return (DateTime.UtcNow.Ticks - 621355968000000000L) / 10000 / 1000;
+        }
+
+        public static HmacResult Sign(String appId, String secret, Dictionary<String, String> parameters, String requestBodyStr)
+        {
+            Dictionary<String, String> dic = CopyDictionary(parameters);
+            //
+            long timeStamp = GetCurrentTimeMillis();
+            dic.Add(HmacConst.KEY_TIMESTAMP, timeStamp.ToString());
+            dic.Add(HmacConst.KEY_APP_ID, appId);
+            //去掉传递过来的sign     
+            dic.Remove(HmacConst.KEY_SIGN);
+            //去掉传递过来的nonce,一律在此统一放入
+            dic.Remove(HmacConst.KEY_NONCE);
+            String nonce = Guid.NewGuid().ToString("").Replace("-", "");
+            dic.Add(HmacConst.KEY_NONCE, nonce);
+
+            String sha1Str = GetSignatureString(dic, secret, requestBodyStr);
+            dic.Add(HmacConst.KEY_SIGN, sha1Str);
+            return new HmacResult(timeStamp, sha1Str, nonce);
+        }
+
+
+        public static bool ValidateRequestTimestamp(String timestampStr, long maxTimestampGap)
+        {
+            // validate the timestamp
+            long timeStamp = long.Parse(timestampStr);
+            long timeStampNow = GetCurrentTimeMillis();
+            return Math.Abs(timeStamp - timeStampNow) < maxTimestampGap;
+        }
+
+        public static bool ValidateRequest(Dictionary<string, string> parameters, string secret, string requestBodyStr)
+        {
+            Dictionary<string, string> dic = CopyDictionary(parameters);
+
+            // get AccessTokenId, sign
+            string sign = null;
+            if (dic.ContainsKey(HmacConst.KEY_SIGN))
+            {
+                sign = dic[HmacConst.KEY_SIGN];
+                dic.Remove(HmacConst.KEY_SIGN);
+            }
+            else
+            {
+                return false;
+            }
+
+            string md5Str = GetSignatureString(dic, secret, requestBodyStr);
+            return md5Str.Equals(sign, StringComparison.OrdinalIgnoreCase);
+        }
+
+        public static string GetSignatureString(Dictionary<string, string> dic, string secret, string requestBodyStr)
+        {
+            Dictionary<string, string> tempDic = CopyDictionary(dic);
+
+            if (!String.IsNullOrEmpty(requestBodyStr))
+            {
+                tempDic.Add(HmacConst.REQUEST_BODY, requestBodyStr);
+            }
+
+            String sortParamStr = GenerateQueryString(tempDic);
+
+            //下面的bapi的签名,xop没使用url编码了
+            //StringBuilder sb = new StringBuilder();
+            //foreach (string key in keyList)
+            //{
+            //    string value = dic[key];
+            //    if (value == null)
+            //    {
+            //        continue;
+            //    }
+            //    sb.Append(key);
+            //    sb.Append("=");
+            //    sb.Append(FormatString(value));
+            //    sb.Append("&");
+            //}
+            //sb.Append("secret=");
+            //sb.Append(secret);
+            //string keyListStr = sb.ToString();
+
+
+            String keyListStr = sortParamStr + "&secret=" + secret;
+            byte[] inputBytes = Encoding.UTF8.GetBytes(keyListStr);
+            string base64Str = Convert.ToBase64String(inputBytes);
+            byte[] bytes = SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(base64Str));
+            return BitConverter.ToString(bytes).Replace("-", "").ToLower();
+        }
+
+        public static String GenerateQueryString(Dictionary<String, String> dic)
+        {
+            List<string> sortedKeyList = dic.Keys.OrderBy(i => i, StringComparer.Ordinal).ToList();
+            List<String> tempParams = new List<string>(dic.Count);
+            foreach (var key in sortedKeyList)
+            {
+                String str = key + "=" + dic[key];
+                tempParams.Add(str);
+            }
+            return String.Join("&", tempParams);
+        }
+
+        public static Dictionary<string, string> CopyDictionary(Dictionary<string, string> dic)
+        {
+            Dictionary<string, string> copyDic = new Dictionary<string, string>();
+            if (dic == null || dic.Count == 0)
+            {
+                return copyDic;
+            }
+            foreach (var item in dic)
+            {
+                copyDic.Add(item.Key, item.Value);
+            }
+            return copyDic;
+        }
+
+
+    }
+
+
+
+    class UrlEncode
+    {
+        const int caseDiff = ('a' - 'A');
+        private static bool ValidateUrlEncodingParameters(byte[] bytes, int offset, int count)
+        {
+            if (bytes == null && count == 0)
+                return false;
+            if (bytes == null)
+            {
+                throw new ArgumentNullException("bytes");
+            }
+            if (offset < 0 || offset > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("offset");
+            }
+            if (count < 0 || offset + count > bytes.Length)
+            {
+                throw new ArgumentOutOfRangeException("count");
+            }
+
+            return true;
+        }
+        public static string Encode(string str, Encoding e)
+        {
+            if (str == null)
+                return null;
+
+            byte[] bytes = e.GetBytes(str);
+            int offset = 0;
+            int count = bytes.Length;
+
+            if (!ValidateUrlEncodingParameters(bytes, offset, count))
+            {
+                return null;
+            }
+
+            int cSpaces = 0;
+            int cUnsafe = 0;
+
+            // count them first
+            for (int i = 0; i < count; i++)
+            {
+                char ch = (char)bytes[offset + i];
+
+                if (ch == ' ')
+                    cSpaces++;
+                else if (!HttpEncoderUtility.IsUrlSafeChar(ch))
+                    cUnsafe++;
+            }
+
+            // nothing to expand?
+            if (cSpaces == 0 && cUnsafe == 0)
+            {
+                // DevDiv 912606: respect "offset" and "count"
+                if (0 == offset && bytes.Length == count)
+                {
+                    return Encoding.ASCII.GetString(bytes);
+                }
+                else
+                {
+                    var subarray = new byte[count];
+                    Buffer.BlockCopy(bytes, offset, subarray, 0, count);
+                    return Encoding.ASCII.GetString(subarray);
+                }
+            }
+
+            // expand not 'safe' characters into %XX, spaces to +s
+            byte[] expandedBytes = new byte[count + cUnsafe * 2];
+            int pos = 0;
+
+            for (int i = 0; i < count; i++)
+            {
+                byte b = bytes[offset + i];
+                char ch = (char)b;
+
+                if (HttpEncoderUtility.IsUrlSafeChar(ch))
+                {
+                    expandedBytes[pos++] = b;
+                }
+                else if (ch == ' ')
+                {
+                    expandedBytes[pos++] = (byte)'+';
+                }
+                else
+                {
+                    expandedBytes[pos++] = (byte)'%';
+                    ch = (char)HttpEncoderUtility.IntToHex((b >> 4) & 0xF);
+                    if (char.IsLetter(ch))
+                    {
+                        ch = (char)((int)ch - caseDiff);
+                    }
+
+                    expandedBytes[pos++] = (byte)ch;
+
+                    ch = HttpEncoderUtility.IntToHex(b & 0x0F);
+                    if (char.IsLetter(ch))
+                    {
+                        ch = (char)((int)ch - caseDiff);
+                    }
+
+                    expandedBytes[pos++] = (byte)ch;
+                }
+            }
+            return Encoding.ASCII.GetString(expandedBytes);
+        }
+    }
+    class HttpEncoderUtility
+    {
+        public static char IntToHex(int n)
+        {
+            Debug.Assert(n < 0x10);
+
+            if (n <= 9)
+                return (char)(n + (int)'0');
+            else
+                return (char)(n - 10 + (int)'a');
+        }
+
+        // Set of safe chars, from RFC 1738.4 minus '+'
+        public static bool IsUrlSafeChar(char ch)
+        {
+            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))
+                return true;
+
+            switch (ch)
+            {
+                case '-':
+                case '_':
+                case '.':
+                case '!':
+                case '*':
+                    //JAVA t appears that both Netscape and Internet Explorer escape
+                    //*all special characters from this list with the exception
+                    //*of "-", "_", ".", "*".
+                    //所以这两括号需要转义
+                    ////case '(':
+                    ////case ')':
+                    return true;
+            }
+
+            return false;
+        }
+
+        //  Helper to encode spaces only
+        internal static String UrlEncodeSpaces(string str)
+        {
+            if (str != null && str.IndexOf(' ') >= 0)
+                str = str.Replace(" ", "%20");
+            return str;
+        }
+    }
+}

TEAMModelOS/Controllers/Third/Xkw/OpenAuthClient.cs → TEAMModelOS/Controllers/Third/Xkw/Sdk/OpenAuthClient.cs


+ 120 - 0
TEAMModelOS/Controllers/Third/Xkw/Sdk/XkwAPIHttpService.cs

@@ -0,0 +1,120 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Text.Json;
+using System.Threading;
+using System.Web;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelOS.Controllers.Third.Xkw.Sdk
+{
+
+    public static class XkwAPIHttpServiceExtensions
+    {
+        public static IServiceCollection AddXkwAPIHttpService(this IServiceCollection services, IConfiguration _configuration, string name = "Default")
+        {
+            if (services == null) throw new ArgumentNullException(nameof(services));
+            string location = _configuration.GetValue<string>("Option:Location");
+            services.AddHttpClient<XkwAPIHttpService>();
+            services.Configure<XkwAPIHttpServiceOptions>(name, o => { o.location = location; });
+            return services;
+        }
+    }
+
+    public class XkwAPIHttpServiceOptions
+    {
+        public string location { get; set; }
+    }
+    public class XkwAPIHttpService
+    {
+        private static int DEFAULT_TIMEOUT = 5;
+
+        private String baseUrl;
+        private String appId;
+        private String secret;
+        public int TimeoutInSeconds { get; set; } = DEFAULT_TIMEOUT;
+        private readonly HttpClient _httpClient;
+        public readonly IOptionsMonitor<XkwAPIHttpServiceOptions> options;
+        public XkwAPIHttpService(HttpClient httpClient, IOptionsMonitor<XkwAPIHttpServiceOptions> optionsMonitor, AzureStorageFactory _azureStorageFactory)
+        {
+
+            _httpClient = httpClient;
+            options = optionsMonitor;
+            var table = _azureStorageFactory.GetCloudTableClient().GetTableReference("IESOAuth");
+
+            string domain = "w";
+
+          //  List<OAuthComConfig> configs = await table.FindListByDict<OAuthComConfig>(new Dictionary<string, object>() { { "PartitionKey", "OAuthComConfig" }, { "RowKey", RowKey } });
+            this.baseUrl = baseUrl;
+            this.appId = appId;
+            this.secret = secret;
+        }
+
+
+        public T Get<T>(String uri, Dictionary<String, String> parameters)
+        {
+            return SendRequest<T>(HttpMethod.Get, uri, parameters, null, null, this.TimeoutInSeconds);
+        }
+
+        public T PostAsJson<T>(String uri, Dictionary<String, String> parameters, JsonElement data)
+        {
+
+            string json = data.ToJsonString();
+            return SendRequest<T>(HttpMethod.Post, uri, parameters, json, "application/json", this.TimeoutInSeconds);
+        }
+        public T SendRequest<T>(HttpMethod method, String path, Dictionary<String, String> parameters, String requestBodyStr, String requestContentType, int timeoutInSeconds)
+        {
+            Dictionary<String, String> dic = new Dictionary<string, string>();
+            if (parameters != null)
+            {
+                foreach (var item in parameters)
+                {
+                    dic.Add(item.Key, item.Value);
+                }
+            }
+            // 不对body验签,添加url验签
+            //UriIdentifier uriIdentifier = HmacCommonUtils.SplitUriPrefix(path);
+            dic.Add(HmacConst.KEY_URL, path);
+            HmacResult signRlt = HmacUtils.Sign(appId, secret, dic, requestBodyStr);
+
+            String pathWithQuery = path;
+            if (parameters?.Count > 0)
+            {
+                pathWithQuery = path + "?" + String.Join("&", parameters.Select(i => $"{i.Key}={HttpUtility.UrlEncode(i.Value)}"));
+            }
+
+            HttpRequestMessage request = new HttpRequestMessage(method, baseUrl + pathWithQuery);
+            if (requestBodyStr != null)
+            {
+                StringContent requestContent = new StringContent(requestBodyStr, Encoding.UTF8, requestContentType);
+                request.Content = requestContent;
+            }
+            request.Headers.Add(HmacConst.KEY_TIMESTAMP, signRlt.TimeStamp.ToString());
+            request.Headers.Add(HmacConst.KEY_SIGN, signRlt.Sign);
+            request.Headers.Add(HmacConst.KEY_NONCE, signRlt.Nonce);
+
+            HttpResponseMessage response = null;
+            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds)))
+            {
+                response = _httpClient.SendAsync(request, cts.Token).Result;
+            }
+            String responseText = response.Content.ReadAsStringAsync().Result;
+            if (response.StatusCode != HttpStatusCode.OK)
+            {
+                String message = $"服务错误: 状态码: {(int)response.StatusCode}, resposneText: {responseText}";
+                XopException bapiException = new XopException(message, response);
+                throw bapiException;
+            }
+
+            return responseText.ToObject<T>();
+        }
+    }
+}

+ 25 - 0
TEAMModelOS/Controllers/Third/Xkw/Sdk/XopException.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text;
+
+namespace TEAMModelOS.Controllers.Third.Xkw
+{
+    public class XopException : Exception
+    {
+        public HttpResponseMessage Response { get; set; }
+
+        public XopException()
+        {
+        }
+
+        public XopException(String message) : base(message)
+        {
+        }
+
+        public XopException(String message, HttpResponseMessage response) : base(message)
+        {
+            this.Response = response;
+        }
+    }
+}

+ 151 - 0
TEAMModelOS/Controllers/Third/Xkw/Sdk/XopHttpClient.cs

@@ -0,0 +1,151 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Text;
+using System.Threading;
+using System.Web;
+
+namespace TEAMModelOS.Controllers.Third.Xkw
+{
+    public class XopHttpClient : IDisposable
+    {
+        private static int DEFAULT_TIMEOUT = 5;
+
+        private String baseUrl;
+        private String appId;
+        private String secret;
+
+        public int TimeoutInSeconds { get; set; } = DEFAULT_TIMEOUT;
+
+        private HttpClient httpClient;
+
+
+        public void Dispose()
+        {
+            this.httpClient?.Dispose();
+        }
+
+        public XopHttpClient(String baseUrl, String appId, String secret) : this(baseUrl, appId, secret, null)
+        {
+        }
+
+        public XopHttpClient(String baseUrl, String appId, String secret, WebProxy proxy) : this(baseUrl, appId, secret, DEFAULT_TIMEOUT, proxy)
+        {
+        }
+
+        public XopHttpClient(String baseUrl, String appId, String secret, int timeout) : this(baseUrl, appId, secret, timeout, null)
+        {
+        }
+
+        public XopHttpClient(String baseUrl, String appId, String secret, int timeout, WebProxy proxy)
+        {
+            this.baseUrl = baseUrl;
+            this.appId = appId;
+            this.secret = secret;
+            if (proxy != null)
+            {
+                var httpClientHandler = new HttpClientHandler
+                {
+                    Proxy = proxy
+                };
+                this.httpClient = new HttpClient(httpClientHandler, true);
+            }
+            else
+            {
+                this.httpClient = new HttpClient();
+            }
+            this.httpClient.DefaultRequestHeaders.Add(HmacConst.KEY_APP_ID, appId);
+        }
+
+        public T Get<T>(String uri)
+        {
+            return Get<T>(uri, null);
+        }
+
+        public T Get<T>(String uri, Dictionary<String, String> parameters)
+        {
+            return SendRequest<T>(HttpMethod.Get, uri, parameters, null, null, this.TimeoutInSeconds);
+        }
+
+        public T Post<T>(String uri, Dictionary<String, String> parameters, String text, String contentType)
+        {
+            return SendRequest<T>(HttpMethod.Post, uri, parameters, text, "application/json", this.TimeoutInSeconds);
+        }
+
+        public T PostAsText<T>(String uri, Dictionary<String, String> parameters, String text)
+        {
+            return SendRequest<T>(HttpMethod.Post, uri, parameters, text, "text/plain", this.TimeoutInSeconds);
+        }
+
+        public T PostAsJson<T>(String uri, Dictionary<String, String> parameters, Object data)
+        {
+            
+           string json = JsonConvert.SerializeObject(data);
+            return SendRequest<T>(HttpMethod.Post, uri, parameters, json, "application/json", this.TimeoutInSeconds);
+        }
+
+        //public T PostAsForm<T>(String uri, Dictionary<String, String> parameters, Dictionary<String, String> formData)
+        //{
+        //    if (formData == null)
+        //    {
+        //        formData = new Dictionary<string, string>();
+        //    }
+        //    using (HttpContent requestContent = new FormUrlEncodedContent(formData.ToList()))
+        //    {
+        //        return SendRequest<T>(HttpMethod.Post, uri, parameters, requestContent, this.TimeoutInSeconds);
+        //    }
+        //}
+
+        public T SendRequest<T>(HttpMethod method, String path, Dictionary<String, String> parameters, String requestBodyStr, String requestContentType, int timeoutInSeconds)
+        {
+            Dictionary<String, String> dic = new Dictionary<string, string>();
+            if (parameters != null)
+            {
+                foreach (var item in parameters)
+                {
+                    dic.Add(item.Key, item.Value);
+                }
+            }
+            // 不对body验签,添加url验签
+            //UriIdentifier uriIdentifier = HmacCommonUtils.SplitUriPrefix(path);
+            dic.Add(HmacConst.KEY_URL, path);
+            HmacResult signRlt = HmacUtils.Sign(appId, secret, dic, requestBodyStr);
+
+            String pathWithQuery = path;
+            if (parameters?.Count > 0)
+            {
+                pathWithQuery = path + "?" + String.Join("&", parameters.Select(i => $"{i.Key}={HttpUtility.UrlEncode(i.Value)}"));
+            }
+
+            HttpRequestMessage request = new HttpRequestMessage(method, baseUrl + pathWithQuery);
+            if (requestBodyStr != null)
+            {
+                StringContent requestContent = new StringContent(requestBodyStr, Encoding.UTF8, requestContentType);
+                request.Content = requestContent;
+            }
+            request.Headers.Add(HmacConst.KEY_TIMESTAMP, signRlt.TimeStamp.ToString());
+            request.Headers.Add(HmacConst.KEY_SIGN, signRlt.Sign);
+            request.Headers.Add(HmacConst.KEY_NONCE, signRlt.Nonce);
+
+            HttpResponseMessage response = null;
+            using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutInSeconds)))
+            {
+                response = this.httpClient.SendAsync(request, cts.Token).Result;
+            }
+            String responseText = response.Content.ReadAsStringAsync().Result;
+            if (response.StatusCode != HttpStatusCode.OK)
+            {
+                String message = $"服务错误: 状态码: {(int)response.StatusCode}, resposneText: {responseText}";
+                XopException bapiException = new XopException(message, response);
+                throw bapiException;
+            }
+
+            return JsonConvert.DeserializeObject<T>(responseText);
+        }
+
+    }
+
+}

+ 2 - 24
TEAMModelOS/Controllers/Third/Xkw/XkwOAuth2Controller.cs

@@ -59,22 +59,7 @@ namespace TEAMModelOS.Controllers
         private readonly ThirdApisService _scsApisService;
         private readonly HttpTrigger _httpTrigger;
         private readonly IWebHostEnvironment _environment;
-        /// <summary>
-        /// 机构安全码
-        /// </summary>
-        public string _sc_passKey;
-        /// <summary>
-        /// 机构ID
-        /// </summary>
-        public string _sc_trainComID;
-        /// <summary>
-        /// 机构 AES 密钥
-        /// </summary>
-        public string _sc_privateKey;
-        /// <summary>
-        /// 访问地址
-        /// </summary>
-        public string _sc_url;
+ 
         public IConfiguration _configuration { get; set; }
         public XkwOAuth2Controller(IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
           AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, ThirdApisService scsApisService, HttpTrigger httpTrigger)
@@ -340,13 +325,6 @@ namespace TEAMModelOS.Controllers
 
         }
 
-        [HttpGet("paper-notice")]
-        //[Authorize(Roles = "IES")]
-        //[AuthToken(Roles = "teacher,admin,area,student")]
-        public async Task<IActionResult> PaperNotice([FromQuery] OAuthCode authCode)
-        {
-            await _dingDing.SendBotMsg($"学科网推送消息:{authCode.ToJsonString()}", GroupNames.成都开发測試群組);
-            return Ok();
-        }
+        
     }
 }

+ 88 - 0
TEAMModelOS/Controllers/Third/Xkw/XkwServiceController.cs

@@ -0,0 +1,88 @@
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using System.Text.Json;
+using TEAMModelOS.SDK.Models;
+using Microsoft.AspNetCore.Http;
+using TEAMModelOS.SDK.Extension;
+using Azure.Cosmos;
+using System.Text;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using Microsoft.Extensions.Options;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Configuration;
+using HTEXLib.COMM.Helpers;
+using TEAMModelOS.SDK;
+using System.IdentityModel.Tokens.Jwt;
+using TEAMModelOS.Services;
+using TEAMModelOS.SDK.Models.Service;
+using System.IO;
+using System.Dynamic;
+using Microsoft.AspNetCore.Authorization;
+using Azure.Storage.Blobs.Models;
+using static TEAMModelOS.SDK.Models.Teacher;
+using System.Web;
+using static TEAMModelOS.Controllers.FixDataController;
+using static TEAMModelOS.SDK.SchoolService;
+using Microsoft.AspNetCore.Hosting;
+using TEAMModelOS.Filter;
+using TEAMModelOS.Controllers.Third.Xkw;
+using Microsoft.Extensions.Primitives;
+using System.Net.Http;
+namespace TEAMModelOS.Controllers.Third.Xkw
+{ 
+    // <summary>
+    ///  标准OAuth2
+    /// </summary>
+    ///  
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+    //
+    //[Route("")]
+    [Route("xkw")]
+    [ApiController]
+    public class XkwServiceController: ControllerBase
+    {
+        private readonly SnowflakeId _snowflakeId;
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly ThirdApisService _scsApisService;
+        private readonly HttpTrigger _httpTrigger;
+        private readonly IWebHostEnvironment _environment;
+        public IConfiguration _configuration { get; set; }
+        public XkwServiceController(IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
+            AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, ThirdApisService scsApisService, HttpTrigger httpTrigger)
+        {
+            _azureCosmos = azureCosmos;
+            _snowflakeId = snowflakeId;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _azureStorage = azureStorage;
+            _serviceBus = serviceBus;
+            _configuration = configuration;
+            _azureRedis = azureRedis;
+            _coreAPIHttpService = coreAPIHttpService;
+            _scsApisService = scsApisService;
+            _httpTrigger = httpTrigger;
+            _environment = environment;
+        }
+
+        [HttpGet("paper-notice")]
+        //[Authorize(Roles = "IES")]
+        //[AuthToken(Roles = "teacher,admin,area,student")]
+        public async Task<IActionResult> PaperNotice([FromQuery] OAuthCode authCode)
+        {
+            await _dingDing.SendBotMsg($"学科网推送消息:{authCode.ToJsonString()}", GroupNames.成都开发測試群組);
+            return Ok();
+        }
+    }
+}

+ 2 - 0
TEAMModelOS/Startup.cs

@@ -27,6 +27,7 @@ using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Primitives;
 using Microsoft.IdentityModel.Tokens;
 using TEAMModelOS.Controllers;
+using TEAMModelOS.Controllers.Third.Xkw.Sdk;
 using TEAMModelOS.Filter;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK;
@@ -154,6 +155,7 @@ namespace TEAMModelOS
             //等保安全性验证。
             //  services.AddScoped<SecurityHeadersAttribute>();
             services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));
+            services.AddXkwAPIHttpService(Configuration);
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

+ 1 - 0
TEAMModelOS/TEAMModelOS.csproj

@@ -13,6 +13,7 @@
     <None Remove="libwkhtmltox.dll" />
   </ItemGroup>
   <ItemGroup>
+    <Folder Include="Controllers\Third\Xkw\Hmac\" />
     <Folder Include="logfile\" />
     <Folder Include="Lib\" />
     <Folder Include="wwwroot\" />