I’ve been researching the following issue for a couple of days and I have not been able to figure out why this is happening.
The issue: After about 30 min or so of being able to send user information through the infusionsoft api we suddenly have to reauthorize the application.
Access token, Refresh token and expires_in are being stored in a MSSQL database.
I am using a very recent version of the php SDK and running this on a Centos server running php 5.6.
<?php
if(!session_id()) session_start();
ini_set("include_path", strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'
? "/wamp/common/inc"
: "/var/www/common/inc:"
);
require_once "adminresponse.php";
require_once "dataadmin.php";
require_once "lib/infusionsoft/vendor/autoload.php";
use Infusionsoft\Infusionsoft;
use Infusionsoft\Token;
use Infusionsoft\TokenExpiredException;
use Infusionsoft\Http\HttpException;
define('API_URL', 'https://api.infusionsoft.com/crm/rest/v1');
// admediary app
define('CLIENT_ID', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('CLIENT_SECRET', 'XXXXXXXXXXXXX');
$clientId = (array_key_exists('client_id', $_GET) && !empty($_GET['client_id']))
? $_GET['client_id']
: CLIENT_ID;
$clientSecret = (array_key_exists('client_secret', $_GET) && !empty($_GET['client_secret']))
? $_GET['client_secret']
: CLIENT_SECRET;
$redirectUri = (array_key_exists('redirect_uri', $_GET) && !empty($_GET['redirect_uri']))
? $_GET['redirect_uri']
: ( (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}/{$_SERVER['REQUEST_URI']}" );
//need to strip out the code from the uri and then rebuild out the uri
$parsed = parse_url($redirectUri);
$query = $parsed['query'];
parse_str($query, $params);
unset($params['code']);
unset($params['scope']);
unset($params['state']);
$redirectUri = http_build_query($params);
$redirectUri = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://{$_SERVER['HTTP_HOST']}".substr($parsed['path'],1)."?".$redirectUri;
try
{
$response_output = new AdminResponse();
// Get configuration parameters for this campaign
$campaignName = 'infusionsoft';
if (empty($clientId)) {
throw new Exception('Client ID value is empty. Enter value to the client_id query parameter or remove client_id parameter from query to use default value.');
}
if (empty($clientSecret)) {
throw new Exception('Client Secret value is empty. Enter value to the client_secret query parameter or remove client_secret parameter from query to use default value.');
}
if (empty($redirectUri)) {
throw new Exception('Client Secret value is empty. Enter value to the client_secret query parameter or remove client_secret parameter from query to use default value.');
}
$data = new DataAdmin();
$db = $data->GetDBHandle();
$config= getCampaignConfig($db, $campaignName);
$token = new Token([
'access_token' => $config['access_token'],
'refresh_token' => $config['refresh_token'],
'expires_in' => (isset($config['expires_in']))?$config['expires_in']:null
]);
$infusionSoftClient = new Infusionsoft(array(
'clientId' => $clientId,
'clientSecret' => $clientSecret,
'redirectUri' => $redirectUri,
));
// If we are returning from InfusionSoft we need to exchange the code for an access token
if (isset($_GET['code']) AND !$infusionSoftClient->getToken()) {
$token = $infusionSoftClient->requestAccessToken($_GET['code']);
} else {
$infusionSoftClient->setToken($token);
}
$token = $infusionSoftClient->refreshAccessToken();
// Save new access token and refresh token to the data DB
$config['access_token'] = $token->getAccessToken();
$config['refresh_token'] = $token->getRefreshToken();
$config['expires_in'] = $token->getEndOfLife();
saveCampaignConfig($db, $campaignName, $config);
$action = array_key_exists('action', $_REQUEST) ? $_REQUEST['action'] : 'addContact';
switch ( $action )
{
case 'addContact':
$email = isset($_GET['email']) ? $_GET['email'] : null;
$fname = isset($_GET['fname']) ? $_GET['fname'] : null;
$lname = isset($_GET['lname']) ? $_GET['lname'] : null;
$recordId = isset($_GET['record_id']) ? $_GET['record_id'] : null;
$optInReason = isset($_GET['opt_in_reason']) ? $_GET['opt_in_reason'] : "Customer opted-in through webform";
if (empty($email)) {
throw new Exception('Email value is empty. Enter value to the email query parameter.');
}
$email1 = new \stdClass;
$email1->field = 'EMAIL1';
$email1->email = $email;
$contact = [
'given_name' => $fname,
'family_name' => $lname,
'email_addresses' => [$email1],
];
if (!empty($optInReason)) {
$contact['opt_in_reason'] = $optInReason;
}
// Add custom 'Record ID' field [id=2]
if (!empty($recordId)) {
$contact['custom_fields'] = [
[
'id' => 2,
'content' => $recordId
]
];
}
$isExist = false;
$collection = $infusionSoftClient->contacts()->where(['email' => $email, 'limit' => 1])->get();
if (!$collection->isEmpty() && $collection->count() > 0) {
$items = $collection->toArray();
if (!empty($items[0])) {
$isExist = true;
$contact['id'] = $items[0]->id;
}
}
$cid = $infusionSoftClient->contacts()->mock($contact)->save();
$response_output->response_code = 1;
$response_output->response_msg = 'Contact was ' . ($isExist ? 'updated' : 'created');
$response_output->response_data = $cid->toArray();
break;
default:
throw new Exception('Unknown action: ' . $action);
break;
}
}
catch (HttpException $e)
{
if ( strpos($e->getMessage(), '{"error":"invalid_grant","error_description":"Invalid refresh token"}' ) !== false ) {
echo '<a href="' . $infusionSoftClient->getAuthorizationUrl() . '">Click here to authorize</a>';
exit();
}
$response_output->response_error = $e->getMessage();
}
catch (TokenExpiredException $e)
{
// If the request fails due to an expired access token, we can refresh
// the token and then do the request again.
$token = $infusionSoftClient->refreshAccessToken();
// Save the token to the data DB
$config['access_token'] = $token->getAccessToken();
$config['refresh_token'] = $token->getRefreshToken();
$config['expires_in'] = $token->getEndOfLife();
try
{
saveCampaignConfig($db, $campaignName, $config);
} catch (Exception $e)
{
throw $e;
}
header("Location: $redirectUri");
exit();
}
catch (Exception $e)
{
$response_output->response_error = $e->getMessage();
}
print json_encode($response_output);
/**
* param $db
* param $campaignName
* return array Config
* throws Exception
*/
function getCampaignConfig($db, $campaignName)
{
$query = "SELECT TOP 1 * FROM data..esp_campaign WHERE campaign_name = '{$campaignName}'";
$result = odbc_exec($db, $query);
if (!$result) {
throw new Exception('Error from: ' . $query . odbc_errormsg());
}
if (odbc_fetch_row($result)) {
$config = odbc_result($result, 'params_json');
} else {
throw new Exception("Configuration for the {$campaignName} campaign doesn't exist in the DB.");
}
odbc_free_result($result);
$config = json_decode($config, true);
return $config;
}
/**
* param $db
* param $campaignName
* param array $config
* throws Exception
*/
function saveCampaignConfig($db, $campaignName, $config)
{
$config = json_encode($config);
$query = "UPDATE data..esp_campaign SET params_json='{$config}' WHERE campaign_name='{$campaignName}'";
$result = odbc_exec($db, $query);
if (!$result) {
throw new Exception('Error from: ' . $query . odbc_errormsg());
}
odbc_free_result($result);
}