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.