using dotAPNS; using FirebaseAdmin; using FirebaseAdmin.Messaging; using Google.Apis.Auth.OAuth2; using Newtonsoft.Json.Linq; using ServiceOutside.Models; using ServiceShared; using ServiceShared.Crypto; using System.Net.Security; using System.Net.Sockets; using System.Security.Authentication; using System.Security.Cryptography.X509Certificates; using static ServiceShared.Models.Database.Device; using static ServiceShared.Models.Database.Results; namespace ServiceOutside.Service { public static class Notification { /// /// PushNotificationsConfigurations for Notification Service /// private static PushNotificationsConfiguration Configurations { get; set; } /// /// Sets configurations for push service /// /// PushNotificationsConfiguration object public static void SetConfigurations(PushNotificationsConfiguration pushNotificationsConfiguration) { Configurations = pushNotificationsConfiguration; } /// /// Sends the notification message to the mobile device /// /// device token of receiver /// device type of receivr /// message object, that contains title, subtitle and body /// public static async Task Send(string deviceToken, DeviceTypes deviceType, Message message) { bool result = false; Log.Debug("Notification Service send to device: " + (!string.IsNullOrEmpty(deviceToken) ? deviceToken : "") + ", " + (message != null && !string.IsNullOrEmpty(message.Body) ? message.Body : "")); if(!string.IsNullOrEmpty(deviceToken) && deviceType != DeviceTypes.NONE && message != null) { switch(deviceType) { case DeviceTypes.IOS: result = await SendToIOS(deviceToken, message.Title, message.Subtitle, message.Body); break; case DeviceTypes.ANDROID: result = await SendToAndroid(deviceToken, message.Title, message.Body); break; } } return result; } /// /// Sends notification message to the ios devices /// /// device_token, that should get the notification message /// title of notification message /// subtitle of notification message /// body of notification message /// returns true if successfully sent public static async Task SendToIOS(string deviceToken, string title, string subtitle, string body) { bool result = false; try { if (Configurations.Valid && !string.IsNullOrEmpty(deviceToken) && !string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(subtitle) && !string.IsNullOrEmpty(body)) { var options = new ApnsJwtOptions() { BundleId = Configurations.APNS_BUNDLE_ID, CertFilePath = Configurations.APNS_CERT, KeyId = Configurations.APNS_KEY_ID, TeamId = Configurations.APNS_TEAM_ID }; ApnsClient client = ApnsClient.CreateUsingJwt(new HttpClient(), options); ApplePush push = new ApplePush(ApplePushType.Alert); push.AddAlert(title, subtitle, body); push.AddBadge(1); push.AddSound(); push.AddToken(deviceToken); Log.Debug("Sending notification(IOS): " + (!string.IsNullOrEmpty(deviceToken) ? deviceToken : " device token not found")); ApnsResponse apnsResponse = await client.SendAsync(push); result = apnsResponse.IsSuccessful; Log.Debug("ApnsResponse: success: " + (apnsResponse != null && apnsResponse.IsSuccessful ? " true " : " false ") + " reason: "+ (apnsResponse != null && !string.IsNullOrEmpty(apnsResponse.ReasonString) ? apnsResponse.ReasonString : "")); } else { Log.Debug("Apple ApnsJwt, deviceToken or message is invalid"); } } catch (Exception ex) { Log.Debug("ServiceOutside.Service.Notification.SendToIOS EX: " + ex.Message); } return result; } private static bool ServerCertificateCustomValidation(HttpRequestMessage requestMessage, X509Certificate2 certificate, X509Chain chain, SslPolicyErrors sslErrors) { return true; } /// /// Sends notification message to the android devices /// /// device_token, that should get the notification message /// title of notification message /// body of notification message /// returns true if successfully sent public static async Task SendToAndroid(string deviceToken, string title, string body) { bool result = false; try { if (Configurations.Valid && !string.IsNullOrEmpty(deviceToken) && !string.IsNullOrEmpty(title) && !string.IsNullOrEmpty(body)) { Log.Debug("GoogleCredential file: " + Configurations.GOOGLE_CREDENTIAL_JSON); GoogleCredential googleCredential = GoogleCredential.FromFile(Configurations.GOOGLE_CREDENTIAL_JSON); if(FirebaseApp.DefaultInstance == null) { FirebaseApp.Create(new AppOptions() { Credential = googleCredential }); } FirebaseAdmin.Messaging.Message message = new FirebaseAdmin.Messaging.Message(); message.Token = deviceToken; message.Notification = new FirebaseAdmin.Messaging.Notification(); message.Notification.Title = title; message.Notification.Body = body; //BatchResponse response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(multicastMessage).ConfigureAwait(true); Log.Debug("Sending notification(Android): " + (!string.IsNullOrEmpty(deviceToken) ? deviceToken : " device token not found")); string response = await FirebaseMessaging.DefaultInstance.SendAsync(message).ConfigureAwait(true); result = !string.IsNullOrEmpty(response); Log.Debug(response); } else { Log.Debug("Google credential, deviceToken or message is invalid"); } } catch (Exception ex) { Log.Debug("ServiceOutside.Service.Notification.SendToAndroid EX: " + ex.Message); } return result; } /// /// Message object that contains title, subtitle and body of push notification /// public class Message { public string Title { get; set; } public string Subtitle { get; set; } public string Body { get; set; } public Message() { } public Message(bool available, ResultsStatus status) { if(available && status == ResultsStatus.COMPLETED) { this.Title = "Neuigkeiten zu Ihrem Befund"; this.Subtitle = "Ihr Befund ist fertig"; this.Body = "Ihr Befund ist fertig und kann in der App abgerufen werden."; } else { // TODO: Handle other status switch(status) { case ResultsStatus.REJECTED: this.Title = "Neuigkeiten zu Ihrem Befund"; this.Subtitle = "Ihre Angaben konnten nicht eindeutig einem Auftrag zugeordnet werden"; this.Body = "Bitte wenden Sie sich an den Support"; break; case ResultsStatus.NOT_FOUND: this.Title = "Neuigkeiten zu Ihrem Befund"; this.Subtitle = "Die Auftragsnummer wurde nicht gefunden"; this.Body = "Bitte überprüfen Sie Ihre Auftragsnummer oder wenden Sie sich an den Support"; break; } } } } } }