Intermittent bad Facebook app access_token - facebook

I'm creating test users in Facebook for my application. It works sometimes. When it doesn't, the error occurs on this call:
function getTestAccounts($fb, $a) {
$s = urlencode($a);
**$accounts = $fb->api("/{$fb->getAppId()}/accounts/test-users?access_token=$s");**
if( isset($accounts['data']) )
return $accounts;
else
return null;
}
Error is:
Uncaught OAuthException: (#15) This method must be called with an app access_token.
Previously I've obtained the token with this function:
function getAppAccessToken($fb) {
$access_token_url = "https://graph.facebook.com/oauth/access_token";
$parameters = "grant_type=client_credentials&client_id=" . $fb->getAppId() . "&client_secret=" . $fb->getApiSecret() . "&junk=1";
return file_get_contents($access_token_url . "?" . $parameters);
}
When I output the offending token, it looks something like this and does not change (should it?)
access_token=229234510434203|TK2UDoGCPthCBeDIvhRIPkSG8Wk
I've tried clearing cookies. That seemed to work but might have been coincidental with something else because it does not now.
I assume the access token returned from FB changes but it's always coming back the same.

Mark
for a user access token i use the below, where the number is my app id. "used with php-sdk"
$access_token = $_SESSION['fb_135669679827333_access_token'];
for an application access token i use cURL
$app_access_token = GetCH();
function GetCH(){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&client_secret=YOUR_APP_SECRET&grant_type=client_credentials");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
if(substr($url,0,8)=='https://'){
// The following ensures SSL always works. A little detail:
// SSL does two things at once:
// 1. it encrypts communication
// 2. it ensures the target party is who it claims to be.
// In short, if the following code is allowed, CURL won't check if the
// certificate is known and valid, however, it still encrypts communication.
curl_setopt($ch,CURLOPT_HTTPAUTH,CURLAUTH_ANY);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
}
$sendCH = curl_exec($ch);
curl_close($ch);
return $sendCH;
};
Let me know if this helps.

I made a greenhorn mistake. What I failed to notice was that this problem was only occurring after I opened another browser tab and logged to Facebook as myself or a test user. The new Facebook session was interfering with the API.
I guess the API uses the access token of the logged on user instead of what's passed in the request. Kind of obvious once you understand it!
Hope this helps the next person :-)

Related

PayPal Payments Advanced Setup Error

I am trying to integrate PayPal advanced payments into my website so that users can make payments directly on the website, however I am having trouble with setting it up. This is what my code looks like:
$amt = 10.00;
$txt = "Pay Now!";
$PF_HOST_ADDR = "https://pilot-payflowpro.paypal.com";
$secureTokenId = uniqid('', true);
$postData = "USER=" . "username"
. "&VENDOR=" . "username"
. "&PARTNER=" . "PayPalCA"
. "&PWD=" . "Password"
. "&CREATESECURETOKEN=Y"
. "&SECURETOKENID=" . $secureTokenId
. "&TRXTYPE=S"
. "&AMT=" . $amt;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $PF_HOST_ADDR);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$resp = curl_exec($ch);
if (!$resp) {echo "<p>To order, please contact us.</p>";}
parse_str($resp, $arr);
if ($arr['RESULT'] != 0) {echo "<p>To order, please contact us.</p>";}
echo "<iframe src='https://pilot-payflowlink.paypal.com?SECURETOKEN=" . $arr['SECURETOKEN'] . "&SECURETOKENID=" . $secureTokenId . "&MODE=TEST' width='490' height='565' border='0' frameborder='0' scrolling='no' allowtransparency='true'>";
I'm using layout C (embedded iframe) instead of A or B (Hosted checkout pages, which would use a form at the end instead of an iframe).
The result I get looks like this:
Array ( [RESULT] => 1 [RESPMSG] => User authentication failed )
And the iframe gives the following error:
Error: Invalid Merchant or Merchant doesn't exist!
I am entering the same information I use to log into my account at https://manager.paypal.com/ and I have done all the required setup on that website. Any help would be greatly appreciated.
The code you have provided works fine as long as the manager credentials are working properly.
The only way I was able to get that error with correct credentials is changing from TEST to LIVE inside of the hosted checkout setup page inside the manager account.
You may want to try creating a secondary user in your manager account if those settings are correct.
I solved this by logging into the PayPal Manager, going to Service Settings->Customize and clicking Save and Publish.

How to make a personal facebook app

I'm trying to make a facebook application that would do something on my own timeline. I can't understand facebook's own manual about this so i'm not really sure how things work there, so i'm hoping someone can clarify things here. I don't want anyone installing that application or somehow abusing it to post things on my timeline in my name. What steps should i take to prevent these things if possible?
Beyond what you have learned yet, you can use the php-sdk to authenticate and then check the visitors user id.
"i will edit in code as we discover what you are trying to accomplish, action wise."
php sdk example.
// init php sdk here.
// check if we have a user
// call api to get info about use
$user_profile = $facebook->api('/me');
// if we have a user, we can use that user id as a wrapper to filter content.
if($user_profile[id]==='000000000'){
// 000000000 is your facebook id for this example.
// i am logged in, and only i can see this.
// get some info, make a few posts, add photos etc; here.
}
cURL example
when you curl 'me', it ensures that it is the current session user, then when you compare that to your actual user id, you can gate "so to speak" content that only you can see and use.
cURL'ing to the me connection is only needed to create gate, you can do all your other curl calls after you know it is you doing it.
http://anotherfeed.com/curl.api.php?objid=me
here is an example, when i curl me, it looks for a logged in user, if there is an access token which for this example i excluded, it will return an array with my "me" info including my id.
Hard coded i will use $me=$curlresults[id] which is my user id returned by the session call.
to gate i simply
$me=$curlresults[id]
if($me==='myfacebookuserid'){
// do my other curl calls here, i know only i can see this.
}
Full cURL example.
get your user access token for your app from the token tool below, store it somewhere safe so you can pass it in via url param or session param.... https://developers.facebook.com/tools/access_token/
add your facebook user id where it says myfacebookuserid
to secure this you will need to pass the access token in with post, get or session.
for this example we will use the get method.
yourpage.php?user_token=youruseraccesstoken is how it is passed in this example.
$access_token = $_GET['user_token'];
$build = 'https://graph.facebook.com/me?'.$access_token.'';
function GetCH($url){
$ch=null;
if(!$ch){
$ch = curl_init();
}
curl_setopt($ch, CURLOPT_URL, "".$url."");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$return=curl_exec($ch);
if(!curl_errno($ch)){
return $return;
}else{
$fb_fail=curl_error($ch);
return $fb_fail;
}
curl_close($ch);
unset($ch);
};
$returned=GetCH($build);
$locs=json_decode($returned, true);
$meid=$locs[id];
if($meid==='myfacebookuserid'){
// do my other curl calls here, i know only i can see this.
}

Facebook extending user access token

Facebook documentation says offline_access is depreca ted.How do I extend the access token for 60 day?
I did enabled deprecated offline_access from advanced settings for app.
you can try to two ways:
1. enable the offline deprecation functionality, and grab the exchanged token value in available and then run cUrl functionality. After running the cUrl just pass the response value in var_dump().. you could see the access token and the expires date..
you will get different value for the opposite process of (1).
You can use https://developers.facebook.com/docs/howtos/login/extending-tokens/ for long lived access tokens, or https://developers.facebook.com/docs/howtos/login/login-as-app/ for non-expiring app access tokens. But you probably need the first.
function fb_renew_access_token($args=array()){
$token_url = "https://graph.facebook.com/oauth/access_token?client_id=".$args["app_id"]."&client_secret=".$args["app_secret"]."&grant_type=fb_exchange_token&fb_exchange_token=".$args["old_token"];
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_URL, $token_url);
$contents = curl_exec($c);
$err = curl_getinfo($c,CURLINFO_HTTP_CODE);
curl_close($c);
$paramsfb = null;
parse_str($contents, $paramsfb);
return $paramsfb;
}
//to get the extended access token
$extended_access = fb_renew_access_token(array("app_id"=>"4545454544s45454545","app_secret"=>"sdfgds2fg4d2f54g5df4gdsdsfgdsfg54dfg","old_token"=>"54sdf54sd54f35asdgs4ghdsd5sh4d5trh4djhdfj45fdh"));

Facebook Auth with high traffic sites: empty access tokens, empty /me

We have an app running on a Facebook tab at the moment which is receiving a good deal of traffic. People are signing up every few seconds, and most are successful. However I am running into the following problems:
- access token not received at all (empty response, no error)
- or if it is received, then API call to /me fails (empty response, no error)
EDIT: Apparently limiting of API calls is not the issue, since the 600/600 calls/sec is per user which makes a lot more sense :).
Is anyone else experiencing such issues? I am getting about 20-30 successful app signups a minute and about 2-3 failing ones. Note: these are not users who deny access to the app - those are handled elsewhere...
EDIT: I am getting "failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request"
$token_url = "https://graph.facebook.com/oauth/access_token?client_id=".$oauth_clientid."&redirect_uri=".urlencode($redirect_url)."&client_secret=".$oauth_secret."&code=".$code;
$access_token = file_get_contents($token_url);
Update: After modifying my code to use curl, there was some improvement, but it did not resolve the issue. The application in question is now past its peak usage, so obviously the number of errors have gone down drastically. It still happens sometimes. The errors are (most often):
Curl error (6): Couldn't resolve host 'graph.facebook.com'
Curl error (28): SSL connection timeout
...and other similar errors.
From my experience with a week or two of data, it seems to effect about a percent of requests when there is high traffic, less when there is low - but this is quite unscientific. :)
--
So the solution? Well there is none really. It seems that some percent of requests will fail and my (your) application needs to handle these errors as elegantly as possible.
My only question is, has anyone else had such experience with high traffic apps? (meaning in this case 100 000-500 000 daily pageviews and 50 000-100 000 active users)
Try to log the curl error and return value when you obtain the access_token the answer should be there.
I think it's because php_openssl extension is either absent or disabled. See this question to enable it. Or you can use cURL. Take fb_ca_chain_bundle.crt from PHP SDK official (or set CURLOPT_SSL_VERIFYPEER to false):
$base_url = 'https://graph.facebook.com/oauth/access_token';
$params = array();
$params['client_id'] = $client_id;
$params['client_secret'] = $client_secret;
$params['redirect_uri'] = $redirect_uri;
$params['code'] = $code;
$options = array(
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_CAINFO => __DIR__ .'/fb_ca_chain_bundle.crt',
CURLOPT_RETURNTRANSFER => true,
CURLINFO_HEADER_OUT => false,
CURLOPT_HEADER => false,
CURLOPT_URL => $base_url . '?' . http_build_query($params),
);
// Init cURL and send the request
$ch = curl_init();
curl_setopt_array($ch, $params);
$result = curl_exec($ch);
$infos = curl_getinfo($ch);
curl_close($ch);
var_dump($result, $infos);
EDIT: i warn you this is a quick copy and paste from my code so you would double check $options.

Delete requests returns true, but request still exists?

Possible answer or bug: Using the user access token seems to work, it deletes the request and will throw an error when trying to read it in the future, but it still exists in the graph and providing apptoken still shows it, and for some reason wouldn't delete it. Seems contrary to documentation, but changing apptoken to access token seemed to at least provide a workaround for me.
First, the code I'm using (as the one in the documentation always returned an entity not visible by user type message)
function do_delete_request($url, $optional_headers = null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//include array of additional headers
if (count($optional_headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $optional_headers);
}
return curl_exec($ch);
}
$full_request_id = build_full_request_id($request_id, $user_id);
$delete_url = "https://graph.facebook.com/" .$full_request_id. "?access_token=".$apptoken;
$result = do_delete_request($delete_url);
I'm sorry if that's messy, I don't know how to format stuff here. I'm at a loss after a lot of googling, I never ask this stuff.
$result returns true, over and over again. Graph explorer shows the request still exists.
By deleting it, does that just mean I remove it from the requests interface for a user? Or am I doing something wrong in my delete process?
I need a way to tell whether or not a request has been accepted already or not. Thanks for any help.
Facebook sends the user to your app with the Request ID(s) in the URL, that's how you tell when a request has been accepted. It's up to you to check for a process a response to a request.
https://apps.facebook.com/[app_name]/?request_ids=[request_ids]
As far as delete not working, is the request still their after some time? Facebook, and many busy sites, do heavy caching so things like delete may not be processed immediately.