I've done a lot of searching and I've found outdated tutorials that don't work...
I have a site made with PHP and when I submit a particular form in my admin area, I want to publish to my Facebook "fan page"
There is no RSS available, so do you have any example to directly post to the Facebook fan page (not user wall) using php sdk?
Thank you!
Finally, after a lot of tests, it worked, without the PHP SDK. This is the step by step guide:
1. Get permissions and the page token
Go to https://developers.facebook.com/tools/explorer/ and select your app from the first drop down menu, in the left.
Click on the button "Get access token", and in the "Select Permissions" window, click in "Extended Permissions" and check manage_pages and publish_stream, and click in "Get Access Token" blue button.
You may be asked in this step to grant permissions to your app to access to your Facebook account, accept.
Next, click at the end of the text field next to the "GET" drop down, and replace the numbers for: me/accounts, and click in the blue button next to this text field.
You'll get the tokens for all your pages, including your app page. Find your page name in the list, will look like this: "name": "Your page name"
When you located your page, copy the access token for the page (will be really long), that can look like this: "access_token": "XXXXXXXX". Also copy the id of the page: "id": "XXXXX".
That's all for this step, we can start coding now.
2. Post to your page wall via PHP
First, for this script, you'll need a server supporting curl.
We start the PHP document defining the page access token and the page id that we've get in the 1st step:
<?php
$page_access_token = 'XXXXXXX';
$page_id = 'YYYYYYYY';
After that, we create an array with the info to post to our page wall:
$data['picture'] = "http://www.example.com/image.jpg";
$data['link'] = "http://www.example.com/";
$data['message'] = "Your message";
$data['caption'] = "Caption";
$data['description'] = "Description";
You can of course, use any other post parameter described in https://developers.facebook.com/docs/reference/api/post/ and if you don't need one or many of the parameters above you can simply delete it.
Ok, At this point we add to the array the access token:
$data['access_token'] = $page_access_token;
And we set our post URL, to post in our page:
$post_url = 'https://graph.facebook.com/'.$page_id.'/feed';
And the last step, we'll use a curl to post our message in our page wall:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);
?>
After that, we can save our PHP document, and try to execute it. The post may appear in our Facebook page.
Hope this code helps to other people with the same problem!
You can test tokens using
Facebook Access Token Debugger
Working solution for API v.2.5
Get code for app_id as parameter of response_uri
https://www.facebook.com/dialog/oauth?client_id=".$app_id."&redirect_uri=".$response_uri."&response_type=code&scope=manage_pages,publish_pages
Get access_token based on code, app_id and app_secret as result of response_uri
https://graph.facebook.com/oauth/access_token?grant_type=authorization_code&client_id=".$app_id."&client_secret=".$app_secret."&code=".$code."&redirect_uri=".$response_uri
Get never expiring page_access_token for page_id based on access_token
https://graph.facebook.com/v2.5/".$page_id."?fields=access_token&access_token=".$access_token
As an addition to nmarti answer. Valid for API v.2.4.
If you don't want to go Facebook API console, rather do API calls, there are some instructions.
First of all, you have to have Facebook user, being admin on the page you want to post, also you have to create Facebook App in order to proceed.
Do login request, to get user token:
https://www.facebook.com/dialog/oauth?client_id=%app-id%&redirect_uri=%your-site-url%&response_type=token&scope=manage_pages,publish_pages
In response, you should get %user-token%, save it, you will need in the next step.
Read More
Ask for long lived token:
https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=%app-id%&client_secret=%app-secret%&fb_exchange_token=%user-token%
Now you will have %long-lived-token%, required to get long lived page token.
Read More
Now, get a list of your Facebook Pages,
https://graph.facebook.com/v2.4/%page-admin-user-id%/accounts/?access_token=%long-lived-token%
Find in the list your Page, and a page token, now you can continue with posting to page using nmarti example.
Also Facebook says:
The resulting page access token will not have any expiry time.
Read More
Here is the resource you are looking for. Scroll down to Page Login and read from there.
You have to get an access token for your page and then use that token when posting. This is assuming that you want your post to appear "from the page". IE - posting as if you were the page.
the actual call to the graph api to create a post object, and how to do it, can be found at this url from the facebook documentation.
Related
I am trying to post to a Facebook account (with permissions) using the PHP
API. I am giving our users two options - posting to the Feed, and posting
to a specific facebook page. I am getting an error in the first case, but
not in the second case. In the code below:
$access_token is the access token I got back from linking to my app. It's of type
"User", and has the following permissions:
email
pages_show_list
business_management
pages_read_engagement
pages_manage_metadata
pages_read_user_content
pages_manage_ads
pages_manage_posts
pages_manage_engagement
public_profile
Where $page_token is, well, a "Page" type token, with the same set of permissions.
When I post to the page, it works fine. But when I try to post to the timeline, I get
the error:
Graph Error 200 : [Timeline]: [(#200) If posting to a group, requires app being
installed in the group, and either publish_to_groups permission with user token,
or both pages_read_engagement and pages_manage_posts permission with page token;
If posting to a page, requires both pages_read_engagement and pages_manage_posts
as an admin with sufficient administrative permission]
I'm not trying to post to a group, I'm posting to an account's timeline. And, per the
access token debugger, I have the permissions requested anyway. What's going on?
My code is below:
$linkData = [
'link' => $link_to_post,
'appsecret_proof' => $app_secret_proof
];
if ( POSTING TO TIMELINE )
{
$token = $access_token;
$post_to = "/me/feed";
}
else
{
$page_id = $page_id;
$token = $page_token;
$post_to = "/$page_id/feed";
}
// THIS THROWS THE EXCEPTION:
$response = $this->fb->post($post_to, $linkData, $token);
You can not post to a personal timeline via API any more, that was removed ages ago already. (With introduction of API v2.4, if I remember correctly.)
You can only use the Share or the Feed dialog, to offer the user a way to actively share / make a post themselves, https://developers.facebook.com/docs/sharing/web
My chat bot is working great but I am having trouble debugging the Welcome message functionality because it only shows up when a conversation is initiated (although i'm pretty sure it's not working having tried it on a colleagues phone). How do I reset my chat so it sees me as a new user interacting with it?
This is my welcome PHP Script at the moment
<?php
function webhook() {
$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];
if ($verify_token === 'MYTOKEN') {
echo $challenge;
}
$input = json_decode(file_get_contents('php://input'), true);
$sender = $input['entry'][0]['messaging'][0]['sender']['id'];
$welcomejson = welcomemessage();
welcomesend($json);
function message() {
$json = '{
"setting_type":"call_to_actions",
"thread_state":"new_thread",
"call_to_actions":[
{
"message":{
"text":"Welcome to My BOT!"
}
}
]
}';
return $json;
}
function send($json) {
$url = 'https://graph.facebook.com/v2.6/MYPAGEID/thread_settings?access_token=MYTOKEN';
//Initiate cURL.
$ch = curl_init($url);
//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
$result = curl_exec($ch);
}
Try this:
Open Facebook in a desktop browser and go to the page linked to your messenger bot
Press "Message"
Inside the message popup/discussion choose "Options" (cog icon)
Select "Delete Conversation..." and say "Delete Conversation" in the confirmation prompt
Select "Message" again
Select "Get Started"
Step 4. really deletes the chat history you are having with the page/app so beware.
On desktop, delete the conversation and message the page again.
This will allow you to see the "Get Started" button again, allowing you to test it and your welcome message's functionality.
If you're trying to test the "Messenger Greeting", it's a lot more complicated. See below.
On Desktop the "Messenger Greeting" still will not show up after deleting the conversation. Only the "get started" button reappears. I believe this is a bug that I will be opening up a ticket for most likely.
You can get a similar experience on mobile by deleting the conversation, uninstalling, and reinstalling Messenger, but once again that does not display the Messenger greeting, it only shows the get started button.
Not being able to see the Messenger Greeting again is an issue for developers who are picky about the line-by-line formatting of the Messenger greeting, or who simply need to see it again for a demo of the messenger bot once the greeting has already been seen.
Thankfully, although EXTREMELY painful, there's a workaround. Basically have to re-setup your bot.
Create a new page
NEVER OPEN A MESSAGE WITH THE PAGE/BOT UNTIL STEP 17
Click settings, Messenger, and set your messenger greeting, and press save.
Since that doesn't actually save the toggled setting for some reason, select a different thing from messenger in the sidebar
Reselect Messenger
Turn on the greeting (the message should have saved properly, just not the toggle for whether its on or off)
Change to a different thing in sidebar
Re-select Messenger and double check that the messenger greeting is enabled
Create a new app
Add Messenger as a product
Select the page and copy the page access token
Put the page access token where it is needed in your code
Run your code
Connect to the webhook url with your verify token and all the boxes checked
After webhook connection is successful, subscribe it to your new page
Run your curl command to enable the 'get started' button and your welcome message that will happen after the button is pressed
Open a message with your page, and the Messenger greeting and get started button should appear. YOU GET ONE CHANCE AND THEN YOU'LL HAVE TO REPEAT ALL OF THESE STEPS TO SEE THE GREETING AGAIN.
I believe the toggle on messenger greeting not saving right is also a bug, and I may open a ticket for it.
There is a way to get the welcome screen in Messenger on iOS (at least as of Apr 28th), although it's super annoying. Basically, in addition to deleting the convo, you have to reinstall the app on your phone.
Go to the paged linked to your bot in facebook on desktop
Archive the conversation
Open Messenger on your phone and delete the conversion by swiping right on the cell in the conversation list
Delete Messenger from your phone
Reinstall Messenger from the App Store
I want to find the list of friends of Google+ user who have authorized the app without asking for authorization again.
For example: Once the user login using the Google+ to my website, I store the auth token, code, Google+ user id in the db.
So once that is done I want to find the list of users friends in his circle.
I managed to get the first part working and it saves the auth token, code, Google+ user id in the db.
But in the second case i.e. finding the list of users friends, I again get a the screen where user have to authorize the app.
Can someone please help me in this?
Also is it possible to get all the user details in offline mode like using the auth token, code, Google+ user id which is in the db?
Initial code(login):
require_once __DIR__.'/social-api/google/Google_Client.php';
require_once __DIR__.'/social-api/google/contrib/Google_PlusService.php';
$this->sn_obj = new Google_Client($google_app_id, $google_secret_key, $call_back_url);
$this->plus_obj = new Google_PlusService($this->sn_obj);
$this->sn_obj->setRedirectUri($call_back_url);
$this->sn_obj->setState($redirect_url);
$requestVisibleActions = array('http://schemas.google.com/AddActivity','http://schemas.google.com/ReviewActivity');
$this->sn_obj->setRequestVisibleActions($requestVisibleActions);
$this->sn_obj->setAccessType('offline');
$this->sn_obj->setScopes(array('https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/plus.login'));
$this->sn_obj->createAuthUrl();
In callback page:
require_once __DIR__.'/social-api/google/Google_Client.php';
require_once __DIR__.'/social-api/google/contrib/Google_PlusService.php';
$this->sn_obj = new Google_Client($google_app_id, $google_secret_key, $call_back_url);
$this->plus_obj = new Google_PlusService($this->sn_obj);
$this->sn_obj->setRedirectUri($call_back_url);
$this->sn_obj->setState($redirect_url);
$requestVisibleActions = array('http://schemas.google.com/AddActivity','http://schemas.google.com/ReviewActivity');
$this->sn_obj->setRequestVisibleActions($requestVisibleActions);
$this->sn_obj->setAccessType('offline');
$this->sn_obj->setScopes(array('https://www.googleapis.com/auth/userinfo.profile','https://www.googleapis.com/auth/userinfo.email','https://www.googleapis.com/auth/plus.login'));
$this->sn_obj->authenticate();
$google_auth_token = $this->sn_obj->getAccessToken();
$google_user_info = $this->plus_obj->people->get('me');
Friends listing page:
require_once __DIR__.'/social-api/google/Google_Client.php';
require_once __DIR__.'/social-api/google/contrib/Google_PlusService.php';
$this->sn_obj = new Google_Client($google_app_id, $google_secret_key, $call_back_url);
$this->plus_obj = new Google_PlusService($this->sn_obj);
$this->sn_obj->setRedirectUri($call_back_uri);
$this->sn_obj->authenticate();
$user_info = $this->plus_obj->people->listPeople($token['oauth_uid'],'visible');
In general, when working in offline mode, you need to store the entire object that comes back from the server - not just the auth token. This object includes the long-lived refresh token as well as information about when it needs to do a refresh. Passing this entire token to the service allows it to refresh the token for you.
The answer you came up with looks like you do the refresh yourself manually - which is fine, but shouldn't be necessary in general.
In some cases, if a user authorizes your app before you have requested offline mode, and you later request offline mode, you still won't get the refresh token. Google will only give a refresh token when asked if there is no auth token, current or expired, that was issued. There are two ways around this:
When you switch to using offline mode, invalidate your old client id / secret and start using a new one. or
Have the user de-authorize your app via https://accounts.google.com/b/0/IssuedAuthSubTokens or (if you're using Google+ Sign-In) via https://plus.google.com/apps
Finally managed to get get it done
On Friends listing page:
require_once __DIR__.'/social-api/google/Google_Client.php';
require_once __DIR__.'/social-api/google/contrib/Google_PlusService.php';
$this->sn_obj = new Google_Client($google_app_id, $google_secret_key, $call_back_url);
$this->plus_obj = new Google_PlusService($this->sn_obj);
if(!$this->sn_obj->getAccessToken()){
$this->sn_obj->refreshToken($refresh_token_from_db);
}
$google_auth_token = $this->sn_obj->getAccessToken();
$google_auth_token_arr = json_decode($google_auth_token,true);
$url = 'https://www.googleapis.com/plus/v1/people/'.$uid_from_db.'/people/visible?access_token='.$google_auth_token_arr['access_token'].'&format=json';
$c = curl_init($url);
curl_setopt($c, CURLINFO_HEADER_OUT, 1);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
$contents = curl_exec($c);
curl_close($c);
$user_info = json_decode($contents, true);
I have spent quite some time now trying to establish how, and then the best practise to push some data from my web server to the facebook page created for this purpose.
I have read and understand the process of using access tokens. I have generated an access token for myself, which can be used to post to the page as me ok. I understand this should be used to generate the access token for the page to post as the page which is a ittle more tricky. However, this process involves me logging in and generating an access token which seem inherently bad / inconvenient for an automated process.
For this reason i followed the guides to create an app. I (think I have) linked the app to the page, and thus attempt to push data via the appid and secret from my php code to the page.
When doing this I am presented with this error
{"error":{"message":"(#210) Subject must be a page.","type":"OAuthException","code":210}}
my testing code is this:
$data['picture'] = "http://www.example.com/image.jpg";
$data['link'] = "http://www.example.com/";
$data['message'] = "Your message";
$data['caption'] = "Caption";
$data['description'] = "Description";
$data['access_token'] = $app_token2;
$post_url = 'https://graph.facebook.com/'.$app_id.'/feed';
$url1 = "https://graph.facebook.com/endpoint?key=value&access_token=".$app_id."|". $app_secret ;
echo "<br>$post_url";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $post_url);
//curl_setopt($ch, CURLOPT_URL, $url1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);
echo "$return";
I appreciate using the app for server initiated posting using a permanent (ish) secret is the correct way, but I have found very little documentation on how this process is achieved, hence this question.
Your $post_url is pointing to your $app_id variable, the message says it should point to a page, try getting the id of your page from the /me/accounts endpoint of the graph and putting that in there instead. Though I suspect you will need to use a page access_token (also from the /me/accounts endpoint ) to post to your page
Right, I have worked on this for quite some time and found several errors in my code, but have not answered the question fully.
For starters, you do not post to the appid as mentioned above - its just wrong. The code for posting to userid/feed works when using an access token generated from appid + secret using
$url2 = "https://graph.facebook.com/oauth/access_token?client_id=".$app_id."&client_secret=". $app_secret."&grant_type=client_credentials";
this app access token is valid for as long as your app secret is. Also, if I generate a temporary access code for ME via the graph explorer, parse me/accounts manually and use the page token in
$post_url = 'https://graph.facebook.com/'.$page_id.'/feed';
It posts correctlly as the page.
Secondly, all server side call are required to have appsecret_spoof in them which is generated from
$appsecret_proof= hash_hmac('sha256', $app_token2, $app_secret);
now, according to the facebook docs, a http get call to my userid/accounts should yield page access tokens for all pages the user administers (and also presumably the app).
This can also be called directly by using
$url3 = "https://graph.facebook.com/".$page_id."?fields=access_token";
so when a get is made to this address (including app access token & appsecret_spoof) all i get is 'True' ??
Likewise, when the correct call to
$rob1 = "https://graph.facebook.com/".$user_id."/accounts";
I receive an error
{"error":{"message":"(#10) Application does not have permission for this action","type":"OAuthException","code":10}}
OK permission issue then ! Well the documentation says that only manage_pages is required to retrieve the page token from page_id/accounts, so I trawl through lots of pages and find you can do this by calling this url
https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope=read_stream
This throws up via facebook gui an accept / deny page for each scope (i ended up adding manage_pages, publish_stream & read_stream to my app) none of which seem to solve the problem !
Right sorted !! FWIW the code above functions correctly, however the way it is setup on facebook leaves a lot to be desired !!!
I began messing with my app and changed its name, type (was an app linked to the page - now isnt) removed perms and also changed the domain name (removed) and all site url details (also removed). this prompted a different error msg which stated the domains did not match. So, I readded just the app domain & site url, saved and all of a sudden my failed code started working !
Having tidied my code up a little I can now see the page access token just fine as I expected. I just wish the facebook guides would cross reference this setup as it is not at all obvious !!!
my working code ended up as thus ($perm_url is used as one time link to allow perms via gui)
$perm_url = "https://www.facebook.com/dialog/oauth?client_id=".$appid."&redirect_uri=https://www.facebook.com/connect/login_success.html&response_type=token&scope=publish_stream,manage_pages,read_stream,status_update";
echo "<br>Test";
$facebook = new Facebook(array('appId' => $appid , 'secret' => $appsecret ,));
$access_token = $facebook->getAccessToken();
$pageinfo = $facebook->api("/".$page_id."?fields=access_token");
$page_access_token = $pageinfo['access_token'];
echo "<br>Holy Grail = $page_access_token ";
I'm able to update the status on my PROFILE wall using this code:
require_once 'facebook-platform/php/facebook.php';
$facebook = new Facebook('APP API KEY','APP SECRET KEY');
$user_id = 'MY USER ID';
$facebook->api_client->users_setStatus('This is a new status');
...after authorizing using this address:
http://facebook.com/authorize.php?api_key=MYAPPAPIKEY&v=1.0&ext_perm=publish_stream
This code, however, does not work to update the status on my Facebook PAGE Wall. Are there additional parameters that I can add to the authorize.php url to specify authorizing the PAGE and not just my profile?
Or, are there better ways to post updates to Fan Page Walls?
Thanks!
I solved the problem by consulting the Facebook desktop application documentation (even though this is a web application).
I first had to authorize offline access with this url (replacing 'MYAPIKEY'):
http://www.facebook.com/login.php?api_key=MYAPIKEY&connect_display=popup&v=1.0&next=http://www.facebook.com/connect/login_success.html&cancel_url=http://www.facebook.com/connect/login_failure.html&fbconnect=true&return_session=true&session_key_only=true&req_perms=read_stream,publish_stream,offline_access
Then, I needed to grant 'publish_stream' permissions to the PAGE with this url (replacing 'MYAPIKEY' and 'THEPAGEID'):
http://www.facebook.com/connect/prompt_permissions.php?api_key=MYAPIKEY&v=1.0&next=http://www.facebook.com/connect/login_success.html?xxRESULTTOKENxx&display=popup&ext_perm=publish_stream&enable_profile_selector=1&profile_selector_ids=THEPAGEID
I could then use the following code to publish to the Fan Page wall:
require_once 'facebook-platform/php/facebook.php';
$facebook = new Facebook(MYAPIKEY, MYAPISECRET);
try{
$facebook->api_client->stream_publish('INSERT_STATUS_HERE',null,null,null,'THEPAGEID');
}catch(Exception $o ){
print_r($o);
}
Based on the above, i tried out a couple of querystring parameters on the graph API authorize URL, and it appears this works:
https://graph.facebook.com/oauth/authorize?client_id=[APP_ID]&redirect_uri=[REDIRECT_URL]&scope=publish_stream&enable_profile_selector=1&profile_selector_ids=[PAGE_IDS]
EDIT: Never mind, the above displays all the UI correctly, but still get the "(#200) The user hasn't authorized the application to perform this action" error --- it's clear it doesn't work because the access token contains my USER id but not the page's ID.