feat 消息推送api

This commit is contained in:
2025-03-06 16:04:08 +08:00
parent 413a3ae77d
commit 7e71884b32
10 changed files with 259 additions and 1 deletions

View File

@@ -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);
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
<DockerfileContext>..\..</DockerfileContext>
@@ -16,4 +16,10 @@
<ProjectReference Include="..\Dlhis.Entity\Dlhis.Entity.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.Development.json">
<DependentUpon>appsettings.json</DependentUpon>
</Content>
</ItemGroup>
</Project>

View File

@@ -15,4 +15,51 @@ public class Startup : DefaultStartup
{
IdentityModelEventSource.ShowPII = true;
}
/// <inheritdoc />
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;
});
}
}

View File

@@ -0,0 +1,6 @@
namespace Dlhis.Message.Services;
public interface IJinkoApiService : ISingletonDependency
{
Task SendWorkMessageAsync(JinkoSendWorkMessageRequest request);
}

View File

@@ -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<string> GetTokenAsync()
{
var token = string.Empty;
if (string.IsNullOrEmpty(token))
{
var httpClient = _httpClientFactory.CreateClient("jinko.httpclient");
var form = new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "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<string>("errcode") == "0").ThrowIfFalse(jObj.Value<string>("errmsg"));
token = jObj.Value<string>("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<string>("errcode") == "0").ThrowIfFalse(jObj.Value<string>("errmsg"));
}
private async Task<List<JinkoOaInfo>> GetJinkoOaInfoByWorkCodes(List<string> 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<JinkoOaResponse<JinkoData<List<JinkoOaInfo>>>>(responseJson);
(oaInfo.Code == 200).ThrowIfFalse(oaInfo.Message);
return oaInfo.Result.Data;
}
}

View File

@@ -0,0 +1,22 @@
namespace Dlhis.Message.Services
{
public class JinkoOaResponse<T>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
}
public class JinkoData<T>
{
public T Data { get; set; }
}
public class JinkoOaInfo
{
public int Id { get; set; }
public string Email { get; set; }
public string Lastname { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
namespace Dlhis.Message.Services;
public class JinkoSendWorkMessageRequest
{
/// <summary>
/// 发送内容
/// </summary>
public string Content { get; set; }
/// <summary>
/// 工号
/// </summary>
public List<string> WorkCodes { get; set; }
}