0

TLDR: Trying to post a tweet everytime someone posts on wordpress but can't authenticate correctly with oauth 1 to use the /2/tweets endpoint.

So I was annoyed when Jetpack social on my site decided to start charging for tweet scheduling. Usually I would be fine with this but it just seemed dumb that they were charging for something that I could build in a few days. So I'm planning on making an open source plugin that let's anyone use their wordpress as a tweet scheduler.

I'm currently struggling to properly authenticate with oauth to use the api v2. There's a lot of content out there for v1 but far less for v2 and particuarly v2 with wordpress.

Here's the resources I've used:

-https://www.youtube.com/watch?v=jOlJ5VJ_kSw for the oauth code

-https://developer.wordpress.org/reference/functions/wp_remote_post/ for the wp_remote_post() api call

-Numerous stack articles ie Wordpress twitter api 1.1 search class which provides a good solution for 1.1 but I have made the possibly false assumption based on what I've seen that 1.1 is now deprecated

-https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature shows you how to make a signature for a 1.1 endpoint to post a tweet.

I believe the problem is with the parameters I pass in for oauth, I used all that params from the above twitter docs article but that was 1.1 so possibly an issue.

Here's my code:

function focus_tweet_getSignature($endpoint, $method, $params, $focus_tweet_api_key_secret, $focus_tweet_access_token_secret)
{
    uksort($params, 'strcmp');

    foreach ($params as $key => $value) {
        $params[$key] = rawurlencode($key) . '=' . rawurlencode($value);
    }

    $signatureBase = array(
        rawurlencode($method),
        rawurlencode($endpoint),
        rawurlencode(implode('&', $params)),
    );
    $signatureBaseString = implode('&', $signatureBase);

    $signatureKey = array(
        rawurlencode($focus_tweet_api_key_secret),
        rawurlencode($focus_tweet_access_token_secret),
    );

    $signatureKeyString = implode('&', $signatureKey);

    return base64_encode(hash_hmac('sha1', $signatureBaseString, $signatureKeyString, true));
}

// 'oauth_consumer_key',
// 'oauth_nonce',
// 'oauth_signature',
// 'oauth_signature_method',
// 'oauth_timestamp',
// 'oauth_token',
// 'oauth_version',
// 'status'

function focus_tweet_getAuthorizationString($oauth)
{
    $authorizationString = 'Authorization OAuth:';
    $count = 0;

    foreach ($oauth as $key => $value) {
        $authorizationString .= !$count ? ' ' : ', ';
        $authorizationString .= rawurlencode($key) . '="' . rawurlencode($value) . '"';
        $count++;
    }

    return $authorizationString;
}

function focus_tweet_makeApiCall( $apiParams, $focus_tweet_status ){
    $response = wp_remote_post($apiParams['endpoint'], array(
        'method' => $apiParams['method'],
        'headers' => array(
            array(
                'Accept: application/json', 
                $apiParams['authorization'], 
                'Expect:'
            ),
        ),
        'body' => "{
            'text': $focus_tweet_status
        }",
    )
    );
    //If response is not 200, trigger fatal error
    if (is_wp_error($response) || wp_remote_retrieve_response_code($response) != 200) {
        //Combine response details and build auth header function
        $focus_tweet_res_body = wp_remote_retrieve_body($response);
        wp_die($apiParams['authorization'] . '&' . $focus_tweet_res_body);
    } else {
        wp_die("Tweeted!");
    }
}

function focus_tweet_tweet($focus_tweet_status)
{
    $focus_tweet_api_key = '';
    $focus_tweet_api_key_secret = '';
    $focus_tweet_access_token = '';
    $focus_tweet_access_token_secret = '';
    $oauth = array(
        'oauth_consumer_key' => $focus_tweet_api_key,
        'oauth_nonce' => md5(microtime() . mt_rand()),
        'oauth_signature_method' => 'HMAC-SHA1',
        'oauth_token' => $focus_tweet_access_token,
        'oauth_timestamp' => time(),
        'oauth_version' => '1.0',
        'status' => $focus_tweet_status,
    );
    $oauth['oauth_signature'] = focus_tweet_getSignature('https://api.twitter.com/2/tweets', 'POST', $oauth, $focus_tweet_api_key_secret, $focus_tweet_access_token_secret);
    $apiParams = array(
        'method' => 'POST',
        'endpoint' => 'https://api.twitter.com/2/tweets',
        'authorization' => focus_tweet_getAuthorizationString($oauth),
        'url_params' => array(),
    );
    focus_tweet_makeApiCall($apiParams, $focus_tweet_status);
}

Triggered when I save a post for now while I'm testing.

Warning: Array to string conversion in C:\Users\Will\Local Sites\plugintestbench\app\public\wp-includes\class-requests.php on line 800 Authorization OAuth: oauth_consumer_key="", oauth_nonce="", oauth_signature_method="HMAC-SHA1", oauth_token="", oauth_timestamp="1672918493", oauth_version="1.0", status="Hello%20World%21", oauth_signature=""&{ "title": "Unauthorized", "type": "about:blank", "status": 401, "detail": "Unauthorized" }

The warning I believe is fine for now although will fix later.

I have used the credentials to post a tweet from postman so that's not the issue.

I initially believed that it was not possible to use curl in wordpress so may try switching to that although I really believe that the issue is with the oauth params.

(Including twitter/flickr api calls on every page load (WordPress))

Will keep this post updated while I work on this and will ofcourse post the finished github code once it's completed.

Goady
  • 29
  • 1
  • 2
  • 6

0 Answers0