diff --git a/Src/Dlhis.Message.Api/Dlhis.Message.Api.csproj b/Src/Dlhis.Message.Api/Dlhis.Message.Api.csproj
new file mode 100644
index 00000000..4100a696
--- /dev/null
+++ b/Src/Dlhis.Message.Api/Dlhis.Message.Api.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Src/Dlhis.Message.Api/IDingTalkApi.cs b/Src/Dlhis.Message.Api/IDingTalkApi.cs
new file mode 100644
index 00000000..7b7c7f17
--- /dev/null
+++ b/Src/Dlhis.Message.Api/IDingTalkApi.cs
@@ -0,0 +1,13 @@
+using Dlhis.Message.Api.Requests;
+using Kurisu.RemoteCall.Attributes;
+
+namespace Dlhis.Message.Api;
+
+[RequestLog]
+[RequestResultHandler]
+[EnableRemoteClient(Name = "message-service", BaseUrl = "${InternalRequest:MessageRequestUrl}")]
+public interface IDingTalkApi
+{
+ [Post("/api/messages/dingtalk/workmessage")]
+ Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request);
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Message.Api/Requests/JinkoSendWorkMessageRequest.cs b/Src/Dlhis.Message.Api/Requests/JinkoSendWorkMessageRequest.cs
new file mode 100644
index 00000000..794621a5
--- /dev/null
+++ b/Src/Dlhis.Message.Api/Requests/JinkoSendWorkMessageRequest.cs
@@ -0,0 +1,14 @@
+namespace Dlhis.Message.Api.Requests;
+
+public class JinkoSendWorkMessageRequest
+{
+ ///
+ /// 发送内容
+ ///
+ public string Content { get; set; }
+
+ ///
+ /// 工号
+ ///
+ public List WorkCodes { get; set; }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Message/Controllers/MessagesController.cs b/Src/Dlhis.Message/Controllers/MessagesController.cs
new file mode 100644
index 00000000..e56529b1
--- /dev/null
+++ b/Src/Dlhis.Message/Controllers/MessagesController.cs
@@ -0,0 +1,24 @@
+using Dlhis.Message.Services;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Dlhis.Message.Controllers;
+
+
+[Route("api/[controller]")]
+[ApiController]
+public class MessagesController : ControllerBase
+{
+ private readonly IJinkoApiService _jinkoApiService;
+
+ public MessagesController(IJinkoApiService jinkoApiService)
+ {
+ _jinkoApiService = jinkoApiService;
+ }
+
+
+ [HttpPost("dingtalk/workmessage")]
+ public async Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request)
+ {
+ await _jinkoApiService.SendWorkMessageAsync(request);
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Message/Dlhis.Message.csproj b/Src/Dlhis.Message/Dlhis.Message.csproj
index 4b57436f..2ebfed6c 100644
--- a/Src/Dlhis.Message/Dlhis.Message.csproj
+++ b/Src/Dlhis.Message/Dlhis.Message.csproj
@@ -2,7 +2,7 @@
net6.0
- enable
+ disable
enable
Linux
..\..
@@ -16,4 +16,10 @@
+
+
+ appsettings.json
+
+
+
diff --git a/Src/Dlhis.Message/Program.cs b/Src/Dlhis.Message/Program.cs
index 3c574499..36d1a96b 100644
--- a/Src/Dlhis.Message/Program.cs
+++ b/Src/Dlhis.Message/Program.cs
@@ -15,4 +15,51 @@ public class Startup : DefaultStartup
{
IdentityModelEventSource.ShowPII = true;
}
+
+ ///
+ public override void ConfigureServices(IServiceCollection services)
+ {
+ base.ConfigureServices(services);
+
+ services.AddHttpClient("jinko.oa", (_, _) => { })
+ .ConfigurePrimaryHttpMessageHandler(() =>
+ {
+ var handler = new HttpClientHandler
+ {
+ ClientCertificateOptions = ClientCertificateOption.Manual,
+ ServerCertificateCustomValidationCallback = (_, _, _, _) => true
+ };
+
+ return handler;
+ });
+
+ services.AddHttpClient("jinko.httpclient", (sp, httpClient) =>
+ {
+ // "BaseUrl": "https://oapi.dingtalk.com",
+ // "AgentId": "2768073678",
+ // "AppId": "dingumelppews6rah7x9",
+ // "AppSecret": "nsWfJTVjYesHVzrLiP-t1TQqMQvC1L_kZNfXfnIyzcXK4pCTfKprkjZcxAbsDR_l",
+
+ httpClient.BaseAddress = new Uri("https://oapi.dingtalk.com");
+ httpClient.Timeout = TimeSpan.FromSeconds(30);
+ })
+ // .SetHandlerLifetime(TimeSpan.FromMinutes(5))
+ // .addd((res) =>
+ // {
+ // return HttpPolicyExtensions
+ // .HandleTransientHttpError()
+ // .OrResult(msg => msg.StatusCode != HttpStatusCode.OK)
+ // .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
+ // })
+ .ConfigurePrimaryHttpMessageHandler(() =>
+ {
+ var handler = new HttpClientHandler
+ {
+ ClientCertificateOptions = ClientCertificateOption.Manual,
+ ServerCertificateCustomValidationCallback = (_, _, _, _) => true
+ };
+
+ return handler;
+ });
+ }
}
\ No newline at end of file
diff --git a/Src/Dlhis.Message/Services/IJinkoApiService.cs b/Src/Dlhis.Message/Services/IJinkoApiService.cs
new file mode 100644
index 00000000..94350ac0
--- /dev/null
+++ b/Src/Dlhis.Message/Services/IJinkoApiService.cs
@@ -0,0 +1,6 @@
+namespace Dlhis.Message.Services;
+
+public interface IJinkoApiService : ISingletonDependency
+{
+ Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request);
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Message/Services/JinkoApiService.cs b/Src/Dlhis.Message/Services/JinkoApiService.cs
new file mode 100644
index 00000000..329fcb99
--- /dev/null
+++ b/Src/Dlhis.Message/Services/JinkoApiService.cs
@@ -0,0 +1,99 @@
+using System.Text;
+using Kurisu.AspNetCore.Utils.Extensions;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace Dlhis.Message.Services;
+
+public class JinkoApiService : IJinkoApiService
+{
+ private readonly IHttpClientFactory _httpClientFactory;
+
+ public JinkoApiService(IHttpClientFactory httpClientFactory)
+ {
+ _httpClientFactory = httpClientFactory;
+ }
+
+ public async Task GetTokenAsync()
+ {
+ var token = string.Empty;
+ if (string.IsNullOrEmpty(token))
+ {
+ var httpClient = _httpClientFactory.CreateClient("jinko.httpclient");
+
+ var form = new FormUrlEncodedContent(new Dictionary
+ {
+ { "appkey", "dingumelppews6rah7x9" },
+ { "appsecret", "nsWfJTVjYesHVzrLiP-t1TQqMQvC1L_kZNfXfnIyzcXK4pCTfKprkjZcxAbsDR_l" }
+ });
+
+ //appkey=dingumelppews6rah7x9&appsecret=nsWfJTVjYesHVzrLiP-t1TQqMQvC1L_kZNfXfnIyzcXK4pCTfKprkjZcxAbsDR_l
+ var response = await httpClient.GetStringAsync($"/gettoken?{await form.ReadAsStringAsync()}");
+ var jObj = JObject.Parse(response);
+ (jObj.Value("errcode") == "0").ThrowIfFalse(jObj.Value("errmsg"));
+
+ token = jObj.Value("access_token");
+ }
+
+ return token;
+ }
+
+
+ public async Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request)
+ {
+ request.Content.IsEmpty().ThrowIfTrue("发送内容不能为空");
+ var token = await GetTokenAsync();
+
+ var users = await GetJinkoOaInfoByWorkCodes(request.WorkCodes);
+ var userStringIds = string.Join(",", users.Select(x => x.Id));
+ (userStringIds.Length > 100).ThrowIfTrue("超出消息接受人数,length > 100");
+
+ var body = new
+ {
+ agent_id = "2768073678",
+ userid_list = userStringIds,
+ msg = new
+ {
+ msgtype = "text",
+ text = new
+ {
+ content = request.Content
+ },
+ },
+ }.ToJson();
+
+ var httpClient = _httpClientFactory.CreateClient("jinko.httpclient");
+ var url = $"/topapi/message/corpconversation/asyncsend_v2?access_token={token}";
+ var content = new StringContent(body, Encoding.UTF8, "application/json");
+
+ var response = await httpClient.PostAsync(url, content);
+ var jsonResponse = await response.Content.ReadAsStringAsync();
+
+ //_logger.LogInformation("请求参数:{Request} \r\n 钉钉请求参数:{DingTalkRequest} \r\n 钉钉响应:{DingTalkResponse}", JsonConvert.SerializeObject(request), body, jsonResponse);
+
+ var jObj = JObject.Parse(jsonResponse);
+ (jObj.Value("errcode") == "0").ThrowIfFalse(jObj.Value("errmsg"));
+ }
+
+
+ private async Task> GetJinkoOaInfoByWorkCodes(List codes)
+ {
+ var httpClient = _httpClientFactory.CreateClient("jinko.oa");
+
+ var body = new
+ {
+ token = "TTMlaplWIEjmJHiVShWybekyyNnJXDHD",
+ type = "workCode",
+ workCode = string.Join(",", codes)
+ }.ToJson();
+
+ var content = new StringContent(body, Encoding.UTF8, "application/json");
+ var response = await httpClient.PostAsync("http://oa.jinkosolar.com/api/commonRequestService/getUserByWorkCode/v2", content);
+ var responseJson = await response.Content.ReadAsStringAsync();
+
+ var oaInfo = JsonConvert.DeserializeObject>>>(responseJson);
+ (oaInfo.Code == 200).ThrowIfFalse(oaInfo.Message);
+
+ return oaInfo.Result.Data;
+ }
+}
\ No newline at end of file
diff --git a/Src/Dlhis.Message/Services/JinkoOaResponse.cs b/Src/Dlhis.Message/Services/JinkoOaResponse.cs
new file mode 100644
index 00000000..87d59646
--- /dev/null
+++ b/Src/Dlhis.Message/Services/JinkoOaResponse.cs
@@ -0,0 +1,22 @@
+namespace Dlhis.Message.Services
+{
+ public class JinkoOaResponse
+ {
+ public int Code { get; set; }
+ public string Message { get; set; }
+ public T Result { get; set; }
+ }
+
+ public class JinkoData
+ {
+ public T Data { get; set; }
+ }
+
+
+ public class JinkoOaInfo
+ {
+ public int Id { get; set; }
+ public string Email { get; set; }
+ public string Lastname { get; set; }
+ }
+}
diff --git a/Src/Dlhis.Message/Services/JinkoSendWorkMessageRequest.cs b/Src/Dlhis.Message/Services/JinkoSendWorkMessageRequest.cs
new file mode 100644
index 00000000..502dc60d
--- /dev/null
+++ b/Src/Dlhis.Message/Services/JinkoSendWorkMessageRequest.cs
@@ -0,0 +1,14 @@
+namespace Dlhis.Message.Services;
+
+public class JinkoSendWorkMessageRequest
+{
+ ///
+ /// 发送内容
+ ///
+ public string Content { get; set; }
+
+ ///
+ /// 工号
+ ///
+ public List WorkCodes { get; set; }
+}
\ No newline at end of file