using System.Security.Cryptography; using System.Text; using System.Text.Json; namespace CampusErrand.Services; /// /// 腾讯 IM 服务,负责生成 UserSig 和调用服务端 REST API /// public class TencentIMService { private readonly long _sdkAppId; private readonly string _secretKey; private readonly HttpClient _httpClient; private const string AdminAccount = "administrator"; public TencentIMService(IConfiguration configuration, IHttpClientFactory httpClientFactory) { var config = configuration.GetSection("TencentIM"); _sdkAppId = config.GetValue("SDKAppId"); _secretKey = config["SecretKey"]!; _httpClient = httpClientFactory.CreateClient(); } public long SDKAppId => _sdkAppId; /// /// 生成 UserSig /// public string GenerateUserSig(string userId, int expireSeconds = 604800) { var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); var obj = new Dictionary { ["TLS.ver"] = "2.0", ["TLS.identifier"] = userId, ["TLS.sdkappid"] = _sdkAppId, ["TLS.expire"] = expireSeconds, ["TLS.time"] = now }; var contentToSign = $"TLS.identifier:{userId}\nTLS.sdkappid:{_sdkAppId}\nTLS.time:{now}\nTLS.expire:{expireSeconds}\n"; using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_secretKey)); var sig = hmac.ComputeHash(Encoding.UTF8.GetBytes(contentToSign)); obj["TLS.sig"] = Convert.ToBase64String(sig); var jsonBytes = Encoding.UTF8.GetBytes(JsonSerializer.Serialize(obj)); using var output = new MemoryStream(); using (var zlib = new System.IO.Compression.ZLibStream(output, System.IO.Compression.CompressionLevel.Optimal)) { zlib.Write(jsonBytes, 0, jsonBytes.Length); } return Convert.ToBase64String(output.ToArray()) .Replace('+', '*') .Replace('/', '-') .Replace('=', '_'); } /// /// 通过服务端 REST API 拉取两个用户之间的漫游消息 /// public async Task GetRoamMessagesAsync(string fromUserId, string toUserId, int maxCnt = 100, long minTime = 0, long maxTime = 0) { var adminSig = GenerateUserSig(AdminAccount); var random = Random.Shared.Next(100000, 999999); var url = $"https://console.tim.qq.com/v4/openim/admin_getroammsg?sdkappid={_sdkAppId}&identifier={AdminAccount}&usersig={adminSig}&random={random}&contenttype=json"; var body = new { Operator_Account = fromUserId, Peer_Account = toUserId, MaxCnt = maxCnt, MinTime = minTime, MaxTime = maxTime > 0 ? maxTime : DateTimeOffset.UtcNow.ToUnixTimeSeconds() }; var content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json"); var response = await _httpClient.PostAsync(url, content); var json = await response.Content.ReadAsStringAsync(); Console.WriteLine($"[IM] 拉取漫游消息: {fromUserId} -> {toUserId}, 响应: {json}"); return JsonSerializer.Deserialize(json); } }