Facebook messenger checkbox plugin confirm_optin not triggering messaging_optin webhook to post to my server - facebook

i am working with Facebook Checkbox Plugin everything is working fine and I am able to render the plugin. My problem is that facebook is not sending request to my webhook url when Confirming Opt-in. in the facebook docs it is mentioned that
After the opt-in event, we will post a webhook event to your server
if the checkbox state was checked. This callback has the same format
as the opt-in callback, but instead of a sender field, it has an optin
object with a user_ref field.
my code for subscribing to the webhook is .
if request.method=='GET':
try:
myfb_token='xxxx'#to go to settings
if self.request.query_params['hub.mode']:
if self.request.query_params['hub.verify_token']==myfb_token:
res=int(self.request.query_params['hub.challenge'])
status_code=200
else:
status_code=422
res={"unable to verify"}
except Exception as e:
res={"invalid request"}
status_code = 422
return Response(res, status=200)
else:
print(request.data)
return Response("webhook posts", status=200)
This works fine and am able to subscribe. Am also able to test my webhook and hit my server from my app . However the webhook does post to my server when the plugin is checked. My app is still in development mode and am using my facebook account for testing as an admin.
I have also subcribed to the messaging_optin webhook

Related

Actions on Google implicit account linking works in simulator/browser, but not on device (via Google Home app)

I've implemented the implicit flow for Actions on Google account linking, and am using Dialogflow (previously API.AI) to define intents.
The full flow works in the device simulator (from AOG). The first intent gets a "It looks like your account isn't linked yet..." response, and the debug pane includes a URL to initiate linking:
https://assistant.google.com/services/auth/handoffs/auth/start?account_name=[account]#gmail.com&provider=[project_id]_dev&scopes=email&return_url=https://www.google.com/
If I follow this URI in a cache-less window:
I'm redirected to my app's authentication page
I choose to sign in with my Google account (same as [account] above)
I'm redirected to google.com with a success message in the URI bar
The simulator now accepts actions via my app and responds correctly
However, if I follow the same flow using a physical Google Home & the gH app for Android.
Device tells me account not yet linked
Open Google home and follow 'Link to [my app]' link
Browser opens to authentication page
Sign in as user
Redirected to a white page with a single link "Return to app", which has an href: about:invalid#zClosurez
Linking was unsuccessful, so additional attempts to run intents on the Google Home get the same "Account not yet linked" response.
I've inspected the intermediate access_token and state variables at length, and they all match and look to be correctly formatted:
Authentication URL (app sign in page): https://flowdash.co/auth/google?response_type=token&client_id=[client_id]&redirect_uri=https://oauth-redirect.googleusercontent.com/r/[project_id]&scope=email&state=[state]
After authenticating, redirected to (this is the white screen with 'return to app' broken link): https://oauth-redirect.googleusercontent.com/r/genzai-app#access_token=[token]&token_type=bearer&state=[state]
So, it seems there's something non-parallel about the way the simulator and physical devices work in terms of implicit flow account linking.
I've been struggling with this, and with the AOG support team for a very long time to no avail. Anyone else see a similar issue?
Updated with response redirect code:
Login handled by react-google-login component with profile & email scopes. On success we call:
finish_auth(id_token) {
let provider = {
uri: '/api/auth/google_auth',
params: ['client_id', 'redirect_uri', 'state', 'response_type'],
name: "Google Assistant"
}
if (provider) {
let data = {};
provider.params.forEach((p) => {
data[p] = this.props.location.query[p];
});
if (id_token) data.id_token = id_token;
api.post(provider.uri, data, (res) => {
if (res.redirect) window.location = res.redirect;
else if (res.error) toastr.error(res.error);
});
} else {
toastr.error("Provider not found");
}
}
provider.uri hits this API endpoint:
def google_auth(self):
client_id = self.request.get('client_id')
redirect_uri = self.request.get('redirect_uri')
state = self.request.get('state')
id_token = self.request.get('id_token')
redir_url = user = None
if client_id == DF_CLIENT_ID:
# Part of Google Home / API.AI auth flow
if redirect_uri == "https://oauth-redirect.googleusercontent.com/r/%s" % secrets.GOOGLE_PROJECT_ID:
if not user:
ok, _email, name = self.validate_google_id_token(id_token)
if ok:
user = User.GetByEmail(_email, create_if_missing=True, name=name)
if user:
access_token = user.aes_access_token(client_id=DF_CLIENT_ID)
redir_url = 'https://oauth-redirect.googleusercontent.com/r/%s#' % secrets.GOOGLE_PROJECT_ID
redir_url += urllib.urlencode({
'access_token': access_token,
'token_type': 'bearer',
'state': state
})
self.success = True
else:
self.message = "Malformed"
else:
self.message = "Malformed"
self.set_response({'redirect': redir_url}, debug=True)
I am able to make it work after a long time. We have to enable the webhook first and we can see how to enable the webhook in the dialog flow fulfillment docs If we are going to use Google Assistant, then we have to enable the Google Assistant Integration in the integrations first. Then follow the steps mentioned below for the Account Linking in actions on google:-
Go to google cloud console -> APIsand Services -> Credentials -> OAuth 2.0 client IDs -> Web client -> Note the client ID, client secret from there -> Download JSON - from json note down the project id, auth_uri, token_uri -> Authorised Redirect URIs -> White list our app's URL -> in this URL fixed part is https://oauth-redirect.googleusercontent.com/r/ and append the project id in the URL -> Save the changes
Actions on Google -> Account linking setup 1. Grant type = Authorisation code 2. Client info 1. Fill up client id,client secrtet, auth_uri, token_uri 2. Enter the auth uri as https://www.googleapis.com/auth and token_uri as https://www.googleapis.com/token 3. Save and run 4. It will show an error while running on the google assistant, but dont worry 5. Come back to the account linking section in the assistant settings and enter auth_uri as https://accounts.google.com/o/oauth2/auth and token_uri as https://accounts.google.com/o/oauth2/token 6. Put the scopes as https://www.googleapis.com/auth/userinfo.profile and https://www.googleapis.com/auth/userinfo.email and weare good to go. 7. Save the changes.
In the hosting server(heroku)logs, we can see the access token value and through access token, we can get the details regarding the email address.
Append the access token to this link "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" and we can get the required details in the resulting json page.
`accessToken = req.get("originalRequest").get("data").get("user").get("accessToken")
r = requests.get(link)
print("Email Id= " + r.json()["email"])
print("Name= " + r.json()["name"])`
Not sure which python middleware or modules you are using but
self.set_response({'redirect': redir_url}, debug=True)
seems to be setting parameters for a returning a response which isn't correct. Instead you should redirect your response to the redirect_url. For example importing the redirect module in Flask or Django like:
from flask import redirect or from django.shortcuts import redirect
then redirect like:
return redirect(redirect_url)
It appears Google has made a change that has partially solved this problem in that it is now possible to complete the implicit account linking flow outside of the simulator, in the way outlined in my question.
It seems the problem stemmed from an odd handling (on the AOG side) of the client-side redirect case used after sign in with the Google sign-in button.
From Jeff Craig in this thread:
The current workaround, where we provide the "Return to app" link
currently what we're able to provide. The issue is with the way that
redirecting to custom-scheme URIs is handled in Chrome, specifically,
with regard to the redirect happening in the context of a user action.
XHR will break that context, so what is happening is that you click
the Google Sign-In Button, which triggers an XHR to Google's servers,
and then you (most likely) do a client-side redirect back to the
redirect_url we supply, our handler executes, and isn't able to do a
JS redirect to the custom scheme URI of the app, because were outside
of the context of a direct user click.
This is more of a problem with the Implicit (response_type=token) flow
than with the authorization code (response_type=code) flow, and the
"Return to app" link is the best fallback case we currently have,
though we are always looking for better solutions here as well.
The current behavior shows the 'Return to app' link, but as of last week, this link's href is no longer about:invalid#zClosurez, but instead successfully completes the sign-in and linking process. It's an odd and confusing UX that I hope Google will improve in the future, but it was sufficient to get my app approved by the AOG team without any changes to my flow.

Facebook Messenger Sender Actions

I am trying to use Sender Actions as described in the messenger Send API docs. However when I send a typing_on POST I do no see anything happen in messenger. I have tried on chrome desktop and the messenger android app.
I am able to send a mark_seen POST and this does update the chat with an icon indicating my message has been seen.
The request body looks as follows:-
{
"recipient":{
"id":"<PSID>"
},
"sender_action":"typing_on"
}
When sending mark_seen, typing_on or typing_off I always get the following response body.
{
"recipient_id": "<PSID>"
}
Are there additional steps needed to get the typing indicator to display? Does it only work on a specific platform? I cannot find any more documentation, and I am not getting any error messages, the POST status comes back OK identically when sending mark_seen or typing_on, I just can't see any effect after typing_on.
Okay I got reply from Facebook developer team on Facebook Developers group
Quote:
"This changed recently for mobile and is currently assigned to an internal team". Looks like something internal.

MS Bot Framework Response to Facebook Payment Buy Request

When you show a buy button on Facebook the callback to your bot is an "invoke". Details here [Show the buy button and process the payment on facebook messenger with Bot Framework
It is up to the bot to respond to FB with a 200 for success or something else for a failure. No matter what response I've sent Facebook processes the request as if it were successful.
v3.0 of the bot framework with the C# Connector SDK
I've attempted:
Standard reply:
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl));
Activity replyToConversation = activity.CreateReply();
replyToConversation.Recipient = activity.From;
replyToConversation.Type = "invoke";
connector.Conversations.ReplyToActivity(replyToConversation);
or
return Request.CreateResponse(HttpStatusCode.InternalServerError);
or
return Request.CreateErrorResponse(...);
or
return null;
I've also forced the Controller to respond with an error by throwing a new exception.
There was a suggestion to rely using channelData however channelData seems to only support attachment type replies and what is needed here is a direct reply to the Payment request.
How do I correctly respond to FB to indicate the payment was NOT successful?

Facebook Messenger webhook setup, but not triggered

So I'm trying to setup a bot for the new Facebook Messenger API.
I'm following the quickstart.
I setup the webhook ok, and see it in my webhooks,
I called this:
https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=%3Ctoken%3E
and it did not throw any errors,
But when I go to the Page that I generated the access token on, and send a message, it does not call my webhook.
I check the httpaccess, and it does not call it.
Any way to debug this or any ideas?
Also, one thing I'm still puzzled over is how to support managing multiple pages from one Facebook app? Anyone know the answer to this, or do you need to create anew app and get permission for every page?
I have recently worked with the new chat bot API and there's a lot that can go wrong. So, here are some Ideas.
Make sure you've verified your webhook under the product settings tab.
subscribe your app to the page using your page access token. It returns {"success" : "true"} if everything goes right.
Important
Make sure the Facebook user from which you're sending the message is listed as the Admin or Developer or Tester in your app roles (https://developers.facebook.com/apps/YOUR_APP_ID/roles/). Messages from other users won't work unless your app is approved and publicly released.
Have you received any call back from the facebook api ? or is it just the messages? Take a look at the logs of your web server and check if you're getting any hits on the webhook. Also check the error logs.
Try hitting your webhook manually and see if it responds. You can use
curl to generate a manual request. This is what the request from
Facebook looks like:
Command:
curl -i -X POST -H 'Content-Type: application/json' -d '{"object":"page","entry":[{"id":43674671559,"time":1460620433256,"messaging":[{"sender":{"id":123456789},"recipient":{"id":987654321},"timestamp":1460620433123,"message":{"mid":"mid.1460620432888:f8e3412003d2d1cd93","seq":12604,"text":"Testing Chat Bot .."}}]}]}' https://www.YOUR_WEBHOOK_URL_HERE
So my issue was I was calling GET when trying to subscribe instead of POST
https://graph.facebook.com/v2.6/:pageid/subscribed_apps?access_token=:token
GET will return the current subscriptions (empty {[]}), POST returns {"success" : "true"}
Some other gotchas I hit were,
the examples use https://graph.facebook.com/v2.6/me/.. but I seemed to need to use, https://graph.facebook.com/v2.6/:pageid
the access token is the messenger access token, not your API access token
if your webhook throws a error, Facebook will stop sending you messages for a while
One thing I'm still puzzled over is how to support managing multiple pages from one Facebook app? Anyone know the answer to this, or do you need to create anew app and get permission for every page?
Another thing which can prevent some responses from being sent to your webhook is when a message type gets blocked in a queue.
If a particular message type is delivered to your webhook but doesn't receive it's 200 response within 20 seconds it will keep trying to send you that message again for hours.
What's more facebook messenger will stop sending you any more of that message type until the first one has been acknowledged. It essentially puts them into a queue.
In the meantime, other message types will continue to send fine.
This happened to me when I accidentally introduced an undeclared variable inside my code which handled standard messages. It meant that postback messages all worked fine, but quick replies and normal messages would never get sent to my webhook. As soon as you fix the error, they all come piling through at once.
As mentioned by others, using a service such as POSTMAN to send messages to your webhook is a great way to find this kind of errors, otherwise, messenger just fails silently.
Exluding of your bot rout from CSRF verification can help if you use framework. This helps for me (Laravel 5.4, app/Http/Middleware/VerifyCsrfToken.php):
protected $except = [
'/your_bot_route'
];
I too had the same issue when I was working on a bot couple of days ago. Followed this gist and modified the code as below, and everything is working fine.
public function index()
{
$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];
// Set this Verify Token Value on your Facebook App
if ($verify_token === 'MyVerifyToken!') {
echo $challenge;
}
$input = json_decode(file_get_contents('php://input'), true);
// Get the Senders Graph ID
$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
// Get the returned message
$message = $input['entry'][0]['messaging'][0]['message']['text'];
//$senderName = $input['entry'][0]['messaging'][0]['sender']['name'];
$reply="Sorry, I don't understand you";
switch($message)
{
case 'hello':
$reply = "Hello, Greetings from MyApp.";
break;
case 'pricing':
$reply = "Sample reply for pricing";
break;
case 'contact':
$reply = "Sample reply for contact query";
break;
case 'webinar':
$reply = "Sample reply for webinar";
break;
case 'support':
$reply = "sample reply for support";
break;
default:
$reply="Sorry, I don't understand you";
}
//API Url and Access Token, generate this token value on your Facebook App Page
$url = 'https://graph.facebook.com/v2.6/me/messages?access_token=MYACCESSTOKEN';
//Initiate cURL.
$ch = curl_init($url);
//The JSON data.
$jsonData = '{
"recipient":{
"id":"' . $sender . '"
},
"message":{
"text":"'.$reply.'"
}
}';
//Tell cURL that we want to send a POST request.
curl_setopt($ch, CURLOPT_POST, 1);
//Attach our encoded JSON string to the POST fields.
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonData);
//Set the content type to application/json
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
//Execute the request but first check if the message is not empty.
if (!empty($input['entry'][0]['messaging'][0]['message'])) {
$result = curl_exec($ch);
}
}
Note : Ensure the user roles within the application page to get the responses from the web hook. I have set Administrator, and Tester user. Only there were able to get the responses. Other users will get once this is published. Also, change verify token, and page token accordingly.
There is an option that is asked while publishing the app about the number of business this bot going to be used by. But I have no idea how to use it. Still searching that though.
If you still can not solve your problem, try to check and update your Privacy policy link.
I updated worry link to Privacy policy, and Facebook show 404 error even the webhoob is verified...
You can link multiple pages to your app, under Add or Remove Pages tab in your Messenger Settings

Can't send FB Notifications with new API

Really need some help with this one!
I'm trying to send notifications from a canvas app using the new notifications API but I keep getting the following exception:
OAuthException: (#200) Only web canvas apps can send app notifications
However, the app IS loaded in the Facebook canvas -- I'm making an ajax call to my server when the user takes a particular action which triggers the notification POST request. The user has also authorized the app.
This is the code I'm using:
$graphUrl = $user_id . "/notifications";
$params = array( "access_token" => $admintoken,
"href" => $link,
"template" => "string of text < 180 chars"
);
try {
$result = $facebook->_graph($graphUrl, 'POST', $params);
} catch (Exception $e){
echo $e;
}
I just ran into this too and this is how I solved it, but this may not be relevant to you as you seem certain yours is a Canvas app. Mine is an app that mostly runs off Facebook, but has Facebook integration hooks that means users can authorise my Facebook App and then receive updates about interesting events via the Facebook framework.
I went to edit my App settings in the Facebook Developers app, look on the Settings->Basic page near the bottom. I only had "Website With Facebook Login" checked. I checked "App on Facebook" and this gave me a "Canvas Page" and various other settings. With these filled in and saved, the POST to uid/notifications worked immediately.
Incidentally, going to apps.facebook.com/myappnamehere fails because it redirects to https and the request to my site fails because my SSL isn't set up right, but this didn't prevent notifications being sent under that apps credentials.
Recently, I was facing this same issue and I found that Facebook Web Games are formally known as Facebook Canvas.
So, Just create an Facebook game configuration under Settings->Basic page (You will see add button at the bottom of this page) and your API will start sending notifications.
1:\ Go to developer.facebook.com
2:\ Go to your app Settings \ Basic
3:\ Add new platform from plus at button bottom of the page
4:\ Choose Facebook Canvas
now you may need to fill form with your url
That's it