<?php
/*
WHMCS MachPanel Integration Package: v 4.4
Supported MachPanel version: 6.3.30 Or Later
Last modified: 01-Jun-2023

Caution: any changes in this file except for those mentioned in corresponding MachPanel integration guide 
may result in failure in server module commands.

Developed and maintained by: MachSol, Inc.
web url: https://www.machsol.com
Machsol support: support@machsol.com
*/

//Import ConfigInfo
if(!class_exists('ConfigInfo'))
{
    require_once('configuration.php');
}

if(!class_exists('ConfigInfo'))
{
  require_once(dirname(__FILE__)."/configuration.php");
}

if(!class_exists('ConfigInfo'))
{
    die("Config file not found:\'".dirname(__FILE__)."/configuration.php\'");
}

//Import ProxyClasses
require_once('ProxyClasses.php');
if(!class_exists('BusinessObjectEntityBase'))
{
    require_once('ProxyClasses.php');
}

if(!class_exists('BusinessObjectEntityBase'))
{
  require_once(dirname(__FILE__)."/ProxyClasses.php");
}

if(!class_exists('BusinessObjectEntityBase'))
{
    die("ProxyClasses file not found:\'".dirname(__FILE__)."/ProxyClasses.php\'");
}

class MachPanelClientHandler
{
  //Private members
  private $url = '';
  private $pKey = '';
  private $config;
  
  //Public members
  var $user = '';
  var $pwd = '';
  var $securityCode = '';
  
  var $SvcClient; 
  var $BaseUrl;  
  var $WHMCS_HostName = '';
  var $WHMCS_DBName = '';
  var $WHMCS_DBUserName = '';
  var $WHMCS_DBUserPswrd = '';
	
  function __construct()
  {
    $this->config = new ConfigInfo(); //$GLOBALS['configObj'];
    
    $this->url = $this->config->server->url;
    $this->pKey = $this->config->server->privateKey;
    $this->user = $this->config->server->apiUsername;
    $this->pwd = $this->config->server->apiPassword;
    $this->securityCode = $this->config->server->securityCode;
  
    $this->WHMCS_HostName = $this->config->database->hostName;
    $this->WHMCS_DBName = $this->config->database->dbName;
    $this->WHMCS_DBUserName = $this->config->database->userName;
    $this->WHMCS_DBUserPswrd = $this->config->database->password;
    
    if (!class_exists('SoapClient'))
    {
      die("PHP-Soap module is required and was not found on current server");
    }

    try
    {
      // define our service to client class mapping
      $classMap = array('BusinessObjectEntityBase' => 'BusinessObjectEntityBase',
      /*'ServiceHostingBase' => 'ServiceHostingBase',
      'SaaSHostingBase' => 'SaaSHostingBase',
      'WebHosting' => 'WebHosting',
      'VPSHosting' => 'VPSHosting',
      'ExchangeHosting' => 'ExchangeHosting',
      'LyncHosting' => 'LyncHosting',
      'SharePointHosting' => 'SharePointHosting',
      'CRMHosting' => 'CRMHosting',
	    'O365Subscription' => 'O365Subscription',
	    'O365Hosting' => 'O365Hosting',*/
      'Customer' => 'Customer',
      'ResellerCustomer' =>  'ResellerCustomer',
      'ResellerModuleSettings' => 'ResellerModuleSettings',
      'LocaleInfo' => 'LocaleInfo',
      'StateInfo' => 'StateInfo',
      'CountryInfo' => 'CountryInfo');


      //Set service options
      $SvcClientopts = array();
      $SvcClientopts['trace']  =  '1';
      $SvcClientopts['exceptions'] = '1';
      $SvcClientopts['classmap'] = $classMap; //provide class level mapping for concrete and base classes to soap client

      //Set Service client
      $this->SvcClient = new SoapClient($this->url."/WebServices/MachPanelService.asmx?wsdl",$SvcClientopts);
      //Set base url property
      $this->BaseUrl = $this->url;
			
      $authParams = array();
      $authParams['UserName'] = $this->user;
      $authParams['UserPassword'] = $this->pwd;
      $authParams['AuthenticationToken'] = '';
      $authParams['CompanyId'] = '0';
      $authParams['EmployeeId'] = '0';
      $authParams['ImpersonateAsResellerId'] = '0';

      $header = new SOAPHeader("http://machsol.com/", 'MPAuthenticationHeader',$authParams);

      $this->SvcClient->__setSoapHeaders($header);
    } 
    catch (Exception $e) 
    {
      die("Error in initializing client for MachPanel service".$e->getMessage());
    }
  }
  
  function getRandStr($length) 
  {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $charactersLength = strlen($characters);
    $randomString = '';
    for ($i = 0; $i < $length; $i++) {
      $randomString .= $characters[rand(0, $charactersLength - 1)];
    }
    return $randomString;
  }
  
  function addpadding($string,$blocksize = 32)
  {
    $len = strlen($string);
    $pad = $blocksize - ($len % $blocksize);
    $string .= str_repeat(chr($pad), $pad);
    return $string;
  }

  function encrypt($string = "")
  {
    $encrypted = "";
    if (extension_loaded("openssl")) {
      $iv = $this->getRandStr(16);
      $encrypted = base64_encode(openssl_encrypt($string, "AES-256-CBC", $this->pKey, OPENSSL_RAW_DATA, $iv)).$iv;
    }
    else {
	    $iv = $this->getRandStr(32);
	    $encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->pKey, $this->addpadding($string), MCRYPT_MODE_CBC, $iv)).$iv;
    }
	
    return $encrypted;
  }

	
  function getAdminEmail($adminid)
  {
    $adminEmail = '';
    $con=mysqli_connect($this->WHMCS_HostName,$this->WHMCS_DBUserName,$this->WHMCS_DBUserPswrd,$this->WHMCS_DBName);
    // Check connection
    if (!$con) 
    {
      die("Database Connection failed: " . mysqli_connect_error());
    }
		
    $query = "select email, username from ".$this->WHMCS_DBName.".tbladmins where id = ".$adminid;
    $resultset = mysqli_query($con,$query);
    $resultrow = mysqli_fetch_array($resultset);
    $adminEmail = $resultrow['email'];
    mysqli_close($con);
    return $adminEmail;
  }
  
  function getClientCustomField($fieldname, $clientid)
  {
    $fieldvalue = '';
    $con=mysqli_connect($this->WHMCS_HostName,$this->WHMCS_DBUserName,$this->WHMCS_DBUserPswrd,$this->WHMCS_DBName);
	
    // Check connection
    if (!mysqli_connect_errno()) 
    {
      $query = "SELECT f.type,f.fieldname,f.description,fv.value FROM ".$this->WHMCS_DBName.".tblcustomfields as f"
      ." INNER JOIN ".$this->WHMCS_DBName.".tblcustomfieldsvalues as fv ON f.id = fv.fieldid" 
      ." WHERE fv.relid = '".$clientid."' AND f.type = 'client' AND f.fieldname = '".$fieldname."' order by f.type desc";
	  
	  $resultset = mysqli_query($con,$query);
			
      if(isset($resultset))
      { 
		$resultrow = mysqli_fetch_array($resultset);
	    $fieldvalue = $resultrow['value'];
      }
      mysqli_close($con);
    }
    else
    {
        die("Failed to connect to whmcs database, Details: " . mysqli_connect_error());
    }
    return isset($fieldvalue) ? $fieldvalue : '';
  }

function getUserOwnerClientId($userid)
  {
    $fieldvalue = '';
    $con=mysqli_connect($this->WHMCS_HostName,$this->WHMCS_DBUserName,$this->WHMCS_DBUserPswrd,$this->WHMCS_DBName);
	
    // Check connection
    if (!mysqli_connect_errno()) 
    {
    
      $query = "select * from ".$this->WHMCS_DBName.". tblusers_clients WHERE auth_user_id = '".$userid."' and owner = '1' ";
	  
	  $resultset = mysqli_query($con,$query);
			
      if(isset($resultset))
      { 
		$resultrow = mysqli_fetch_array($resultset);
	    $fieldvalue = $resultrow['client_id'];
      }
      mysqli_close($con);
    }
    else
    {
      die("Failed to connect to whmcs database, Details: " . mysqli_connect_error());
    }
    return isset($fieldvalue) ? $fieldvalue : '0';
  }

  
  function createCustomerObject($params)
  {
	  //when function is called from hooks it has no sub array for clientsdetails
	  //whereas when called from module file create account function it has client data in 'clientsdetails' sub array
	  //hence we create sub array for clientsdetails when it is not set.
	if(!isset($params["clientsdetails"]))
	{
		$params["clientsdetails"] = array();
		$params["clientsdetails"]['state'] = $params['state'];
		$params["clientsdetails"]['country'] = $params['country'];
		$params["clientsdetails"]['userid'] = $params['userid'];
		$params["clientsdetails"]['address1'] = $params['address1'];
		$params["clientsdetails"]['address2'] = $params['address2'];
		$params["clientsdetails"]['city'] = $params['city'];
		$params["clientsdetails"]['firstname'] = $params['firstname'];
		$params["clientsdetails"]['lastname'] = $params['lastname'];
		$params["clientsdetails"]['phonenumber'] = $params['phonenumber'];
		$params["clientsdetails"]['email'] = $params['email'];
		$params["clientsdetails"]['postcode'] = $params['postcode'];
		$params["clientsdetails"]['companyname'] = $params['companyname'];
		$params["clientsdetails"]['password'] = $params['password'];
        $params["clientsdetails"]["tax_id"] = $params['tax_id'];
		
	}
    //LocaleInfo object initialization
    $localeInfo = new LocaleInfo();
    $localeInfo->LocaleId = '1';
    $localeInfo->LocaleName = '';
    $localeInfo->LocaleCode = '';
    $localeSoapVar = new SoapVar($localeInfo, // the object to wrap
                                SOAP_ENC_OBJECT,
                                get_class($localeInfo), // the concrete class name
                                'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                );
    //StateInfo object initialization
    $stateInfo = new StateInfo();
    $stateInfo->StateId = '0';
    $stateInfo->StateCountryId = '0';
    $stateInfo->StateCode = '';
    $stateInfo->StateName = $params["clientsdetails"]['state'];
    $stateSoapVar = new SoapVar($stateInfo, // the object to wrap
                                SOAP_ENC_OBJECT,
                                get_class($stateInfo), // the concrete class name
                                'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                );
    //CountryInfo object initialization
    $countryInfo = new CountryInfo();
    $countryInfo->CountryId = '0';
    $countryInfo->CountryISOCode = '';
    $countryInfo->CountryISONumber = '';
    $countryInfo->CountryRegionNumber = '';
    $countryInfo->CountryPhoneCode = '';
    $countryInfo->CountryName = $params["clientsdetails"]['country'];
    $countrySoapVar = new SoapVar($countryInfo, // the object to wrap
                                  SOAP_ENC_OBJECT,
                                  get_class($countryInfo), // the concrete class name
                                  'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                  );
	
    //Need to check for 'IsReseller' custom field to create a reseller or end customer
    //on machpanel server module accordingly.
    
    $IsReseller = $this->getClientCustomField('IsReseller', $params["clientsdetails"]['userid']);
    
    //Need to fetch custom password field as default password field in clientdetials is md5 hashed and cannot be set as password in machpanel
    //so the password in client custom field 'ServerPassword' shall be provided for server module customer account.
    $cfpassword = $this->getClientCustomField('ServerPassword', $params["clientsdetails"]['userid']);
    $customerObject;
    //customer object either end customer or reseller customer
    if($IsReseller == 'on')
    {
      $customerObject = new ResellerCustomer();
    }
    else
    {
      $customerObject = new Customer();
    }
  
    #Customer Object settings start
    $customerObject->Address1 = $params["clientsdetails"]['address1'];
    $customerObject->Address2 = $params["clientsdetails"]['address2'];
    $customerObject->City = $params["clientsdetails"]['city'];
    $customerObject->CustomerNumber = "WHMCS-".$params["clientsdetails"]['userid'];
    $customerObject->DateCreated = date('Y-m-d');
    $customerObject->Fax = '';
    $customerObject->FirstName = $params["clientsdetails"]['firstname'];
    $customerObject->IsTaxable = '1';
    $customerObject->LastName = $params["clientsdetails"]['lastname'];
    $customerObject->Mobile = $params["clientsdetails"]['phonenumber'];
    $customerObject->PassportLogin = $params["clientsdetails"]['email'];
	
    $customerObject->Phone = $params["clientsdetails"]['phonenumber'];
    $customerObject->PhoneCountryCode = '00';
    $customerObject->PrimaryEmail = $params["clientsdetails"]['email'];
    $customerObject->Province = $params["clientsdetails"]['state'];
    $customerObject->ResellerId = 0;
    $customerObject->SecondaryEmail = $params["clientsdetails"]['email'];
    $customerObject->Zip = $params["clientsdetails"]['postcode'];
    $customerObject->IsCompanyAdmin = '0';
    $customerObject->IsStillCustomer = '1';
    $customerObject->IsPendingForSetup = '1';
    $customerObject->IsSuspend = '0';
    $customerObject->IsFraud = '0';
    $customerObject->SuspendReason = '';
    $customerObject->BillingDay = '1';
    $customerObject->CustomerId = '0';
    $customerObject->CompanyId = '0';
    $customerObject->WHMCS_UserId = $params["clientsdetails"]['userid'];
    $customerObject->LocaleId = '1';
    //$customerObject->CustomerLocale = $localeInfo;
    $customerObject->CustomerLocale = $localeSoapVar;
    //$customerObject->State = $stateInfo;
    $customerObject->State = $stateSoapVar;
    //$customerObject->Country = $countryInfo;
    $customerObject->Country = $countrySoapVar;
    $customerObject->PGID = '0';
    $customerObject->CompanyName = $params["clientsdetails"]['companyname'];
    $customerObject->PassportPassword = empty($cfpassword) ? $params['clientsdetails']['password']:$cfpassword; //when password in custom field 'Password' is empty or custom field is not set then MP will generate random password for customer account.
	$customerObject->HouseNumber = '0';
    $customerObject->VATNumber = $params["clientsdetails"]['tax_id'];
    #Customer Object settings end
	
    if($IsReseller == 'on')
    {
      //StateInfo object initialization
      $CompstateInfo = new StateInfo();
      $CompstateInfo->StateId = '0';
      $CompstateInfo->StateCountryId = '0';
      $CompstateInfo->StateCode = '';
      $CompstateInfo->StateName = $params['state'];
      $CompstateSoapVar = new SoapVar($CompstateInfo, // the object to wrap
                                      SOAP_ENC_OBJECT,
                                      get_class($CompstateInfo), // the concrete class name
                                      'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                      );
      //CountryInfo object initialization
      $CompcountryInfo = new CountryInfo();
      $CompcountryInfo->CountryId = '0';
      $CompcountryInfo->CountryISOCode = '';
      $CompcountryInfo->CountryISONumber = '';
      $CompcountryInfo->CountryRegionNumber = '';
      $CompcountryInfo->CountryPhoneCode = '';
      $CompcountryInfo->CountryName = $params['country'];
      $CompcountrySoapVar = new SoapVar($CompcountryInfo, // the object to wrap
                                        SOAP_ENC_OBJECT,
                                        get_class($CompcountryInfo), // the concrete class name
                                        'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                        );
			
      //reseller company properties
      
      $resellerModuleSettings = new ResellerModuleSettings();
      $resellerModuleSettings->CRMEnabled = true;
      $resellerModuleSettings->DomainRegistrarsEnabled = true;
      $resellerModuleSettings->DedicatedProductEnabled = true;
      $resellerModuleSettings->ExchangeEnabled = true;
      $resellerModuleSettings->LyncEnabled = true;
      $resellerModuleSettings->MiscProductEnabled = true;
      $resellerModuleSettings->SharepointEnabled = true;
      $resellerModuleSettings->SSLVendorsEnabled = true;
      $resellerModuleSettings->VPSEnabled = true;
      $resellerModuleSettings->WirelessEnabled = true;
      $resellerModuleSettings->WebHostingEnabled = true;
      $resellerModuleSettings->Office365Enabled = true;
      $resellerModuleSettings->IsRDSEnabled = true;
      $resellerModuleSettings->IsWorkFolderEnabled = true;
      $resellerModuleSettings->IsSIPHostingEnabled = true;
	  $resellerModuleSettings->IsHostedVoiceEnabled = true;
      $resellerModuleSettingsSoapVar = new SoapVar($resellerModuleSettings, // the object to wrap
                                                  SOAP_ENC_OBJECT,
                                                  get_class($resellerModuleSettings), // the concrete class name
                                                  'http://machsol.com/' // namespace that proxy classes belong to (in WSDL)
                                                  );
      $customerObject->ResellerModules = $resellerModuleSettingsSoapVar;
      $customerObject->ResellerType = 'Subscription';
      
      $customerObject->CompanyAddress1 = $params['address1'];
      $customerObject->CompanyAddress2 = $params['address2'];
      $customerObject->CompanyCity = $params['city'];
      $customerObject->CompanyCountry = $CompcountrySoapVar;
      $customerObject->CompanyFax = '';
      $customerObject->CompanyName = $params['companyname'];
      $customerObject->CompanyPhone = $params['phonenumber'];
      $customerObject->CompanyProvince = $params['state'];
      $customerObject->CompanyState = $CompstateSoapVar;
      $customerObject->CompanyZipCode = $params['postcode'];
      $customerObject->BillingEmail = $params['email'];
      $customerObject->BillingPhone = $params['phonenumber'];
      $customerObject->BillingSignature = "--Billing Department--";
      $customerObject->SalesEmail = $params['email'];
      $customerObject->SalesPhone = $params['phonenumber'];
      $customerObject->SalesSignature = "--Sales Department--";
      $customerObject->SupportEmail = $params['email'];
      $customerObject->SupportPhone = $params['phonenumber'];
      $customerObject->SupportSignature = "--Support Department--";
      $customerObject->WhiteLabelUrl = "";
      $customerObject->WebURL = "";
	  
    }
    
	
									
	return $customerObject;
  }
  
  function submitConfigOptions($params)
  {
    try
    {
      $paramArray = array();
      $paramArray['WServiceId'] = $params["serviceid"];
      $paramArray['WProductId'] = $params["pid"];
      $paramArray['configoptions'] = $params['configoptions'];
      $paramArray['customfields'] = $params["customfields"];
      $paramArray['domain'] = $params["domain"];
	    //var_dump($paramArray);
      $RespArgs = $this->SvcClient->SubmitWHMCSOrderConfigOptions($paramArray)->SubmitWHMCSOrderConfigOptionsResult;
      
      if(!$RespArgs->ResponseStatus)
		  {
			  return "Submit order config options to machpanel module request ended with message: ".$RespArgs->ResponseMessage;
		  }
		  else
		  {
			  return "success";
		  }
    }
    catch(Exception $sf)
	  {
		  $errMsg = 'Error: '.$sf->getMessage();
		  $errMsg = $errMsg.'<br /><b>Request:</b> '.$this->SvcClient->__getLastRequest();
		  $errMsg = $errMsg.'<br /><b>Response:</b> '.$this->SvcClient->__getLastResponse();
		  $errMsg = $errMsg.'<br /><b>Request Header:</b> '.$this->SvcClient->__getLastRequestHeaders();
		  $errMsg = $errMsg.'<br /><b>Response Header:</b> '.$this->SvcClient->__getLastResponseHeaders();
		  return 'Soap Fault in submitting the order config options. Details: '.$errMsg;
	  }
  }
}
?>