skip to Main Content

I can get an image_id but can’t update the status with the image …

I make a first request to "media / upload.json" and I get the media_id, then I make a request to "statuses / update.json" with the status message and the media_id received previously. Only the text is displayed but not the image.

My php code :

<?php
$oauth_access_token = "XXXX";
$oauth_access_token_secret = "XXXX";
$consumer_key = "XXXX";
$consumer_secret = "XXXX";

//twitter api urls
$URLS = array(
    "image" => "https://upload.twitter.com/1.1/media/upload.json",
    "status" => "https://api.twitter.com/1.1/statuses/update.json"
);

function buildBaseString($baseURI, $method, $params)
{
    $r = array();
    ksort($params);
    foreach ($params as $key => $value) {
        $r[] = "$key=" . rawurlencode($value);
    }
    return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
}

function buildAuthorizationHeader($oauth)
{
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach ($oauth as $key => $value)
        $values[] = "$key="" . rawurlencode($value) . """;
    $r .= implode(', ', $values);
    return $r;
}

function makeRequest($postfields, $url)
{
    global $consumer_key;
    global $consumer_secret;
    global $oauth_access_token;
    global $oauth_access_token_secret;
    $oauth = array(
        'oauth_consumer_key' => $consumer_key,
        'oauth_nonce' => time(),
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_token' => $oauth_access_token,
        'oauth_timestamp' => time(),
        'oauth_version' => '1.0'
    );
    $base_info = buildBaseString($url, 'POST', $oauth);
    $composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
    $oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
    $oauth['oauth_signature'] = $oauth_signature;
    $header = array(buildAuthorizationHeader($oauth), 'Content-Type: multipart/form-data;');
    $options = array(
        CURLOPT_HTTPHEADER => $header,
        CURLOPT_POSTFIELDS => $postfields,
        CURLOPT_HEADER => false,
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_SSL_VERIFYPEER => false
    );
    $feed = curl_init();
    curl_setopt_array($feed, $options);
    $json = curl_exec($feed);
    curl_close($feed);
    return $json;
}


//Upload image to twitter and get media_id
$file = file_get_contents("C:wamp64appsannonces_insolitesautoannonces_insolitesimgmercedes.jpg");
$postfields = array("media_data" => base64_encode($file));
$result = makeRequest($postfields, $URLS['image']);
$imageresult = json_decode($result);
$imageid = $imageresult->media_id_string;
var_dump($imageresult);

// update status with status and media_id
$postfields = array(
    "media_ids" => $imageid,
    "status" => "test messsage with image"
);
var_dump($postfields);
$result = makeRequest($postfields, $URLS['status']);
$statusresult = json_decode($result);
var_dump($statusresult);

The twitter api response :
I have the media_id in the response to my first request.
With a media_id but not working when update status …

C:wamp64appsannonces_insolitesautoannonces_insolitesreseauxtwittertwitter_fct2.php:82:
object(stdClass)[1]
  public 'media_id' => int 1446017066218164228
  public 'media_id_string' => string '1446017066218164228' (length=19)
  public 'size' => int 161329
  public 'expires_after_secs' => int 86400
  public 'image' => 
    object(stdClass)[2]
      public 'image_type' => string 'image/jpeg' (length=10)
      public 'w' => int 1200
      public 'h' => int 900
C:wamp64appsannonces_insolitesautoannonces_insolitesreseauxtwittertwitter_fct2.php:91:
array (size=2)
  'media_ids' => string '1446017066218164228' (length=19)
  'status' => string 'test messsage with image' (length=24)
C:wamp64appsannonces_insolitesautoannonces_insolitesreseauxtwittertwitter_fct2.php:96:
object(stdClass)[3]
  public 'created_at' => string 'Thu Oct 07 07:38:29 +0000 2021' (length=30)
  public 'id' => int 1446017068470611973
  public 'id_str' => string '1446017068470611973' (length=19)
  public 'text' => string 'test messsage with image' (length=24)
  public 'truncated' => boolean false
  public 'entities' => 
    object(stdClass)[4]
      public 'hashtags' => 
        array (size=0)
          empty
      public 'symbols' => 
        array (size=0)
          empty
      public 'user_mentions' => 
        array (size=0)
          empty
      public 'urls' => 
        array (size=0)
          empty
  public 'source' => string '<a href="XXXX" rel="nofollow">XXXX</a>' (length=83)
  public 'in_reply_to_status_id' => null
  public 'in_reply_to_status_id_str' => null
  public 'in_reply_to_user_id' => null
  public 'in_reply_to_user_id_str' => null
  public 'in_reply_to_screen_name' => null
  public 'user' => 
    object(stdClass)[5]
      public 'id' => int XXXX
      public 'id_str' => string 'XXXX' (length=19)
      public 'name' => string 'XXXX' (length=23)
      public 'screen_name' => string 'XXXX' (length=6)
      public 'location' => string 'XXXX' (length=19)
      public 'description' => string 'XXXX' (length=59)
      public 'url' => null
      public 'entities' => 
        object(stdClass)[7]
          public 'description' => 
            object(stdClass)[6]
              ...
      public 'protected' => boolean false
      public 'followers_count' => int 54
      public 'friends_count' => int 47
      public 'listed_count' => int 0
      public 'created_at' => string 'Sun Jan 20 11:36:11 +0000 2019' (length=30)
      public 'favourites_count' => int 2163
      public 'utc_offset' => null
      public 'time_zone' => null
      public 'geo_enabled' => boolean false
      public 'verified' => boolean false
      public 'statuses_count' => int 172
      public 'lang' => null
      public 'contributors_enabled' => boolean false
      public 'is_translator' => boolean false
      public 'is_translation_enabled' => boolean false
      public 'profile_background_color' => string 'F5F8FA' (length=6)
      public 'profile_background_image_url' => null
      public 'profile_background_image_url_https' => null
      public 'profile_background_tile' => boolean false
      public 'profile_image_url' => string 'XXXX' (length=75)
      public 'profile_image_url_https' => string 'XXXX' (length=76)
      public 'profile_banner_url' => string 'XXXX' (length=68)
      public 'profile_link_color' => string '1DA1F2' (length=6)
      public 'profile_sidebar_border_color' => string 'C0DEED' (length=6)
      public 'profile_sidebar_fill_color' => string 'DDEEF6' (length=6)
      public 'profile_text_color' => string '333333' (length=6)
      public 'profile_use_background_image' => boolean true
      public 'has_extended_profile' => boolean true
      public 'default_profile' => boolean true
      public 'default_profile_image' => boolean false
      public 'following' => boolean false
      public 'follow_request_sent' => boolean false
      public 'notifications' => boolean false
      public 'translator_type' => string 'none' (length=4)
      public 'withheld_in_countries' => 
        array (size=0)
          empty
  public 'geo' => null
  public 'coordinates' => null
  public 'place' => null
  public 'contributors' => null
  public 'is_quote_status' => boolean false
  public 'retweet_count' => int 0
  public 'favorite_count' => int 0
  public 'favorited' => boolean false
  public 'retweeted' => boolean false
  public 'lang' => string 'en' (length=2)

2

Answers


  1. Chosen as BEST ANSWER

    I created this code and it work perfectly : If somewone need help or want to upload image and status to twitter without any library ;)

    <?php
    
    function post_media_status($url, $method, $media_ids, $status, $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret)
    {
    
        $nonce = time();
        $timenow = time();
        $signature = build_signature($url, $method, $media_ids, $status, $nonce, $timenow, $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret);
        //print($signature);
    
        $oauth = array(
            'oauth_consumer_key' => $oauthconsumerkey,
            'oauth_nonce' => $nonce,
            'oauth_signature_method' => 'HMAC-SHA1',
            'oauth_token' => $oauthtoken,
            'oauth_timestamp' => $timenow
        );
        $oauth['oauth_signature'] = $signature;
    
        $header = array(buildAuthorizationHeader($oauth));
        var_dump($header);
    
        curl_post_status_media($url, $header, $media_ids, $status);
    }
    
    function build_signature($url, $method, $media_ids, $status, $nonce, $timenow, $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret)
    {
    
        $key = rawurlencode($clientsecret) . "&" . rawurlencode($tokensecret);
    
        $paramstring = "media_ids=" . $media_ids . "&oauth_consumer_key=" . $oauthconsumerkey . "&oauth_nonce=" . $nonce . "&oauth_signature_method=HMAC-SHA1" . "&oauth_timestamp=" . $timenow . "&oauth_token=" . $oauthtoken . "&status=" . $status;
        $encodeurl = $method . "&" . rawurlencode($url) . "&" . rawurlencode($paramstring);
        $signature = hash_hmac('sha1', $encodeurl, $key, TRUE);
        $signature = base64_encode($signature);
        return $signature;
    }
    
    function curl_post_status_media($url, $header, $media_ids, $status)
    {
        $options = array(
            CURLOPT_HTTPHEADER => $header,
            CURLOPT_POSTFIELDS => "status=" . $status . "&media_ids=" . $media_ids,
            CURLOPT_HEADER => false,
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false
        );
    
        $request = curl_init();
        curl_setopt_array($request, $options);
        $response = curl_exec($request);
        $decoded = json_decode($response);
        var_dump($decoded);
        curl_close($request);
        return $response;
    }
    
    function buildAuthorizationHeader($oauth)
    {
        $r = 'Authorization: OAuth ';
        $values = array();
        foreach ($oauth as $key => $value)
            $values[] = "$key="" . rawurlencode($value) . """;
        $r .= implode(', ', $values);
        return $r;
    }
    
    
    function upload_media($postfields, $url, $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret)
    {
        $oauth = array(
            'oauth_consumer_key' => $oauthconsumerkey,
            'oauth_nonce' => time(),
            'oauth_signature_method' => 'HMAC-SHA1',
            'oauth_token' => $oauthtoken,
            'oauth_timestamp' => time(),
            'oauth_version' => '1.0'
        );
        $base_info = buildBaseString($url, 'POST', $oauth);
        $composite_key = rawurlencode($clientsecret) . '&' . rawurlencode($tokensecret);
        $oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
        $oauth['oauth_signature'] = $oauth_signature;
        $header = array(buildAuthorizationHeader($oauth));
        $options = array(
            CURLOPT_HTTPHEADER => $header,
            CURLOPT_POSTFIELDS => $postfields,
            CURLOPT_HEADER => false,
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false
        );
        $feed = curl_init();
        curl_setopt_array($feed, $options);
        $json = curl_exec($feed);
        //var_dump($json);
        curl_close($feed);
        return $json;
    }
    
    function buildBaseString($baseURI, $method, $params)
    {
        $r = array();
        ksort($params);
        foreach ($params as $key => $value) {
            $r[] = "$key=" . rawurlencode($value);
        }
        return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));
    }
    
    
    function post_media_with_status($file_location, $status, $oauthconsumerkey, $clientsecret, $tokensecret, $oauthtoken)
    {
        $file = file_get_contents($file_location);
        $postfields = array("media_data" => base64_encode($file));
        $result = upload_media($postfields, "https://upload.twitter.com/1.1/media/upload.json", $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret);
        $imageresult = json_decode($result);
        var_dump($imageresult);
        $imageid = $imageresult->media_id_string;
        $result = post_media_status("https://api.twitter.com/1.1/statuses/update.json", "POST", $imageid, $status, $oauthconsumerkey, $oauthtoken, $clientsecret, $tokensecret);
        return $result;
    }
    
    post_media_with_status("IMAGE_URL", "Test", TWITTER_API_KEY, TWITTER_API_SECRET_KEY, "TOKEN_SECRET", "TOKEN");
    
    

  2. I had exactly the same problem. After almost giving up a few times I finally cracked it.

    A Few things that you need to know/do.

    1. Make sure to append your post params onto the OAuth array you are passing to buildBaseString and then do a ksort before URL encoding them

    2. If you pass the post params to curl as an array then it changes the content-type header to multipart/form-data which you don’t want, so instead make sure to do something like this first: $post = http_build_query($data, "", "&"); before passing to curl.

    3. The OAuth spec says that the body should be included in the base string to sign if and only if, the encoding is x-www-form-urlencoded.

    4. As to why Twitter accepts all bar the media_ids params if you send as multipart/form-data I have no idea but it would seem that that is the case.

    5. Do NOT include the post params into the OAuth array that you pass to the buildAuthorisationHeader func 🙂

    I hope that helps you out as it drove me mad for a good few hours before I could get it working. I now know more about OAuth than I ever wanted to know lol.

    PS – when successful, you should receive a chunk of extended attributes in the JSON response that detail the image/video included in the tweet.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search