using System; using System.Diagnostics; using System.Net.Http; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using AcaMate.V1.Models; using Version = System.Version; namespace AcaMate.V1.Services; public class ApnsPushService { public ApnsPushService() { } public async Task SendPushNotificationAsync(string deviceToken, PushFile pushFile, Payload payload) { // 존재 안하면 예외 던져 버리는거 if (!File.Exists(pushFile.p12Path) || !File.Exists(pushFile.p12PWPath)) throw new FileNotFoundException("[푸시] : p12 관련 파일 확인 필요"); var jsonPayload = JsonSerializer.Serialize(payload); var keys = JsonSerializer.Deserialize>(await File.ReadAllTextAsync(pushFile.p12PWPath)) ?? throw new FileContentNotFoundException("[푸시] : 파일 내부의 값을 읽어오지 못함"); try { // var certificate = new X509Certificate2(pushFile.p12Path, keys["Password"]); var handler = new HttpClientHandler(); handler.ClientCertificates .Add(new X509Certificate2(pushFile.p12Path, keys["Password"])); handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12; using var client = new HttpClient(handler) { BaseAddress = new Uri(pushFile.uri), Timeout = TimeSpan.FromSeconds(60) }; var request = new HttpRequestMessage(HttpMethod.Post, $"/3/device/{deviceToken}") { Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"), Version = new Version(2, 0) // HTTP/2 사용 }; // 필수 헤더 추가 request.Headers.Add("apns-topic", pushFile.apnsTopic); request.Headers.Add("apns-push-type", "alert"); var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) return true; else { var errorContent = await response.Content.ReadAsStringAsync(); throw new ServiceConnectionFailedException($"[푸시] : APNS 통신 실패 - {errorContent}"); } } catch (HttpRequestException httpEx) { Console.WriteLine($"HttpRequestException: {httpEx.Message}"); throw new ServiceConnectionFailedException($"[푸시] : APNS 통신 실패 - {httpEx.Message}"); } } }