APN Status '400,' How can I get more data about error? - ios

I'm using node-apn to send push notifications to my device. Whenever I try, I get the following:
{ sent: [],
failed:
[ { device: '****',
status: '400',
response: [Object] } ] }
I'm fairly certain my device token is correct. Is there any way to find out more info about why this error occurs. Is there info in the "response"—if so how do I get it? It would be helpful to get one of the error strings listed here (https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html) like "BadCollapseId"
Here is my node.js code for reference.
var deviceToken = "***";
var notification = new apn.Notification();
notification.topic = '*****';
notification.alert = "HI DER";
notification.payload = {id: 3};
apnProvider.send(notification, deviceToken).then(function(result) {
console.log(result);
});
The app is built using ionic 2, but I don't think that would make a difference.
Thanks!

Basically all I needed was this line:
console.log(result.failed);
instead of
console.log(result);
This gave me the code "DeviceTokenNotForTopic" and I was able to go from there!

Related

Fetch not working on react native when run on Expo from iphone

So it's actually been on and off the past few days, the fetch function for POST method (for login purposes) on my app would suddenly stop working when I'm not even making any changes to the code.
I spent hrs tracking down the bug the first time this happened but realized that the code is still running fine on Android simulator that I run from Android studio.
This problem only happens on my iphone device when I run the code via expo.
is there any sort of convention on how to tackle this issue?
I've been googling for a few days now but no one forum actually agreed on a solution, some works but says it's unstable and some just doesn't work.
I'm pretty new to expo, react native, and everything in general, so please enlighten me using "english" lol
EDIT: since I was asked about the code, here it is, I hope it helps:
export function login(user, callback){
var endpoint = "oauth/token";
const { username, password } = user;
//from https://scotch.io/tutorials/how-to-encode-and-decode-strings-with-base64-in-javascript
var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9+/=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}};
let header = {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": ("Basic " + Base64.encode(username+":"+password))
};
let userData = {
"grant_type": "password",
"username": username,
"password": password
};
return fetchAPI(endpoint,'POST', header, userData)
.then((tokenJson) => {
alert("\nAccess Token:\n\n" + tokenJson.access_token + "");
callback(true, {exists : true, token : tokenJson.access_token}, null);
})
.catch((error) => {
alert(error);
callback(false, null, error);
});
}
And here's the fetchAPI function (a generic fetch function) called from that function:
export function fetchAPI(endpoint, method, header, data) {
let url = 'http://10.64.2.149:8081/' + endpoint;
let options = {
method: method,
headers: header,
body: stringify(data) //from qs-stringify package
};
return fetch(url, options)
.then(response => {
return response.json()
.then((json) => { ...//not relevant from this point on
The fetch 'POST' seems to always get stuck at response.json(), it just never resolves until it returns "network request failed". But as I said only happens sometimes when I run it on iphone via expo. It is fine on Android sim.
Thanks! :)

Firebase Cloud functions - collapsible IOS notifications

I use cloud functions to send notifications. It works, but I want collapsible messages. How can I do it? Here is my current function:
exports.sendNotifications = functions.database
.ref("/users/{userId}/data")
.onWrite(event => {
const userId = event.params.userId;
if (!event.data.val()) {
return;
}
const payload = {
notification: {
title: `Hey`,
body: 'It's your turn!'
//icon: receiver.photoURL
}
};
const options = {
collapseKey: 'myturnkey'
};
return admin
.database()
.ref(`users\/${userId}\/data\/notificationkey`)
.once('value')
.then(data => {
console.log('inside key', data.val());
if (data.val()) {
return admin.messaging().sendToDevice(data.val(), payload, options);
}
});
});
I tried "collapseKey" and "collapse_key" in options but none of them works, I still receive notifications every time my function is called, so I get a list of notifications on my iphone whereas I want only one.
EDIT
I also tried the parameter "apns-collapse-id" according to the FCM messages documentation, but when when I try to deploy the functions the console says " apns-collapse-id: 'myturnkey', ^ SyntaxError: Unexpected token -"
Thank you,
Alexandre
You can do this, or manipulate current notifications in other ways, using the registration.getNotifications() API which gives you access to all the currently visible notifications for your web app.
But you need to write this code in your Service-worker
see this documention for merging-notifications

how to trigger push notifications of firebase from an ios device using swift3

I am new iOS developer.
I am using firebase and I am trying to make a chat application in which I need to notify user when he/she receives any message.
For this purpose I tried firebase push notifications, but couldn't be able to trigger them when other user send the message.
The only way I found is using firebase console to send push notification, but it doesn't fulfill my requirements.
I've just configured local notifications.
Please guide me how can we trigger push notifications without using the firebase console.
Finally found the solution after struggling for almost 1 month.
These are the basic steps
Firs off all you need to make sure that you have an active apple developers account
just enable firebase push notifications
here ie the link of youtube video for this step
Now your app is set up for firebase remote notifications but we can only trigger them from the firebase console so here is the tricky part. here is the link of video to enable firebase console on your mac
for the first time it will be good to see this video too because in this video they'll learn to write code in node.js and deploy it to the firebase.
Now if anyone wants to make an API instead of making a trigger then here is a code of API which sends the notification to other user by getting his FCM token from the firebase...
You can modify it according to your need
i am finding it difficult to post code in its exact form but the code starts from here
const functions = require('firebase-functions');
const admin =require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const ref=admin.database().ref();
exports.sendNotification=functions.https.onRequest((req,res) =>{
const id = req.query.id
const title = req.query.title
const message = req.query.message
const key = req.query.key
// admin.database.ref()
const payload ={
notification: {
title: title,
body: message,
//badge: '1',
sound: 'default',
}
};
console.log('Param [key] is '+key);
const keys = [] ;
ref.child('keys').once('value')
.then(snap => {
snap.forEach(childSnap => {
const loopKey=childSnap.val().key;
keys.push(loopKey);
})
return keys;
})
.then(keys=>{
//console.log('Keys in database : '+keys.join());
if(keys.indexOf(key)>-1)
{
if(!key || !id || !message)
{
res.status(400).send('Bad request');
}
else{
ref.child('users').child(id).child('fcmToken').once('value')
.then(snapshot => {
if (snapshot.val()){
const token = snapshot.val()
console.log(token);
return admin.messaging().sendToDevice(token,payload).then(response =>{
res.status(200).send('Notification sent')
});
}
});
}
}
else
{
console.log("In-valid key : "+key);
res.status(400).send('Bad request');
}
})
.catch(error => {
res.send(error)
});
});
ends at this point
this is the function to store your fcm to database
func postToken(token: String, id: String){
print("FCM Token \(token)")
let ref = Database.database().reference().child("users").child(id)
ref.child("fcmToken").setValue(token)
}
here is the function which i used to trigger this API
func sendNotification(id: String, title: String, message: String){
var url = "your URL"
var urlComponents = NSURLComponents(string: url)
urlComponents?.queryItems = [
URLQueryItem(name: "key", value: self.apiKey),
URLQueryItem(name: "id", value: id),
URLQueryItem(name: "title", value: title),
URLQueryItem(name: "message", value: message)
]
Alamofire.request((urlComponents?.url)!).responseJSON { (response) in
print(response.response)
print(response.response)
print(response.result)
}
}
the above API was written according to my database structure. you can change it easily for your own structure.
after doing this all you'll be able to send your notifications after hitting the URL
Hope it will give a nice idea to you people to work with your own notifications according to your need.
I was able to send Push Notifications from my code using PushNotificationSender class from this article -
https://www.iosapptemplates.com/blog/ios-development/push-notifications-firebase-swift-5

Not receiving back a delivery_receipt_notification from GCM CCS

I'm trying to get a receipt from CCS, but I'm just not able to.
Here is what I'm doing:
I have a go script:
package main
import (
"fmt"
"github.com/brunohenrique/go-gcm/ccs"
)
var (
user = struct {
gcmToken string
}{"mg0xe56LfjE:APA91bFHtHVQt85iNgyzTeDowovIGPAD_NbBjURppy1LgV9_oaM2R_9zn1fDXNuEeOoALTj7F8e8JmNPI3Md-CbbgTxdvxVrONFVfGz2dOujsaGkZjEhJcBH8sWvRNYZNIp2j2QliAEX"}
)
func main() {
con := connect()
// Sends a message
con.Send(&ccs.OutMsg{
To: user.gcmToken,
ID: "m-1366082849205",
Notification: map[string]interface{}{
"title": "Hey!",
"body": "There",
"sound": "default",
},
TimeToLive: 600,
DeliveryReceiptRequested: true,
DelayWhileIdle: true,
})
// Listen to messages
for {
m, err := con.Receive()
if err != nil {
fmt.Printf(">>> Err: %+v \n", err)
}
go func(m *ccs.InMsg) {
fmt.Printf(">>> InMsg: %+v \n", m)
}(m)
}
}
Everything seems alright when I run the script, but no receipt message back:
And this is what I'm doing when I get the notification:
Am I doing something wrong or missing something?
Thanks for trying out GCM on iOS.
Unfortunately, delivery receipts are not available for display notifications on iOS at the moment.
Not sure if you're trying this on Android or iOS, since it works for me on Android but it doesn't always work on iOS.
Delivery receipts for iOS do not work with the notification parameter in the request. I was able to get it to work for a plain data message i.e. with payload
{
"to" : <reg id>,
"data" : {
"hello" : "world",
"id" : 123
}
}
But if I added the notification payload to the above one it didn't work.
I would assume that since a notification payload message needs to be sent via APNS there is no way for them to know whether the message was delivered or not since APNS does not return any result.
For a no notification message since it's received only when the app is in the foreground they would be able to verify if the message was delivered or not.

Push Notification Not Arriving from Parse Cloud Code

I wrote a simple job to try sending a push notification to myself. Here's the code:
Parse.Cloud.job("testPush", function(request, status) {
Parse.Cloud.useMasterKey();
var installationQuery = new Parse.Query(Parse.Installation);
installationQuery.equalTo("user", "6t1JIuNqe1"); // I triple checked - this is the value of my user in the installation table.
Parse.Push.send({
where: installationQuery,
data: {
alert: "Test"
},
}, {
success: function() {
console.log("The Push Test Worked!");
status.success("All done with the push test!");
}, error: function(error) {
console.error("Something bad happened " + error);
status.error("Something bad happened during the Parse test...");
}
});
});
Although it logs in Parse that the job was run successfully, I never see a notification appear on my iPhone. I checked in Settings - it's all set up properly there (notifications are allowed to appear and should appear as banners, they should show up in notification center, they should show up on my lock screen). And yet the notification never appears.
What more do I need to check? What am I missing?
Pointer field should work with an instance.
Try replacing installationQuery.equalTo("user", "6t1JIuNqe1"); with the following:
var user = new Parse.User();
user.id = '6t1JIuNqe1';
installationQuery.equalTo('user', user);

Resources