I am trying but in response did not get entered number. I have one post api which give me an OTP which bring me in next screen for registration.
//In below code i get response.
createPost(String url, {Map body}) async {
return http
.post(url, body: body)
.then((http.Response response) {
print("Response" + response.body);//response get from api
return Post.fromJson(json.decode(response.body));
});
}
//I am taking number as a string
Post newPost = new Post(
usernumber: _numbercontroller.text,
contrycode: code.toString()
);//contrycode taken ans var datatype
Post p = await createPost(url, body: newPost.toMap());
print("Number --> " + newPost.usernumber);//here did not get mobile number
},
When I entered mobile number I get otp number from API for registration.
Kindly check the API. If entered phone number is not getting means your response is getting something different. Kindly elaborate the response from API.
Related
I have a link to default email verification function in Firebase.
Using this link from the browser works fine, however it fails when being used from server side with the following code:
try {
const url = `https://example.com/__/auth/action?mode=verifyEmail&oobCode=${oobCode}&apiKey=${apiKey}&lang=en`;
const response = await axios.get(url);
if (response.data.success) {
return next();
} else {
return next(new ErrorResponse("Failed email verification", FORBIDDEN));
}
} catch (error) {
return sendFailedWithErr(res, error.message);
}
When I am copying the URL used in the server side the exact same URL works from the browser, but fails on the server side.
Would appreciate any idea what is the problem.
This is because a call to this URL is not going to return a response that you can check like the response of a REST API endpoint with, e.g. response.data.success.
As you will see here, this URL is supposed to be used to open a web page in which you will:
Get the values passed as QueryString parameters (e.g. mode or oobCode)
Call, from the web page some methods of the Firebase JavaScript SDK, like applyActionCode() in the case of email verification.
You may be able to mimic this action from a server, but I've never tried.
I'm trying to send images to a whatsapp user via Twilio, but I'm always getting 400 error
(400) Bad Request. -> {"code": 21620, "message": "Media urls: https://image-charts.com/chart?cht=pd&chd=a:10238,10200&chs=400x300&chdls=9e9e9e,10&chco=FFC00C,03A9F4&chtt=Ocupaci%C3%B3n%20en%20almac%C3%A9n&chdl=Contratado%7COcupado&chli=100.37%25&chl=10238%7C10200&chdlp=b&chof=.png are invalid. Please use only valid http and https urls", "more_info": "https://www.twilio.com/docs/errors/21620", "status": 400}
The image works fine in browser or when is send directly to the user directly in whatsapp
I'm encoding the image like this (js):
img_url = encodeURI(img_url);
Any ideas or workaround?
thanks
It seems not every parameter was encoded, example: chd=a:10238,10200 should be chd=a%3A10238%2C10200.
encodeURI won't produce URL safe, you will need to rely on encodeURIComponent but it will encode the whole url ('/chart?' included) so it's not an option either.
If you are doing this server-side from NodeJS:
// node v10+
const url = require('url');
const querystring = require('querystring');
function encode_uri(chart_url) {
const parsed_url = url.parse(chart_url);
// parse the querytring and then encode every parameter values
parsed_url.query = querystring.stringify(querystring.parse(parsed_url.query));
// generate the full url
return url.format({
...parsed_url,
href:undefined,
path:undefined,
search:'?' + parsed_url.query,
});
}
let chart_url = 'https://image-charts.com/chart?cht=pd&chd=a:10238,10200&chs=400x300&chdlp=b&chdls=9e9e9e,10&chco=FFC00C,03A9F4&chtt=Ocupación en almacén&chli=100.37%&chl=10238|10200&chdl=Contratado|Ocupado&chof=.png';
console.log(encode_uri(chart_url));
// Fully encoded URL
// https://image-charts.com/chart?cht=pd&chd=a%3A10238%2C10200&chs=400x300&chdlp=b&chdls=9e9e9e%2C10&chco=FFC00C%2C03A9F4&chtt=Ocupaci%C3%B3n%20en%20almac%C3%A9n&chli=100.37%25&chl=10238%7C10200&chdl=Contratado%7COcupado&chof=.png
If you are doing this on the browser side then use:
function encode_uri(chart_url) {
// use https://developer.mozilla.org/en-US/docs/Web/API/URL
// not supported in IE10
const parsed_url = new URL(chart_url);
// encode every parameter values
[...parsed_url.searchParams.keys()].forEach(key => parsed_url.searchParams.set(key, encodeURIComponent(parsed_url.searchParams.get(key))));
// generate back the full url
return parsed_url.toString();
}
let chart_url = 'https://image-charts.com/chart?cht=pd&chd=a:10238,10200&chs=400x300&chdlp=b&chdls=9e9e9e,10&chco=FFC00C,03A9F4&chtt=Ocupación en almacén&chli=100.37%&chl=10238|10200&chdl=Contratado|Ocupado&chof=.png';
console.log(encode_uri(chart_url));
// https://image-charts.com/chart?cht=pd&chd=a%253A10238%252C10200&chs=400x300&chdlp=b&chdls=9e9e9e%252C10&chco=FFC00C%252C03A9F4&chtt=Ocupaci%25C3%25B3n%2520en%2520almac%25C3%25A9n&chli=100.37%2525&chl=10238%257C10200&chdl=Contratado%257COcupado&chof=.png
I'm trying to connect Google Home to an external chatbot with actionssdk. I have an API that take user inputs and send them to my chatbot with webhook, but my chatbot make a response calling another endpoint of my API in an async way, and I can't show the response in actions on Google or Google Home.
I create an actionssdkApp.
const {
actionssdk,
SimpleResponse,
Image,
} = require('actions-on-google');
var app = actionssdk();
var express_app = express();
My API has 2 endpoints. One of them is for actions on google to send user inputs to my chatbot:
app.intent('actions.intent.MAIN', conv => {
console.log('entra en main');
conv.ask('Hi, how is it going?');
});
app.intent('actions.intent.TEXT', (conv, input) => {
var userId = conv.body.user.userId;
console.log(userId);
if(userId && input){
textFound(conv, input, userId);
}else{
textnotFound(conv);
}
});
TextFound function send user inputs to my chatbot with webhook, but the request doesn't receive the response. My chatbot call another endpoint with the text answer:
express_app.post('/webhook', bodyParser.json(), (req, res)=>{
console.log("Webhook");
const userId = req.body.userId;
if (!userId) {
return res.status(400).send('Missing User ID');
}
console.log(req.body);
res.sendStatus(200);
});
And here is where I want to send the answer to Google Home. But I need the conv object to show the answer in google Home, or actions on google, or any other device.
Edit:
My textFound function:
webhook.messageToBot(metadata.channelUrl, metadata.channelSecretKey, userId, input, function(err){
if(err){
console.log('Error in sending message');
conv.ask("Error in sending message");
}else{
conv.ask("some text");
}
});
From here my api send user inputs to my bot through messageToBot function:
request.post({
uri: channelUrl,
headers: headers,
body: body,
timeout: 60000,
followAllRedirects: true,
followOriginalHttpMethod: true,
callback: function(err, res, body) {
if (err) {
console.log('err: '+err);
callback(err);
} else {
console.log('Message sent');
callback(null);
}
}
});
From now on, my bot doesn't send a response but makes a call to /webhook endpoint of my api with the answer. But in this function I haven't de conv object and I can't send the answer to google. I don't know how to access to this object. Maybe there is an uri to connect with my project in actions on google from my api.
Typically, Actions on Google works in a request-response way. The user says something to the Action, and the Action replies with a response. That reply needs to come within about 5 seconds. If you think the call to /webhook can come that quickly, and you will only deliver a message to the user after they say something, you can have /webhook save the response in a queue for the user, and have your Intent handler be in a loop that checks this queue for any messages to reply with - if there is a message within 5 seconds, you reply with it, if not, you need to reply before the 5 seconds are up.
If you can't guarantee it will be done within 5 seconds, however, there are a couple of workarounds that might be useful depending on your needs.
The first is that you might be able to use notifications. In this scenario, you would send the message from the user and then close the conversation. When your /webhook endpiont is triggered, you would locate the user and send the notification to their Assistant. Unfortunately, this is a bit bulky, doesn't lead to a very interactive chat system, and notifications also aren't supported on smart speakers.
You can also look into using a Media Response to set up a way for you to poll for new messages periodically. Under this scheme, your user would send their message. In your reply to them, you would include a Media Response for some audio that plays for, say, 15 seconds. When the audio finishes, your Action will be called again and you can check to see if any messages have been queued up to be delivered to the user. If so, you relay those messages, followed by a Media Response gain. Otherwise, just send a Media Response. Your call to /webhook would have to put messages in a queue to be delivered to the user. This is more complex, especially to scale, but can be made more interactive. It is also a more general case of trying to handle it in a loop inside 5 seconds.
How do I use notification actions with the Firebase Messaging SDK on the web?
There are a few common pitfalls people hit when attempting this.
Firebase Notifications - There is a feature of the Firebase Messaging SD
K's none as "Firebase Notifications". When you send a push message to a Firebase Instance-ID (IID) token, you can use a "notification" key which the SDK's will look for and if found, construct a notification for you. The benefit of this is that you have to write no code to show a notification. The downside is that it can be restrictive if you want to do anything complex or perform work on the device once the notification is received. So to use actions, you MUST NOT USE THIS. Instead call the FCM API with the IID token and a "data" payload.
Data Payload - The data payload has a restriction where it can only be key value pairs, where the value must be a string, i.e. no arrays. What this means is that you can't just send an array of actions and construct a notification with that. The way around this is to create a JSON string, send that to the FCM API and then parse and use the JSON on the device.
Time for an example.
Calling the FCM API
The format of your payload should be something like this:
{
"data": {
"some-data": "Im a string",
"some-other-data": "Im also a string",
"json-data": "{\"actions\": [{\"action\":\"yes\", \"title\":\"Yes\"},{\"action\":\"no\",\"title\":\"No\"}]}"
},
"to": "YOUR-IID-TOKEN"
}
You can send this with curl like so:
curl -X POST -H "Authorization: key=YOUR-SERVER-KEY" -H "Content-Type: application/json" -d '{
"data": {
"some-data": "Im a string",
"some-other-data": "Im also a string",
"json-data": "{\"actions\": [{\"action\":\"yes\", \"title\":\"Yes\"},{\"action\":\"no\",\"title\":\"No\"}]}"
},
"to": "YOUR-IID-TOKEN"
}' "https://fcm.googleapis.com/fcm/send"
With that you'll be able to get the data in the onBackgroundMessage callback in your service worker.
Receiving the Payload on the Device
In a service worker we could have the following code:
messaging.setBackgroundMessageHandler(function(payload) {
console.log('Message received: ', payload);
});
Which would print out the following in the console:
Notice the JSON data is still just a string, not an object.
Next up we can parse the JSON data and check its the right format to use as our notification actions.
We can change our code to the following:
messaging.setBackgroundMessageHandler(function(payload) {
console.log('Message received: ', payload);
const parsedJSON = JSON.parse(payload.data['json-data']);
console.log('Actions:', parsedJSON);
});
This will give the following log:
With this, we can finally create our notification with the following code:
messaging.setBackgroundMessageHandler(function(payload) {
console.log('Message received: ', payload);
const parsedJSON = JSON.parse(payload.data['json-data']);
console.log('Actions:', parsedJSON);
// Customize notification here
const notificationTitle = 'Actions Title';
const notificationOptions = {
body: 'Actions body.',
actions: parsedJSON.actions,
};
return self.registration.showNotification(notificationTitle,
notificationOptions);
});
Now you should have a notification with actions:
Testing
As Meggin as pointed out in the comments, it's not obvious how to test it, so a few guiding principles.
The biggest pain point is that if your web server sets a cache header for you service worker file, it won't update between refreshes, one way to fix this it to open your service worker file in a new tab and refresh that page until your service worker is up to date (This is viewing the actual source code of your service worker). Then when you refresh your web page your service worker will be the latest one and you can tell it's updated by the number next to the service worker incrementing.
Alternatively, just unregister the service worker the service worker and refresh the page - this should give you the latest service worker.
To test your notification, you'll need to click a tab that is for a different web page before sending a push message.
The reason for this is that if the user is currently on one of your pages, the push message is sent to the pages onMessage() callback instead of the onBackgroundMessage() callback.
Following Matt's advice, I was able to get a proper notification with content from my firebase function passed into my service worker (including actions), but I had to pass all of my data through the one json object, otherwise it wouldn't work for me.
Here's what my firebase functions code looks like:
function sendPayload(tokenArray) {
const payload = {
"data": {
"jsondata": "{\"body\":\"Meggin needs help\", \"title\":\"Can you help her make the code work?\",\"actions\": [{\"action\":\"yes\", \"title\":\"Yes\"},{\"action\":\"no\",\"title\":\"No\"}]}"
}
};
admin.messaging().sendToDevice(tokenArray, payload)
.then(function(response) {
// See the MessagingDevicesResponse reference documentation for
// the contents of response.
console.log("Successfully sent message:", response);
})
.catch(function(error) {
console.log("Error sending message:", error);
});
}
And here's what my code looks like in my service worker:
messaging.setBackgroundMessageHandler(function(payload) {
console.log('Payload received: ', payload);
const parsedJSON = JSON.parse(payload.data.jsondata);
console.log("What does actions look like? " + parsedJSON.actions);
console.log("What does title look like? " + parsedJSON.title);
const notificationTitle = parsedJSON.title;
const parsedBody = parsedJSON.body;
const parsedActions = parsedJSON.actions;
// Customize notification here
const notificationOptions = {
body: parsedBody,
actions: parsedActions,
};
return self.registration.showNotification(notificationTitle, notificationOptions);
});
It's worth noting that one major hurdle that helped me get passed this is understanding how to test push notifications and service workers!
You actually can't see my notification unless the browser is closed, so obviously, you can't watch the console.
But then once you've pushed the notification, you go into the console, and change the file at the top of console to be the service worker file specifically.
And then you can see the console logs!
I realize this might seem obvious to many people, but it wasn't to me, and it's crucial to understanding how to parse the payload and get it to do what you want!
We'd like to add the facebook messenger checkbox plugin at the end of a request form so users can opt-in for notifications via messenger.
When the user opts in, our webhook receives a callback with the user_ref that we set in the form.
We send a confirmation of opt-in to this user_ref
But other messages we receive like delivery, read receipt or actual messages from the user do contain the user ref anymore but the user id.
This is the official documentation of facebook:
After you receive the callback event, you can call the Send API to start messaging the user using the user_ref identifier in recipient as shown below. Note that this field is the same as the unique user_ref param used before when the plugin was rendered and in confirming the opt-in.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
Therefore it's impossible to keep track between the initial message and new ones. Does anyone found a solution for this?
Thank you very much in advance.
You can, for example, send additional information when the user opts in using the optional ref parameter. You can send the username of the user logged on my website:
function confirmOptIn() {
FB.AppEvents.logEvent('MessengerCheckboxUserConfirmation', null, {
'app_id':'APP_ID',
'page_id':'PAGE_ID',
'ref': 'myuser#mywebsite.com',
'user_ref':'UNIQUE_REF_PARAM'
});
You will receive the username within optin in your webhook event:
{
"recipient":{
"id":"PAGE_ID"
},
"timestamp":1234567890,
"optin":{
"ref":"myuser#mywebsite.com",
"user_ref":"UNIQUE_REF_PARAM"
}
}
Then, you can call the Send API to start messaging the user using the user_ref.
If the call to the Send API is successful, the response will contain a recipient_id parameter, which is a stable user ID that you can now use in future API calls.
...so you will received the Messenger ID which you can map to the username of your website you already have. Here, I modified a little the example from the official developers site to call the send API with user_ref and map the user ID I get in the response to the username of my website:
function callSendAPICheckbox(messageData, userApplicationId) {
((userApplicationId) => {
request({
uri: 'https://graph.facebook.com/v2.6/me/messages',
qs: {
access_token: PAGE_ACCESS_TOKEN
},
method: 'POST',
json: messageData
},
function(error, response, body) {
if (!error && response.statusCode == 200) {
var recipientId = body.recipient_id;
var messageId = body.message_id;
if (messageId) {
console.log("Map messenger user ID %s with the username of my website %s", recipientId, userApplicationId);
} else {
console.log("Successfully called Send API for recipient %s",
recipientId);
}
} else {
console.error("Failed calling Send API for userId " +
recipientId, response.statusCode, response.statusMessage, body.error);
}
});
})(userApplicationId)
}
Why don't you make use of metadata field of sendTextMessage. Each and every message you send to your user, you send the metadata too, and when you receive response of the message being delivered, you find the metadata field in it.
Here is what I do:
When user select the checkbox plugin and event is triggered I receive the call on my server, check if it contains user_ref. If it does, then I send a text message to user with a custom metadata using user_ref. When user receives the message, the webhook send me a json data as mentioned in the documentation. To identify for which user_ref I have received this response, I set custom metadata which is combination of some string + user_ref before sending the message to user using user_ref. Using this custom metadata I identify the sender.id of the user for which I previously sent message using user_ref. The sender.id is my pageid and recipient.id the the user id which you are trying to get and using which we generally send message to the user and is also know as psid.
Above if just the logical part mentioned which I usually do.
For detail solution along with code, I have already posted it here: