I have a nodeJS script set up to send APNs. When in development it always works but when i go to production they never get through. I tried taking the same notification Id it's sending and sending something using my production certificate in Easy Apn Provider and and it goes through. Im not sure why i could be failing. If my profile or certificates were wrong the easy apn wouldnt go through either?
apn config
var options = {
token: {
cert: "certificate.pem",
pfx: "Certificate.p12",
key: "AuthKey_XCVK62CSQF.p8",
keyId: "3Z6SEF7GE5",
teamId: "ASQJ3L7765"
},
production: true,
gateway: 'gateway.push.apple.com', // gateway address
port: 2195
};
var apnProvider = new apn.Provider(options);
Result of:
//IOS notif function
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);
})
}
is successfully sent message to 5D..
Edit:
When displaying my response i see that the notification actually failed with a 403 error (id doesnt exist however it works just fine with easy apn).
I assume its because im generating a non production id but i dont understand how thats possible. I signed my build and have it on testflight and ive removed all signes of development profiles and only have production profiles and certificates. Not sure how thiis is happening
The issue was that when i changed to production and it wasnt working I tried creating a new .p8 key. It was likely working at that point but i only changed the reference to .p8 and not the key parameter to the key of the .p8 found on my developer account. Once i updated that key all my problems were solved
Related
The Dapp sends Bep20 token from a remote wallet(My wallet) to users after they perform a certain activity such as accepting BNB to be sent to ICO, it works well on a desktop in which metamask is installed. The code that executes this is:
var amountTosend = amount;
var privateKey = 'PRIVATE_KEY';
var accountFrom = web3provider.eth.accounts.privateKeyToAccount(privateKey).address;
var contractCall = contractInstance.methods.transfer(addressTo, "0x"+amountTosend.toString(16));
var icoAccount = web3provider.eth.accounts.privateKeyToAccount(privateKey);
web3provider.eth.accounts.wallet.add(icoAccount);
contractCall.send({ from: accountFrom, gas: 2000000 }).then(function(hashdata) {
console.log(hashdata);
var rawTransaction = {
"from": accountFrom,
"nonce": nonce,
"gasPrice": 20000000000,
"gas": gas,
"to": SmartContractAddress,
"value": "0x" + amountTosend.toString(16),
"data": hashdata.events.Transfer.raw.data,
"chainId": chainid
};
var privKey = new ethereumjs.Buffer.Buffer(privateKey, 'hex');
let tx = new ethereumjs.Tx(rawTransaction);
tx.sign(privKey)
let serializedTx = tx.serialize();
console.log('serializedTx:', serializedTx);
web3provider.eth.sendSignedTransaction('0x' + serializedTx.toString('hex'), function(err, receipt) {
if (!err) {
console.log('success token sent to user: ' + receipt);
alert('You have received your Tokens in your Wallet');
} else {
console.log('error: ' + err);
alert("An error Occured: " + err);
}
});
})
On mobile wallets such as trust and metamask mobile connected with web3modal using wallet connect as provider, I successfully interacted with the wallet, prompt user to send BNB but
contractCall.send({ from: accountFrom, gas: 2000000 })
which is used to change the state of the smart contract to send user Bep20 token fails with Unknown account error after adding remote wallet to local using:
web3provider.eth.accounts.wallet.add(icoAccount);
Note: If I try skipping
contractCall.send({ from: accountFrom, gas: 2000000 })
and use contractCall.encodeABI() for data parameter, it works fine but no token is actually sent to the user and I guess is because the smart contact state needs to be changed/altered with
myContract.methods.myMethod([param1[, param2[, ...]]]).send
Please I need any useful help/tip to make this work on mobile wallet, I have been on this bug for a few days now, thanks
I finally fixed this error, and I will like to answer comprehensively for future visitors. The short answer will come first to implement the solution, and the long comprehensive answer afterward to help you understand better and learn the technicalities of fixing the bug
Note: I am using walletconnect and web3modal under the hood for my DAPP on Mobile browser and Metamask for Desktop and I'm using vanilla javascript for web3 implemenation
Short Answer:
I had to set givenProvider to the currentProvider which was initialized on web3 instance and that was my RPC URL provider, for me my RPC URL provider is: https://getblock.io/ which was passed in walletconnect/web3modal provider options paramater
I'm connecting to BSC so my RPC URL is: https://bsc.getblock.io/mainnet/?api_key=API_KEY
You may use other RPC URL providers of your choice
So the givenProvider is set like this:
web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;
read walletconnect docs on setting provider(s) here: https://docs.walletconnect.com/quick-start/dapps/web3-provider
Setting the web3.givenProvider to web3.currentProvider fixed the issue as web3.givenProvider was null
Long Answer:
You need to understand what is currentProvider and givenProvider are, as the bug resolves around the web3 provider.
In my understanding as of writting this answer givenProvider is the provider injected in an Ethereum enabled browser while currentProvider is the provider that you passed in on the initialization of web3.
The error is: Unknown account
This problem doesn't appear on a desktop browser where metamask is installed because injects the givenProvider, except of course is a remote account that doesn't exist on the provider node
You have to add the account to the provider node using:
var account= web3provider.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3provider.eth.accounts.wallet.add(account);
This solves the error on desktop browser without having to configure or set up much and that is because masks makes your browser Ethereum enabled and injects givenProvider
But for mobile browsers, you will face this issue because mobile browsers aren't Ethereum enabled environment. You will have to set givenProvider to a valid provider after initializing web3 through walletconenct.
Note: givenProvider talks to the blockchain through the web and it is null on mobile browsers. Console.log(web3) will show you the values of web3 instance
Putting all together your code should look like this:
import WalletConnectProvider from "#walletconnect/web3-provider";
import Web3 from "web3";
// Create WalletConnect Provider
const provider = new WalletConnectProvider({
rpc: {
1: "https://mainnet.mycustomnode.com",
3: "https://ropsten.mycustomnode.com",
100: "https://dai.poa.network",
// ...
},
});
await provider.enable();
// Create Web3 instance
const web3 = new Web3(provider);
//FIX STARTS HERE
//set givenProvider to currentProvider
web3.givenProvider = web3.currentProvider;
web3.eth.givenProvider = web3.currentProvider;
web3.eth.accounts.givenProvider = web3.currentProvider;
//add wallet to provider node
var account= web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY);
var addAccount = web3.eth.accounts.wallet.add(account);
var accountFrom = account.address;
var gas = contractCall.estimateGas({ from: accountFrom });
gas.then(function(gasTouse) {
contractCall.send({
from: accountFrom, gas: gasTouse }).then(function(hashdata){
console.log(hashdata);
});
});
Note: Be sure you estimate gas and include it, as without it you may encounter some gas-related errors.
Happy coding :)
I'm looking at implementing a login system in an Electron[0] application which I'm building but getting stuck on the part of handling the session. Basically I want to store the users session so it is persisted between application restarts (if "Remember me" is enabled).
I have to make use of an existing back-end which works with cookie authentication and I'm not able to change anything there.
From the Electron documentation on the Session object[1] I gathered that I should be using a partition like f.e. persist:someName in order to have a persistent storage, but this is not persisted between application restarts as it seems.
The way I currently set the cookie is as follows:
// main-process/login.js
const session = require('electron').session;
const currentSession = session.fromPartition('persist:someName').cookies;
currentSession.set({
name: 'myCookie',
url: 'https://www.example.com',
value: 'loggedin=1',
expirationDate: 1531036000
}, function(error) {
console.log('Cookie set');
if (error) {
console.dir(error);
}
});
After running this, I see the Cookie set output, but when restarting the app and running the following code:
// main.js
const session = require('electron').session;
const currentSession = session.fromPartition('persist:someName').cookies;
currentSession.get({}, function(error, cookies) {
console.dir(cookies);
if (error) {
console.dir(error);
}
});
The output returned is [].
Any pointers as to what I'm doing wrong or need to do differently would be highly appreciated!
[0] http://electron.atom.io
[1] http://electron.atom.io/docs/api/session/
An alternative might be to take a look at electron-json-storage. Using this plugin, you can write JSON to a system file throughout the user experience and then recall that file on the application load to replace the user "state".
First we set up our app in the fiware lab:
the code that we are using to create the app is on this site
The only thing we changed from that link is the config.js:
var config = {}
config.idmURL = 'https://account.lab.fiware.org/';
config.client_id = 'f9b5940d67a741a38039690e4d6e6c6f';
config.client_secret = 'c9f854c96c9e4c70a0d402bce3233a17';
config.callbackURL = 'http://panonit.com:8802/user_info';
// Depending on Grant Type:
// Authorization Code Grant: code
// Implicit Grant: token
config.response_type = 'code';
module.exports = config;
When deploying the node server we have the following site up and running (on a colleagues laptop):
You can see it for yourself between the hours of 09h and 18h CET.
After we click log in we are properly taken to the fiware site where the user can authenticate:
And this is where the site breaks (it says page unavailable):
To over come this issue we only changed the server.js to output only the response:
// Ask IDM for user info
app.get('/user_info', function(req, res){
var url = config.idmURL + '/user/';
// Using the access token asks the IDM for the user info
oa.get(url, req.session.access_token, function (e, response) {
//var user = JSON.parse(response);
var user = response;
console.log("Getting user response is: " + user)
//res.send("Welcome " + user.displayName + "<br> Your email address is " + user.email + "<br><br><button onclick='window.location.href=\"/logout\"'>Log out</button>");
res.send("Welcome " + user)
});
});
After doing this we have restarted the server. From here we once again pressed the log in and authenticated the app usage and instead of the site break we get:
here we have concluded that the response is an empty object because undefined is printed out.
What are we doing wrong here?
Checking it, the problem is that you are using a wrong callback URL. If you check the server.js, the path for the callback URL you are using is /user_info, and to use that, first you need the req.session.access_token that you retrieve at /login. Just change the callback url for:
config.callbackURL = 'http://panonit.com:8802/login';
And everything should work. Also remember to change it in your IdM app configuration!
yes, the issue is what albertinisg has pointed out. The callbackURL must be /login in order to get the code and from it retrieve the access token. Then with the access token you will be able to retrieve the user info.
BR
I am using realtime.co for realtime messaging in my .NET 4.5/Javascript webapp.
I created a connection using the code:
xRTML.ready(function () {
xRTML.Config.debug = true;
globalRealtimeConnectionId = generateUUID();
globalRealtimeToken = getRealtimeToken();
globalMyConnection = xRTML.ConnectionManager.create(
{
id: globalRealtimeConnectionId,
appkey: 'xxxx',
authToken: globalRealtimeToken, // insert token
url: 'http://ortc-developers.realtime.co/server/2.1'
});
globalMyConnection.bind(
{
// When we get a message, process it
message: function (e) {
var user = e.message; // the use that just joined
}
});
globalMyConnection.active = true;
});
On the server I gave permissions to "main:*" (all sub channels) and returned a token.
When I send a message to the user from the server using the following code:
OrtcClient client = (OrtcClient)Application["realtime"]; // get reference to client, which initialized in global.asax
client.Send(channel, user); // send message
user is a string with the username, channel is the channel name (e.g. main:12_323_34_. I get the following error in xrtml-custom-3.2.0-min.js:1
Uncaught TypeError: boolean is not a function xrtml-custom-3.2.0-min.js:1
c.Connection.process
(anonymous function)
f.proxy
IbtRealTimeSJ.d.sockjs.d.sockjs.onmessage
x.dispatchEvent
m._dispatchMessage
m._didMessage
m.websocket.d.ws.onmessage
From what I can tell, the client is subscribed because it triggers something when a message is sent to it from the server. But I can't understand the source of the error. Because of the error, the function binded to "message:" is not triggered.
For debugging purposes, if I were you, I would include the non-minified version so you can see exactly what function is causing the error. Once you've done that, it should be easier to track down.
One other quick note is when making RESTful calls you should try to do this in the back end so your api key is not exposed to the public. This would obviously only be an issue when you are creating a public facing website, so if this is an organizational (internal) application you can disregard.
I need to send iOS push notifications to user whenever a certain child is added to a Firebase path.
I was thinking, that the best way to do that, would be to make a Node.js worker on Heroku, that would listen for changes and send a notification using Urban Airship.
I'm not sure what the best way is to listen for changes on Firebase from a Node.js worker on Heroku is. I'm not that familiar with heroku workers and Node.js.
Can anyone give me some pointers? Examples?
Sending push notifications with Firebase and node-apn is easy:
var apn = require("apn");
var Firebase = require("firebase");
// true for production pipeline
var service = new apn.connection({ production: false });
// Create a reference to the push notification queue
var pushRef = new Firebase("<your-firebase>.firebaseio.com/notificationQueue");
// listen for items added to the queue
pushRef.on("child_added", function(snapshot) {
// This location expects a JSON object of:
// {
// "token": String - A user's device token
// "message": String - The message to send to the user
// }
var notificationData = snapshot.val();
sendNotification(notificationData);
snapshot.ref().remove();
});
function sendNotification(notificationData) {
var notification = new apn.notification();
// The default ping sound
notification.sound = "ping.aiff";
// Your custom message
notification.alert = notificationData.message;
// Send the notification to the specific device token
service.pushNotification(notification, [notificationData.token]);
// Clean up the connection
service.shutdown();
}
For hosting this script, you won't be able to use a PaaS like Heroku. They tend to kill idle sockets. Instead you'll have to use a virtual machine.
Google Cloud Platform has a Node.js launcher that works well.