Friday, May 12, 2017

HTML2PDF Ahead of TCPDF - PHP PDF LIBRARY

Generate PDF from Html is always difficult, because if you want a better look PDF then you must need to spend good amount of time of it. TCPDF is well known to us as a rich PDF library. No problem with it but HTML2PDF is some type of as layer over TCPDF which makes it better. It has great custom page header and footer support.

Below is a code snippet:

require_once(dirname(__FILE__) . '/../vendor/autoload.php');
try {
    $html2pdf = new HTML2PDF('P', 'A4', 'en');
    $html2pdf->setDefaultFont('Arial');
    $html2pdf->writeHTML($html_content);
    $html2pdf->Output('PdfName.pdf');
} catch (HTML2PDF_exception $e) {
    echo $e;
    exit;

}

You can download full example code from link below.
Click here to download.

Below are attached some screenshots:






Thursday, May 11, 2017

PHP explode at capital letters

<?php
$str = "ExplodeAtCapitalLetters";
$str[0] = strtolower($str[0]);
$pieces = preg_split('/(?=[A-Z])/',$str);
$pieces[0][0] = strtoupper($pieces[0][0]);
print_r($pieces);



Array
(
    [0] => Explode
    [1] => At
    [2] => Capital
    [3] => Letters
)

Wednesday, May 10, 2017

jQuery Nice Select Plugin with Position And OptGroup Support

Nice Select is a small plugin to show html select in stylish way. But there are some limitations such no optgroup support. And positioning is not supported yet. I come up with this two problems and below is the code a screenshot.

First download Nice Select plugin from link below:


https://drive.google.com/drive/folders/0B5nZNPW48dpFcjhqQTItSGkxMlk?usp=sharing

<link rel="stylesheet" type="text/css" href="nice-select.css"/>
<script src="jquery-2.1.1.min.js"></script>
<script src="jquery.nice-select.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $("select").niceSelect();
    });
</script>


Saturday, May 6, 2017

Connect to MYOB Api Using Php Application

At first you need to create an application in MYOB, follow the below link to create an application:

https://my.myob.com.au/au/bd/DevAppList.aspx








Next step is to authorize your MYOB, to do so you have to visit below link:

https://secure.myob.com/oauth2/account/authorize?client_id=xxxxx&redirect_uri=http://localhost/ci/myob/&response_type=code&scope=CompanyFile

This will redirect to MYOB login page if you not logged in and then Authorization page.




After authorize you will back to you application with a code. 

You need to get access token and refresh token from MYOB using the code.

http://localhost/ci/myob/?code=.....

After you get access token and refresh token store that, its required to get company data. To get company related data it may need username and password for that company file.

Output of contact list will be below:


Array
(
    [code] => 200
    [error] => 
    [response] => stdClass Object
        (
            [Items] => Array
                (
                    [0] => stdClass Object
                        (
                            [UID] => 6cacb476-u6fd-451e-bb93-575d971c7189
                            [CompanyName] => Pritom
                            [IsIndividual] => 
                            [DisplayID] => OK-0019
                            [IsActive] => 1
                            [Addresses] => Array()
                            [Notes] => 
                            [Identifiers] => 
                            [CustomList1] => 
                            [CustomList2] => 
                            [CustomList3] => 
                            [CustomField1] => 
                            [CustomField2] => 
                            [CustomField3] => 
                            [CurrentBalance] => 750.82
                            [SellingDetails] => stdClass Object
                            [PaymentDetails] => stdClass Object
                            [LastModified] => 2016-02-26T06:06:37.277
                            [PhotoURI] => 
                            [URI] => https://ar2.api.myob.com/.....
                            [RowVersion] => -629937699343564800
                        )

                )

            [NextPageLink] => https://.../accountright/.../Contact/Customer?$top=5&$skip=5
            [Count] => 760
        )

)

Full PHP script below:


<?php
session_start();

$configs = array(
    "api_key" => "qv5s8qga.....hkhacwkn",
    "api_secret" => "aZJCySs.....vaDBD",
    "redirect_uri" => "http://localhost/myob.php"
);
$myob_connector = new MyobConnector($configs);
if (isset($_GET["expire"])) {
    unset($_SESSION["access_token"]);
    unset($_SESSION["company"]);
    unset($_SESSION["state"]);
}
if (isset($_GET["contacts"])) {
    $contacts = $myob_connector->execute("Contact/Customer?\$top=5&\$skip=0", "GET", "Administrator");
    $myob_connector->prettyPrint($contacts);
}
elseif (isset($_GET["company"])) {
    echo "<a href='myob.php?contacts=true'>List Contacts</a>";
    $contacts = $myob_connector->execute("Company", "GET", "Administrator");
    $myob_connector->prettyPrint($contacts);
}
elseif (isset($_SESSION["access_token"])) {
    $company_list = $myob_connector->getCompanyList();
    if ($company_list["code"] == 200) {
        $_SESSION["company"] = $company_list["response"][0]->Id;
        header("Location: " . $configs["redirect_uri"] . "?company=true");
    }
    else {
        $myob_connector->prettyPrint($company_list);
    }
}
elseif (isset($_GET["code"])) {
    $myob_connector->getAccessToken($_GET["code"]);
    header("Location: " . $configs["redirect_uri"] . "?company");
}
else {
    $_SESSION["state"] = uniqid();
    $myob_connector->authorize();
}

class MyobConnector {
    private $conigs = null;

    function __construct($configs) {
        $this->conigs = $configs;
    }

    public function authorize() {
        $authorize_url = "https://secure.myob.com/oauth2/account/authorize?" .
            "client_id=" . $this->conigs["api_key"] .
            "&redirect_uri=" . rawurlencode($this->conigs['redirect_uri']) .
            "&response_type=code&scope=CompanyFile&state=".$_SESSION["state"];
        header("Location: $authorize_url");
        exit();
    }

    public function getAccessToken($access_code) {
        $params = array(
            'client_id' => $this->conigs["api_key"],
            'client_secret' => $this->conigs["api_secret"],
            'scope' => "CompanyFile",
            'code' => rawurlencode($access_code),
            'redirect_uri' => rawurlencode($this->conigs["redirect_uri"]),
            'grant_type' => 'authorization_code'
        );
        $post = "";
        foreach ($params as $k => $v) {
            $post .= "$k=$v&";
        }
        $headers[] = "Content-Type: application/x-www-form-urlencoded";
        $response = $this->getToken(substr($post, 0, strlen($post) - 1), $headers);
        if ($response["code"] == 200) {
            $_SESSION["access_token"] = $response["response"]->access_token;
            $_SESSION["refresh_token"] = $response["response"]->refresh_token;
            $_SESSION["expires_in"] = $response["response"]->expires_in + time();
        }
        else {
            $this->prettyPrint($response);
            die();
        }
    }

    public function refreshAccessToken() {
        $params = array(
            'client_id' => $this->conigs["api_key"],
            'client_secret' => $this->conigs["api_secret"],
            'refresh_token' => $_SESSION["refresh_token"],
            'grant_type' => 'refresh_token',
        );
        $post = "";
        foreach ($params as $k => $v) {
            $post .= "$k=$v&";
        }
        $headers[] = "Content-Type: application/x-www-form-urlencoded";
        $response = $this->getToken(substr($post, 0, strlen($post) - 1), $headers);
        if ($response["code"] == 200) {
            $_SESSION["access_token"] = $response["response"]->access_token;
            $_SESSION["refresh_token"] = $response["response"]->refresh_token;
            $_SESSION["expires_in"] = $response["response"]->expires_in + time();
        }
        else {
            $this->prettyPrint($response);
            die();
        }
    }

    private function getToken($params, $headers = null) {
        return $this->getURL("https://secure.myob.com/oauth2/v1/authorize", "POST", $params, $headers);
    }

    public function execute($end_point, $method = "GET", $userName = null, $password = "") {
        $company = $_SESSION["company"];
        $end_point = "https://api.myob.com/accountright/$company/$end_point";
        $headers[] = "Authorization: Bearer " . $_SESSION["access_token"];
        if ($userName) {
            $headers[] = "x-myobapi-cftoken: " . base64_encode("$userName:$password");
        }
        $headers[] = "x-myobapi-key: " . $this->conigs["api_key"];
        $headers[] = "x-myobapi-version: v2";
        $response = $this->getURL($end_point, $method, null, $headers);
        if ($response["code"] == 401) {
            $this->refreshAccessToken();
        }
        return $this->getURL($end_point, $method, null, $headers);
    }

    public function getCompanyList() {
        $end_point = "https://api.myob.com/accountright";
        $headers[] = "Authorization: Bearer " . $_SESSION["access_token"];
        $headers[] = "x-myobapi-cftoken: ";
        $headers[] = "x-myobapi-key: " . $this->conigs["api_key"];
        $headers[] = "x-myobapi-version: v2";
        return $this->getURL($end_point, "GET", null, $headers);
    }

    private function getURL($url, $method = "GET", $params = null, $headers = null) {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_USERAGENT, "Test APP");
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        if ($method == "POST") {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        }

        if (isset($headers)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        $error = curl_error($ch);
        curl_close($ch);
        $response2 = json_decode($response);
        if (strlen($response) > 0 && is_null($response2)) {
            $response2 = $response;
        }
        return array(
            "code" => $code,
            "error" => $error,
            "response" => $response2
        );
    }

    public function prettyPrint($o) {
        echo "<pre>";
        print_r($o);
        echo "</pre>";
    }
}
  

Create Contact in Xero Via API using PHP

The very first step you make a connection between your application and Xero API. To do so you need to create and application in Xero and establish a connection. Follow the below link to see how PHP communicates with Xero Application:

http://pritomkumar.blogspot.com/2017/05/connect-to-xero-private-application.html

And below is full PHP script which will create Contacts in Xero:


<?php
define('BASE_PATH', dirname(__FILE__));
$configs = array(
    "consumer_key" => "OVLVISLORWW72YRDYAV3KI........",
    "consumer_secret" => "HRTPKPBSSBNN4TA32BKW.......",
    "core_version" => "2.0",
    "payroll_version" => "1.0",
    "file_version" => "1.0",
    "rsa_private_key" => BASE_PATH . "/XeroCerts/privatekey.pem",
    "application_type" => "Private",
    "oauth_callback" => "oob",
    "user_agent" => "Trial #3"
);

$parameters = array();

createContact($configs, $parameters);

function createContact($configs, $parameters)
{
    $post = array(
        "Contacts" => array(
            "Contact" => array(
                "Name" => "Xero Contact 1"
            ),
            "Contact 2" => array(
                "Name" => "Xero Contact 2"
            )
        )
    );
    $xero_connector = new XeroConnector($configs, $parameters);
    $contact_data = $xero_connector->execute("POST", "Contact", $post);
    XeroConnector::prettyPrint($contact_data);
}

class XeroConnector
{
    private $configs = null;
    private $headers = array();
    private $parameters = array();
    private $nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

    function __construct($configs, $parameters)
    {
        $this->configs = $configs;
        $this->parameters = $parameters;
    }

    function execute($method, $target, $post_body = "")
    {
        if (is_array($post_body)) {
            $this->post_body = $this->arrayToXml($post_body);
        } else {
            $this->post_body = $post_body;
        }
        $this->method = strtoupper($method);
        $this->path = "https://api.xero.com/api.xro/2.0/$target";
        $this->buildParameters();
        $this->sign();
        return $this->curlRequest($this->sign["signed_url"]);
    }

    private function sign()
    {
        $this->parameters["oauth_signature"] = $this->generateSignature();
        $this->sign = array(
            'parameters' => $this->parameters,
            'signature' => $this->escape($this->parameters["oauth_signature"]),
            'signed_url' => $this->path . '?' . $this->normalizeParameters('true'),
            'header' => $this->getHeaderString(),
            'sbs' => $this->sbs
        );
    }

    private function curlRequest($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_USERAGENT, "Test APP");
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $this->headers['Accept'] = 'application/json';
        switch ($this->method) {
            case "GET":
                $this->content_length = 0;
                break;
            case 'POST':
                $this->headers['Content-Length'] = strlen($this->post_body);
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post_body);
                $this->headers['Content-Type'] = 'application/xml';
                break;
            case 'PUT' :
                $this->headers['Content-Length'] = strlen($this->post_body);
                $fh = tmpfile();
                fwrite($fh, $this->post_body);
                rewind($fh);
                curl_setopt($ch, CURLOPT_PUT, true);
                curl_setopt($ch, CURLOPT_INFILE, $fh);
                curl_setopt($ch, CURLOPT_INFILESIZE, $this->headers ['Content-Length']);
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
                break;
            default :
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
        }

        if (count($this->headers) > 0) {
            $headers = array();
            foreach ($this->headers as $k => $v) {
                $headers [] = trim($k . ': ' . $v);
            }
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        return array('body' => json_decode($response), 'code' => $code);
    }

    private function safe_encode_xml_entity($data)
    {
        return str_ireplace(
            array("<",    ">",    "'",      "\"",    "&"),
            array("&lt;", "&gt;", "&apos;", "&quot", "&amp;"),
            $data
        );
    }

    private function getHeaderString($args = array())
    {
        $result = 'OAuth ';

        foreach ($this->parameters as $pName => $pValue) {
            if (strpos($pName, 'oauth_') !== 0)
                continue;
            if (is_array($pValue)) {
                foreach ($pValue as $val) {
                    $result .= $pName . '="' . $this->escape($val) . '", ';
                }
            } else {
                $result .= $pName . '="' . $this->escape($pValue) . '", ';
            }
        }
        return preg_replace('/, $/', '', $result);
    }

    private function generateSignature()
    {
        switch ($this->parameters['oauth_signature_method']) {
            case 'RSA-SHA1':
                $private_key = openssl_pkey_get_private($this->readFile($this->configs['rsa_private_key']));
                $this->sbs = $this->escape($this->method) . "&" . $this->escape($this->path) . "&" .
                    $this->escape($this->normalizeParameters());
                openssl_sign($this->sbs, $signature, $private_key);
                openssl_free_key($private_key);
                return base64_encode($signature);
            case 'PLAINTEXT':
                return urlencode($this->configs["consumer_secret"]);
            case 'HMAC-SHA1':
                $this->sbs = $this->escape($this->method) . '&' . $this->escape($this->path) . '&' . $this->escape($this->normalizeParameters());
                return base64_encode(hash_hmac('sha1', $this->sbs, $this->configs["consumer_secret"], true));
            default:
                throw new OAuthSimpleException('Unknown signature method for OAuthSimple');
        }
    }

    private function normalizeParameters($filter = 'false')
    {
        $elements = array();
        ksort($this->parameters);
        foreach ($this->parameters as $k => $v) {
            if ($k == 'xml') {
                if ($filter == "true")
                    continue;
            }
            if (preg_match('/\w+_secret/', $k))
                continue;
            if (is_array($v)) {
                sort($v);
                foreach ($v as $element)
                    array_push($elements, $this->escape($k) . '=' . $this->escape($element));
                continue;
            }
            array_push($elements, $this->escape($k) . '=' . $this->escape($v));
        }
        return join('&', $elements);
    }

    private function readFile($file_path)
    {
        $fp = fopen($file_path, "r");
        $file_contents = fread($fp, 8192);
        fclose($fp);
        return $file_contents;
    }

    private function arrayToXml($data, $tab = 0)
    {
        $xml = "\r\n";
        foreach ($data as $k => $v)
        {
            $sp = "";
            for ($i = 0; $i < $tab; $i++)
            {
                $sp .= "\t";
            }
            if (strpos($k, " ") !== false) {
                $k = substr($k, 0, strpos($k, " "));
            }
            if (is_array($v)) {
                $tab2 = $tab + 1;
                $v = $this->arrayToXml($v, $tab2);
                $xml .= "$sp<$k>$v". "$sp</$k>\r\n";
            } else {
                $v = $this->safe_encode_xml_entity($v);
                $xml .= "$sp<$k>$v</$k>\r\n";
            }
        }
        return $xml;
    }

    private function escape($string)
    {
        if ($string === 0)
            return 0;
        if (empty($string))
            return '';
        if (is_array($string))
            throw new OAuthSimpleException('Array passed to _oauthEscape');

        $string = rawurlencode($string);
        $string = str_replace('+', '%20', $string);
        $string = str_replace('!', '%21', $string);
        $string = str_replace('*', '%2A', $string);
        $string = str_replace('\'', '%27', $string);
        $string = str_replace('(', '%28', $string);
        $string = str_replace(')', '%29', $string);
        return $string;
    }

    private function buildParameters()
    {
        $this->parameters["oauth_nonce"] = $this->getNonce(20);
        $this->parameters["oauth_token"] = $this->configs["consumer_key"];
        $this->parameters["oauth_version"] = "1.0";
        $this->parameters["oauth_timestamp"] = time();
        $this->parameters["oauth_consumer_key"] = $this->configs["consumer_key"];
        $this->parameters["oauth_signature_method"] = "RSA-SHA1";
    }

    private function getNonce($length)
    {
        $result = '';
        $nonce_length = strlen($this->nonce_chars);
        for ($i = 0; $i < $length; $i++) {
            $index = rand(0, $nonce_length);
            $result .= substr($this->nonce_chars, $index, 1);
        }
        return $result;
    }

    public static function prettyPrint($o)
    {
        echo "<pre>";
        print_r($o);
        echo "</pre>";
    }
}




Below is a screen-shot of my Xero portal:




Output will be as follows:


Array
(
    [code] => 200
    [body] => stdClass Object
        (
            [Id] => e614f8ea-07b1-4b69-88b0-c174ffb062d5
            [Status] => OK
            [ProviderName] => Trial #2
            [DateTimeUTC] => /Date(1494045918570)/
            [Contacts] => Array
                (
                    [0] => stdClass Object
                        (
                            [ContactID] => 7de72cb7-7d6f-13f8-9e76-ea191269553a
                            [ContactStatus] => ACTIVE
                            [Name] => Xero Contact 1
                            [EmailAddress] => 
                            [BankAccountDetails] => 
                            [Addresses] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [AddressType] => STREET
                                            [City] => 
                                            [Region] => 
                                            [PostalCode] => 
                                            [Country] => 
                                        )

                                    [1] => stdClass Object
                                        (
                                            [AddressType] => POBOX
                                            [City] => 
                                            [Region] => 
                                            [PostalCode] => 
                                            [Country] => 
                                        )

                                )

                            [Phones] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [PhoneType] => DEFAULT
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [1] => stdClass Object
                                        (
                                            [PhoneType] => DDI
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [2] => stdClass Object
                                        (
                                            [PhoneType] => FAX
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [3] => stdClass Object
                                        (
                                            [PhoneType] => MOBILE
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                )

                            [UpdatedDateUTC] => /Date(1494044711587+0000)/
                            [ContactGroups] => Array
                                (
                                )

                            [IsSupplier] => 
                            [IsCustomer] => 
                            [SalesTrackingCategories] => Array
                                (
                                )

                            [PurchasesTrackingCategories] => Array
                                (
                                )

                            [ContactPersons] => Array
                                (
                                )

                            [HasValidationErrors] => 
                        )

                    [1] => stdClass Object
                        (
                            [ContactID] => 8eb00757-74f3-4302-99a8-3453dd4d456c
                            [ContactStatus] => ACTIVE
                            [Name] => Xero Contact 2
                            [EmailAddress] => 
                            [BankAccountDetails] => 
                            [Addresses] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [AddressType] => STREET
                                            [City] => 
                                            [Region] => 
                                            [PostalCode] => 
                                            [Country] => 
                                        )

                                    [1] => stdClass Object
                                        (
                                            [AddressType] => POBOX
                                            [City] => 
                                            [Region] => 
                                            [PostalCode] => 
                                            [Country] => 
                                        )

                                )

                            [Phones] => Array
                                (
                                    [0] => stdClass Object
                                        (
                                            [PhoneType] => DEFAULT
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [1] => stdClass Object
                                        (
                                            [PhoneType] => DDI
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [2] => stdClass Object
                                        (
                                            [PhoneType] => FAX
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                    [3] => stdClass Object
                                        (
                                            [PhoneType] => MOBILE
                                            [PhoneNumber] => 
                                            [PhoneAreaCode] => 
                                            [PhoneCountryCode] => 
                                        )

                                )

                            [UpdatedDateUTC] => /Date(1494044711620+0000)/
                            [ContactGroups] => Array
                                (
                                )

                            [IsSupplier] => 
                            [IsCustomer] => 
                            [SalesTrackingCategories] => Array
                                (
                                )

                            [PurchasesTrackingCategories] => Array
                                (
                                )

                            [ContactPersons] => Array
                                (
                                )

                            [HasValidationErrors] => 
                        )

                )

        )

)

How to safely escape invalid XML characters

When you want to make string to XML, it is very important that you have to escape invalid characters from the string. The table below shows the invalid XML characters and their escaped characters. 


Invalid Character Replace Character
< &lt;
> &gt;
" &quot;
' &apos;
& &amp;
\n &#xA;
\r &#xD;

Friday, May 5, 2017

Connect to Xero Private Application Using Php Application

The link below is for Xero dashboard:
https://my.xero.com

Very first you need to create an application in Xero, follow the link below to create application:
https://app.xero.com/Application/

Click on "Add Application" and fill up required fields. In this step you will need public/private key pair. To generate public/pair key follow the link. You need to upload "publickey.cer" in xero application form and other file named "privatekey.perm" need to place in a folder named "XeroCerts" in your application directory.




After click save you will forward to next page, from where you can get Consumer Key & Consumer Secret which will need to connect to your organization via this application.





You are done with create application in Xero.

Next step to write some PHP script to connect to Xero.
Below is a small PHP script which help you to connect to Xero.


<?php
define('BASE_PATH', dirname(__FILE__));
$configs = array(
    "consumer_key" => "QM6QQSESK2KVGTRUGY1........",
    "consumer_secret" => "LHAHIPRIIP6ZZASIHPP........",
    "core_version" => "2.0",
    "payroll_version" => "1.0",
    "file_version" => "1.0",
    "rsa_private_key" => BASE_PATH . "/XeroCerts/privatekey.pem",
    "rsa_public_key" => BASE_PATH . "/XeroCerts/publickey.cer",
    "application_type" => "Private",
    "oauth_callback" => "oob",
    "user_agent" => "Trial #3"
);

$parameters = array();

$xero_connector = new XeroConnector($configs, $parameters);
$organization_data = $xero_connector->execute("GET", "Organisation");
XeroConnector::prettyPrint($organization_data);

class XeroConnector
{
    private $configs = null;
    private $headers = array();
    private $parameters = array();

    function __construct($configs, $parameters)
    {
        $this->configs = $configs;
        $this->parameters = $parameters;
    }

    function execute($method, $target, $post_body = "")
    {
        $this->post_body = $post_body;
        $this->method = strtoupper($method);
        $this->path = "https://api.xero.com/api.xro/2.0/$target";
        $this->nonce_chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
        $this->buildParameters();
        $this->sign();
        return $this->curlRequest($this->sign["signed_url"]);
    }

    private function sign()
    {
        $this->parameters["oauth_signature"] = $this->generateSignature();
        $this->sign = array(
            'parameters' => $this->parameters,
            'signature' => $this->escape($this->parameters["oauth_signature"]),
            'signed_url' => $this->path . '?' . $this->normalizeParameters('true'),
            'header' => $this->getHeaderString(),
            'sbs' => $this->sbs
        );
    }

    private function curlRequest($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

        $this->headers['Accept'] = 'application/json';
        switch ($this->method) {
            case "GET":
                $this->content_length = 0;
                break;
            case 'POST':
                $this->headers['Content-Length'] = strlen($this->post_body);
                curl_setopt($ch, CURLOPT_POST, TRUE);
                curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post_body);
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
                break;
            case 'PUT' :
                $this->headers['Content-Length'] = strlen($this->post_body);
                $fh = tmpfile();
                fwrite($fh, $this->post_body);
                rewind($fh);
                curl_setopt($ch, CURLOPT_PUT, true);
                curl_setopt($ch, CURLOPT_INFILE, $fh);
                curl_setopt($ch, CURLOPT_INFILESIZE, $this->headers ['Content-Length']);
                $this->headers['Content-Type'] = 'application/x-www-form-urlencoded';
                break;
            default :
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method);
        }

        if (count($this->headers) > 0) {
            $headers = array();
            foreach ($this->headers as $k => $v) {
                $headers [] = trim($k . ': ' . $v);
            }
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        }

        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        curl_close($ch);

        return array('body' => json_decode($response), 'code' => $code);
    }

    private function getHeaderString($args = array())
    {
        $result = 'OAuth ';

        foreach ($this->parameters as $pName => $pValue) {
            if (strpos($pName, 'oauth_') !== 0)
                continue;
            if (is_array($pValue)) {
                foreach ($pValue as $val) {
                    $result .= $pName . '="' . $this->escape($val) . '", ';
                }
            } else {
                $result .= $pName . '="' . $this->escape($pValue) . '", ';
            }
        }
        return preg_replace('/, $/', '', $result);
    }

    private function generateSignature()
    {
        switch ($this->parameters['oauth_signature_method']) {
            case 'RSA-SHA1':
                $private_key = openssl_pkey_get_private($this->readFile($this->configs['rsa_private_key']));
                $this->sbs = $this->escape($this->method) . "&" . $this->escape($this->path) . "&" .
                    $this->escape($this->normalizeParameters());
                openssl_sign($this->sbs, $signature, $private_key);
                openssl_free_key($private_key);
                return base64_encode($signature);
            case 'PLAINTEXT':
                return urlencode($this->configs["consumer_secret"]);
            case 'HMAC-SHA1':
                $this->sbs = $this->escape($this->method) . '&' . $this->escape($this->path) . '&' . $this->escape($this->normalizeParameters());
                return base64_encode(hash_hmac('sha1', $this->sbs, $this->configs["consumer_secret"], true));
            default:
                throw new OAuthSimpleException('Unknown signature method for OAuthSimple');
        }
    }

    private function normalizeParameters($filter = 'false')
    {
        $elements = array();
        ksort($this->parameters);
        foreach ($this->parameters as $paramName => $paramValue) {
            if ($paramName == 'xml') {
                if ($filter == "true")
                    continue;
            }
            if (preg_match('/\w+_secret/', $paramName))
                continue;
            if (is_array($paramValue)) {
                sort($paramValue);
                foreach ($paramValue as $element)
                    array_push($elements, $this->escape($paramName) . '=' . $this->escape($element));
                continue;
            }
            array_push($elements, $this->escape($paramName) . '=' . $this->escape($paramValue));

        }
        return join('&', $elements);
    }

    private function readFile($file_path)
    {
        $fp = fopen($file_path, "r");
        $file_contents = fread($fp, 8192);
        fclose($fp);
        return $file_contents;
    }

    private function escape($string)
    {
        if ($string === 0)
            return 0;
        if (empty($string))
            return '';
        if (is_array($string))
            throw new OAuthSimpleException('Array passed to _oauthEscape');

        $string = rawurlencode($string);
        $string = str_replace('+', '%20', $string);
        $string = str_replace('!', '%21', $string);
        $string = str_replace('*', '%2A', $string);
        $string = str_replace('\'', '%27', $string);
        $string = str_replace('(', '%28', $string);
        $string = str_replace(')', '%29', $string);
        return $string;
    }

    private function buildParameters()
    {
        $this->parameters["oauth_nonce"] = $this->getNonce(5);
        $this->parameters["oauth_token"] = $this->configs["consumer_key"];
        $this->parameters["oauth_version"] = "1.0";
        $this->parameters["oauth_timestamp"] = time();
        $this->parameters["oauth_consumer_key"] = $this->configs["consumer_key"];
        $this->parameters["oauth_signature_method"] = "RSA-SHA1";
    }

    private function getNonce($length = 5)
    {
        $result = '';
        $cLength = strlen($this->nonce_chars);
        for ($i = 0; $i < $length; $i++) {
            $rnum = rand(0, $cLength);
            $result .= substr($this->nonce_chars, $rnum, 1);
        }
        return $result;
    }

    public static function prettyPrint($o)
    {
        echo "<pre>";
        print_r($o);
        echo "</pre>";
    }
}


And output will be like this on execution the above script:


Array
(
    [body] => stdClass Object
        (
            [Id] => 0d1fe562-8621-4bbb-b249-6a5ea051f308
            [Status] => OK
            [ProviderName] => Trial #3
            [DateTimeUTC] => /Date(1494001316337)/
            [Organisations] => Array
                (
                    [0] => stdClass Object
                        (
                            [APIKey] => W2N0UZYHPLFSPABKS2SS42AF5GDKMD
                            [Name] => Trial #3
                            [LegalName] => Trial #3
                            [PaysTax] => 1
                            [Version] => AU
                            [OrganisationType] => COMPANY
                            [BaseCurrency] => AUD
                            [CountryCode] => AU
                            [IsDemoCompany] => 
                            [OrganisationStatus] => ACTIVE
                            [FinancialYearEndDay] => 30
                            [FinancialYearEndMonth] => 6
                            [SalesTaxBasis] => ACCRUALS
                            [SalesTaxPeriod] => QUARTERLY1
                            [DefaultSalesTax] => Tax Exclusive
                            [DefaultPurchasesTax] => Tax Inclusive
                            [CreatedDateUTC] => /Date(1493991850000)/
                            [OrganisationEntityType] => COMPANY
                            [Timezone] => AUSEASTERNSTANDARDTIME
                            [ShortCode] => !GS3w5
                            [OrganisationID] => c653628f-a901-4836-8de1-6b00d23664fe
                            [LineOfBusiness] => Software Development & Consulting
                            [Addresses] => Array
                                (
                                )

                            [Phones] => Array
                                (
                                )

                            [ExternalLinks] => Array
                                (
                                )

                            [PaymentTerms] => stdClass Object
                                (
                                )

                        )

                )

        )

    [code] => 200
)