Authorizing with oAuth, posting to Twitter
I had three problems:
(1) I did not include it in this question, but my signature wasn't created correctly.
What I was doing was base64_encode(hash_hmac('sha1', $base, $key));
but I should have set the hash_hmac fourth parameter to true
to return a raw binary instead of the hexidecimal (the hexidecimal is shown as the example in the Twitter docs, which was what was confusing me). The correct function is therefore: base64_encode(hash_hmac('sha1', $base, $key, true));
.
(2) The cURL was not set up correctly. I required CURLOPT_HTTPHEADER to set the Authorization, and CURL_VERBOSE set to true:
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: ' . $DST));curl_setopt($ch, CURLOPT_VERBOSE, 1);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, 'status='.rawurlencode($status));curl_setopt($ch, CURLOPT_URL, $url);
(3) As seen in the above code, I had to post the status as a string, and not an array. I found the solution to this problem on this question: Why can't I authenticate with OAuth?.
All of this is now working perfectly. Also, make sure that your access token in your Twitter application says that the access level is "Read and write". If not, change the permissions in Settings, then go back to Details and recreate your access token.
Full Script
<?phpclass Tweet {public $url = 'https://api.twitter.com/1/statuses/update.json';function the_nonce(){ $nonce = base64_encode(uniqid()); $nonce = preg_replace('~[\W]~','',$nonce); return $nonce;}function get_DST($status){ $url = $this->url; $consumer_key = $your_consumer_key_here; $nonce = $this->the_nonce(); $sig_method = 'HMAC-SHA1'; $timestamp = time(); $version = "1.0"; $token = $your_token_here; $access_secret = $your_access_secret_here; $consumer_secret = $your_consumer_secret_here; $param_string = 'oauth_consumer_key='.$consumer_key. '&oauth_nonce='.$nonce. '&oauth_signature_method='.$sig_method. '&oauth_timestamp='.$timestamp. '&oauth_token='.$token. '&oauth_version='.$version. '&status='.rawurlencode($status); $sig_base_string = 'POST&'.rawurlencode($url).'&'.rawurlencode($param_string); $sig_key = rawurlencode($consumer_secret).'&'.rawurlencode($access_secret); $tweet_sig = base64_encode(hash_hmac('sha1', $sig_base_string, $sig_key, true)); $DST = 'OAuth oauth_consumer_key="'.rawurlencode($consumer_key).'",'. 'oauth_nonce="'.rawurlencode($nonce).'",'. 'oauth_signature="'.rawurlencode($tweet_sig).'",'. 'oauth_signature_method="HMAC-SHA1",'. 'oauth_timestamp="'.rawurlencode($timestamp).'",'. 'oauth_token="'.rawurlencode($token).'",'. 'oauth_version="1.0"'; return $DST;}function set($status){ $url = $this->url; $ch = curl_init();curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: ' . $this->get_DST($status)));curl_setopt($ch, CURLOPT_VERBOSE, 1);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch, CURLOPT_POST, 1);curl_setopt($ch, CURLOPT_POSTFIELDS, 'status='.rawurlencode($status));curl_setopt($ch, CURLOPT_URL, $url); $result = json_decode(curl_exec($ch));if(!curl_errno($ch)){ $info = curl_getinfo($ch); if($info['http_code']!='200'){//error postingecho 'Error: '.$result->{'error'}; }else{//successecho 'Success! <a href="https://twitter.com/AOKHalifax/status/'.$result->{'id_str'}.'" target="_blank">View Tweet</a>'; }}else{ //error connecting echo 'error posting'; } curl_close($ch); }}/* Usage example:$status = new Tweet();$status->set('checking'); */?>
Hi and thank you for your help.
I had the same problem, you'll find below my code:
<?phppublic function updateStatus($message){ // Encoding message for the curl data parameter $messageData = rawurlencode($message); // Double encoding message for the message in signature base string $messageSignature = rawurlencode($messageData); // URL for posting a new tweet $statusURL = rawurlencode('https://api.twitter.com/'.$this->version.'/statuses/update.json'); // Create oauth_nonce parameter $oauth_nonce = preg_replace('~[\W]~','',base64_encode(uniqid())); // Create timestamp $oauth_timestamp = time(); // Create signature base string parameter $signature_base_string = "POST&".$statusURL."&oauth_consumer_key%3D".CB_TWITTER_API_KEY."%26oauth_nonce%3D".$oauth_nonce."%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D".$oauth_timestamp."%26oauth_token%3D".$this->sessionData['oauth_token']."%26oauth_version%3D1.0%26status%3D".$messageSignature.""; // Create signature key $signature_key = CB_TWITTER_SECRET_KEY.'&'.$this->sessionData['oauth_token_secret']; // Create new signature $newSignature = rawurlencode(base64_encode(hash_hmac('sha1', $signature_base_string, $signature_key, true))); // Create header $header="Authorization: OAuth oauth_consumer_key=\"".CB_TWITTER_API_KEY."\", oauth_nonce=\"".$oauth_nonce."\", oauth_signature=\"".$newSignature."\", oauth_signature_method=\"HMAC-SHA1\", oauth_timestamp=\"".$oauth_timestamp."\", oauth_token=\"".$this->sessionData['oauth_token']."\", oauth_version=\"1.0\""; // Replace line breaks and tabulations in header $header = preg_replace( "/\r|\n|\t/", "", $header); // Init cURL $ch = curl_init(); // Put header curl_setopt($ch, CURLOPT_HTTPHEADER, array($header)); // Set request type to POST for POSTing a tweet curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); // Enable verbose for debugging only curl_setopt($ch, CURLOPT_VERBOSE, false); // Return the transfer in a string curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Set URL of cURL request curl_setopt($ch, CURLOPT_URL, rawurldecode($statusURL)); // Do a POST request (HTML POST) curl_setopt($ch, CURLOPT_POST, 1); // Set data curl_setopt($ch, CURLOPT_POSTFIELDS, 'status='.$messageData); // Execute cURL and store result $output = curl_exec($ch); // Close cURL curl_close($ch); if ($output) { $output = json_decode($output); } if ($this->hasErrors($output, false)) { return false; } return true;}?>
Hope it'll help.