diff --git a/Back.csproj b/Back.csproj index 5d97d26..5d91557 100644 --- a/Back.csproj +++ b/Back.csproj @@ -11,7 +11,6 @@ - diff --git a/Program/V1/Controllers/PushController.cs b/Program/V1/Controllers/PushController.cs index 8fc0902..410e638 100644 --- a/Program/V1/Controllers/PushController.cs +++ b/Program/V1/Controllers/PushController.cs @@ -1,3 +1,4 @@ +using AcaMate.V1.Models; using Microsoft.AspNetCore.Mvc; using AcaMate.V1.Services; @@ -28,38 +29,33 @@ public class PushController : ControllerBase [HttpPost("send")] [CustomOperation("푸시전송", "저장된 양식으로, 사용자에게 푸시를 전송한다.", "푸시")] - public async Task SendPush(string deviceToken, string title, string body, int badge) + // public async Task SendPush(string deviceToken, string title, string body, int badge) + public async Task SendPush(string deviceToken, [FromBody] Payload payload) { - var keysFilePath = "/src/private/appleKeys.json"; - // var keysFilePath = "private/appleKeys.json"; - var uri = ""; - var p12FilePath = ""; - + + string p12Path = ""; + string p12PWPath = "private/appleKeys.json"; + string apnsTopic = "me.myds.ipstein.acamate.AcaMate"; + string uri = ""; + if (_env.IsDevelopment()) { - // TEST - Console.WriteLine($"Current Directory: {Environment.CurrentDirectory}"); - - - uri = "https://api.sandbox.push.apple.com"; - p12FilePath = "/src/private/AM_Push_Sandbox.p12"; - // p12FilePath = "private/AM_Push_Sandbox.p12"; + uri = "https://api.sandbox.push.apple.com/"; + // p12Path = "/src/private/AM_Push_Sandbox.p12"; + p12Path = "private/AM_Push_Sandbox.p12"; } else { - uri = "https://api.push.apple.com"; - p12FilePath = "/src/private/AM_Push.p12"; - // p12FilePath = "private/AM_Push.p12"; + uri = "https://api.push.apple.com/"; + // p12Path = "/src/private/AM_Push.p12"; + p12Path = "private/AM_Push.p12"; } - var apnsTopic = "me.myds.ipstein.acamate.AcaMate"; - - Console.WriteLine($"{uri} || {p12FilePath}"); - var pushService = new PushServiceWithP12(keysFilePath, p12FilePath, apnsTopic); - + + // ApnsPushService 인스턴스 생성 + var pushService = new ApnsPushService(uri, p12Path, p12PWPath, apnsTopic); + // 푸시 알림 전송 - await pushService.SendPushAsync(uri, deviceToken, title, body, badge); - - return Ok("Push notification sent."); - + await pushService.SendPushNotificationAsync(deviceToken, payload); + return Ok("done"); } } \ No newline at end of file diff --git a/Program/V1/Services/PushService.cs b/Program/V1/Services/PushService.cs index 4d5f264..a9e6b75 100644 --- a/Program/V1/Services/PushService.cs +++ b/Program/V1/Services/PushService.cs @@ -1,109 +1,65 @@ -using System.Net; +using System; using System.Net.Http; -using System.Net.Http.Headers; -using System.Net.Security; -using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Text.Json; - -namespace AcaMate.V1.Services; +using System.Threading.Tasks; using AcaMate.V1.Models; +using Version = System.Version; -public class PushServiceWithP12 +public class ApnsPushService { - private readonly string p12Path; - private readonly string p12Password; - private readonly string apnsTopic; + private readonly string _uri; + private readonly string _p12Path; + private readonly string _p12PWPath; + private readonly string _apnsTopic; - public PushServiceWithP12(string keysFilePath, string p12Path, string apnsTopic) + public ApnsPushService(string uri,string p12Path, string p12PWPath, string apnsTopic) { - // 존재 안하면 예외 던져 버리는거 - if (!File.Exists(keysFilePath)) - { - Console.WriteLine($"File not found: {keysFilePath}"); - throw new FileNotFoundException("The specified file was not found", keysFilePath); - } - - var keys = JsonSerializer.Deserialize>(File.ReadAllText(keysFilePath)); - - Console.WriteLine("Keys content:"); - foreach (var key in keys) - { - Console.WriteLine($"{key.Key}: {key.Value}"); - } - - p12Password = keys["Password"]; - this.p12Path = p12Path; - this.apnsTopic = apnsTopic; + _uri = uri ?? throw new ArgumentNullException(nameof(uri)); + _p12Path = p12Path ?? throw new ArgumentNullException(nameof(p12Path)); + _p12PWPath = p12PWPath ?? throw new ArgumentNullException(nameof(p12PWPath)); + _apnsTopic = apnsTopic ?? throw new ArgumentNullException(nameof(apnsTopic)); } - public async Task SendPushAsync(string uri,string deviceToken, string title, string body, int badge) + public async Task SendPushNotificationAsync(string deviceToken, Payload payload) { - var payload = new Payload() - { - aps = new Aps() - { - alert = new Alert() - { - title = title, - body = body - }, - badge = badge - } - }; + var jsonPayload = JsonSerializer.Serialize(payload); - var handler = new SocketsHttpHandler + var keys = JsonSerializer.Deserialize>(File.ReadAllText(_p12PWPath)); + var p12Password = keys["Password"]; + + try { - SslOptions = new SslClientAuthenticationOptions + var certificate = new X509Certificate2(_p12Path, p12Password); + Console.WriteLine($"Certificate Subject: {certificate.Subject}"); + Console.WriteLine($"Certificate Issuer: {certificate.Issuer}"); + + var handler = new HttpClientHandler(); + handler.ClientCertificates.Add(certificate); + handler.SslProtocols = System.Security.Authentication.SslProtocols.Tls12; + + using var client = new HttpClient(handler) { - EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12 // TLS 1.2 활성화 - } - }; + BaseAddress = new Uri(_uri), + Timeout = TimeSpan.FromSeconds(60) + }; - try - { - // .p12 인증서 로드 - var certificate = new X509Certificate2(p12Path, p12Password, - X509KeyStorageFlags.MachineKeySet | - X509KeyStorageFlags.PersistKeySet | - X509KeyStorageFlags.Exportable); - handler.SslOptions.ClientCertificates = new X509CertificateCollection { certificate }; - Console.WriteLine("Certificate successfully loaded and attached to handler."); - } - catch (CryptographicException ex) - { - Console.WriteLine($"[Error] CryptographicException: {ex.Message}"); - throw; - } - catch (Exception ex) - { - Console.WriteLine($"[Error] Unexpected error: {ex.Message}"); - throw; - } + var request = new HttpRequestMessage(HttpMethod.Post, $"/3/device/{deviceToken}") + { + Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"), + Version = new Version(2, 0) // HTTP/2 사용 + }; - using var client = new HttpClient(handler) - { - BaseAddress = new Uri($"{uri}") - }; - - client.DefaultRequestHeaders.ExpectContinue = false; - client.DefaultRequestHeaders.Add("apns-topic", "me.myds.ipstein.acamate.AcaMate"); - client.DefaultRequestHeaders.Add("apns-priority", "10"); - - - var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"); + // 필수 헤더 추가 + request.Headers.Add("apns-topic", _apnsTopic); + request.Headers.Add("apns-push-type", "alert"); - try - { + Console.WriteLine("Sending push notification..."); Console.WriteLine($"Payload: {jsonPayload}"); - Console.WriteLine($"Request URI: {client.BaseAddress}3/device/{deviceToken}"); - - var response = await client.PostAsync($"3/device/{deviceToken}", content); - Console.WriteLine("이건 넘음?"); - - + + var response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { Console.WriteLine("Push notification sent successfully."); @@ -111,22 +67,12 @@ public class PushServiceWithP12 else { var errorContent = await response.Content.ReadAsStringAsync(); - Console.WriteLine($"Failed to send push notification. Status Code: {response.StatusCode}, Error: {errorContent}"); - - } - } - - catch (HttpRequestException httpEx) - { - Console.WriteLine($"HttpRequestException: {httpEx.Message}"); - if (httpEx.InnerException != null) - { - Console.WriteLine($"Inner Exception: {httpEx.InnerException.Message}"); + Console.WriteLine($"Failed. Status Code: {response.StatusCode}, Error: {errorContent}"); } } catch (Exception ex) { - Console.WriteLine($"General Exception: {ex.Message}"); + Console.WriteLine($"Error sending push notification: {ex.Message}"); } } } \ No newline at end of file