push notification using node.js in ios app while develepment - ios

I am trying to send push notification from my app ,I have configured everything.After configuration i got cert.pem and key.pem. I have followed this https://blog.engineyard.com/2013/developing-ios-push-notifications-nodejs link . I am able to connect with apple server but not able to send the notification .can anyone help me what can be the issue as i have tried alot but did not get an appropriate solution for my problem. I am using the following code for communicating the apple server
Thanks in advance.
var http = require('http');
var apn = require('apn');
var url = require('url');
var myPhone = "f0e56d999e14ab0504b403efd39b90deb49306045b4ed698e33602abaa862111";
var myDevice = new apn.Device(myPhone);
var note = new apn.Notification();
note.badge = 1;
note.sound = "r.mp3";
note.alert = { "body" : "Your turn!", "action-loc-key" : "Play" , "launch-image" : ""};
note.payload = {'messageFrom': 'Holly'};
note.device = myDevice;
var callback = function(errorNum, notification){
console.log('Error is: %s', errorNum);
console.log("Note " + notification);
}
var options = {
gateway: 'gateway.sandbox.push.apple.com', // this URL is different for Apple's Production Servers and changes when you go to production
errorCallback: callback,
cert: __dirname+'/_certs/cert.pem',
key: __dirname+'/_certs/key.pem',
passphrase: null,
port: 2195,
enhanced: true,
cacheLength: 100
}
var apnsConnection = new apn.Connection(options);
apnsConnection.sendNotification(note);

Related

iOS Push Notification Error: {reason: 'TopicDisallowed'}

[Please read carefully before answering.]
I'm struggling to resolve notifications for more than a week and still, it's halfway resolved.
I'm using the production certificate.
It's working fine sometimes and suddenly starts throwing: { reason: 'TopicDisallowed' }
It's working perfectly fine on localhost.
It works fine sometimes on the server too (the issue is unstable). It automatically starts working and stops.
Here is the provider config:
const apn = require('apn'); // version: "apn": "^2.2.0"
const iosOptions = {
token: {
key: path.resolve('./lib/AuthK*********.p8'),
keyId: '*********',
teamId: '*******'
},
production: true
};
const apnProvider = new apn.Provider(iosOptions);
const apnNotification = new apn.Notification();
apnNotification.sound = 'default';
apnNotification.title = 'Hello';
apnNotification.body = 'Hello message';
apnNotification.aps.threadId = 'thread_id';
apnNotification.topic = topic;
apnNotification.payload = payload;
return apnProvider.send(apnNotification, token)
Is there anything wrong with the config?
Error message: reason: 'TopicDisallowed'
Please help if someone knows the solution.
Finally, I've resolved it by removing the package and writing a custom notification sender with Apple's official documentation for https://api.push.apple.com.
Here's more: https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html#//apple_ref/doc/uid/TP40008194-CH11-SW3

Can't receive Firebase data messages in background Xamarin.iOS app

I have setup firebase cloud messaging in my Xamarin iOS app successfully. When I send messages via the firebase console, everything works fine.
On my backend, I added Firebase admin SDK for dotnet, and tried sending "data" messages to my iOS app in this way:
FIrst, using normal messages to topics:
var iOSMsg = new Message()
{
Topic = iOSDemoUsersTopic,
Apns = new ApnsConfig
{
Headers = new Dictionary<string, string>
{
{ "priority", "high" }
},
Aps = new Aps
{
ContentAvailable = true,
MutableContent = true
}
},
Data = notificationData.ToDictionary(kv => kv.Key, kv => kv.Value.ToString())
};
var response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
This approach didn't work. Since I receive messages only when my app is open, when it goes I close it, notifications are not received anymore.
I then decided to try old Multicast messages, hopping it will work. I did as follows:
var msg = new MulticastMessage
{
Apns = new ApnsConfig
{
Headers = new Dictionary<string, string>
{
{ "priority", "high" }
},
Aps = new Aps
{
ContentAvailable = true,
MutableContent = true,
}
},
Data = notificationData.ToDictionary(kv => kv.Key, kv => kv.Value.ToString()),
Tokens = iOSTokens.ToList()
};
var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(msg);
But, the thing still behaves the same way.
On android, I can receive messages in background and when the app is killed when they are data messages. I have tried a million things, please can someone help ?
Finally, I found a solution.
My notifications where sent well, but when gotten by iOS, the alert object of aps was not found, so the OS couldn't display the notification.
To make this property available, the "Notification" property too should be set in the message.
var msg = new Message
{
Apns = new ApnsConfig
{
Aps = new Aps
{
ContentAvailable = true,
MutableContent = true,
}
},
Notification = new Notification
{
Body = body,
Title = title
},
Data = notificationData.ToDictionary(kv => kv.Key, kv => kv.Value.ToString()),
Topic = iOSDemoUsersTopic
};
So, after adding the notification property, everything went fine.

How to prepare APN for production

Im trying to deploy my app with notifications but it's giving me the biggest headache in the world. All other questions ive seen with regards to this seem outdated.
I set up APNs to be sent from a nodeJS script that I have running. When running in my sandbox everything was working well. As soon as I sent my app to TestFlight, notifications stopped sending. My script is still Successfully sending to the Notification Id registered with my phone but im assuming its not the correct production Id. If anyone canhelp get me sending production notifications it would be greatly appreciated! Thank you
APN Server code
var options = {
token: {
key: "AuthKey_6V27D43P5R.p8",
keyId: "3Z6SEF7GE5",
teamId: "ASQJ3L7765"
},
production: true
};
var apnProvider = new apn.Provider(options);
function SendIOSNotification(token, message, sound, payload, badge){
var deviceToken = token; //phone notification id
var notification = new apn.Notification(); //prepare notif
notification.topic = 'com.GL.Greek-Life'; // Specify your iOS app's Bundle ID (accessible within the project editor)
notification.expiry = Math.floor(Date.now() / 1000) + 3600; // Set expiration to 1 hour from now (in case device is offline)
notification.badge = badge; //selected badge
notification.sound = sound; //sound is configurable
notification.alert = message; //supports emoticon codes
notification.payload = {id: payload}; // Send any extra payload data with the notification which will be accessible to your app in didReceiveRemoteNotification
apnProvider.send(notification, deviceToken).then(function(result) { //send actual notifcation
// Check the result for any failed devices
var subToken = token.substring(0, 6);
console.log("Succesfully sent message to ", subToken);
}).catch( function (error) {
console.log("Faled to send message to ", subToken);
})
}

Send push notification to iOS device via Firebase (FCM) using HTTP Request after app is killed [duplicate]

This question already has answers here:
Can't send push notifications using the server API
(4 answers)
Closed 6 years ago.
I am having trouble sending push notifications via Firebase through HTTP Request to my iOS device after the app is killed. When the app is in the foreground or active in the background everything work as expected. But if I kill the app it won't work. I am able to send notifications to my app through the Firebase console if the app is killed, so I believe something must be wrong with the code I am using.
This is my code for sending the push notification:
private void SendPushNotification(string devicetoken, string header, string content, string pushdescription)
{
var textNotification = new
{
to = devicetoken,
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
priority = "high",
id = pushdescription,
},
project_id = "rrp-mobile",
};
var senderId = "212579566459";
var notificationJson = Newtonsoft.Json.JsonConvert.SerializeObject(textNotification);
using (var client = new WebClient())
{
client.Encoding = Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.Headers[HttpRequestHeader.Authorization] = "key=AIfrSyAtgsWCMH4s_bOyj-Us4CrdsifHv-GqElg";
client.Headers["Sender"] = $"id={senderId}";
client.Headers[HttpRequestHeader.ContentType] = "application/json";
client.UploadString("https://fcm.googleapis.com/fcm/send", "POST", notificationJson);
}
}
Am I forgetting something here? This works for sending push notifications to Android devices both in foreground, background and when app is killed, and like I said also to iOS devices in foreground and background.
The only issue is sending push notifications to iOS devices when the app has been killed. Does anyone have any idea as to how I would solve this issue?
I just realized my mistake, and it was very simple. I am posting this here because I believe this may be an easy thing to miss.
var textNotification = new
{
to = devicetoken,
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
**priority = "high",**
id = pushdescription,
},
project_id = "rrp-mobile",
};
You need to make sure that the priority property is defined outside the "notification" scope, like this:
var textNotification = new
{
to = devicetoken,
**priority = "high",**
notification = new
{
title = header,
text = content,
content_available = true,
sound = "enabled",
id = pushdescription,
},
project_id = "rrp-mobile",
};
This will make your push notifications deliver even if the app is killed.

Parse.Cloud.afterSave for sending push notifications not working from Heroku server

I did the migration, from Parse to Heroku and everything went smooth. At this point I didn't have any cloud code or push notifications set up on Parse. When I was done with the migration I begin to implement cloud code to handle push notification every time I save a new text message, but the Parse.Cloud.afterSave method is not running. I know main.js is working because if I implement
Parse.Cloud.define('hello', function(req, res) {
res.success('Hi');
});
I get "Hi" return to my console in Xcode, but for some reason Parse.Cloud.afterSave does nothing. I also know my Parse.Cloud.afterSave code is correct because it's that same code I use on another app through parse though. What am I missing?
Here in my index.js file
var express = require('express');
var ParseServer = require('parse-server').ParseServer;
var path = require('path');
var databaseUri = process.env.DATABASE_URI || process.env.MONGOLAB_URI;
if (!databaseUri) {
console.log('DATABASE_URI not specified, falling back to localhost.');
}
var api = new ParseServer({
databaseURI: databaseUri || '',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || '',
masterKey: process.env.MASTER_KEY || '',
fileKey: 'XXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX', // file key from parse
serverURL: process.env.SERVER_URL || '',
push: {
ios: {
pfx: '/Users/alexcruz/Desktop/Certificates.p12', // The filename of private key and certificate in PFX or PKCS12 format from disk
bundleId: 'com.daps.DapsPush', // The bundle identifier associate with your app
production: false // Specifies which environment to connect to: Production (if true) or Sandbox
}
}
});
var app = express();
// Serve static assets from the /public folder
app.use('/public', express.static(path.join(__dirname, '/public')));
// Serve the Parse API on the /parse URL prefix
var mountPath = process.env.PARSE_MOUNT || '/parse';
app.use(mountPath, api);
// Parse Server plays nicely with the rest of your web routes
app.get('/', function(req, res) {
res.status(200).send('Make sure to star the parse-server repo on GitHub!');
});
// There will be a test page available on the /test path of your server url
// Remove this before launching your app
app.get('/test', function(req, res) {
res.sendFile(path.join(__dirname, '/public/test.html'));
});
var port = process.env.PORT || 1337;
var httpServer = require('http').createServer(app);
httpServer.listen(port, function() {
console.log('parse-server-example running on port ' + port + '.');
});
// This will enable the Live Query real-time server
ParseServer.createLiveQueryServer(httpServer);
Here is my main.js file
//Push Notification for messages that are received
Parse.Cloud.afterSave("MXTMessage", function(request) {
var messageText = request.object.get('message');
var usersReceived = request.object.get('receiver');
var currentUser = Parse.User.current();
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.equalTo('user', usersReceived);
pushQuery.notEqualTo('user', currentUser);
Parse.Push.send({
where: pushQuery, // Set our Installation query
data: {
alert: "New message: " + messageText
}
}, {
success: function() {
// Push was successful
},
error: function(error) {
throw "Got an error " + error.code + " : " + error.message;
}
});
});
Thank you
As I am not allowed to comment, I'm going to have to put this in an answer, but just treat it as a comment:
Did you verify the function itself is actually never being called e.g. by adding a console.log at the beginning of the function, or could it be that push itself is not working (you can check that by sending pushes via REST API Calls)? For example, push seems to be broken in parse-server 2.2.0, I had to downgrade to 1.6.0 to get it working.
Workaround could be to create a cloud code function for sending the push and have this function explicitly called by the clients after the message has been saved on the server.
Also you should check this: https://github.com/ParsePlatform/parse-server/issues/301 as you are using Parse.User.current() in your code.
Also, I get the impression that parse-server is not really stable at this time. I experience many bugs using parse-server and Heroku that the app running on parse.com does not have.

Resources