Skip to content

Commit 254b4f5

Browse files
Merge pull request #78 from andrei-m-code/feature/fcm-http-v1
Firebase HTTP v1 API
2 parents 7c5190d + 45ee7aa commit 254b4f5

File tree

16 files changed

+161
-123
lines changed

16 files changed

+161
-123
lines changed

CorePush.Tester/CorePush.Tester.csproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net6.0</TargetFramework>
5+
<TargetFramework>net7.0</TargetFramework>
66
</PropertyGroup>
77

88
<ItemGroup>
99
<ProjectReference Include="..\CorePush\CorePush.csproj" />
1010
</ItemGroup>
1111

12+
<ItemGroup>
13+
<PackageReference Include="FirebaseAdmin" Version="2.3.0" />
14+
</ItemGroup>
15+
1216
</Project>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace CorePush.Tester;
2+
3+
public class FirebasePayload
4+
{
5+
public FirebaseMessage Message { get; set; }
6+
}
7+
8+
public class FirebaseMessage
9+
{
10+
public string Token { get; set; }
11+
public FirebaseNotification Notification { get; set; }
12+
public object Data { get; set; }
13+
}
14+
15+
public class FirebaseNotification
16+
{
17+
public string Title { get; set; }
18+
public string Body { get; set; }
19+
}

CorePush.Tester/Program.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
using System;
22
using System.Net.Http;
33
using System.Threading.Tasks;
4+
45
using CorePush.Apple;
5-
using CorePush.Google;
6+
using CorePush.Firebase;
67

78
namespace CorePush.Tester
89
{
@@ -15,21 +16,26 @@ class Program
1516
private const string apnP8PrivateKeyId = "TODO";
1617
private const string apnTeamId = "TODO";
1718
private const string apnDeviceToken = "TODO";
18-
private const ApnServerType apnServerType = ApnServerType.Development;
19+
private const ApnServerType apnServerType = ApnServerType.Production;
1920

2021
#endregion
2122

2223
#region FCM Sender Settings
24+
25+
private const string googleProjectId = "TODO";
26+
private const string fcmBearerToken = "TODO";
2327
private const string fcmReceiverToken = "TODO";
24-
private const string fcmSenderId = "TODO";
25-
private const string fcmServerKey = "TODO";
26-
28+
2729
# endregion
2830

29-
private static readonly HttpClient http = new HttpClient();
31+
private static readonly HttpClient http = new();
3032

3133
static async Task Main()
3234
{
35+
// var serviceAccountJsonFilepath ="path-to-your-service-account-json-file/yourproject-123456-e883841.json";
36+
// await Utils.GenerateFirebaseJWTAsync(serviceAccountJsonFilepath);
37+
// await Utils.SendNotificationViaFirebaseSDKAsync(serviceAccountJsonFilepath, fcmReceiverToken);
38+
3339
//await SendApnNotificationAsync();
3440
//await SendFcmNotificationAsync();
3541

@@ -60,16 +66,24 @@ private static async Task SendApnNotificationAsync()
6066

6167
private static async Task SendFcmNotificationAsync()
6268
{
63-
var settings = new FcmSettings
69+
var settings = new FirebaseSettings
6470
{
65-
SenderId = fcmSenderId,
66-
ServerKey = fcmServerKey
71+
GoogleProjectId = googleProjectId,
72+
FcmBearerToken = fcmBearerToken
6773
};
6874

69-
var fcm = new FcmSender(settings, http);
70-
var payload = new
75+
var fcm = new FirebaseSender(settings, http);
76+
var payload = new FirebasePayload
7177
{
72-
notification = new { body = "Hello World!" }
78+
Message = new FirebaseMessage
79+
{
80+
Token = fcmReceiverToken,
81+
Notification = new FirebaseNotification
82+
{
83+
Title = "Test",
84+
Body = "Test Body"
85+
}
86+
}
7387
};
7488

7589
var response = await fcm.SendAsync(payload);

CorePush.Tester/Utils.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Threading.Tasks;
2+
using FirebaseAdmin;
3+
using FirebaseAdmin.Messaging;
4+
using Google.Apis.Auth.OAuth2;
5+
6+
namespace CorePush.Tester;
7+
8+
public class Utils
9+
{
10+
public static async Task SendNotificationViaFirebaseSDKAsync(string pathToJsonServiceAccountFile, string token)
11+
{
12+
var credential = GoogleCredential.FromFile(pathToJsonServiceAccountFile);
13+
FirebaseApp.Create(new AppOptions {Credential = credential});
14+
15+
var message = new Message
16+
{
17+
Notification = new Notification
18+
{
19+
Title = "Hello!",
20+
Body = "World!"
21+
},
22+
Token = token,
23+
};
24+
var messaging = FirebaseMessaging.DefaultInstance;
25+
var result = await messaging.SendAsync(message);
26+
}
27+
28+
public static async Task GenerateFirebaseJWTAsync(string pathToJsonServiceAccountFile)
29+
{
30+
var credential = GoogleCredential.FromFile(pathToJsonServiceAccountFile);
31+
FirebaseApp.Create(new AppOptions {Credential = credential});
32+
33+
var jwt = await credential
34+
.CreateScoped("https://www.googleapis.com/auth/firebase.messaging")
35+
.UnderlyingCredential.GetAccessTokenForRequestAsync();
36+
}
37+
}

CorePush/CorePush.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net6.0</TargetFramework>
4+
<TargetFramework>net7.0</TargetFramework>
55
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
66

77
<Title>Server Side library for sending ✅Web, ✅Android and ✅iOS Push Notifications</Title>
@@ -10,8 +10,8 @@
1010
<Summary>Server Side library for sending ✅Web, ✅Android and ✅iOS Push Notifications</Summary>
1111
<Authors>andrei-m-code</Authors>
1212

13-
<AssemblyVersion>4.0.0-beta01</AssemblyVersion>
14-
<FileVersion>4.0.0-beta01</FileVersion>
13+
<AssemblyVersion>4.0.0</AssemblyVersion>
14+
<FileVersion>4.0.0</FileVersion>
1515
<Version>4.0.0-beta01</Version>
1616

1717
<PackageProjectUrl>https://github.com/andrei-m-code/CorePush</PackageProjectUrl>
@@ -26,7 +26,7 @@
2626

2727
<PackageReleaseNotes>
2828
v4.0.0
29-
- Use .NET 6.0 as a target framework
29+
- Use .NET 7.0 as a target framework
3030
- Use System.Text.Json as a default serializer
3131

3232
v3.1.x
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace CorePush.Firebase
2+
{
3+
public class FirebaseResponse
4+
{
5+
public string Name { get; set; }
6+
}
7+
}

CorePush/Google/FcmSender.cs renamed to CorePush/Firebase/FirebaseSender.cs

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,59 +7,58 @@
77
using CorePush.Interfaces;
88
using CorePush.Serialization;
99

10-
namespace CorePush.Google
10+
namespace CorePush.Firebase
1111
{
1212
/// <summary>
1313
/// Firebase message sender
1414
/// </summary>
15-
public class FcmSender : IFcmSender
15+
public class FirebaseSender : IFirebaseSender
1616
{
17-
// TODO: Migrate to the new API: https://firebase.google.com/docs/cloud-messaging/send-message
18-
private const string fcmUrl = "https://fcm.googleapis.com/fcm/send";
19-
20-
private readonly FcmSettings settings;
17+
private readonly FirebaseSettings settings;
2118
private readonly HttpClient http;
22-
private readonly Serialization.IJsonSerializer serializer;
19+
private readonly IJsonSerializer serializer;
2320

24-
public FcmSender(FcmSettings settings, HttpClient http) : this(settings, http, new DefaultJsonSerializer())
21+
public FirebaseSender(FirebaseSettings settings, HttpClient http) : this(settings, http, new DefaultJsonSerializer())
2522
{
23+
2624
}
2725

28-
public FcmSender(FcmSettings settings, HttpClient http, IJsonSerializer serializer)
26+
public FirebaseSender(FirebaseSettings settings, HttpClient http, IJsonSerializer serializer)
2927
{
30-
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
3128
this.http = http ?? throw new ArgumentNullException(nameof(http));
3229
this.serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
30+
this.settings = settings ?? throw new ArgumentNullException(nameof(settings));
3331

32+
if (string.IsNullOrWhiteSpace(settings.GoogleProjectId) ||
33+
string.IsNullOrWhiteSpace(settings.FcmBearerToken))
34+
{
35+
throw new ArgumentException("Some settings are not defined", nameof(settings));
36+
}
37+
3438
if (http.BaseAddress == null)
3539
{
36-
http.BaseAddress = new Uri(fcmUrl);
40+
var url = $"https://fcm.googleapis.com/v1/projects/{settings.GoogleProjectId}/messages:send";
41+
http.BaseAddress = new Uri(url);
3742
}
3843
}
3944

4045
/// <summary>
41-
/// Send firebase notification.
46+
/// Send firebase notification. Token must be present in order to send direct push notification.
4247
/// Please check out payload formats:
4348
/// https://firebase.google.com/docs/cloud-messaging/concept-options#notifications
44-
/// The SendAsync method will add/replace "to" value with deviceId
49+
/// https://firebase.google.com/docs/cloud-messaging/send-message
4550
/// </summary>
4651
/// <param name="payload">Notification payload that will be serialized using Newtonsoft.Json package</param>
4752
/// <param name="cancellationToken">Cancellation token</param>
4853
/// <exception cref="HttpRequestException">Throws exception when not successful</exception>
49-
public async Task<FcmResponse> SendAsync(object payload, CancellationToken cancellationToken = default)
54+
public async Task<FirebaseResponse> SendAsync(object payload, CancellationToken cancellationToken = default)
5055
{
5156
var json = serializer.Serialize(payload);
5257

5358
using var message = new HttpRequestMessage();
5459

5560
message.Method = HttpMethod.Post;
56-
message.Headers.Add("Authorization", $"key = {settings.ServerKey}");
57-
58-
if (!string.IsNullOrEmpty(settings.SenderId))
59-
{
60-
message.Headers.Add("Sender", $"id = {settings.SenderId}");
61-
}
62-
61+
message.Headers.Add("Authorization", $"Bearer {settings.FcmBearerToken}");
6362
message.Content = new StringContent(json, Encoding.UTF8, "application/json");
6463

6564
using var response = await http.SendAsync(message, cancellationToken);
@@ -70,7 +69,7 @@ public async Task<FcmResponse> SendAsync(object payload, CancellationToken cance
7069
throw new HttpRequestException("Firebase notification error: " + responseString);
7170
}
7271

73-
return serializer.Deserialize<FcmResponse>(responseString);
72+
return serializer.Deserialize<FirebaseResponse>(responseString);
7473
}
7574
}
7675
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace CorePush.Firebase
2+
{
3+
public class FirebaseSettings
4+
{
5+
/// <summary>
6+
/// Google Project ID. E.g. your-project-123456
7+
/// </summary>
8+
public string GoogleProjectId { get; set; }
9+
10+
/// <summary>
11+
/// FCM Service Account Bearer Token
12+
/// </summary>
13+
public string FcmBearerToken { get; set; }
14+
}
15+
}

CorePush/Google/FcmResponse.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.

CorePush/Google/FcmResult.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)