So we wanted to create a private API that would allow others to interact with our services such as saving certain things in our db via api or getting certain information.
The API itself only expects JSON data that can be pased via any programming language to the API. Unlike other APIs like facebook, we don't give any files to users to use API like facebook does provide classes for different languages to interact with their api. So we thought api users can use any language to send us json data and based on that json data, we can call certain functions of api via use
parameter they provide via query string.
Here is code of the API at most basic level to get you an idea of how it works:
class Api
{
/**
* Default function called when API url is accessed
*
* @return mixed
* @throws Exception
*/
public function index()
{
$appId = isset($_GET['appId']) ? $_GET['appId'] : null;
$apiKey = $_GET['apiKey'] ? $_GET['apiKey'] : null;
$method = $_GET['use'] ? $_GET['use'] : null;
$data = json_decode(file_get_contents("php://input"), true);
if ($this->validateRequest($appId, $apiKey, $method)) {
return call_user_func_array(array($this, $method), array($data));
}
}
private function validateRequest($appId, $apiKey, $method)
{
# check referer
$requestUri = isset($_SERVER["HTTP_REFERER"]) ? $_SERVER["HTTP_REFERER"] : null;
if (!$requestUri) {
$this->bye('HTTP_REFERER is required!');
}
# check if method exists
if (!$method || !method_exists('Apicall', $method)) {
$this->bye('Invalid \'use\' value!');
}
# check appId, apiKey and requestUri
if (!$appId) {
$this->bye('Invalid appId!');
}
if (!$apiKey) {
$this->bye('Invalid apiKey!');
}
$db = new DB();
$db->where('appid', $appId);
$db->where('apikey', $apiKey);
$db->where('request_uri', pathWithoutEndingSlash($requestUri));
$db->get();
if ($db->exists() && $db->result_count() > 0) {
return true;
}
$this->bye('Request Denied!');
}
private function bye($error)
{
echo json_encode(array('Error' => $error));
exit;
}
private function getIntervals()
{
$values = array('monthly', 'quarterly', 'yearly', 'single_payment');
echo json_encode($values);
}
}
As can be seen, we validate if provided appId
, apiKey
and requestURI
exists in our db (which we already generated for api users) then call the method specified via the use
query string variable in the call:
http://localhost/myapi/api.php?appId=local&apiKey=98a4d2e5b7fa21d424a0932c7f47a6943d57d64b&use=getIntervals
Is this correct way of making a private API or am I still missing something ?
Anyone who listens on requests (so if you call your api on WIFI or as AJAX calls) will be able to see your appId and apiKey. So they will be able to call your api as well. A better method is to:
If you want a quick REST API I can recommend Restler. It also incorporates authentication. http://luracast.com/products/restler