forked from AcaMate/AcaMate_API
[✨] 11차 푸시 확인 - 로컬에서 수신 확인 완료
Signed-off-by: seonkyu.kim <sean.kk@daum.net>
This commit is contained in:
parent
f4efd70507
commit
6f9880b9d3
|
@ -11,7 +11,6 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.10" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8"/>
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.8"/>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.10" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
|
||||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.1.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.1.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.1.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.1.0" />
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using AcaMate.V1.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
using AcaMate.V1.Services;
|
using AcaMate.V1.Services;
|
||||||
|
@ -28,38 +29,33 @@ public class PushController : ControllerBase
|
||||||
|
|
||||||
[HttpPost("send")]
|
[HttpPost("send")]
|
||||||
[CustomOperation("푸시전송", "저장된 양식으로, 사용자에게 푸시를 전송한다.", "푸시")]
|
[CustomOperation("푸시전송", "저장된 양식으로, 사용자에게 푸시를 전송한다.", "푸시")]
|
||||||
public async Task<IActionResult> SendPush(string deviceToken, string title, string body, int badge)
|
// public async Task<IActionResult> SendPush(string deviceToken, string title, string body, int badge)
|
||||||
|
public async Task<IActionResult> SendPush(string deviceToken, [FromBody] Payload payload)
|
||||||
{
|
{
|
||||||
var keysFilePath = "/src/private/appleKeys.json";
|
|
||||||
// var keysFilePath = "private/appleKeys.json";
|
string p12Path = "";
|
||||||
var uri = "";
|
string p12PWPath = "private/appleKeys.json";
|
||||||
var p12FilePath = "";
|
string apnsTopic = "me.myds.ipstein.acamate.AcaMate";
|
||||||
|
string uri = "";
|
||||||
|
|
||||||
if (_env.IsDevelopment())
|
if (_env.IsDevelopment())
|
||||||
{
|
{
|
||||||
// TEST
|
uri = "https://api.sandbox.push.apple.com/";
|
||||||
Console.WriteLine($"Current Directory: {Environment.CurrentDirectory}");
|
// p12Path = "/src/private/AM_Push_Sandbox.p12";
|
||||||
|
p12Path = "private/AM_Push_Sandbox.p12";
|
||||||
|
|
||||||
uri = "https://api.sandbox.push.apple.com";
|
|
||||||
p12FilePath = "/src/private/AM_Push_Sandbox.p12";
|
|
||||||
// p12FilePath = "private/AM_Push_Sandbox.p12";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uri = "https://api.push.apple.com";
|
uri = "https://api.push.apple.com/";
|
||||||
p12FilePath = "/src/private/AM_Push.p12";
|
// p12Path = "/src/private/AM_Push.p12";
|
||||||
// p12FilePath = "private/AM_Push.p12";
|
p12Path = "private/AM_Push.p12";
|
||||||
}
|
}
|
||||||
var apnsTopic = "me.myds.ipstein.acamate.AcaMate";
|
|
||||||
|
// ApnsPushService 인스턴스 생성
|
||||||
Console.WriteLine($"{uri} || {p12FilePath}");
|
var pushService = new ApnsPushService(uri, p12Path, p12PWPath, apnsTopic);
|
||||||
var pushService = new PushServiceWithP12(keysFilePath, p12FilePath, apnsTopic);
|
|
||||||
|
|
||||||
// 푸시 알림 전송
|
// 푸시 알림 전송
|
||||||
await pushService.SendPushAsync(uri, deviceToken, title, body, badge);
|
await pushService.SendPushNotificationAsync(deviceToken, payload);
|
||||||
|
return Ok("done");
|
||||||
return Ok("Push notification sent.");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,109 +1,65 @@
|
||||||
using System.Net;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Net.Security;
|
|
||||||
using System.Security.Cryptography;
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
namespace AcaMate.V1.Services;
|
|
||||||
using AcaMate.V1.Models;
|
using AcaMate.V1.Models;
|
||||||
|
using Version = System.Version;
|
||||||
|
|
||||||
public class PushServiceWithP12
|
public class ApnsPushService
|
||||||
{
|
{
|
||||||
private readonly string p12Path;
|
private readonly string _uri;
|
||||||
private readonly string p12Password;
|
private readonly string _p12Path;
|
||||||
private readonly string apnsTopic;
|
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)
|
||||||
{
|
{
|
||||||
// 존재 안하면 예외 던져 버리는거
|
_uri = uri ?? throw new ArgumentNullException(nameof(uri));
|
||||||
if (!File.Exists(keysFilePath))
|
_p12Path = p12Path ?? throw new ArgumentNullException(nameof(p12Path));
|
||||||
{
|
_p12PWPath = p12PWPath ?? throw new ArgumentNullException(nameof(p12PWPath));
|
||||||
Console.WriteLine($"File not found: {keysFilePath}");
|
_apnsTopic = apnsTopic ?? throw new ArgumentNullException(nameof(apnsTopic));
|
||||||
throw new FileNotFoundException("The specified file was not found", keysFilePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
var keys = JsonSerializer.Deserialize<Dictionary<string, string>>(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 jsonPayload = JsonSerializer.Serialize(payload);
|
||||||
|
|
||||||
var handler = new SocketsHttpHandler
|
var keys = JsonSerializer.Deserialize<Dictionary<string, string>>(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
|
var request = new HttpRequestMessage(HttpMethod.Post, $"/3/device/{deviceToken}")
|
||||||
{
|
{
|
||||||
// .p12 인증서 로드
|
Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"),
|
||||||
var certificate = new X509Certificate2(p12Path, p12Password,
|
Version = new Version(2, 0) // HTTP/2 사용
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var client = new HttpClient(handler)
|
// 필수 헤더 추가
|
||||||
{
|
request.Headers.Add("apns-topic", _apnsTopic);
|
||||||
BaseAddress = new Uri($"{uri}")
|
request.Headers.Add("apns-push-type", "alert");
|
||||||
};
|
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
try
|
Console.WriteLine("Sending push notification...");
|
||||||
{
|
|
||||||
Console.WriteLine($"Payload: {jsonPayload}");
|
Console.WriteLine($"Payload: {jsonPayload}");
|
||||||
Console.WriteLine($"Request URI: {client.BaseAddress}3/device/{deviceToken}");
|
|
||||||
|
var response = await client.SendAsync(request);
|
||||||
var response = await client.PostAsync($"3/device/{deviceToken}", content);
|
|
||||||
Console.WriteLine("이건 넘음?");
|
|
||||||
|
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Push notification sent successfully.");
|
Console.WriteLine("Push notification sent successfully.");
|
||||||
|
@ -111,22 +67,12 @@ public class PushServiceWithP12
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var errorContent = await response.Content.ReadAsStringAsync();
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
Console.WriteLine($"Failed to send push notification. Status Code: {response.StatusCode}, Error: {errorContent}");
|
Console.WriteLine($"Failed. 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}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"General Exception: {ex.Message}");
|
Console.WriteLine($"Error sending push notification: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user