fcm web push notification- not opening url (using click_action) - firebase

As mentioned in the title, I am unable to redirect to a url upon click on the notification. here's my code.
// Index.php
<html>
<meta charset="utf-8"/>
<title>Firebase Messaging </title>
<link rel="manifest" href="manifest.json">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<style>
div {
margin-bottom: 15px;
}
</style>
<body>
<div id="token"></div>
<div id="msg"></div>
<div id="notis"></div>
<div id="err"></div>
<script src="https://www.gstatic.com/firebasejs/4.6.2/firebase.js"></script>
<script>
MsgElem = document.getElementById("msg")
TokenElem = document.getElementById("token")
NotisElem = document.getElementById("notis")
ErrElem = document.getElementById("err")
var config = {
//some PRIVATE value
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
messaging
.requestPermission()
.then(function () {
console.log("Notification permission granted.");
return messaging.getToken()
})
.then(function(token) {
sendToken(token);
setTokenSentToServer(true);
})
.catch(function (err) {
ErrElem.innerHTML = ErrElem.innerHTML + "; " + err
console.log("Unable to get permission to notify.", err);
});
messaging.onMessage(function(payload) {
console.log("Message received. ", payload);
notificationTitle = payload.data.title;
notificationOptions = {
body: payload.data.body,
icon: payload.data.icon,
click_action: payload.data.url,
};
var notification= new
Notification(notificationTitle,notificationOptions);
});
function setTokenSentToServer(sent)
{
window.localStorage.setItem('sentToServer', sent ? 1 : 0);
}
//this is ajax to send token to send.php
function sendToken(token)
{
$.ajax({
url: 'action.php',
method: 'POST',
data: 'tokens=' + token,
}).done(function(result){
console.log(result);
})
}
</script>
</body>
</html>
here's the next page, where i am using cookies to store the token and use it on next page.
<?php
if(isset($_POST['tokens']))
{ if(isset($_COOKIE["tokens"]))
{$tokens=$_POST['tokens'];
}
else
{
$tokens=$_POST['tokens'];
setcookie("tokens", $tokens, time() + (86400 * 30), "/");
}
}
header("Location: send.php");
?>
then the token is processed on send.php most likely with
<?php
$tokens= array($_COOKIE["tokens"]);
$msg=[
'title'=>'Title',
'body'=>'description.',
'icon'=>'logo.jpg',
'url'=>"https://google.com"
];
$payload=[
'registration_ids'=>$tokens,
'data'=>$msg
];
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://fcm.googleapis.com/fcm/send",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS =>json_encode($payload),
CURLOPT_HTTPHEADER => array(
"authorization: key=/*the key*/",
"cache-control: no-cache",
"content-type: application/json",
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
}
else
echo $response;
?>
and finally the service worker,
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.9.0/firebase-
messaging.js');
// Initialize the Firebase app in the service worker by passing in the
// messagingSenderId.
firebase.initializeApp({
'messagingSenderId': 'MY_SENDER_ID'
});
// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
console.log('[firebase-messaging-sw.js] Received background message ',payload);
// Customize notification here
const notificationTitle = payload.data.title;
const notificationOptions = {
body: payload.data.body,
icon: payload.data.icon,
click_action: payload.data.url,
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
The notification is coming very well, but whenever i click on it, it doesn't redirect. can anyone help me out with this code please.
thanks in advance.

Related

Next Js File Attachments in Contact Forms

I'm trying to upload a file to my server to send in the contact form and then have the file delete itself once sent. I've made a start with my code by using multer and I've followed a few guides that were using express to handle the api but I want to use the Next js api provided. I just can not seem to get this file to upload.
I've commented out the nodemailer call so it doesn't send an email every time I test it but, here is my current code.
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import nodemailer from "nodemailer";
import multer from "multer";
export default async function handler(req, res) {
let Storage = multer.diskStorage({
destination: (req, file, callback) => {
callback(null, "../../files");
},
filename: (req, file, callback) => {
console.log(file);
callback(
null,
file.fieldname + "_" + Date.now() + "_" + file.originalname
);
},
});
let upload = multer({
storage: Storage,
}).single("careerCV");
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.end("something went wrong");
} else {
var {
careerName,
careerEmail,
careerMessage,
careerTelephone,
careerBadge,
careerCV,
} = req.body;
console.log(careerName);
console.log(careerEmail);
console.log(careerMessage);
console.log(careerTelephone);
console.log(careerBadge);
console.log(careerCV);
}
});
// const {
// careerName,
// careerEmail,
// careerMessage,
// careerTelephone,
// careerBadge,
// careerCV,
// } = req.body;
// const transporter = nodemailer.createTransport({
// host: "smtp.gmail.com",
// port: 465,
// secure: true,
// auth: {
// user: process.env.user,
// pass: process.env.pass,
// },
// });
// try {
// const emailRes = await transporter.sendMail({
// from: `${careerName} <${careerEmail}>`,
// replyTo: `${careerName} <${careerEmail}>`,
// to: "deanparkim1987#gmail.com",
// subject: `Career Form Submission from ${careerName}`,
// html: `<p>You have a new Career form submission</p><br>
// <p><strong>Name: </strong> ${careerName}</p><br>
// <p><strong>Email: </strong> ${careerEmail}</p><br>
// <p><strong>Phone Number: </strong> ${careerTelephone}</p><br>
// <p><strong>Badge Number: </strong> ${careerBadge}</p><br>
// <p><strong>Message: </strong> ${careerMessage}</p>`,
// attachments: careerCV,
// });
// console.log("Message sent: %s", emailRes.messageId);
// } catch (error) {
// console.error(error);
// }
console.log(req.body);
res.status(200).json(req.body);
}

How to fetch credential for azure cognitive speech services

I have created a Speech Cognitive services on Azure portal and I would like to follow this guideline. somewhere in the mentioned guideline there is something like the following:
fetch('https://webchat-mockbot.azurewebsites.net/speechservices/token', { method: 'POST' }).
My question is with which address should I replace this part of the code?
I have tried several things with no success. For instance, I tried https://westeurope.api.cognitive.microsoft.com/sts/v1.0/issuetoken and tried to give one of the two keys that I see under Keys and Endpoints as the parameter of the post method. But it didn't work.
I even tried using subscription key and the region, but it also didn't work. Maybe I have not used the correct syntax.
I would be grateful if anybody could help me.
Update:
Here is my updated code which still has problem with the microphone:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Speech Services using JavaScript</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script crossorigin="anonymous" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
function createFetchSpeechServicesCredentials() {
let expireAfter = 0;
let lastPromise;
return () => {
const now = Date.now();
if (now > expireAfter) {
expireAfter = now + 300000;
lastPromise = fetch(
'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken',
{ method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': 'my_subscription-key-speech-services' } }
).then(
res => res.json(),
err => {
expireAfter = 0;
return Promise.reject(err);
}
);
}
return lastPromise;
};
}
const fetchSpeechServicesCredentials = createFetchSpeechServicesCredentials();
(async function () {
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate',
{ method: 'POST', headers: { Authorization: 'Bearer My_direct_line_secret_key1' } });
const { token } = await res.json();
const webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({
credentials: fetchSpeechServicesCredentials
});
window.WebChat.renderWebChat(
{
directLine: window.WebChat.createDirectLine({ token }),
webSpeechPonyfillFactory
},
document.getElementById('webchat')
);
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
</script>
</body>
</html>
For simplicity, I copy the code which worked after the long discussion with #Hury Shen:
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Web Chat: Cognitive Services Speech Services using JavaScript</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script crossorigin="anonymous" src="https://cdn.botframework.com/botframework-webchat/latest/webchat.js"></script>
<style>
html,
body {
height: 100%;
}
body {
margin: 0;
}
#webchat {
height: 100%;
width: 100%;
}
</style>
</head>
<body>
<div id="webchat" role="main"></div>
<script>
(async function () {
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST', headers: { Authorization: 'Bearer my-directline-secret-key' } });
const { token } = await res.json();
let authorizationToken;
const tokenRes = await fetch(
'https://westeurope.api.cognitive.microsoft.com/sts/v1.0/issuetoken',
{ method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': 'my-cognitive-services-subscription-key' } }
);
if (tokenRes.status === 200) {
region = 'westeurope',
authorizationToken = await tokenRes.text()
} else {
return (new Error('error!'))
}
const webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory({
authorizationToken: authorizationToken,
region: region
});
window.WebChat.renderWebChat({
directLine: window.WebChat.createDirectLine({ token }),
webSpeechPonyfillFactory: webSpeechPonyfillFactory
}, document.getElementById('webchat'));
})().catch(err => console.error(err));
</script>
</body>
</html>
Best,
Hanna
You need to use one of the keys under "Keys and Endpoints" in the header of your post request but not as the parameter of your post request. Below is a request sample for your reference:
const tokenRes = await fetch(
'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken',
{ method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': 'yourCognitiveServicesSubscriptionKey' } }
);
if (tokenRes.status === 200) {
region = 'westus',
authorizationToken = await tokenRes.text()
} else {
return (new Error('error!'))
}
You can also test it in postman. Below screenshot is my test, I put the key in "header" of the post request but not in "Params".
======================Update=====================
According to some test, I think you should use the endpoint address as below:
If do it in one app service, you should use:
https://webchat-mockbot.azurewebsites.net/directline/token
The js code should be:
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
If just for test(expose the key in page), you should use:
https://directline.botframework.com/v3/directline/tokens/generate
The js code should be:
const res = await fetch('https://directline.botframework.com/v3/directline/tokens/generate', { method: 'POST', headers: { Authorization: 'Bearer your_secret' }});
const { token } = await res.json();
======================Update 2=====================
You can modify your code according to the code below:
let authorizationToken;
const tokenRes = await fetch(
'https://westus.api.cognitive.microsoft.com/sts/v1.0/issueToken',
{ method: 'POST', headers: { 'Ocp-Apim-Subscription-Key': 'yourCognitiveServicesSubscriptionKey' } }
);
if (tokenRes.status === 200) {
authorizationToken = await tokenRes.text()
} else {
return (new Error('error!'))
}
const webSpeechPonyfillFactory = await window.WebChat.createCognitiveServicesSpeechServicesPonyfillFactory( {
authorizationToken: authorizationToken
} );
window.WebChat.renderWebChat({
directLine: directLine,
webSpeechPonyfillFactory: webSpeechPonyfillFactory
}, document.getElementById('webchat') );

Service Worker sending multiple notifications

I have created a wordpress plugin Web push notification where the user can allow a notification and subscribe to our website. The user will receive desktop notification when we publish new post. I have a user service worker for that.
The issue is that when the user subscribes they will receive welcome notification with a link on click of notification to our website which is working perfectly, but when we publish post users receive multiple notifications. For example, some of the users receive two notifications and some receive more than two and in all these notifications they have only one notification with the link where they redirect to posts page and other notifications have no link.
Below is the service-worker.js file:
self.addEventListener('install', function (event) {
console.log('installed!');
});
self.addEventListener('activate', function (event) {
console.log('activated!');
});
self.addEventListener('message', function (event) {
});
Then we have generated a token using generate-token.js file which is below:
var obj = JSON.parse(notifyonnewpost.ajax_data);
var config = {
apiKey: obj.apiKey,
authDomain: obj.authDomain,
databaseURL: obj.databaseURL,
projectId: obj.projectId,
storageBucket: obj.storageBucket,
messagingSenderId: obj.messagingSenderId,
};
firebase.initializeApp(config);
const messaging = firebase.messaging();
var permission = Notification.permission;
if (permission == "default")
{
window.localStorage.setItem('UDID', 0);
}
var UDID = window.localStorage.getItem('UDID');
var eww_epush = obj.eww_epush;
var check_mob = isMobileDevice();
if(!check_mob)
{
if (UDID != guid())
{
window.localStorage.setItem('UDID', guid());
if ('serviceWorker' in navigator) {
var myId = obj.messagingSenderId;
navigator.serviceWorker.register(notifyonnewpost.message_sw_path+'?messagingSenderId=' + myId+'&notifyappjs=' +notifyonnewpost.notify_app_path+'&notifymsgjs=' +notifyonnewpost.notify_msg_path).then(function(reg) {
console.log("SW registration succeeded. Scope is " + reg.scope);
messaging.useServiceWorker(reg);
reg.update();
}).catch(function(err) {
console.error("SW registration failed with error " + err);
});
}
requestPermission();
}
}
else if(check_mob && eww_epush)
{
if (UDID != guid())
{
window.localStorage.setItem('UDID', guid());
if ('serviceWorker' in navigator) {
var myId = obj.messagingSenderId;
navigator.serviceWorker.register(notifyonnewpost.message_sw_path+'?messagingSenderId=' + myId+'&notifyappjs=' +notifyonnewpost.notify_app_path+'&notifymsgjs=' +notifyonnewpost.notify_msg_path).then(function(reg) {
console.log("SW registration succeeded. Scope is " + reg.scope);
messaging.useServiceWorker(reg);
reg.update();
}).catch(function(err) {
console.error("SW registration failed with error " + err);
});
}
requestPermission();
}
}
const tokenDivId = 'divToken';
const permissionDivId = 'permission_div';
messaging.onTokenRefresh(function() {
messaging.getToken()
.then(function(refreshedToken) {
console.log('Token refreshed.');
setTokenSentToServer(false);
sendTokenToServer(refreshedToken);
})
.catch(function(err) {
console.log('Unable to retrieve refreshed token ', err);
showToken('Unable to retrieve refreshed token ', err);
});
});
messaging.onMessage(function(payload) {
appendMessage(payload);
});
function resetUserInterface() {
console.log('Loading the token...');
messaging.getToken()
.then(function(currentToken) {
if (currentToken) {
sendTokenToServer(currentToken);
updateUIForPushEnabled(currentToken);
} else {
console.log('Request permission to generate Token.');
updateUIForPushPermissionRequired();
setTokenSentToServer(false);
}
})
.catch(function(err) {
console.log('Error occurred while retrieving token. ', err);
setTokenSentToServer(false);
});
}
function sendTokenToServer(currentToken) {
if (!isTokenSentToServer()) {
console.log('Sending token to the server...');
setTokenSentToServer(true);
} else {
console.log('Token sent to server!');
}
}
function isTokenSentToServer() {
if (window.localStorage.getItem('sentToServer') == 1) {
return true;
}
return false;
}
function setTokenSentToServer(sent) {
window.localStorage.setItem('sentToServer', sent ? 1 : 0);
}
function requestPermission() {
console.log('Requesting permission...');
messaging.requestPermission()
.then(function(event) {
console.log(event);
console.log('Notification permission granted.');
resetUserInterface();
})
.catch(function(err) {
console.log('Unable to get permission for notification.', err);
});
}
function deleteToken() {
messaging.getToken()
.then(function(currentToken) {
messaging.deleteToken(currentToken)
.then(function() {
console.log('Token deleted.');
setTokenSentToServer(false);
})
.catch(function(err) {
console.log('Unable to delete token. ', err);
});
})
.catch(function(err) {
console.log('Error retrieving token. ', err);
showToken('Error retrieving token. ', err);
});
}
function updateUIForPushEnabled(currentToken) {
var id = guid();
fetch(notifyonnewpost.ajaxurl, {
mode : 'no-cors',
method: 'POST',
data:"action=fwpn_push_welcome&nonce="+notifyonnewpost.nonce,
body: JSON.stringify({
token: currentToken,
id: id
})
})
}
function guid() {
var nav = window.navigator;
var screen = window.screen;
var guid = nav.mimeTypes.length;
guid += nav.userAgent.replace(/\D+/g, '');
guid += nav.plugins.length;
guid += screen.height || '';
guid += screen.width || '';
guid += screen.pixelDepth || '';
return guid;
}
function isMobileDevice() {
return (typeof window.orientation !== "undefined") || (navigator.userAgent.indexOf('IEMobile') !== -1);
};
Then we had used firebase messaging to send web push notification to user which is below firebase-messaging-sw.js
get_sw_url_parameters( 'notifyappjs' ); //loaded this js : https://www.gstatic.com/firebasejs/3.7.4/firebase-app.js
get_sw_url_parameters( 'notifymsgjs' ); //loaded this js :https://www.gstatic.com/firebasejs/3.7.4/firebase-messaging.js
var notifyappjs = get_sw_url_parameters( 'notifyappjs' );
var notifymsgjs = get_sw_url_parameters( 'notifymsgjs' );
importScripts(notifyappjs);
importScripts(notifymsgjs);
var messagingSenderId="";
var myId = get_sw_url_parameters( 'messagingSenderId' );
function get_sw_url_parameters( param ) {
var vars = {};
self.location.href.replace( self.location.hash, '' ).replace(
/[?&]+([^=&]+)=?([^&]*)?/gi,
function( m, key, value ) {
vars[key] = value !== undefined ? value : '';
}
);
if( param ) {
return vars[param] ? vars[param] : null;
}
return vars;
}
firebase.initializeApp({
'messagingSenderId': myId
});
const initMessaging = firebase.messaging();
self.addEventListener('push', function (event) {
var eventData = event.data.text();
var obj = JSON.parse(eventData);
var title = obj.notification.title;
var tag = 'FWPN_TAG';
var options = {
body: obj.notification.body,
icon: obj.notification.icon,
image: obj.notification.sound,
data: obj.data,
};
event.waitUntil(self.registration.showNotification(title, options,tag));
});
self.addEventListener('notificationclick', function (event) {
event.notification.close();
event.waitUntil(
clients.openWindow(event.notification.data.link)
);
});
self.addEventListener('pushsubscriptionchange', function (event) {
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
event.waitUntil(
self.registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function (newSubscription) {
console.log('Push subscription is changed. New Subscription is: ', newSubscription);
})
);
});
This is the php code to send a push notification when a new post is published:
function fwpn_send_push($token,$msg)
{
$registrationIds = $token;
$fields = array(
'to' => $registrationIds,
'notification' => $msg,
'data'=>array('link'=> get_permalink($post_id),'tag' => time()),
);
$headers = array('Authorization' => 'key=' . get_option('Serverkey'), 'Content-Type' => 'application/json');
$fwpn_remote_args = array(
'method' => 'POST',
'timeout' => 45,
'redirection' => 5,
'httpversion' => '1.0',
'blocking' => true,
'body' => json_encode($fields),
'headers' => $headers,
'cookies' => array()
);
$response = wp_remote_post( 'https://fcm.googleapis.com/fcm/send', $fwpn_remote_args );
}
Below hook will fire and call the function for new post publish and from that function i have called fwpn_send_push().
add_action( 'publish_post', array( $this, 'fwpn_post_published_notification' ), 10, 2 );
function fwpn_post_published_notification($ID, $post)
{
$original_post_status = $_POST[ 'original_post_status' ];
if($original_post_status == 'auto-draft' || $original_post_status == 'draft' )
{
$current_post_id = $post->ID;
if($_POST[ 'do_not_send_push_notifications_for_this_post' ] == 1)
{
$push_post_data = update_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', $_POST[ 'do_not_send_push_notifications_for_this_post' ] );
}
else
{
$push_post_data = update_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', 0 );
}
$display_notification = get_post_meta( $current_post_id, 'do_not_send_push_notifications_for_this_post', true );
if($display_notification == 0)
{
global $wpdb;
$prifix=$wpdb->prefix;
$current_data = $wpdb->get_results("SELECT * FROM ".$prifix."push_notification");
$post_result = array(
"post_type" => 'post',
"post_status" => "publish",
"posts_per_page" => 1,
"order" => "DESC",
"orderby" => "date"
);
$post_result_data = new WP_Query($post_result);
$post_id=$post_result_data->post->ID;
$thumb = $this->fwpn_get_thumb_url($post_id);
$message = $this->fwpn_get_push_message($post_result_data,$thumb);
foreach ($current_data as $value) {
$this->fwpn_send_push($value->authSecret,$message);
}
}
}
}

401 when trying to create a post in Wordpress API using Oauth 1.0

I'm trying to create a Wordpress post through Wordpress API v2, however the oauth 1.0 is throwing 401 at me when I do axios.post. When I do axios.get, everything's perfect and I get the result.
I can create or delete posts through Postman without a problem, but it configures itself automatically. It would be nice if I could copy the request somehow from postman and put it into axios code, but couldn't find this option.
I tried specifying the header for content-type as application/json like so:
headers: {
'Content-Type': 'application/json'
}
as it was in Postman, but still no change.
I'm using a generator for Oauth signature and it's working in GET request as pointed out. https://www.npmjs.com/package/oauth-signature
Here's the code for the get and post requests:
getRequest = () => {
const requestParams = { ...this.state.parameters }
requestParams.oauth_nonce = this.generateNonce()
requestParams.oauth_timestamp = new Date()
.getTime()
.toString()
.slice(0,10)
const encodedSignature = oauthSignature.generate(
'GET',
'http://localhost/wordpress-api/wp-json/wp/v2/posts/29',
requestParams,
this.state.consumerSecret,
this.state.tokenSecret
)
axios({
url: 'http://localhost/wordpress-api/wp-json/wp/v2/posts/29',
method: 'get',
auth: `
OAuth oauth_consumer_key="${requestParams.oauth_consumer_key}",
oauth_token="${requestParams.oauth_token}",
oauth_signature_method="${requestParams.oauth_signature_method}",
oauth_timestamp="${requestParams.oauth_timestamp}",
oauth_nonce="${requestParams.oauth_nonce}",
oauth_version="${requestParams.oauth_version}",
oauth_signature="${encodedSignature}"
`
})
.then(res => {
this.setState({
requestResponse: res
})
})
}
postRequest = (e) => {
e.preventDefault()
const postData = {
title: this.refs.title.value,
status: 'publish',
content: this.refs.content.value,
}
const requestParams = { ...this.state.parameters }
requestParams.oauth_nonce = this.generateNonce()
requestParams.oauth_timestamp = new Date()
.getTime()
.toString()
.slice(0,10)
const encodedSignature = oauthSignature.generate(
'POST',
'http://localhost/wordpress-api/wp-json/wp/v2/posts',
requestParams,
this.state.consumerSecret,
this.state.tokenSecret
)
axios({
url: 'http://localhost/wordpress-api/wp-json/wp/v2/posts',
method: 'post',
data: postData,
auth: `
OAuth oauth_consumer_key="${requestParams.oauth_consumer_key}",
oauth_token="${requestParams.oauth_token}",
oauth_signature_method="${requestParams.oauth_signature_method}",
oauth_timestamp="${requestParams.oauth_timestamp}",
oauth_nonce="${requestParams.oauth_nonce}",
oauth_version="${requestParams.oauth_version}",
oauth_signature="${encodedSignature}"
`
})
.then(res => {
this.setState({
requestResponse: res
})
})
}
Finally, I've figured out what's the problem. It would be nice if Wordpress API had more examples. My authorization header was not properly set.
Below is the updated code that should be used in any Oauth 1.0 secured requests to Wordpress API (GET, POST, PUT, DELETE, just replace 'post' with any method in oauthSignature.generate() function and the axios request). Checked and working properly.
Just remember that this is just an example with all tokens and secrets in the component's state. You should store these in the backend and pass them to front-end only after providing some credentials.
I've uploaded the whole React component code, because I've learnt the hard way how many small, unusable snippets of code there are on the internet instead of a whole solution, which annoyed me greatly. This should be more explanatory to all those that want to have a working example.
// dependencies
import React, { Component } from 'react'
import axios from 'axios'
import oauthSignature from 'oauth-signature'
// components
import '../Styles/Css/Moderator.css'
class Moderator extends Component {
constructor() {
super()
this.state = {
requestResponse: null,
parameters: {
oauth_consumer_key : 'xxxxxxxxxxxxx', // your consumer_key
oauth_token : 'xxxxxxxxxxxxxxxxx', // your token
oauth_signature_method : 'HMAC-SHA1',
oauth_timestamp : '',
oauth_nonce : '',
oauth_version : '1.0'
},
consumerSecret: 'xxxxxxxxxxxxxxxxxxxxx', // your consumer_secret
tokenSecret: 'xxxxxxxxxxxxxxxxxxxxx', // your token_secret
}
}
generateNonce = () => {
let text = ''
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
for (let i = 0; i < 11; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length))
}
return text
}
handleSubmit = (e) => {
e.preventDefault()
let postData = {
title: this.refs.title.value,
status: 'publish',
content: this.refs.content.value,
}
const requestParams = { ...this.state.parameters }
requestParams.oauth_nonce = this.generateNonce() // unique identifier
requestParams.oauth_timestamp = new Date()
.getTime()
.toString()
.slice(0,10) // we need just the first 10 digits from current time
const encodedSignature = oauthSignature.generate(
'POST',
'http://localhost/wordpress-api/wp-json/wp/v2/posts',
requestParams,
this.state.consumerSecret,
this.state.tokenSecret
)
const authorizationHeader =
'OAuth oauth_consumer_key="' + requestParams.oauth_consumer_key
+ '",oauth_token="' + requestParams.oauth_token
+ '",oauth_signature_method="' + requestParams.oauth_signature_method
+ '",oauth_timestamp="' + requestParams.oauth_timestamp
+ '",oauth_nonce="' + requestParams.oauth_nonce
+ '",oauth_version="' + requestParams.oauth_version
+ '",oauth_signature="' + encodedSignature +'"'
axios({
method: 'post',
url: 'http://localhost/wordpress-api/wp-json/wp/v2/posts',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': authorizationHeader
},
data: postData
})
.then(res => {
console.log(res)
})
}
render() {
return (
<div className='moderator'>
<form onSubmit={this.handleSubmit}>
<label>
Title
<input type='text' ref='title' />
</label><br />
<label>
Content
<textarea ref='content' />
</label>
<input type='submit' value='Submit' />
</form>
</div>
)
}
}
export default Moderator

Service worker event waitUntil() was passed a promise that rejected with 'TypeError: b is null'

This is my service worker file that shows the push notification:
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js');
var config = {
apiKey: "my_key",
authDomain: "my_domain.firebaseapp.com",
databaseURL: "https://my_db.firebaseio.com",
storageBucket: "my_bucket.appspot.com",
messagingSenderId: "my_sender_id"
};
firebase.initializeApp(config);
var messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function (payload) {
var notificationTitle = 'Hello World';
var notificationOptions = {
body: 'Test push notification'
};
return self.registration.showNotification(notificationTitle,notificationOptions);
});
This is my html, where it registers the service worker:
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>TODO write content</div>
<script src="https://www.gstatic.com/firebasejs/3.5.0/firebase.js"></script>
<script>
var config = {
apiKey: "my_key",
authDomain: "my_domain.firebaseapp.com",
databaseURL: "https://my_db.firebaseio.com",
storageBucket: "my_bucket.appspot.com",
messagingSenderId: "my_sender_id"
};
firebase.initializeApp(config);
</script>
<script>
var messaging = firebase.messaging();
var ser = '/serviceworker.js';
if ('serviceWorker' in navigator) {
// Register service worker
navigator.serviceWorker.register('./public/serviceworker.js').then(function (reg) {
messaging.useServiceWorker(reg);
messaging.requestPermission()
.then(function () {
console.log('Notification permission granted.');
return messaging.getToken()
.then(function (currentToken) {
if (currentToken) {
console.log('in if', currentToken);
if (window.XMLHttpRequest) {
xhttp = new XMLHttpRequest();
} else {
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
}
};
xhttp.open("POST", "/notification", true);
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhttp.send(JSON.stringify({token: currentToken}));
} else {
console.log('in else', currentToken);
}
}).catch(function (err) {
console.log('An error occurred while retrieving token. ', err);
});
})
.catch(function (err) {
console.log('Unable to get permission to notify. ', err);
});
messaging.onMessage(function (payload) {
var options = {
body: payload.data.body
}
var notificationObj = new Notification(payload.data.title, options);
});
}).catch(function (err) {
console.error("SW registration failed with error " + err);
});
}
</script>
</body>
</html>
Everything is working fine but when i load page for first time then i see the following error after allowing the notification permission. I am using FCM for push notification.
Service worker event waitUntil() was passed a promise that rejected with 'TypeError: b is null'.
This was fixed in version 3.5.1 of Firebase Messaging.

Resources