I'm struggling to get an Access Token back from the Sage API via cURL.
I need the browser to receive an Authorization Code from Sage ID and send this back so I can exchange it for an Access Token and a Refresh Token. These tokens will then be used to request data from Sage using the API. However, I'm getting an error from the start.
I've used https://github.com/ryanmitchell/sageone-api-php as a starter on how to gather the token, I just don't know how to fix.
api.php
<?php
class SageAPI {
private $clientId;
private $clientSecret;
private $oAuthAuthoriseURL = 'https://id.sage.com/authorize?audience=s200ukipd/sage200';
private $oAuthAccessTokenURL = 'https://id.sage.com/oauth/token';
private $accessToken;
private $debug = true;
function __construct($clientId, $clientSecret) {
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
}
public function getAuthoriseURL($callback) {
$authoriseURL = $this->oAuthAuthoriseURL;
$authoriseURL .= '&response_type=code';
$authoriseURL .= '&client_id='.$this->clientId;
$authoriseURL .= '&state=Sage';
$authoriseURL .= '&scope=openid%20profile%20email%20offline_access';
$authoriseURL .= '&redirect_uri='.urlencode($callback);
return $authoriseURL;
}
public function getAccessToken($code, $callback) {
if ($this->accessToken) {
return $this->accessToken;
}
$params = array(
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'code' => $code,
'grant_type' => 'authorization_code',
'redirect_uri' => $callback
);
$result = $this->call($params);
// Save accessToken
$this->accessToken = $result['access_token'];
// Return the response as an array
return $result;
}
private function call($data=false) {
$ch = curl_init();
$curlURL = $this->oAuthAccessTokenURL;
// Setup curl options
$curl_options = array(
CURLOPT_URL => $curlURL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTPHEADER => array(
'Accept: */*',
'Content-Type: application/json',
),
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data
);
print "<pre>";
print_r($curl_options);
print "</pre>";
// Set curl options
curl_setopt_array($ch, $curl_options);
// Send the request
$this->result = $result = curl_exec($ch);
$this->error = $error = curl_errno($ch);
$this->httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($this->debug) {
var_dump($result);
var_dump($error);
var_dump(curl_getinfo($ch, CURLINFO_HTTP_CODE));
}
// Close the connection
curl_close($ch);
return json_decode($result, true);
}
}
?>
Callback.php
<?php
require dirname(__FILE__).'/api.php';
define('SAGE_CLIENT_ID', 'XXXXXX-XXXXXX');
define('SAGE_CLIENT_SECRET', 'XXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXX');
$client = new SageAPI(SAGE_CLIENT_ID, SAGE_CLIENT_SECRET);
$callbackURL = 'https://example.com/callback.php';
if (!isset($_GET['code'])) {
$authoriseURL = $client->getAuthoriseURL($callbackURL);
header("Location: ".$authoriseURL);
exit;
} else {
$accessToken = $client->getAccessToken($_GET['code'], $callbackURL);
echo '<pre>';
print_r($accessToken);
echo '</pre>';
}
?>
So when I run https://example.com/callback.php first time, I'm presented with the login box for Sage. I successfully login and it redirects me to a page that now has a code in the URL, e.g. https://example.com/callback.php?code=1a2d3f4g5h6j7k8l
On redirect, this is where it's meant to present me with the Access Token to use in future calls to the API but the response I'm getting is "403: Something went wrong" and this is in the styling from Sage itself.
Does anyone know what I'm doing wrong here?
I can run this in Postman and it works straight away. I've compared the data I'm sending in my code to the one in Postman Console and it's pretty much the same! The only thing that differs is the User Agent (which I've tried changing) and the code response is obviously unique to that call.
I've accessed APIs via cURL before but I've never had to do it to this degree so any help here would be greatly appreciated.

Thanks to @Cbroe I ended up going down a route that eventually pointed me in the right direction for fixing this!
The code I was using had the
$dataarray as is but after a bit of googling, I found that I should concatenate the data using & instead.So I changed this:
CURLOPT_POSTFIELDS => $dataTo this:
CURLOPT_POSTFIELDS => http_build_query($data, '', '&')And now it works! I also changed the content type to:
'Content-Type: application/x-www-form-urlencoded'