My application connects with keap by using PHP ISDK code (xml-rpc - Keap Developer Portal), and I have followed the instruction to change the legacy key to the SAK key in isdk php file and in conn cfg php file. also change the urls from myappid to api in isdk php file.
but Im getting the following error
Fatal error : Uncaught iSDKException: ERROR: 5 - Didn’t receive 200 OK from remote server. (HTTP/2 401 ) in /home/kayadeve/public_html/kayaIS/isdk.php:88 Stack trace: #0 /home/kayadeve/public_html/kayaIS/index.php(7): iSDK->cfgCon(‘ISCON’) #1 {main} thrown in /home/kayadeve/public_html/kayaIS/isdk.php on line 88
can you please help to resolve this? also once resolved, is there anything I need to do further to avoid any future issue?
Hi @Marion_Dorsett2 , I have downloaded updated isdk file you shared along with xml folder.
gave SAK key in the $key variable
there is no $name filed I could found in isdk file to give app name, i gave app name to it to $logname veriable. and getting the following error
Fatal error : Uncaught iSDKException: ERROR: 5 - Didn’t receive 200 OK from remote server (HTTP/2 401 ) in /home/kayadeve/public_html/kayaIS/isdk.php:95 Stack trace: #0 /home/kayadeve/public_html/kayaIS/index.php(7): iSDK->cfgCon(‘ISCON’) #1 {main} thrown in /home/kayadeve/public_html/kayaIS/isdk.php on line 95
It is possible that you may have made a typing mistake. If the Legacy iSDK worked with the Legacy API Key, then you only need to change the necessary parts to make it work with the Service Account Key.
If you are using the “conn.cfg.php” file, then the format would be the following below.
InfusionSoftApp:<< APP NAME >>:i:<< SERVICE ACCOUNT KEY >>:This is the API key for the proposed project <<APP NAME>>.infusionsoft.com
Where “<< APP NAME >>” is your Keap Application Name, the Subdomain of the Web Address. And the “<< SERVICE ACCOUNT KEY >>” is the replacement key.
If you are using the “cfgCon” function directly, then set the Application Name and Service Account Key as the first two parameters.
As Marion said, make sure the Header Key has been set. Note, you need to make sure you have the right XML-RPC Library to set that. Marion iSDK should work for you.
can you tell me where exactly I will have to perform the 3rd step
Pass the SAK in the custom header: X-Keap-Api-Key: {SAK_GOES_HERE}
hopefully this will resolve my issue
Im geeting this error now
Fatal error : Uncaught iSDKException: No connection information found. in /home/kayadeve/public_html/farrukh/isdk.php:59 Stack trace: #0 /home/kayadeve/public_html/farrukh/index.php(7): iSDK->cfgCon(‘ISCON’) #1 {main} thrown in /home/kayadeve/public_html/farrukh/isdk.php on line 59
@Farrukh_Naseem, if you look at Marion code you will see what he has done.
If you are using the original XML-RPC Library with the SDK then that will need upgrading.
The Newer Version of the XML-RPC Library has support for Customisable Headers.
I posted a reply to Marion in which you can use that instead of modifying the library.
I made changes to the “methodCaller” function. Here is what I changed to work with the latest XML-RPC Library.
// * Original Way *
// $call = $this->xmlrpc_request($service, $callArray);
// array_unshift($call->params, $this->encKey);
/* Set up the call */
// 2023-06-05 - Fix to make it work for the PHP XML-RPC library v4.10.1 as "params" is not exposed anymore.
$call = $this->xmlrpc_request($service, array_merge([ $this->xmlrpc_encode($this->key) ], $callArray));
// Check the OAuth Token to see if it needs to be refreshed prior to the call.
$headers =
[
"Content-Type: text/xml",
"Accept-Charset: UTF-8,ISO-8859-1,US-ASCII",
"Expect:",
"X-Keap-API-Key: {$this->key}"
];
$this->client->setOption('extracurlopts', [ CURLOPT_HTTPHEADER => $headers ]);
My iSDK has been modified over the years, so it is not the same as the original one.
@Farrukh_Naseem, I will share you the parts that are the most relevant to you, and for other developers to see. The iSDK that I have got has been modified over the years, so there is differences in some areas.
Firstly, what version of PHP are you using? If you got PHP v8.1, v8.2, v8.3 then you should be okay below.
Anything older, then I recommend that you update it to a newer version if you can.
Secondly, you need to download the latest PHP XML-RPC Library from here.
Thirdly, in the iSDK the following areas would need to be changes.
Replace loading of the “xmlrpc.inc” file with the XML-RPC Libray Autoloader.
require_once('__DIR__ . /phpxmlrpc/src/Autoloader.php'); // Path to the Autoloader.
\PhpXmlRpc\Autoloader::register(); // Register the Autoloader.
Here are the changes done within the “cfgCon” function so that it points to new API Endpoint.
// * Original Location *
// $this->client = $this->xmlrpc_client("https://$appname.infusionsoft.com/api/xmlrpc");
// * New Location *
$this->client = $this->xmlrpc_client("https://api.infusionsoft.com/crm/xmlrpc");
Here are the changes done to the “methodCaller” function.
Note, there is an “api_access_mode” property that has been added to switch between the Legacy API Key / Service Account Key and OAuth. The Headers are different for the different connection methods.
public function methodCaller($service, $callArray)
{
// Set up the Headers Array based on the PHP XML-RPC Library default Headers.
$headers =
[
"Content-Type: text/xml",
"Accept-Charset: UTF-8,ISO-8859-1,US-ASCII",
"Expect:"
];
if($this->api_access_mode === INFUSIONSOFT_ISDK_API_ACCESS_MODE_LEGACY_API_ENCRYPTED_KEY ||
$this->api_access_mode === INFUSIONSOFT_ISDK_API_ACCESS_MODE_SERVICE_ACCOUNT_KEY)
{
$headers[] = "X-Keap-API-Key: {$this->key}";
}
elseif($this->api_access_mode === INFUSIONSOFT_ISDK_API_ACCESS_MODE_OAUTH)
{
$headers[] = "Authorization: Bearer {$this->key}";
}
// * Original Way *
// $call = $this->xmlrpc_request($service, $callArray);
// array_unshift($call->params, $this->encKey);
// Change done to make it work for the PHP XML-RPC Library v4.10.1 onwards as "params" is not exposed anymore.
$call = $this->xmlrpc_request($service, array_merge([ $this->xmlrpc_encode($this->key) ], $callArray));
// Set this for PHP XML-RPC so that the Headers can be overridden.
$this->client->setOption('extracurlopts', [ CURLOPT_HTTPHEADER => $headers ]);
/* Send the call */
$now = time();
$start = microtime();
$result = $this->client->send($call);
$stop = microtime();
/* Check the returned value to see if it was successful and return it */
if (!$result->faultCode())
{
if ($this->log_function)
{
$this->log(array('Method' => $service, 'Call' => $this->log_data, 'Start' => $start, 'Stop' => $stop, 'Now' => $now, 'Result' => $result, 'Error' => 'No', 'ErrorCode' => 'No Error Code Received' ));
}
return $result->value();
}
else
{
if ($this->log_function)
{
$this->log(array('Method' => $service, 'Call' => $this->log_data, 'Start' => $start, 'Stop' => $stop, 'Now' => $now, 'Result' => $result, 'Error' => 'Yes', 'ErrorCode' => "ERROR: " . $result->faultCode() . " - " . $result->faultString()));
}
if ($this->debug == "kill") {
die("ERROR: " . $result->faultCode() . " - " .
$result->faultString());
} elseif ($this->debug == "on") {
return "ERROR: " . $result->faultCode() . " - " .
$result->faultString();
} elseif ($this->debug == "throw") {
throw new iSDKException($result->faultString(), $result->faultCode());
} elseif ($this->debug == "off") {
//ignore!
}
}
}
here is what I did, I am using php 8.2 version, and I xmlrpc-4.10.3.
Please look at the sequence of my code below
in index.php Im creating the instance as follow
<?php
require_once("isdk.php");
$myApp = new iSDK;
if ($myApp->cfgCon("ISCON"))
{echo "connected";
}else
{echo "Not Connected...";}
?>
here is my conn.cfg.php
$connInfo = array(‘ISCON:APP_NAME:i:SAK_KEY:This is the connection for APP_NAME.infusionsoft.com’);
in isdk.php (that I downloaded from Marion’s link along with xmlrpc-4.10.3 folder), it already includes
require_once(‘DIR . /phpxmlrpc/src/Autoloader.php’); // Path to the Autoloader.
\PhpXmlRpc\Autoloader::register(); // Register the Autoloader.
$this->client = $this->xmlrpc_client("https://api.infusionsoft.com/crm/xmlrpc");```
and I replaced methodCaller with your function. but Im getting the following error
Warning: Undefined property: iSDK::$api_access_mode in /home/kayadeve/public_html/farrukh/isdk.php on line 133
Fatal error: Uncaught Error: Undefined constant "INFUSIONSOFT_ISDK_API_ACCESS_MODE_LEGACY_API_ENCRYPTED_KEY" in /home/kayadeve/public_html/farrukh/isdk.php:133 Stack trace: #0 /home/kayadeve/public_html/farrukh/isdk.php(680): iSDK->methodCaller('DataService.get...', Array) #1 /home/kayadeve/public_html/farrukh/isdk.php(89): iSDK->dsGetSetting('Application', 'enabled') #2 /home/kayadeve/public_html/farrukh/index.php(7): iSDK->cfgCon('ISCON') #3 {main} thrown in /home/kayadeve/public_html/farrukh/isdk.php on line 133
I know, Im very near, can you please help me to identify the issue.
I no longer use the “conn.cfg.php” file as I feed the Application Name and API Key directly to the “cfgCon” function.
In Marion iSDK code, that has a modified XML-RPC Library. What I have shared earlier is to avoid modifying it, so you can use its own functions directly to set the Header.
The main parts to change in the iSDK are the following.
as legacy key will not be. used anymore in the future, should I skip
define(‘INFUSIONSOFT_ISDK_API_ACCESS_MODE_LEGACY_API_ENCRYPTED_KEY’, ‘legacy_api_encrypted_key’);
because in the condition below its using OR operator between legacy and SAK. so giving SAK will work
Fatal error : Uncaught Error: Undefined constant “INFUSIONSOFT_ISDK_API_ACCESS_MODE_SERVICE_ACCOUNT_KEY” in /home/kayadeve/public_html/farrukh/index.php:5 Stack trace: #0 {main} thrown in /home/kayadeve/public_html/farrukh/index.php on line 5
I have made the “methodCaller” simpler, by removing the api_access_mode variable and constants from it. It will work for both the Legacy API Key and Service Account Key.
public function methodCaller($service, $callArray)
{
// Set up the Headers Array based on the PHP XML-RPC Library default Headers.
$headers =
[
"Content-Type: text/xml",
"Accept-Charset: UTF-8,ISO-8859-1,US-ASCII",
"Expect:",
"X-Keap-API-Key: {$this->key}";
];
// * Original Way *
// $call = $this->xmlrpc_request($service, $callArray);
// array_unshift($call->params, $this->encKey);
// Change done to make it work for the PHP XML-RPC Library v4.10.1 onwards as "params" is not exposed anymore.
$call = $this->xmlrpc_request($service, array_merge([ $this->xmlrpc_encode($this->key) ], $callArray));
// Set this for PHP XML-RPC so that the Headers can be overridden.
$this->client->setOption('extracurlopts', [ CURLOPT_HTTPHEADER => $headers ]);
/* Send the call */
$now = time();
$start = microtime();
$result = $this->client->send($call);
$stop = microtime();
/* Check the returned value to see if it was successful and return it */
if (!$result->faultCode())
{
if ($this->log_function)
{
$this->log(array('Method' => $service, 'Call' => $this->log_data, 'Start' => $start, 'Stop' => $stop, 'Now' => $now, 'Result' => $result, 'Error' => 'No', 'ErrorCode' => 'No Error Code Received' ));
}
return $result->value();
}
else
{
if ($this->log_function)
{
$this->log(array('Method' => $service, 'Call' => $this->log_data, 'Start' => $start, 'Stop' => $stop, 'Now' => $now, 'Result' => $result, 'Error' => 'Yes', 'ErrorCode' => "ERROR: " . $result->faultCode() . " - " . $result->faultString()));
}
if ($this->debug == "kill") {
die("ERROR: " . $result->faultCode() . " - " . $result->faultString());
} elseif ($this->debug == "on") {
return "ERROR: " . $result->faultCode() . " - " . $result->faultString();
} elseif ($this->debug == "throw") {
throw new iSDKException($result->faultString(), $result->faultCode());
} elseif ($this->debug == "off") {
//ignore!
}
}
}