CID Superfecta for ConnectWise using ClientID REST API

CID Superfecta ConnectWise REST API & ClientID requirements.

In June 2019 ConnectWise announced they will no longer support SOAP API and will require a ClientID for their REST API. When SOAP was discontinued CID Superfecta would not connect to ConnectWise installations.
I re-wrote, see below, the CID Superfecta for FreePBX Asterisk to incorporate the ConnectWise ClientID and REST API.

You will be required to request access to the ConnectWise Developer Network and create a private ClientID.

See https:// developer . connectwise . com/ClientID (Needed to break apart URL)

The modification is to the php script located on the FreePBX server at /var/www/html/admin/modules/superfecta/sources/source-ConnectWise.module

The script will check the CW Companies first for the phone number match, returning the Company Name, and then, if not found, the CW contacts, returning the contact First & Last Name.

Cut & Paste the below into the source-ConnectWise.module. Watch out for line returns for lines that should be 1 line, pasting as 2.

Please freely share this outside of CW Forums as long as I am still provided credit. There is a way to have a developer ClientID for mutiple installs. Hopefully Superfecta Developers take this and use it with the Public Development ClientID so each installation site does not have to create one for their own use.

The SOAP user prompts have been replaced with REST API prompts. The ConnectWise Public & Private API key using Members -> API Keys will be used and not integrator logins via the setup tables.

‘’’

<?php

/***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****
 * Module Dev notes:
 *
 *
 * Revision History:
 *    v0.1.0: Initial Release Version by myitguy
 *    v0.1.1: Minor bug fix by bushbomb
 *    v0.1.2: More bug fixes id'd by bushbomb
 *    v0.1.3: Initial migration to 2.11 by lgaetz
 *    2014-08-22  Added user param to set the API version in the URL
 *    2015-05-01  Add field for user supplied CNAM prefix
 *    2018-06-30  Fix for bug FREEPBX-17727
 *    2020-01-06  Modified by Clinton Pownall of Computer Business to
 *                accommodate the ConnectWise REST API and the ConnectWise
 *                Required ClientID.
***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****/

class ConnectWise extends superfecta_base {

    public $description = "Look up data in local or remote ConnectWise CRM.";
    public $version_requirement = "2.11";
    public $source_param = array(
        'DB_Site' => array(
                'description' => 'ConnectWise Site URL not including the initial https://',
                'type' => 'text',
        ),
        'DB_Company' => array(
                'description' => 'ConnectWise Company ID',
                'type' => 'text',
        ),
        'DB_Public_Key' => array(
                'description' => 'Integration Public Key Created in ConnectWise: Members -> API Members -> API Keys',
                'type' => 'text',
        ),
        'DB_Private_Key' => array(
                'description' => 'Integration Private Key Created in ConnectWise: Members -> API Members -> API Keys',
                'type' => 'password',
        ),
        'DB_ClientID' => array(
                'description' => 'Client ID created using the ConnectWise Developer Site, See developer.connectwise.com/ClientID',
                'type' => 'password',
        ),
        'Search_Type' => array(
                'description' => 'The ConnectWise type of entries that should be used to match the number',
                'type' => 'select',
                'option' => array (
                    '1' => 'Companies Only',
                    '2' => 'Contacts Only',
                    '3' => 'Companies --> Contacts',
                ),
                'default' => '3',
        ),
        'Filter_Length' => array(
                'description' => 'The number of rightmost digits to check for a match. Enter zero to disable this setting',
                'type' => 'number',
                'default' => 10
        ),
        'CNAM_prefix' => array(
                'description' => 'This text will be prefixed to all CNAM returned by this module (optional)',
                'type' => 'text',
                'default' => null
        ),
        'API_Version' => array(
                'description' => 'The part of the URL excluding slashes following the host name that indicates the API version, e.g. "v2014_4" or "v4_6_release" (without quotes)',
                'type' => 'text',
                'default' => 'v2014_4',
        ),
    );


    function get_caller_id($thenumber, $run_param=array()) {
        $caller_id = null;
        
                $site = $run_param['DB_Site'];
                $companyid = $run_param['DB_Company'];
                $APIPublicKey = $run_param['DB_Public_Key'];
                $APIPrivateKey = $run_param['DB_Private_Key'];
                $varSearchType = $run_param['Search_Type'];
        $clientid = $run_param['DB_ClientID'];

        $varSearchType = $run_param['Search_Type'];
        if ($run_param['API_Version']) {
            $apiver = $run_param['API_Version'];
        } else {
            $apiver = 'v4_6_release';
        }

        $wquery_string = "";
        $wquery_result = "";
        $wresult_caller_name = "";

        $this->DebugPrint("Searching ConnectWise ... ");
        
        if ($run_param['Filter_Length'] != 0) {
            if (strlen($thenumber) > $run_param['Filter_Length']) $thenumber = substr($thenumber, -$run_param['Filter_Length']);  // keep only the filter_length rightmost digits
        }

        $APIEndpoint = 'https://' .$site. '/'.$apiver.'/apis/3.0';

        $APIkey = 'Basic ' . base64_encode($companyid . '+' . $APIPublicKey . ':' . $APIPrivateKey);


        // Search Companies
        if($run_param['Search_Type'] == 1 || $run_param['Search_Type'] == 3)  {
            $this->DebugPrint("Searching Companies ... ");
            /* COMPANY */
            $conditions='conditions=phoneNumber%20like%20%22'.$thenumber.'%22%20';

            $url = '/company/companies?'.$conditions.'&fields=name&pageSize=1000';

            $url = $APIEndpoint . $url;

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array('clientId:' . $clientid,'Authorization:'. $APIkey,    'Content-Type: application/json',));
               curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
               curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
               curl_setopt($curl, CURLINFO_HEADER_OUT, true);

            $result = curl_exec($curl);

            if(!$result){die("Connection Failure");}
            curl_close($curl);
        
            $name=preg_split('/"*"/i', $result, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);

            if (!empty($name[3])) {
                $wresult_caller_name = $name[3];
            }
            else
            {
                $this->DebugPrint("Not found in Companies... ");
            }
        }

        // Search Contacts
        if($run_param['Search_Type'] == 2 || $run_param['Search_Type'] == 3 && $wresult_caller_name =="")  {
            $this->DebugPrint("Searching Contacts ... ");
            /* CONTACT */
            $conditions='childconditions=communicationItems/value%20like%20%22'.$thenumber.'%22%20AND%20communicationItems/communicationType="Phone"';

            $url = '/company/contacts?'.$conditions.'&fields=&pageSize=1000';

            $url = $APIEndpoint . $url;

            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_HTTPHEADER, array('clientId:' . $clientid,'Authorization:'. $APIkey,    'Content-Type: application/json',));
             curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
            curl_setopt($curl, CURLINFO_HEADER_OUT, true);
            $result = curl_exec($curl);

            if(!$result){die("Connection Failure");}
            curl_close($curl);

            $name=preg_split('/"*"/i', $result, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);;

            if (!empty($name[9])) {
                 $wresult_caller_name = $name[5]." ".$name[9]; }
            
            }
            if ($wresult_caller_name =="")  {
                $this->DebugPrint("Not found in Contacts... ");
            }

        
            if(strlen($wresult_caller_name) > 0) {
                $caller_id = $run_param['CNAM_prefix'].trim(strip_tags($wresult_caller_name));
                return $run_param['CNAM_prefix'].$caller_id;
            }
            else {
                $this->DebugPrint("Not found in ConneceWise");
            }
    }
}

?>

‘’’

1 Like

Please report this at: issues.freepbx.org so it can be pushed to the official code.

Thank you

1 Like

This has been posted as an issue with a fix on https://issues.freepbx.org/browse/FREEPBX-20992

CID Superfecta Developers should request a Public ClientID for ConnectWise Development and then hard code the ClientID into the script.

For now I created the ClientID as a prompt stored in the CID database when setting up CID Superfecta ConnectWise on the FreePBX interface. This will require each site installation to request ConnecWise developer access to create their own ClientID to enter into this field.

  • Clinton Pownall
1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.