Node Push Notifications
A node.js module for interfacing with Apple Push Notification, Google Cloud Messaging, Amazon Device Messaging services.
Installation
npm install node-pushnotifications --save
Features
- Powerful and intuitive.
- Multi platform push notifications.
- Automatically detects destination device type.
- Unified error handling.
- Written in ES6, compatible with ES5 through babel transpilation.
Usage
1. Import and setup push module:
Include the settings for each device type. You should only include the settings for the devices that you expect to have. I.e. if your app is only available for android or for ios, you should only include gcm
or apn
respectively.
const settings = gcm: id: null ... apn: token: key: './certs/key.p8' // optionally: fs.readFileSync('./certs/key.p8') keyId: 'ABCD' teamId: 'EFGH' ... adm: client_id: null client_secret: null ... ;const PushNotifications = ;const push = settings;
iOS: It is recomended to use provider authentication tokens. You need the .p8 certificate that you can obtain in your account membership. You should ask for an Apple Push Notification Authentication Key (Sandbox & Production) or Apple Push Notification service SSL (Sandbox & Production). However, you can also use certificates. See node-apn to see how to prepare cert.pem and key.pem.
2. Define destination device ID. You can send to multiple devices, independently of platform, creating an array with different destination device IDs.
// Single destinationconst registrationIds = 'INSERT_YOUR_DEVICE_ID'; // Multiple destinationsconst registrationIds = ;registrationIds;registrationIds;
Android: If you provide more than 1.000 registration tokens, they will automatically be splitted in 1.000 chunks (see this issue in gcm repo)
3. Create a JSON object with a title and message and send the notification.
Both title
and body
fields are required (or alert
for ios). The other fields are optional (see below how the message is created for each device type):
const data = title: 'New push notification' // REQUIRED body: 'Powered by AppFeel' // REQUIRED topic: '' // REQUIRED for apn and gcm for ios custom: sender: 'AppFeel' priority: 'high' // gcm, apn. Supported values are 'high' or 'normal' (gcm). Will be translated to 10 and 5 for apn. Defaults to 'high' collapseKey: '' // gcm for android, used as collapseId in apn contentAvailable: true // gcm, apn. node-apn will translate true to 1 as required by apn. delayWhileIdle: true // gcm for android restrictedPackageName: '' // gcm for android dryRun: false // gcm for android icon: '' // gcm for android tag: '' // gcm for android color: '' // gcm for android clickAction: '' // gcm for android. In ios, category will be used if not supplied locKey: '' // gcm, apn bodyLocArgs: '' // gcm, apn titleLocKey: '' // gcm, apn titleLocArgs: '' // gcm, apn retries: 1 // gcm, apn encoding: '' // apn badge: 2 // gcm for ios, apn sound: 'ping.aiff' // gcm, apn alert: {} // apn, will take precedence over title and body // alert: '', // It is also accepted a text message in alert titleLocKey: '' // apn and gcm for ios titleLocArgs: '' // apn and gcm for ios launchImage: '' // apn and gcm for ios action: '' // apn and gcm for ios category: '' // apn and gcm for ios mdm: '' // apn and gcm for ios urlArgs: '' // apn and gcm for ios truncateAtWordEnd: true // apn and gcm for ios mutableContent: 0 // apn threadId: '' // apn expiry: Math + 28 * 86400 // seconds timeToLive: 28 * 86400 // if both expiry and timeToLive are given, expiry will take precedency consolidationKey: 'my notification' // ADM; // You can use it in node callback stylepush; // Or you could use it as a promise:push ;
err
will be null if all went fine, will return the error otherwise.result
will contain an array with the following objects (one object for each device type found in device registration id's):
method: 'gcm' // The method used send notifications and which this info is related to multicastId: // (only Android) Array with unique ID (number) identifying the multicast message, one identifier for each chunk of 1.000 notifications) success: 0 // Number of notifications that have been successfully sent. It does not mean that the notification has been deliveried. failure: 0 // Number of notifications that have been failed to be send. message: messageId: '' // (only for android) String specifying a unique ID for each successfully processed message or undefined if error regId: value // The current registrationId (device token id). Beware: For Android this may change if Google invalidates the previous device token. Use "originalRegId" if you are interested in when this changed occurs. originalRegId: value // (only for android) The registrationId that was sent to the push.send() method. Compare this with field "regId" in order to know when the original registrationId (device token id) gets changed. error: 'unknown' // If any, there will be an Error object here method: 'apn' ... // Same structure here, except for message.orignalRegId method: 'adm' ... // Same structure here, except for message.orignalRegId
GCM
NOTE: If you provide more than 1.000 registration tokens, they will automatically be splitted in 1.000 chunks (see this issue in gcm repo)
The following parameters are used to create a GCM message. See https://developers.google.com/cloud-messaging/http-server-ref#table5 for more info:
// Set default custom data from data let custom; if typeof datacustom === 'string' custom = message: datacustom ; else if typeof datacustom === 'object' custom = Object; else custom = data: datacustom ; customtitle = customtitle || datatitle || ''; custommessage = custommessage || databody || ''; customsound = customsound || datasound || undefined; customicon = customicon || dataicon || undefined; custommsgcnt = custommsgcnt || databadge || undefined; if optsphonegap === true && datacontentAvailable custom'content-available' = 1; const message = // See https://developers.google.com/cloud-messaging/http-server-ref#table5 collapseKey: datacollapseKey priority: datapriority === 'normal' ? datapriority : 'high' contentAvailable: datacontentAvailable || false delayWhileIdle: datadelayWhileIdle || false // Deprecated from Nov 15th 2016 (will be ignored) timeToLive: dataexpiry - Math || datatimeToLive || 28 * 86400 restrictedPackageName: datarestrictedPackageName dryRun: datadryRun || false data: datacustom notification: title: datatitle // Android, iOS (Watch) body: databody // Android, iOS icon: dataicon // Android sound: datasound // Android, iOS badge: databadge // iOS tag: datatag // Android color: datacolor // Android click_action: dataclickAction || datacategory // Android, iOS body_loc_key: datalocKey // Android, iOS body_loc_args: datalocArgs // Android, iOS title_loc_key: datatitleLocKey // Android, iOS title_loc_args: datatitleLocArgs // Android, iOS
data is the parameter in push.send(registrationIds, data)
Note: parameters are duplicated in data and in notification, so in fact they are being send as:
data: title: 'title' message: 'body' sound: 'mySound.aiff' icon: undefined msgcnt: undefined // Any custom data sender: 'appfeel-test' notification: title: 'title' body: 'body' icon: undefined sound: 'mySound.aiff' badge: undefined tag: undefined color: undefined click_action: undefined body_loc_key: undefined body_loc_args: undefined title_loc_key: undefined title_loc_args: undefined
In that way, they can be accessed in android in the following two ways:
String title = extras.; title = title != null ? title : extras.;
PhoneGap compatibility mode
In case your app is written with Cordova / Ionic and you are using the PhoneGap PushPlugin,
you can use the phonegap
setting in order to adapt to the recommended behaviour described in
https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/PAYLOAD.md#android-behaviour.
const settings = gcm: id: '<yourId>' phonegap: true
APN
The following parameters are used to create an APN message:
retryLimit: dataretries || -1 expiry: dataexpiry || datatimeToLive || 28 * 86400 + Math priority: datapriority === 'normal' ? 5 : 10 encoding: dataencoding payload: datacustom || {} badge: databadge sound: datasound || 'ping.aiff' alert: dataalert || title: datatitle body: databody 'title-loc-key': datatitleLocKey 'title-loc-args': datatitleLocArgs 'loc-key': datalocKey 'loc-args': datalocArgs 'launch-image': datalaunchImage action: dataaction topic: datatopic // Required category: datacategory || dataclickAction contentAvailable: datacontentAvailable mdm: datamdm urlArgs: dataurlArgs truncateAtWordEnd: datatruncateAtWordEnd collapseId: datacollapseKey mutableContent: datamutableContent || 0
data is the parameter in push.send(registrationIds, data)
- See node-apn fields
- Please note that
topic
is required (see node-apn docs)
ADM
The following parameters are used to create an ADM message:
const data = Object; // _data is the data passed as method parameterconst consolidationKey = dataconsolidationKey;const expiry = dataexpiry;const timeToLive = datatimeToLive; delete dataconsolidationKey;delete dataexpiry;delete datatimeToLive; const ADMmesssage = expiresAfter: expiry - Math || timeToLive || 28 * 86400 consolidationKey data;
data is the parameter in push.send(registrationIds, data)
Resources
- Crossplatform integration example using this library and a React Native app
- Node Push Notify from alexlds
LICENSE
The MIT License (MIT)
Copyright (c) 2016 AppFeel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.