notification-services
Version:
Use email, sms and custom notification services for node.js application easily
340 lines (280 loc) • 8.07 kB
Markdown
# FCM v1 API Migration Guide
This guide helps you migrate from the legacy FCM API to the new FCM v1 API with OAuth2 authentication.
## Overview
The new FCM v1 API provides:
- OAuth2 authentication using service account credentials
- More structured message format
- Better platform-specific targeting
- Enhanced security
## Prerequisites
1. **Firebase Project Setup**
- Create or use an existing Firebase project
- Enable Firebase Cloud Messaging
2. **Service Account Credentials**
- Go to Firebase Console → Project Settings → Service Accounts
- Generate a new private key (JSON file)
- Keep this file secure and never commit it to version control
3. **Install Dependencies**
```bash
npm install google-auth-library
```
## Quick Start
### 1. Configuration
```typescript
import { fcmConfig, fcmSendToToken } from 'notification-services';
// Option 1: Using service account key file path
const fcm = fcmConfig({
projectId: 'your-project-id',
serviceAccountKey: './path/to/service-account-key.json'
});
// Option 2: Using service account key object (for environment variables)
const fcm = fcmConfig({
projectId: 'your-project-id',
serviceAccountKey: {
type: "service_account",
project_id: "your-project-id",
private_key_id: process.env.FCM_PRIVATE_KEY_ID,
private_key: process.env.FCM_PRIVATE_KEY?.replace(/\\n/g, '\n'),
client_email: process.env.FCM_CLIENT_EMAIL,
client_id: process.env.FCM_CLIENT_ID,
auth_uri: "https://accounts.google.com/o/oauth2/auth",
token_uri: "https://oauth2.googleapis.com/token",
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
client_x509_cert_url: process.env.FCM_CLIENT_CERT_URL
}
});
```
### 2. Basic Usage
```typescript
async function sendPushNotification(data: { [key: string]: string }, gcmToken: string) {
const message = {
data: data,
webpush: {
fcm_options: {
link: "/"
},
notification: {
title: data['title'],
body: data['message'],
image: data['image'] || '',
icon: '/icon.png',
},
}
};
try {
const result = await fcmSendToToken(gcmToken, message);
return result;
} catch (error) {
console.error('FCM Error:', error);
return false;
}
}
// Usage
const data = {
title: 'Hello World',
message: 'This is a test notification',
image: 'https://example.com/image.jpg'
};
const result = await sendPushNotification(data, 'user-device-token');
```
## Advanced Usage
### Platform-Specific Configurations
```typescript
const message = {
notification: {
title: 'Cross-platform title',
body: 'Cross-platform body'
},
// Android specific
android: {
priority: 'high',
notification: {
title: 'Android title',
body: 'Android body',
icon: 'notification_icon',
color: '#ff0000',
sound: 'default',
channel_id: 'default_channel'
}
},
// iOS specific
apns: {
payload: {
aps: {
alert: {
title: 'iOS title',
body: 'iOS body'
},
badge: 1,
sound: 'default'
}
}
},
// Web specific
webpush: {
notification: {
title: 'Web title',
body: 'Web body',
icon: '/icon-192x192.png',
requireInteraction: true
},
fcm_options: {
link: '/notification-page'
}
}
};
await fcmSendToToken('device-token', message);
```
### Send to Multiple Devices
```typescript
import { fcmSendMulticast } from 'notification-services';
const tokens = ['token1', 'token2', 'token3'];
const message = {
notification: {
title: 'Broadcast',
body: 'Message to multiple devices'
}
};
const result = await fcmSendMulticast(tokens, message);
console.log(`Success: ${result.successCount}, Failed: ${result.failureCount}`);
```
### Send to Topic
```typescript
import { fcmSendToTopic } from 'notification-services';
const message = {
notification: {
title: 'Topic News',
body: 'Latest news update'
}
};
await fcmSendToTopic('news', message);
```
### Send to Condition
```typescript
import { fcmSendToCondition } from 'notification-services';
// Send to users subscribed to 'news' OR 'weather' topics
const condition = "'news' in topics || 'weather' in topics";
const message = {
notification: {
title: 'Conditional Message',
body: 'Based on topic subscription'
}
};
await fcmSendToCondition(condition, message);
```
## Error Handling
```typescript
const result = await fcmSendToToken(token, message);
if (result.error) {
const { code, message, status } = result.error;
switch (status) {
case 'NOT_FOUND':
// Token is invalid, remove from database
console.log('Invalid token, removing from database');
break;
case 'INVALID_ARGUMENT':
// Message format is invalid
console.log('Invalid message format');
break;
case 'UNREGISTERED':
// App was uninstalled
console.log('App uninstalled, removing token');
break;
default:
console.log('Other error:', message);
}
} else {
// Success
console.log('Message sent successfully:', result.name);
}
```
## Migration from Legacy API
### Before (Legacy API)
```typescript
import { sendCustomNotification } from 'notification-services';
sendCustomNotification({
serverKey: 'legacy-server-key',
title: 'Hello',
text: 'World',
fcm_tokens: ['token1', 'token2']
}, (response, error) => {
if (error) {
console.error(error);
} else {
console.log(response);
}
});
```
### After (FCM v1 API)
```typescript
import { fcmConfig, fcmSendMulticast } from 'notification-services';
// Configure once
fcmConfig({
projectId: 'your-project-id',
serviceAccountKey: './service-account-key.json'
});
// Send messages
const result = await fcmSendMulticast(['token1', 'token2'], {
notification: {
title: 'Hello',
body: 'World'
}
});
```
## Environment Variables Setup
Create a `.env` file:
```env
FCM_PROJECT_ID=your-project-id
FCM_PRIVATE_KEY_ID=key-id
FCM_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
FCM_CLIENT_EMAIL=firebase-adminsdk-xxxxx@your-project-id.iam.gserviceaccount.com
FCM_CLIENT_ID=123456789
FCM_CLIENT_CERT_URL=https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-xxxxx%40your-project-id.iam.gserviceaccount.com
```
Then use in your code:
```typescript
fcmConfig({
projectId: process.env.FCM_PROJECT_ID!,
serviceAccountKey: {
type: "service_account",
project_id: process.env.FCM_PROJECT_ID!,
private_key_id: process.env.FCM_PRIVATE_KEY_ID!,
private_key: process.env.FCM_PRIVATE_KEY!.replace(/\\n/g, '\n'),
client_email: process.env.FCM_CLIENT_EMAIL!,
client_id: process.env.FCM_CLIENT_ID!,
auth_uri: "https://accounts.google.com/o/oauth2/auth",
token_uri: "https://oauth2.googleapis.com/token",
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
client_x509_cert_url: process.env.FCM_CLIENT_CERT_URL!
}
});
```
## TypeScript Support
The library includes full TypeScript support with comprehensive type definitions:
```typescript
import type {
FCMMessage,
FCMResponse,
FCMConfig,
FCMAndroidConfig,
FCMWebpushConfig,
FCMApnsConfig
} from 'notification-services';
const message: FCMMessage = {
notification: {
title: 'Typed Message',
body: 'With full type safety'
}
};
```
## Best Practices
1. **Security**: Never expose service account keys in client-side code
2. **Caching**: Auth tokens are automatically cached for performance
3. **Error Handling**: Always handle FCM errors appropriately
4. **Token Management**: Remove invalid tokens from your database
5. **Testing**: Use `validateOnly: true` to test messages without sending
## Support
For issues and questions:
- Check the [GitHub repository](https://github.com/arachnomesh/Arach-Notify)
- Review the [examples directory](../examples/fcm-v1-usage.ts)
- Consult the [Firebase documentation](https://firebase.google.com/docs/cloud-messaging)