Giter Club home page Giter Club logo

node-pushnotifications's Introduction

Node Push Notifications

A node.js module for interfacing with Apple Push Notification, Google Cloud Messaging, Windows Push Notification, Web-Push Notification and Amazon Device Messaging services.

License NPM version Downloads node-pushnotifications CI Coverage Status Dependencies code style: prettier

Installation

npm install node-pushnotifications --save

Requirements

Node version >= 14.x.x

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.

import PushNotifications from 'node-pushnotifications';

const settings = {
    gcm: {
        id: 'your-GCM-id',
        phonegap: false, // phonegap compatibility mode, see below (defaults to false)
        ...
    },
    apn: {
        token: {
            key: './certs/key.p8', // optionally: fs.readFileSync('./certs/key.p8')
            keyId: 'ABCD',
            teamId: 'EFGH',
        },
        production: false // true for APN production environment, false for APN sandbox environment,
        ...
    },
    adm: {
        client_id: null,
        client_secret: null,
        ...
    },
    wns: {
        client_id: null,
        client_secret: null,
        notificationMethod: 'sendTileSquareBlock',
        ...
    },
    web: {
        vapidDetails: {
            subject: '< \'mailto\' Address or URL >',
            publicKey: '< URL Safe Base64 Encoded Public Key >',
            privateKey: '< URL Safe Base64 Encoded Private Key >',
        },
        gcmAPIKey: 'gcmkey',
        TTL: 2419200,
        contentEncoding: 'aes128gcm',
        headers: {}
    },
    isAlwaysUseFCM: false, // true all messages will be sent through node-gcm (which actually uses FCM)
};
const push = new PushNotifications(settings);
  • isAlwaysUseFCM: use node-gcm to send notifications to GCM (by default), iOS, ADM and WNS.

iOS: It is recommended 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

Registration id's should be defined as objects (or strings which is not recommended and should be used at your own risk, it is kept for backwards compatibility).

You can send to multiple devices, independently of platform, creating an array with different destination device IDs.

// Single destination
const registrationIds = 'INSERT_YOUR_DEVICE_ID';

// Multiple destinations
const registrationIds = [];
registrationIds.push('INSERT_YOUR_DEVICE_ID');
registrationIds.push('INSERT_OTHER_DEVICE_ID');

The PN.send() method later detects device type and therefore used push method, based on the id stucture. Check out the method PN.getPushMethodByRegId how this detection works.

Actually there are several different supported reg id's:

Object regId

It can be of 2 types:

  • Mobile regId:
{
  "id": "INSERT_YOUR_DEVICE_ID",
  "type": "apn"
}

Where type can be one of: 'apn', 'gcm', 'adm', 'wns', 'webPush'. The types are available as constants:

import { WEB, WNS, ADM, GCM, APN } from 'node-pushnotifications';

const regId = {
  id: 'INSERT_YOUR_DEVICE_ID',
  type: APN,
};

In case of webPush, id needs to be as defined below for Web subscription.

{
  "endpoint": "< Push Subscription URL >",
  "keys": {
    "p256dh": "< User Public Encryption Key >",
    "auth": "< User Auth Secret >"
  }
}

String regId (not recommended)

It is not recommended, as Apple stays that the reg id is of variable length, which makes difficult to identify if it is a APN regId or GCM regId.

  • regId.substring(0, 4) === 'http': 'wns'
  • /^(amzn[0-9]*.adm)/i.test(regId): 'adm'
  • (regId.length === 64 || regId.length === 160) && /^[a-fA-F0-9]+$/.test(regId): 'apn'
  • regId.length > 64: 'gcm'
  • otherwise: 'unknown' (the notification will not be sent)

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)
  • You are able to send to device groups or other custom recipients instead of using a list of device tokens (see node-gcm docs). Documentation can be found in the GCM section..

Example:

const data = { ...data, recipients };

3. Send the notification

Create a JSON object with a title and message and send the notification.

const data = {
    title: 'New push notification', // REQUIRED for Android
    topic: 'topic', // REQUIRED for iOS (apn and gcm)
    /* The topic of the notification. When using token-based authentication, specify the bundle ID of the app.
     * When using certificate-based authentication, the topic is usually your app's bundle ID.
     * More details can be found under https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns
     */
    body: 'Powered by AppFeel',
    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
    image: '', // gcm for android
    style: '', // gcm for android
    picture: '', // 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
    titleLocKey: '', // gcm, apn
    locArgs: undefined, // gcm, apn. Expected format: Stringified Array
    titleLocArgs: undefined, // gcm, apn. Expected format: Stringified Array
    retries: 1, // gcm, apn
    encoding: '', // apn
    badge: 2, // gcm for ios, apn
    sound: 'ping.aiff', // gcm, apn
    android_channel_id: '', // gcm - Android Channel ID
    notificationCount: 0, // fcm for android. badge can be used for both fcm and apn
    alert: { // apn, will take precedence over title and body
        title: 'title',
        body: 'body'
        // details: https://github.com/node-apn/node-apn/blob/master/doc/notification.markdown#convenience-setters
    },
    silent: false, // gcm, apn, will override badge, sound, alert and priority if set to true on iOS, will omit `notification` property and send as data-only on Android/GCM
    /*
     * A string is also accepted as a payload for alert
     * Your notification won't appear on ios if alert is empty object
     * If alert is an empty string the regular 'title' and 'body' will show in Notification
     */
    // alert: '',
    launchImage: '', // apn and gcm for ios
    action: '', // apn and gcm for ios
    category: '', // apn and gcm for ios
    // mdm: '', // apn and gcm for ios. Use this to send Mobile Device Management commands.
    // https://developer.apple.com/library/content/documentation/Miscellaneous/Reference/MobileDeviceManagementProtocolRef/3-MDM_Protocol/MDM_Protocol.html
    urlArgs: '', // apn and gcm for ios
    truncateAtWordEnd: true, // apn and gcm for ios
    mutableContent: 0, // apn
    threadId: '', // apn
    pushType: undefined, // apn. valid values are 'alert' and 'background' (https://github.com/parse-community/node-apn/blob/master/doc/notification.markdown#notificationpushtype)
    expiry: Math.floor(Date.now() / 1000) + 28 * 86400, // unit is seconds. if both expiry and timeToLive are given, expiry will take precedence
    timeToLive: 28 * 86400,
    headers: [], // wns
    launch: '', // wns
    duration: '', // wns
    consolidationKey: 'my notification', // ADM
};

// You can use it in node callback style
push.send(registrationIds, data, (err, result) => {
    if (err) {
        console.log(err);
    } else {
	    console.log(result);
    }
});

// Or you could use it as a promise:
push.send(registrationIds, data)
    .then((results) => { ... })
    .catch((err) => { ... });
  • err will be null if all went fine, otherwise will return the error from the respective provider module.
  • 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: new Error('unknown'), // If any, there will be an Error object here for depuration purposes (when possible it will come form source libraries aka apn, node-gcm)
            errorMsg: 'some error', // If any, will include the error message from the respective provider module
        }],
    },
    {
        method: 'apn',
        ... // Same structure here, except for message.orignalRegId
    },
    {
        method: 'wns',
        ... // Same structure here, except for message.orignalRegId
    },
    {
        method: 'adm',
        ... // Same structure here, except for message.orignalRegId
    },
    {
        method: 'webPush',
        ... // 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 data.custom === 'string') {
        custom = {
            message: data.custom,
        };
    } else if (typeof data.custom === 'object') {
        custom = Object.assign({}, data.custom);
    } else {
        custom = {
            data: data.custom,
        };
    }

    custom.title = custom.title || data.title;
    custom.message = custom.message || data.body;
    custom.sound = custom.sound || data.sound;
    custom.icon = custom.icon || data.icon;
    custom.msgcnt = custom.msgcnt || data.badge;
    if (opts.phonegap === true && data.contentAvailable) {
        custom['content-available'] = 1;
    }

    const message = new gcm.Message({ // See https://developers.google.com/cloud-messaging/http-server-ref#table5
        collapseKey: data.collapseKey,
        priority: data.priority === 'normal' ? data.priority : 'high',
        contentAvailable: data.contentAvailable || false,
        delayWhileIdle: data.delayWhileIdle || false, // Deprecated from Nov 15th 2016 (will be ignored)
        timeToLive: data.expiry - Math.floor(Date.now() / 1000) || data.timeToLive || 28 * 86400,
        restrictedPackageName: data.restrictedPackageName,
        dryRun: data.dryRun || false,
        data: data.custom,
        notification: {
            title: data.title, // Android, iOS (Watch)
            body: data.body, // Android, iOS
            icon: data.icon, // Android
            image: data.image, // Android
            style: data.style, // Android
            picture: data.picture, // Android
            sound: data.sound, // Android, iOS
            badge: data.badge, // iOS
            tag: data.tag, // Android
            color: data.color, // Android
            click_action: data.clickAction || data.category, // Android, iOS
            body_loc_key: data.locKey, // Android, iOS
            body_loc_args: data.locArgs, // Android, iOS
            title_loc_key: data.titleLocKey, // Android, iOS
            title_loc_args: data.titleLocArgs, // Android, iOS
	        android_channel_id: data.android_channel_id, // Android
        },
    }

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,
	image: undefined,
	style: undefined,
	picture: 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,
	android_channel_id: undefined
    }

In that way, they can be accessed in android in the following two ways:

    String title = extras.getString("title");
    title = title != null ? title : extras.getString("gcm.notification.title");

Silent push notifications

GCM supports silent push notifications which are not displayed to the user but only used to transmit data.

const silentPushData = {
    topic: 'yourTopic',
    silent: true,
    custom: {
        yourKey: 'yourValue',
        ...
    }
}

Internally, silent: true will tell node-gcm not to send the notification property and only send the custom property. If you don't specify silent: true then the push notifications will still be visible on the device. Note that this is nearly the same behavior as phoneGap: true and will set content-available to true.

Send to custom recipients (device groups or topics)

In order to override the default behaviour of sending the notifications to a list of device tokens, you can pass a recipients field with your desired recipients. Supported fields are to and condition as documented in the node-gcm docs.

Example:

const dataWithRecipientTo = { ...yourData, recipients: { to: 'topicName' } };
const dataWithRecipientCondition = { ...yourData, recipients: { condition: 'topicName' } };

push.send(registrationIds, dataWithRecipientTo)
    .then((results) => { ... })
    .catch((err) => { ... });

Be aware that the presence of a valid data.recipient field will take precendence over any Android device tokens passed with the registrationIds.

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: data.retries || -1,
    expiry: data.expiry || ((data.timeToLive || 28 * 86400) + Math.floor(Date.now() / 1000)),
    priority: data.priority === 'normal' ? 5 : 10,
    encoding: data.encoding,
    payload: data.custom || {},
    badge: data.silent === true ? undefined : data.badge,
    badge: data.sound === true ? undefined : data.sound,
    alert: data.sound === true ? undefined : data.alert || {
        title: data.title,
        body: data.body,
        'title-loc-key': data.titleLocKey,
        'title-loc-args': data.titleLocArgs,
        'loc-key': data.locKey,
        'loc-args': data.locArgs,
        'launch-image': data.launchImage,
        action: data.action,
    },
    topic: data.topic, // Required
    category: data.category || data.clickAction,
    contentAvailable: data.contentAvailable,
    mdm: data.mdm,
    urlArgs: data.urlArgs,
    truncateAtWordEnd: data.truncateAtWordEnd,
    collapseId: data.collapseKey,
    mutableContent: data.mutableContent || 0,
    threadId: data.threadId,
    pushType: data.pushType
}

data is the parameter in push.send(registrationIds, data)

Silent push notifications

iOS supports silent push notifications which are not displayed to the user but only used to transmit data.

Silent push notifications must not include sound, badge or alert and have normal priority.

By setting the silent property to true the values for sound, badge and alert will be overridden to undefined.

Priority will be overridden to normal.

const silentPushData = {
    topic: 'yourTopic',
    contentAvailable: true,
    silent: true,
    custom: {
        yourKey: 'yourValue',
        ...
    }
}

WNS

The following fields are used to create a WNS message:

const notificationMethod = settings.wns.notificationMethod;
const opts = Object.assign({}, settings.wns);
opts.headers = data.headers || opts.headers;
opts.launch = data.launch || opts.launch;
opts.duration = data.duration || opts.duration;

delete opts.notificationMethod;
delete data.headers;
delete data.launch;
delete data.duration;

wns[notificationMethod](regId, data, opts, (err, response) => { ... });

data is the parameter in push.send(registrationIds, data)

Note: Please keep in mind that if data.accessToken is supplied, each push notification will be sent after the previous one has been responded. This is because Microsoft may send a new accessToken in the response and it should be used in successive requests. This can slow down the whole process depending on the number of devices to send.

ADM

The following parameters are used to create an ADM message:

const data = Object.assign({}, _data); // _data is the data passed as method parameter
const consolidationKey = data.consolidationKey;
const expiry = data.expiry;
const timeToLive = data.timeToLive;

delete data.consolidationKey;
delete data.expiry;
delete data.timeToLive;

const ADMmesssage = {
  expiresAfter:
    expiry - Math.floor(Date.now() / 1000) || timeToLive || 28 * 86400,
  consolidationKey,
  data,
};

data is the parameter in push.send(registrationIds, data)

Web-Push

Data can be passed as a simple string payload. If you do not pass a string, the parameter value will be stringified beforehand. Settings are directly forwarded to webPush.sendNotification.

const payload = typeof data === 'string' ? data : JSON.stringify(data);
webPush.sendNotification(regId, payload, settings.web);

A working server example implementation can be found at https://github.com/alex-friedl/webpush-example/blob/master/server/index.js

Resources

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.

Made in Barcelona with <3 and Code

node-pushnotifications's People

Contributors

alex-friedl avatar appfeel avatar cjroth avatar davidschuette avatar dchymko avatar dependabot[bot] avatar dirkpostma avatar ieschalier avatar jannomeister avatar jaulz avatar jkblume avatar lukaszenegive avatar mhisham avatar miqmago avatar niranjan-unimity avatar orenkatz avatar orenkatz-lp avatar pushchris avatar r0b1n avatar rwoverdijk avatar shackpank avatar treble-snake avatar vedi avatar vitalyster avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

node-pushnotifications's Issues

Response is not clear

Hi,
The response output after the push sent is not clear especially for failure. Please see this output.

[{"method":"apn","success":1,"failure":1,"message":[{"regId":{"device":"token1"},"error":null},{"regId":"token2","error":{}}]}]

Error response getting {}

Gettin this for result in apn

[{"method":"apn","success":0,"failure":1,"message":[{"regId":"EHAUOOIERYYE18762131H27123H23FC312H12312312L3F12V32G1V","error":{}}]}]

if failure why errors coming an empty object?

Thank's

TypeError: this is not a typed array.

I am getting the following error message:

TypeError: this is not a typed array. when i attempt to do a push using the sample Nodejs code

Below is error log output:

at Function.from (native) at Object.<anonymous> (/Users/codehacker/Documents/projects/nodeProjects/barterfarm/node_modules/node-pushnotifications/node_modules/apn/lib/protocol/endpoint.js:17:31) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:311:12) at Module.require (module.js:366:17) at require (module.js:385:17) at Object.<anonymous> (/Users/codehacker/Documents/projects/nodeProjects/barterfarm/node_modules/node-pushnotifications/node_modules/apn/index.js:27:18) at Module._compile (module.js:435:26) at Object.Module._extensions..js (module.js:442:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:311:12) at Module.require (module.js:366:17) at require (module.js:385:17) at Object.<anonymous> (/Users/codehacker/Documents/projects/nodeProjects/barterfarm/node_modules/node-pushnotifications/lib/sendAPN.js:3:11)

Please assist with this, as soon as you can

GCM id regex test failed

My Android app received the following id

fKSayiCUo1U:APA91bEH4BU6JsmwFNQSrhw7twWFMKowIRY3AdMrmU0gmp-6-AR8qjHdq-xEYFRtRdVjJrEV8lMJ95dG8iWs0FNkcOofIdFHTUrSUdNOVnmUXDtMRp8zqjaf_H_Vxi71ezI9PmDiTlKM

The regex which is used for testing the push ID is too general. In this case it tries to send the notification via ADM not via GCM because the id contains AdM.

if (regId.substring(0, 4) === 'http') {
    regIdsWNS.push(regId);
} else if (/(amzn|adm)/i.test(regId)) {
    regIdsADM.push(regId); // ADM fails to deliver the notification
} else if (regId.length > 64) {
    regIdsGCM.push(regId); // it should be sent by GCM
} else if (regId.length === 64) {
    regIdsAPN.push(regId);
} else {
    regIdsUnk.push(regId);
}

Get newly updated Registration IDs for FCM along with other notification service providers

In android(GCM/FCM) as everybody knows the registration IDs will be updated every now and then by google server. To keep track of it and update them in our application server we should have to read the registration_id parameter inside results array, from the response and update it to the application server accordingly. We can know what's the old registration ID and what's the updated ID by matching the index of results array with that of the index of registration IDs array which we'll send. This is possible when we send only GCM IDs but it's not possible if I send GCM with other notification service providers, as the index of the request registration ID can not be matched with the response. There should be a field inside the message object specifying the old registration ID for GCM.

Wrong message on iOS Push Notification

You are passing title instead of message, when iOS Token is detected. This way, whenever I send a notification like: {title:"My App's name", message:"Information message"}, the device receives a notification alert like:

title: My App's name
message: My App's name

GCM does not send to Android 7.0 and above

I did the exact same thing for Android 6.0 and it works perfectly.
However, when I tried using Postman it gets the notification on all devices. Is there something I need to do on GCM or FCM for Android 7.0 and above to work?

Node v4.3.2 Error

Does not work in NODE version v4.3.2, Error below:

const CLIENT_PRELUDE = Buffer.from("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
                              ^

TypeError: this is not a typed array.
    at Function.from (native)
    at Object.<anonymous> (/home/bruno/projects/environment-config/node_modules/node-pushnotifications/node_modules/apn/lib/protocol/endpoint.js:17:31)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/home/bruno/projects/environment-config/node_modules/node-pushnotifications/node_modules/apn/index.js:27:18)
    at Module._compile (module.js:409:26)

WNS sendRaw: Error: The payload parameter must be the notification payload string.

When trying to send raw notifications using WNS the following error is returned:
Error: The payload parameter must be the notification payload string.

This is happening because in the sendWNS.js file the data being set across to WNS is using
Object.assign({}, _data) (line 49)
before it is sent over, this is fine for all other windows notification type apart from raw which expects a string of data rather than an object.

Not receiving push notifications on IOS device.

I had an issue whereby the Notification was sending through APNS, but that there was no sign of it appearing on my device.

I wanted to reference it here, as it may be valuable to someone in the future.

My issue was that I used the whole example data object from the push example in the docs

3. Create a JSON object with a title and message and send the notification.

What solved it was using the bare minimum in the data object like so.

data: {
    topic: "com.domain.myapp",
    title: 'Message Title',
    body: 'This is the message body',
    badge: 2,
    sound: 'default',
}

fs.readFileSync undefined

I get the following error
TypeError: fs.readFileSync is not a function. (In 'fs.readFileSync('/path/to/apn-key.p8', 'utf8')', 'fs.readFileSync' is undefined)

Importing fs does not seem to help, var fs=require('fs') also does not help.

Please help/advise.

getting error

I am getting this error:
"Cannot read property 'sendPush' of undefined".

Request you to please help me out in this.

results object only have method : 'gcm' when send apn

I configured my push server only with apn service like below:

const settings = {    
    apn: {
        token: {
            key: getAppleCertPath('path'),
            keyId: 'ABCD',
            teamId: 'EFGH',
        }
    }    
};

results object only return method: 'gcm' on the reply.
I don´t see apn info in it and I can´t understand why is sending 'gcm' when is not defined.

[ { method: 'gcm', // Only 
} ... ]

Thanks.

Apple Push notifications along with android

I have few queries,

If i merge apple push notifications inside android in an array will the lib be able to separate them?
I have tested the lib with google push and they work great. However i am having problem regarding apple push notification.

Firstly i have created PEM File without any password.
Here is the code that i am using

var settings = {
  gcm: {
    id: 'AIzaSyAiOx-8EsUbyT8PURircMaDxocYyaLQJiI', // PUT YOUR GCM SERVER API KEY,
    msgcnt: 1,
    dataDefaults: {
      delayWhileIdle: false,
      timeToLive: 3600,// 1hour   4 * 7 * 24 * 3600, // 4 weeks
      retries: 3,
    },
    // Custom GCM request options https://github.com/ToothlessGear/node-gcm#custom-gcm-request-options
    options: {},
  },  
  apn: {
    gateway: 'gateway.push.apple.com',
    badge: 1,
    defaultData: {
      expiry: 3600, // 4 weeks
    },
    // See all available options at https://github.com/argon/node-apn/blob/master/doc/connection.markdown
    options: {
        cert : "/var/www/html/test/Services/cert.pem"
    },
    // I.e., change .cert location file:
    // options: {
    //    cert: "/certs/ios/mycert.cert" // {Buffer|String} The filename of the connection certificate to load from disk, or a Buffer/String containing the certificate data. (Defaults to: cert.pem)
    // }
  }
};

There is no error message in the callback as if something is hanging out. The fs is able to read the cert at the said path.

Why there is no error? I Cant figure out where the problem could be. Secondly how can i set a password if i wish to add password protected pem.

Body not working for Android

{
title: 'This Shows, // REQUIRED
body: 'Uhhh should i show', // REQUIRED
topic: 'some_stuff'
}

That body doesn't show in the android notification.

App does not open on notification tap on Android.

Hi, I have an issue with Android, I can receive push notifications on Android and iOS, but when I tap on the notification on Android the app doesn't open. But it works on iOS.

It just close the status bar and clear the notification.

I'm using this options:
var data = {
title: title, // REQUIRED
body: msg, // REQUIRED
custom: {
sender: title,
},
priority: 'high',
collapseKey: title, // gcm for android, used as collapseId in apn
contentAvailable: true, // gcm for android
restrictedPackageName: 'com.package.name', // gcm for android
tag: title,
retries: 1, // gcm, apn
badge: 1, // gcm for ios, apn
sound: 'default', // gcm, apn
action: 'alert', // apn and gcm for ios
topic: 'com.package.name', // apn and gcm for ios
category: title, // apn and gcm for ios
contentAvailable: '', // apn and gcm for ios
expiry: Math.floor(Date.now() / 1000) + 28 * 86400,
timeToLive: 28 * 86400
};

GCM giving error with new push notification

I am getting this error whenever GCM is being used to send new push notification using new library updated yeseterday

{ method: 'gcm',
11|city    |   multicastId: [],
11|city    |   success: 0,
11|city    |   failure: 1,
11|city    |   message: 
11|city    |    [ { regId: 'APA91bG0Zvg_f8T6bv8XPIFFVRFN9_5IWUjYcPTw6aQcvzGRCXSwFWxAtLHLz42H08nGJeavSxASHeKTYPFXpvidZMw7T7Mp_EfYWKMeH3bHTtFzdjIiwfKdZ9TpQaowOjN6WC9_SVTY',
11|city    |        error: 
11|city    |         Error: Key 'tokens' is not a valid recipient key.
11|city    |             at extractRecipient (/var/www/html/test/node_modules/node-gcm/lib/sender.js:240:35)
11|city    |             at getRequestBody (/var/www/html/test/node_modules/node-gcm/lib/sender.js:189:16)
11|city    |             at Sender.sendNoRetry (/var/www/html/test/node_modules/node-gcm/lib/sender.js:132:5)
11|city    |             at Sender.send (/var/www/html/test/node_modules/node-gcm/lib/sender.js:26:21)
11|city    |             at Timeout._onTimeout (/var/www/html/test/node_modules/node-gcm/lib/sender.js:90:14)
11|city    |             at tryOnTimeout (timers.js:232:11)
11|city    |             at Timer.listOnTimeout (timers.js:202:5) } ] }

The token and the key is valid

Not sending notification in production anymore

const PushNotifications = new require('node-pushnotifications');
const push = new PushNotifications(settings);const settings = {

gcm: {
id: "3273568XXXXX"

},

apn: {
cert:path.join(__dirname ,'../', '/services/cert.pem'),
key:path.join(__dirname ,'../', '/services/key.pem')
}
};

const data = {
title: 'Hi', // REQUIRED
body: "Hey Kai!" // REQUIRED,
};
var registrationIds = ['07fc9f468bc0fd4b8e7d06abbc4fa688f22ac8573a7e8e6f87f951029bddb09c'];
push.send(registrationIds, data, function (err, result) {

console.log(result);
if (err) {
    console.log(err);
} else {
    console.log(result);
}

});

APNs not working in production

I'm using the apns key (.p8 file) and I thought it worked for both development and production environments. I'm also using GCM, and android pushes work just fine in both environments.

Would there be a reason why APNs would not work in production? Maybe I'm missing a step or two.

Any help would be greatly appreciated. Thanks!

How to send iOS 10 Rich Notifications?

Basically I want to know how to send the "mutable-content" = 1 in the APN, I tried sending it with custom, but no luck, there is no actual way to know what is exactly sending to Apple, right?

Possible EventEmitter memory leak detected

I get this warning:

(node:70543) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 wakeup listeners added. Use emitter.setMaxListeners() to increase limit

The warning comes from the APN Module: node-apn/node-apn#518

See someone else this error? Have someone a solution?

What about MPNS

The 3 others are well documented but what about Windows Phone ?
What are the options ?

How do I ignore adm (Amazon)

I removed the adm configuration and now it errors.
When I put in the default one it still errors.

How do I remove it?

Send failure for TestFlight apps

Hi,

I love the lib, which worked great until I tried testing in production.

Here are the steps I have done to get dev & prod certificates.

  1. Export the .cer for development =>apn_development.cer
  2. Export the .cer for production => apn_production.cer
  3. Export the .p12 for push notification push_cert.p12
  4. Convert both .cer to .pem => apn_development.pem & apn_production.pem
  5. Convert .p12 to .pem => push_cert.pem
  6. Test PN for development
    6.1. Get device token from RN package react-native-push-notification
    6.2. Setup NODE project and test
const settings = {
    apn: {
        cert: './certs/aps_development.pem',
        key: './certs/push_cert.pem',
        production: false
    },
}
const registrationIds = []
registrationIds.push('f43719b34e6c48d96ba6cb2055f30e673b474e103a2288d14f1045094c2e1d6d')
const push = new PushNotifications({title:"Test", body:"This is a test PN"})
push.send(registrationIds, customData)
    .then((results) => {
        res.send(JSON.stringify(results))
    })
    .catch((err) => {
        res.send(JSON.stringify(err))
    })

Which works fine.
7. Test PN for production
7.1. Put app on iTunes connect (TestFlight)
7.2. Plug-in iPhone on charger cable and open XCode -> Window -> Devices & Simulators
7.3. Install app through TestFlight and monitor logs for new device token
7.4. Use Pusher to confirm the device token and .p12 file for production. Here the log:

Connecting to APN...  (com.<project>.production)
Connected  (com.<project>.production)
Pushing..
Payload has been pushed

7.5. Change NODE project and test

const settings = {
    apn: {
        cert: './certs/aps_production.pem',
        key: './certs/push_cert.pem',
        production: true
    },
}
const registrationIds = []
registrationIds.push('e90356be05f7296006a5d30232b30a5b4dcf580b83254ee0e27cab0328f228cd')
const push = new PushNotifications({title:"Test", body:"This is a test PN"})
push.send(registrationIds, customData)
    .then((results) => {
        res.send(JSON.stringify(results))
    })
    .catch((err) => {
        res.send(JSON.stringify(err))
    })

Now I get an error [{"method":"apn","success":0,"failure":1,"message":[{"regId":"e90356be05f7296006a5d30232b30a5b4dcf580b83254ee0e27cab0328f228cd","error":{}}]}]
7.6. Try to connect with OpenSSL

openssl s_client -connect gateway.push.apple.com:2195 -cert aps_production.pem -key push_cert.pem
CONNECTED(00000003)
depth=2 O = Entrust.net, OU = www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU = (c) 1999 Entrust.net Limited, CN = Entrust.net Certification Authority (2048)
verify return:1
depth=1 C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2012 Entrust, Inc. - for authorized use only", CN = Entrust Certification Authority - L1K
verify return:1
depth=0 C = US, ST = California, L = Cupertino, O = Apple Inc., CN = gateway.push.apple.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.push.apple.com
   i:/C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2012 Entrust, Inc. - for authorized use only/CN=Entrust Certification Authority - L1K
 1 s:/C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2012 Entrust, Inc. - for authorized use only/CN=Entrust Certification Authority - L1K
   i:/O=Entrust.net/OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/OU=(c) 1999 Entrust.net Limited/CN=Entrust.net Certification Authority (2048)
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFQTCCBCmgAwIBAgIRALUO38 ...
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.push.apple.com
issuer=/C=US/O=Entrust, Inc./OU=See www.entrust.net/legal-terms/OU=(c) 2012 Entrust, Inc. - for authorized use only/CN=Entrust Certification Authority - L1K
---
Acceptable client certificate CA names
/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA
/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
/CN=Apple Application Integration 2 Certification Authority/OU=Apple Certification Authority/O=Apple Inc./C=US
/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
/C=US/ST=California/L=Cupertino/O=Apple Inc./CN=gateway.push.apple.com
/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Application Integration Certification Authority
Client Certificate Types: RSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA256:0x04+0x08:RSA+SHA256:ECDSA+SHA384:0x05+0x08:RSA+SHA384:0x06+0x08:RSA+SHA512:RSA+SHA1
Shared Requested Signature Algorithms: ECDSA+SHA256:RSA+SHA256:ECDSA+SHA384:RSA+SHA384:RSA+SHA512:RSA+SHA1
---
SSL handshake has read 3617 bytes and written 2447 bytes
---
New, TLSv1/SSLv3, Cipher is DES-CBC3-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : DES-CBC3-SHA
    Session-ID: 
    Session-ID-ctx: 
    Master-Key: CE0EB3415E5F3EC25AD66EDB57D148EF1F02E2740D6A4E35C5FA5DB12A2767669C7C809A5759ED05B3FFE8812D268B16
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1510283388
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---

That seemed to work. I can clearly see the certs work.

I wonder what else could be wrong?

Cheers,
Tom

Why does it keep living when all notifications sent?

When I send some notifications the push service seem to live on.
And when I call it again async a few times, it seems like I end up with more instances.

Am I supposed to feed the living service new device_tokens and messages in some way?

Wrong message on apn

For Ios:
when I try to send an apn notification with basic setup and basic data
title: "This is a title",
message: "This is the body",
otherfields: ''

I get this result:
{ device: 'ios', message: 'completed' }
Otherwise msg on device:
undefined Message: This is a title

APN errors not retrieved properly + doc update?

I had a hard time understanding why my iOS push notifications suddenly did not work, and went through multiple issues:

  • The topic property is now REQUIRED since node-apn changed the way to connect to APNs (thanks for the semver breaking BTW...)

  • To find the previous issue, I had to dig in the node-apn code to reveal the error, as node-pushnotifications did not show the error and only shows a successful promise with a failure count and no error message, even though the error message is return from node-apn. It seems that node-apn may have changed the way it returns errors, and the result is that we cannot see the underlying error when a notification sending fails.

It would be nice to fix the doc regarding the topic property and to investigate why error messages are not reported correctly.

[Question] Silent PN (SPN)

Hi there,

Is there a way to send silent push notifications with this library?

According to Apple (see below) the prop contentAvailable has to be set to 1 (i.e. contentAvailable: 1) for SPN to work but this doesn't have any effect.

Configuring a Silent Notification

The aps dictionary can also contain the content-available property. The content- available property with a value of 1 lets the remote notification act as a silent notification. When a silent notification arrives, iOS wakes up your app in the background so that you can get new data from your server or do background information processing. Users aren’t told about the new or changed information that results from a silent notification, but they can find out about it the next time they open your app.

For a silent notification, take care to ensure there is no alert, sound, or badge payload in the aps dictionary. If you don’t follow this guidance, the incorrectly-configured notification might be throttled and not delivered to the app in the background, and instead of being silent is displayed to the user

Error NotRegistered

Hi, I'm trying to use it but it gives error and say :
messageId: undefined,
regId: undefined,
error:
Error: NotRegistered
at /home/lt-101/sebas/api/node_modules/node-pushnotifications/lib/sendGCM.js:37:50
at Array.map (native)
at /home/lt-101/sebas/api/node_modules/node-pushnotifications/lib/sendGCM.js:33:47
at /home/lt-101/sebas/api/node_modules/node-gcm/lib/sender.js:47:24
at /home/lt-101/sebas/api/node_modules/node-gcm/lib/sender.js:211:14
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9) }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.