Saturday, September 17, 2016

osTicket, Create Ticket with API

Hello,

Recently for one of my project we have a requirement to integrate laravel application and osTicket. Data from laravel app to be sent to osTicket and create ticket with that.

Now we all know that in osTicket if send an email, it will automatically create ticket. However in our case it won't work as emails were from different domains so we have to use osTicket API.

First of all you have to create API key for that login to your osTicket admin panel and go to.

Admin Panel -> Manage -> API keys and create new API key.


Here IP address is your source IP address from where you will call an API. In our case it was server IP address. Now API key is created. Following is the code.

$config = array(
'url'=>'http://yourosTicketURL/api/tickets.json', 
'key'=>'yourapikey'  // API Key goes here
);


In above code replace yourosTicketURL with your URL and replace yourapikey with your generated key.

Now prepare data to send.

$name = 'Name of User';
$email = 'Email of User';
$mobile = 'Mobile';
$subject = 'Subject';
$text = 'Dummy message';

$data = array(
'name'      =>     $name,
'email'     =>      $email,
'phone' =>     $mobile,
'subject'   =>      $subject,
'message'   =>   "data:text/html;charset=utf-8,$text",
'ip'        =>      $_SERVER['REMOTE_ADDR'],
'topicId'   =>      '1',
'attachments' => array()
);

Now we will send data to API.

#pre-checks
function_exists('curl_version') or die('CURL support required');
function_exists('json_encode') or die('JSON support required');

#set timeout
set_time_limit(30);

#curl post
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config['url']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_USERAGENT, 'osTicket API Client v1.333');
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Expect:', 'X_API_KEY: '.$config['key']));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$result=curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($code != 201)
die('Unable to create ticket: '.$result);

$ticket_id = (int) $result;

# Continue onward here if necessary. $ticket_id has the ID number of the
# newly-created ticket

function IsNullOrEmptyString($question){
return (!isset($question) || trim($question)==='');
}

That's it and it should work. No wait if you run you will always get following error.

Unable to create ticket:  Invalid API key.

Now that was really strange as API key was valid, IP address was valid everything is good but still it does not create ticket. So what to do. Well there is a bug in osTicket API code. After spending couple of hours I finally figure out the solution. We have to modify osTicket source code for this. Open following file.

include/class.api.php

And find out following functions.

function requireApiKey() {
        # Validate the API key -- required to be sent via the X-API-Key
        # header

        if(!($key=$this->getApiKey()))
            return $this->exerr(401, __('Valid API key required'));
        elseif (!$key->isActive() || $key->getIPAddr()!=$_SERVER['REMOTE_ADDR'])
            return $this->exerr(401, __('API key not found/active or source IP not authorized'));

        return $key;
    }

    function getApiKey() {

        if (!$this->apikey && isset($_SERVER['HTTP_X_API_KEY']) && isset($_SERVER['REMOTE_ADDR']))
            $this->apikey = API::lookupByKey($_SERVER['HTTP_X_API_KEY'], $_SERVER['REMOTE_ADDR']);

        return $this->apikey;
    }

Here the problem was it never get HTTP_X_API_KEY and REMOTE_ADDR was never set. So replace above two function with following code.

function requireApiKey() {
        # Validate the API key -- required to be sent via the X-API-Key
        # header
        if(!($key=$this->getApiKey()))
            return $this->exerr(401, __('Valid API key required'));
        elseif (!$key->isActive() || $key->getIPAddr()!=$_SERVER['REMOTE_ADDR'])
            return $this->exerr(401, __('API key not found/active or source IP not authorized'));

        return $key;
    }

    function getApiKey() {
 
  foreach (getallheaders() as $name => $value) {
  $_SERVER['HTTP_'.$name] = $value;
  }
    if (!$this->apikey && isset($_SERVER['HTTP_X-Api-Key']) && isset($_SERVER['REMOTE_ADDR']))
            $this->apikey = API::lookupByKey($_SERVER['HTTP_X-Api-Key'], $_SERVER['REMOTE_ADDR']);

        return $this->apikey;
    }

As you can see in above code we are getting all headers we set when we call API and put it in $_SERVER variable. and instead of REMOTE_ADDR we are using HTTP_X_REAL_IP.  Now save the file and again run API code. It should work fine.




2 comments:

  1. It's still giving "Unable to create ticket: Valid API key required" - this message.
    I made changes as u mentioned above.
    Can u help me on this?

    ReplyDelete
  2. I made changes in class.api.php file as u mentioned in above. But I'm still getting this message- "Unable to create ticket: Valid API key required".
    Can u help me on this?

    ReplyDelete