Created
February 26, 2012 17:12
-
-
Save Seza/1917812 to your computer and use it in GitHub Desktop.
Pixelpost 2 API client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| class Pixelpost_Api_Client | |
| { | |
| const API_URL = 'http://localhost/pixelpost/api/'; | |
| const PUB_KEY = ''; | |
| const PRIV_KEY = ''; | |
| protected $is_auth = false; | |
| protected $session = ''; | |
| protected $lifetime = ''; | |
| protected $challenge = ''; | |
| protected $token = ''; | |
| protected $nonce = ''; | |
| protected $secret = ''; | |
| protected $err_code = ''; | |
| protected $err_msg = ''; | |
| public function __construct($session) | |
| { | |
| $this->session = $session; | |
| $this->secret = md5(static::PUB_KEY . static::PRIV_KEY); | |
| } | |
| public function request($method, $request) | |
| { | |
| // authenticate if not | |
| if (!$this->is_auth) | |
| { | |
| $this->connect(); | |
| } | |
| // make the api request | |
| if (false === $data = $this->call($method, $request)) | |
| { | |
| // on error, if it's because we have a too old token we refresh it | |
| if ($this->err_code === 'old_token') | |
| { | |
| $this->refresh(); | |
| return $this->request($method, $request); | |
| } | |
| else | |
| { | |
| $this->error('Request error'); | |
| } | |
| } | |
| return $data; | |
| } | |
| protected function salt() | |
| { | |
| return ceil(time() / $this->lifetime) * $this->lifetime; | |
| } | |
| protected function token() | |
| { | |
| return md5($this->challenge . $this->secret . $this->salt()); | |
| } | |
| protected function sign($data) | |
| { | |
| return md5($this->token . $data . $this->secret); | |
| } | |
| protected function hmac($header, $data) | |
| { | |
| return md5($this->nonce . $header . $this->serialize($data) . $this->secret); | |
| } | |
| protected function serialize($request) | |
| { | |
| $serial = ''; | |
| foreach($request as $key => $val) | |
| { | |
| if (!is_scalar($val)) | |
| { | |
| $val = $this->serialize((array) $val); | |
| } | |
| if (is_bool($val)) | |
| { | |
| $val = $val ? 'true' : 'false'; | |
| } | |
| $serial .= sprintf('%s:%s,', $key, $val); | |
| } | |
| return sprintf('{%s}', $serial); | |
| } | |
| protected function error($msg) | |
| { | |
| throw new Exception(sprintf('%s: [%s] %s', $msg, $this->err_code, $this->err_msg)); | |
| } | |
| protected function call($method, $request) | |
| { | |
| // if we are authenticated, add auth info, as extra params, in call url | |
| $auth = ''; | |
| if ($this->is_auth) | |
| { | |
| $auth .= '/token:' . $this->token; | |
| $auth .= '/hmac:' . $this->hmac($method, $request); | |
| } | |
| // the full url to call with http query request | |
| $format = static::API_URL . 'get/%s/json%s?%s'; | |
| $url .= sprintf($format, $method, $auth, http_build_query($request)); | |
| // the JSON response | |
| $data = json_decode($raw = file_get_contents($url, false)); | |
| // if there is no error | |
| if ($data->status == 'valid') | |
| { | |
| // if we are auth, the response have a hmac we check it | |
| if ($this->is_auth) | |
| { | |
| // if the hmac is good we store the nonce for the next request | |
| if ($data->hmac == $this->hmac($data->nonce, $data->response)) | |
| { | |
| $this->nonce = $data->nonce; | |
| } | |
| else | |
| { | |
| throw new Exception('Bad response hmac'); | |
| } | |
| } | |
| // return the response data | |
| return $data->response; | |
| } | |
| else | |
| { | |
| // else we store the error data and return false | |
| $this->err_code = $data->code; | |
| $this->err_msg = $data->message; | |
| return false; | |
| } | |
| } | |
| protected function auth($method, $request) | |
| { | |
| // check if auth.token or auth.refresh have a good signature | |
| if (false === $data = $this->call($method, $request)) | |
| { | |
| return false; | |
| } | |
| if ($data->signature != $this->sign($data->nonce)) | |
| { | |
| throw new Exception('Bad ' . $method . ' signature'); | |
| } | |
| // auth is good, store the nonce for the next request | |
| $this->nonce = $data->nonce; | |
| $this->is_auth = true; | |
| return true; | |
| } | |
| protected function connect() | |
| { | |
| $public_key = static::PUB_KEY; | |
| $session = $this->session; | |
| // call api auth.request | |
| if (false === $data = $this->call('auth.request', compact('public_key', 'session'))) | |
| { | |
| $this->error('Fail to request a challenge'); | |
| } | |
| // generate the token | |
| $this->challenge = $data->challenge; | |
| $this->lifetime = $data->lifetime; | |
| $this->token = $this->token(); | |
| $challenge = $this->challenge; | |
| $signature = $this->sign($this->challenge); | |
| // call api auth.token | |
| if (!$this->auth('auth.token', compact('challenge', 'signature'))) | |
| { | |
| $this->error('Fail to valid a token'); | |
| } | |
| } | |
| protected function refresh() | |
| { | |
| // cancel the authentication | |
| $this->is_auth = false; | |
| // generate a new token | |
| $token = $this->token; | |
| $this->token = $this->token(); | |
| $signature = $this->sign($token); | |
| // call api auth.refresh | |
| if (!$this->auth('auth.refresh', compact('token', 'signature'))) | |
| { | |
| $this->error('Fail to refresh a token'); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment