Why can't I update our Twitter status? - php

I've spent the last three hours trying to get a simple Twitter status update to work using Zend_Service_Twitter and Zend_Oauth_Token_Access. Infuriatingly, I keep getting the following response:
object(Zend_Rest_Client_Result)#34 (2) {
["_sxml:protected"]=>
object(SimpleXMLElement)#39 (2) {
["request"]=>
string(33) "/1/account/verify_credentials.xml"
["error"]=>
string(20) "Invalid / used nonce"
}
["_errstr:protected"]=>
NULL
}
Here is the code I have tried:
$token = new Zend_Oauth_Token_Access();
$token->setToken('my token');
$token->setTokenSecret('my token secret');
$params = array('accessToken' => $token,
'consumerKey' => 'my key',
'consumerSecret' => 'my secret'
);
$twitter = new Zend_Service_Twitter($params);
$response = $twitter->statusUpdate('simpletest');
What on Earth is a 'nonce'? If I mess up the token/token secret the error message in the response changes accordingly. However, with correct credentials I keep getting the above noncence (pun intended). Also, I have tried several alternatives such as the ones in this previous post on SO.
Any help would be appreciated!
Update:
In case it helps, or makes things easier, all I am trying to do is update the status of a single Twitter account, which is the application's twitter account. As I commented below #David Caunt's answer, whenever an 'item' gets posted to our site, the site's Twitter status will update to a brief description of the item as well as a link. That's all! This used to work, before oAuth became compulsory to make API calls (all that was needed was to instantiate a Zend_Service_Twitter and pass in our credentials).

Consulting the reference manual, I believe your error is in creating the Zend_Service_Twitter object.
$twitter = new Zend_Service_Twitter(array(
'username' => 'johndoe',
'accessToken' => $token
));
$response = $twitter->status->update('My Great Tweet');
You do not need to pass in the key and secret again, as they are contained in the access token used to sign the request.
See also my comment above explaining the nonce.
UPDATE:
I've tried the code in a minimal environment and you're right, it simply doesn't work.
You can see all of my code in a GitHub gist. It's deliberately minimal, avoiding MVC and other complications.
You may take comfort in the fact that a Zend_Http_Client returned from the Access Token does work.

Twitter servers were reporting a problem with my nonces, when the error
was in the signature.
My OAuth code was working for most
requests, but when trying to post new
statuses I was getting "Invalid / used
nonce" as a response.
After much debugging, I found out I
was failing to encode spaces as %20
and instead was sending them as +.
After using the correct encoding, it
worked flawlessly.
Twitter servers should have reported a
problem with the signature, not the
nonce.
I don't really expect you guys to
waste any time fixing this (but it
would be nice)... I just want to leave
this note here so next time someone
comes googling for "invalid / used
nonce" they know they have to look at
their encodings too.
From http://code.google.com/p/twitter-api/issues/detail?id=1059
(other solution in comments)

Related

Bigcommerce customer login api (single sign-on) invalid login issue

I'm new to bigcommerce and jwt tokens. I'm trying to get the customer login api to work on a trail store. But have not been able to successfully login a customer automatically.
I got it to work once or twice, but now it doesn't work anymore, and an unable to figure out the odd behavior since nothing changed with the code. I've tried googling if anyone else has had issues with the customer login api but have found nothing.
I've gone thru the tutorial on https://developer.bigcommerce.com/api/v2/#customer-login-api and copied the example provided.
Is there something I'm missing with the code below?
I've gone to developer.bigcommerce.com and created a draft app.
I got the Client ID and Client Secret from the draft app.
I've gone into my trial store and successfully installed the draft app.
I've tested this page on SSL as well.
Could it be because it's a trail store and it will only work if it's a real store?
Thanks.
Here is the php code below:
include "vendor/autoload.php";
use Bigcommerce\Api\Client as Bigcommerce;
use Firebase\JWT\JWT;
function getCustomerLoginToken($id, $redirectUrl = '', $requestIp = '') {
/*
if (empty(self::$client_secret)) {
throw new Exception('Cannot sign customer login tokens without a client secret');
}
*/
$payload = array(
'iss' => '#MyApp1's Client ID#',
'iat' => time(),
'jti' => bin2hex(random_bytes(32)),
'operation' => 'customer_login',
'store_hash' => '#Store Hash#',
'customer_id' => $id
);
if (!empty($redirectUrl)) {
$payload['redirect_to'] = $redirectUrl;
}
if (!empty($requestIp)) {
$payload['request_ip'] = $requestIp;
}
return JWT::encode($payload, "#MyApp1's Client Secret#", "HS256");
}
$jwt = getCustomerLoginToken(1);
header("Location: " . 'https://store-#Store Hash#.mybigcommerce.com/login/token/' . $jwt);
exit();
There are a couple of constraints that can cause errors:
The app must be installed on the store (seems like you're all good here - you can also test with an API token created locally in the store - https://support.bigcommerce.com/articles/Public/Store-API-Accounts/)
The app must have the Login OAuth scope
The JWT URL must be visited within about 30 seconds, or it won't work.
The computer/server that's generating the JWT needs to have a clock that's synchronized, otherwise your IAT value will appear to have been created more than 30 seconds ago or even in the future which will fail.
The URL can only be visited exactly once - if anything runs a GET request against it other than the intended end user's browser, it won't work. For example, if you send the URL in a Slack message, slack will try to preview the link by visiting it and therefore invalidate it.
It's good to double-check that your JWT is valid at https://jwt.io/
BigCommerce support has access to logs which can shed more light on the situation if you've ruled out the above.
Hope this helps!
do not need app client_id and Secret code , you need to api's client_id and secret code

Google Play scraper

I'm trying to develop a Play Store reviews scraper in PHP and I need to make a POST request to this URL https://play.google.com/store/getreviews, and I saw the parameter post with firebug.
I am using Goutte library and here is my code:
require_once 'goutte.phar';
use Goutte\Client;
$client = new Client();
$params = Array(
"id" => "com.trello",
"pageNum" => 2 ,
"reviewSortOrder" => 2 ,
"reviewType" => 0,
"xhr" => 1
);
$crawler = $client->request('POST' , 'https://play.google.com/store/getreviews', $params);
The problem is that the request returns nothing. Is there anyone who already faced this problem and solved it?
I don't think this is possible. Google Play changed their review interface last year. They now have a "token" parameter which is missing here. I have worked before to try and work out what seeds this (see Google play review scraping changes) but I can't figure it out. After a number of attempts to hit that webservice with an incorrect request (presumably without the token) Google Play starts blocking your IP, that's why you'll be getting nothing back after a while (and won't be able to open Google Play in your browser either). If you find a solution, let me know!
This URL works for me, with the form-post data in your example.
https://play.google.com/store/getreviews?authuser=0

$facebook.getUser(); returning all the time 0

I'm posting here due to a problem with php and the sdk of facebook.
For a reason I don't really know, when I try to get the userID of the logged account, continuously I received the same value, 0, even if i'm logged.
I've been trying to debug some variables, $facebook, checking sessions, etc. but with unsuccessfully results, then i'm gonna step by detailing all what i'm doing and the debug log i'm doing:
I'm using hostinger servers, that hosts my website. Due to i've found many problems, i've created a test webpage in which i have 5 files:
index.php
callback.php
facebook.php (comes from facebook)
base_facebook.php
certificate
The code i have on index.php is what i've pasted here: [index.php]: http://pastebin.com/Mfdkxz8H This is only the first part of the code which tries to get the autentification.
The code i have on callback.php is what i've pasted here: [callback.php]: http://pastebin.com/Uw0A3NM8. There i try to get the userID.
I've read some post and for some reasons there were so many cases in which the token
wasn't received in the second file/call.
I don't really know what the problem is and would be happy to find a solution.
P.D It doesn't matter the appId and secret because facebook and webpage were created for a test.
Hard to tell what is going up from your code example (By the way, you should NEVER post your appId and secret in public like that otherwise someone will be able to compromise your application). A gave your code a quick glance and it "looks" fine but here are a couple of pointers:
But here are a couple of pointers.
1) Make sure you have the latest version of the Facebook SDK (assuming you do)
2) For SANITY sake, i would keep your Facebook API files in its their folder ('sdk')
3) DOUBLE CHECK your app settings to make sure the appID and secret are correct (I have made this mistake many times), also make sure that your at is NOT in sandbox mode
4) Then try something like this
include_once("sdk/facebook.php");
//Call Facebook API
$facebook = new Facebook(array(
'appId' => XXXXXXXXXXXXXXXX,
'secret' => XXXXXXXXXXXXXXXX,
'cookie' => true, // enable optional cookie support
));
$params = array(
'scope' => 'email',
'redirect_uri' => 'http://devstarlight.esy.es/facebook/callback.php'
);
$login_url = $facebook->getLoginUrl($params);

How to get user image with Twitter API 1.1?

In API 1.0, we can use users/profile_image/:screen_name
For example : http://api.twitter.com/1/users/profile_image/EA_FIFA_FRANCE
But, it doesn't work anymore in API 1.1.
Do you have a solution, please ?
You can also get the twitter profile image by calling this kind of url :
https://twitter.com/[screen_name]/profile_image?size=original
For instance : https://twitter.com/VancityReynolds/profile_image?size=original
Got the info from this post :
https://twittercommunity.com/t/how-to-get-user-image-original-size-with-api-1-1/10187/14
The user's profile image
Okay, so you want a user's profile image. You're going to need to take a look at the twitter REST API 1.1 docs. This is a list of all the different requests you can make to their API (don't worry, I'll get to how you actually do this later on).
There are multiple ways to get the user's profile image, but the most notable one is: users/show. According to the docs for this, the users/show method:
Returns a variety of information about the user specified by the required user_id or screen_name parameter. The author's most recent Tweet will be returned inline when possible.
Well, the user profile image must be in there somewhere, correct?
Let's have a look at a typical response to a request for this information, using the users/show url (we'll use my profile as an example).
I've cut off some from the bottom, because there is a lot of data to go through. Most importantly, you'll see what you require:
This is the profile_image_url key that you need to get access to.
So, how do you do all this? It's pretty simple, actually.
Authenticated Requests
As you rightly pointed out, as of June 11th 2013 you can't make unauthenticated requests, or any to the 1.0 API any more, because it has been retired. So OAuth is the way to make requests to the 1.1 API.
I wrote a stack overflow post with an aim to help all you guys make authenticated requests to the 1.1 API with little to no effort.
When you use it, you'll get back the response you see above. Follow the posts instructions, step-by-step, and you can get the library here (you only need to include one file in your project).
Basically, the previous post explains that you need to do the following:
Create a twitter developer account
Get yourself a set of unique keys from twitter (4 keys in total).
Set your application to have read/write access
Include TwitterApiExchange.php (the library)
Put your keys in a $settings array
Choose your URL and request method (Post/Get) from the docs (I put the link above!)
Make the request, that's it!
A practical example
I'm going to assume you followed the step-by-step instructions in the above post (containing pretty colour pictures). Here's the code you would use to get what you want.
// Require the library file, obviously
require_once('TwitterAPIExchange.php');
// Set up your settings with the keys you get from the dev site
$settings = array(
'oauth_access_token' => "YOUR_ACCESS_TOKEN",
'oauth_access_token_secret' => "YOUR_ACCESS_TOKEN_SECRET",
'consumer_key' => "YOUR_CONSUMER_KEY",
'consumer_secret' => "YOUR_CONSUMER_SECRET"
);
// Chooose the url you want from the docs, this is the users/show
$url = 'https://api.twitter.com/1.1/users/show.json';
// The request method, according to the docs, is GET, not POST
$requestMethod = 'GET';
// Set up your get string, we're using my screen name here
$getfield = '?screen_name=j7mbo';
// Create the object
$twitter = new TwitterAPIExchange($settings);
// Make the request and get the response into the $json variable
$json = $twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest();
// It's json, so decode it into an array
$result = json_decode($json);
// Access the profile_image_url element in the array
echo $result->profile_image_url;
That's pretty much it! Very simple. There's also users/lookup which effectively does the same thing, but you can:
Returns fully-hydrated user objects for up to 100 users per request, as specified by comma-separated values passed to the user_id and/or screen_name parameters.
If you ever need to get more than one user's details, use that, but as you only require one user's details, use users/show as above.
I hope that cleared things up a bit!
You say you want to use Twitter API 1.1 and yet you don't want to authenticate your requests.
Unauthenticated requests are not supported in API v1.1. So please adjust to the API change. See updates :
https://dev.twitter.com/blog/planning-for-api-v1-retirement
https://dev.twitter.com/docs/rate-limiting/1.1
You can get image from profile_image_url field of https://api.twitter.com/1.1/users/show.json request. Either a id or screen_name is required for this method. For example :
GET https://api.twitter.com/1.1/users/show.json?screen_name=rsarver
See details here https://dev.twitter.com/docs/api/1.1/get/users/show
I try the above methods to get the profile URL but it does not work for me. I think because Twitter changes API v1.1 to API v2.0.
I found a simple method to get a profile URL.
I use Twitter API v2 there User Lookup -> User by Username API part
Code Sample:
https://api.twitter.com/2/users/by/username/{user_name}?user.fields=profile_image_url
For Example:
https://api.twitter.com/2/users/by/username/TwitterDev?user.fields=profile_image_url
Of course, You should request with your Bearer Token then it properly work. For that, I recommend a platform it calls postman. It really helps for calling API.
Above example code return JSON like this:
{
"data": {
"name": "Twitter Dev",
"profile_image_url": "https://pbs.twimg.com/profile_images/1445764922474827784/W2zEPN7U_normal.jpg",
"username": "TwitterDev",
"id": "2244994945"
}
}
Additional:
If You want the Profile Image to be a higher size. Then you can put size in place of normal in the URL. For More Details read this one
Like This:
https://pbs.twimg.com/profile_images/1445764922474827784/W2zEPN7U_400x400.jpg
Give a vote to help more developers. 🍵
As the previous answers and comments point out:
Twitter API v1.0 is deprecated
Twitter API v1.1 requires OAuth
OP (#Steffi) doesn't want to authenticate
Pick any two; with all three it's a no-go. #Jimbo's answer is correct (and the proper way to do it), but excludes #3. Throwing out #1 means going back in time. But, we can throw out #2, and go directly to the source:
curl -s https://twitter.com/EA_FIFA_FRANCE |
sed -ne 's/^.*ProfileAvatar-image.*\(https:[^"]*\).*$/\1/p'
The sed command just says, find the line that contains "ProfileAvatar-image" and print the substring that looks like a quoted URL.
This is less stable than an authenticated API call, since Twitter may change their HTML at any time, but it's easier than dealing with OAuth, and no official rate limits!
The PHP translation should be straightforward.
try this
http://api.twitter.com/1/users/profile_image/{twitter_account}.xml?size=bigger
In API 1.1 the only way is to connect your application, retrieve the user by
https://dev.twitter.com/docs/api/1.1/get/users/show
and retrieve after his picture
profile_image_url
Hare is a very simple way to get Twitter Profile picture.
http://res.cloudinary.com/demo/image/twitter_name/w_300/{User_Name}.jpg
it's my Profile picutre:
Big: http://res.cloudinary.com/demo/image/twitter_name/w_300/avto_key.jpg
Small: http://res.cloudinary.com/demo/image/twitter_name/w_100/avto_key.jpg
you can regulate size by this part of URL - w_100, w_200, w_500 and etc.

Issue with LinkedIn API call after OAuth authentication

I've successfully made my way through the LinkedIn OAuth process (using the REST API - OAuth 1.0a). However I'm having trouble with my first API call after the callback. I set the UserToken, UserTokenSecret and UserVerfier in the library I am writing, and this call this function to get my profile information:
public function getUserProfile()
{
$consumer = new OAuthConsumer($this->consumer_key, $this->consumer_secret, NULL);
$auth_token = new OAuthConsumer($this->getUserToken(), $this->getUserTokenSecret());
$access_token_req = new OAuthRequest("GET", $this->access_token_endpoint);
$params['oauth_verifier'] = $this->getUserVerifier();
$access_token_req = $access_token_req->from_consumer_and_token($this->consumer,
$auth_token, "GET", $this->access_token_endpoint, $params);
$access_token_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,
$auth_token);
$after_access_request = $this->doHttpRequest($access_token_req->to_url());
$access_tokens = array();
parse_str($after_access_request,$access_tokens);
# line 234 below
$access_token = new OAuthConsumer($access_tokens['oauth_token'], $access_tokens['oauth_token_secret']);
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
var_dump($after_request);
}
The function var_dumps a string, which is the basic synopsis of my profile:
string(402) " User Name etc. etc. http://www.linkedin.com/profile?viewProfile=&key=28141694&authToken=HWBC&authType=name&trk=api*a137731*s146100* "
That's good. However, the minute I refresh the page, the same function call fails with:
Undefined index: oauth_token, line number: 234
(this line marked with comment in above code block).
Then, of course, the var_dump reports this error from LinkedIn:
string(290) " 401 1310652477038 R8MHA2787T 0 [unauthorized]. The token used in the OAuth request is not valid. "
something to note:
the user token, secret, and verifier are persisted during the initial authorization callback (right before this function is called). So, they are the same during the first call (when it works, right after coming back from linkedin) and during a page reload (when it fails on line 234).
Also, I must admit I'm not 100% sure I understand everything that's going on in this function. I actually took examples from this tutorial (about a different service, not linkedin) http://apiwiki.justin.tv/mediawiki/index.php/OAuth_PHP_Tutorial and combined it with the information I gathered from the LinkedIn API documentation, spread throughout their developer site. Most notable was the addition of the 'verifier' which the tutorial did not use.
Any insight into this problem would be greatly appreciated. Thanks in advance.
-Nick
UPDATE
The only way I've been able to get this going is to do a new OAuth handshake every single time. Is this the way it's supposed to happen? I was under the impression that once I got my user token/secret and verifier, that I could then use these for continuous API calls until the token expired or was revoked.
As it is now, every time the page reloads I'm requesting a new user token, secret and verifier, then immediately calling to get the user profile (which succeeds). Next reload, I get a whole new key/secret and verifier. Seems like quite a lot of work for each call, and as I understood it, you should be able to perform offline operations with this method - and if I need new authorization each time, then I guess I can't do that?
Well. I've finally figured out what was going on so thought I'd post the answer here, just in case someone else runs into this.
The example that I was using as a guide was flawed. After the access token is retrieved, you should then create a new OAuthRequest object, instead of using the existing $access_token_req instance.
So this:
// prepare for get profile call
$profile_req = $access_token_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$profile_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($profile_req->to_url());
Should be changed to this:
$api_req = new OAuthRequest("GET", $this->api_url.$api_call);
// prepare for get profile call
$api_req = $api_req->from_consumer_and_token($consumer,
$access_token, "GET", $this->api_url.'/v1/people/~');
$api_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(),$consumer,$access_token);
$after_request = $this->doHttpRequest($api_req->to_url());

Categories