OauthSDK.class.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582
  1. <?php
  2. if (! function_exists('curl_init')) {
  3. throw new Exception('Snda needs the CURL PHP extension.');
  4. }
  5. if (! function_exists('json_decode')) {
  6. throw new Exception('Snda needs the JSON PHP extension.');
  7. }
  8. class OauthSDK
  9. {
  10. /**
  11. * Contains the last HTTP status code returned.
  12. *
  13. * @ignore
  14. */
  15. public $http_code;
  16. /**
  17. * Contains the last API call.
  18. *
  19. * @ignore
  20. */
  21. public $url;
  22. /**
  23. * Set timeout default.
  24. *
  25. * @ignore
  26. */
  27. public $timeout = 30;
  28. /**
  29. * Set connect timeout.
  30. *
  31. * @ignore
  32. */
  33. public $connecttimeout = 30;
  34. /**
  35. * Verify SSL Cert.
  36. *
  37. * @ignore
  38. */
  39. public $ssl_verifypeer = FALSE;
  40. /**
  41. * Respons format.
  42. *
  43. * @ignore
  44. */
  45. public $format = 'json';
  46. /**
  47. * Decode returned json data.
  48. *
  49. * @ignore
  50. */
  51. public $decode_json = TRUE;
  52. /**
  53. * Contains the last HTTP headers returned.
  54. *
  55. * @ignore
  56. */
  57. public $http_info;
  58. /**
  59. * Set the useragnet.
  60. *
  61. * @ignore
  62. */
  63. public $useragent = 'SNDA OAuth 2.0';
  64. /* Immediately retry the API call if the response was not successful. */
  65. //public $retry = TRUE;
  66. /**
  67. * The Application ID.
  68. */
  69. protected $appId;
  70. /**
  71. * The Application API Secret.
  72. */
  73. protected $appSecret;
  74. /**
  75. * app callback url
  76. */
  77. protected $redirectURI;
  78. protected $lastErrorCode;
  79. protected $lastErrorMsg;
  80. protected $systemParam = array(
  81. 'connectTimeout' => 5 ,
  82. 'timeout' => 3 ,
  83. 'gatewayUrl' => 'http://api.snda.com' ,
  84. 'authorizeURL' => 'http://oauth.snda.com/oauth/authorize' ,
  85. 'accessTokenURL' => 'http://oauth.snda.com/oauth/token' ,
  86. 'systemTokenURL' => 'http://oauth.snda.com/oauth/token' ,
  87. 'gatewayHost' => 'api.snda.com' ,
  88. 'gatewayPort' => 8888
  89. );
  90. protected $params = array();
  91. private $oauth_debug = FALSE;
  92. private $apiStartTime = 0;
  93. private $apiStopTime = 0;
  94. private $execTime = 0;
  95. /**
  96. * User Authorization url
  97. */
  98. function authorizeURL ()
  99. {
  100. return $this->systemParam['authorizeURL'];
  101. }
  102. /**
  103. * Get User Authorization url
  104. */
  105. function accessTokenURL ()
  106. {
  107. return $this->systemParam['accessTokenURL'];
  108. }
  109. /**
  110. * Get System Authorization url
  111. */
  112. function systemTokenURL ()
  113. {
  114. return $this->systemParam['systemTokenURL'];
  115. }
  116. /**
  117. * ApiPool GateWay Url
  118. */
  119. function apiPoolURL ()
  120. {
  121. return $this->systemParam['gatewayUrl'];
  122. }
  123. function __construct ($apiKey, $appSecret, $redirectURI)
  124. {
  125. $this->appId = $apiKey;
  126. $this->appSecret = $appSecret;
  127. $this->redirectURI = $redirectURI;
  128. }
  129. function setOption ($key, $value)
  130. {
  131. $this->systemParam[$key] = $value;
  132. }
  133. /**
  134. * Set the Application ID.
  135. *
  136. * @param String $appId the Application ID
  137. */
  138. public function setAppId ($appId)
  139. {
  140. $this->appId = $appId;
  141. }
  142. /**
  143. * Get the Application ID.
  144. *
  145. * @return String the Application ID
  146. */
  147. public function getAppId ()
  148. {
  149. return $this->appId;
  150. }
  151. public function setRedirectURI ($redirectURI)
  152. {
  153. $this->redirectURI = $redirectURI;
  154. }
  155. public function getRedirectURI ()
  156. {
  157. return $this->redirectURI;
  158. }
  159. /**
  160. * Set the API Secret.
  161. *
  162. * @param String $appId the API Secret
  163. */
  164. public function setApiSecret ($apiSecret)
  165. {
  166. $this->apiSecret = $apiSecret;
  167. }
  168. /**
  169. * Get the API Secret.
  170. *
  171. * @return String the API Secret
  172. */
  173. public function getApiSecret ()
  174. {
  175. return $this->apiSecret;
  176. }
  177. //Get accesstoken
  178. public function getAccessToken ($code)
  179. {
  180. $this->_clearError();
  181. $clientID = $this->appId;
  182. $redirectURI = $this->redirectURI;
  183. $clientSecret = $this->appSecret;
  184. $accessTokenURL = self::accessTokenURL();
  185. $url = "{$accessTokenURL}?code={$code}&client_id={$clientID}&client_secret={$clientSecret}&redirect_uri={$redirectURI}";
  186. $result = self::http($url);
  187. $access_token = json_decode($result, TRUE);
  188. if (empty($access_token) || isset($access_token['error'])) {
  189. $this->_setOAuthError($access_token);
  190. return FALSE;
  191. } else {
  192. return $access_token;
  193. }
  194. }
  195. //Generate User Authorization url
  196. public function getAuthorizeURL ()
  197. {
  198. $clientID = $this->appId;
  199. $redirectURI = $this->redirectURI;
  200. $authorizeURL = self::authorizeURL();
  201. return "{$authorizeURL}?response_type=code&client_id={$clientID}&redirect_uri={$redirectURI}";
  202. }
  203. //Generate System Authorization token
  204. public function getSystemToken ()
  205. {
  206. $this->_clearError();
  207. $clientID = $this->appId;
  208. $redirectURI = $this->redirectURI;
  209. $clientSecret = $this->appSecret;
  210. $accessTokenURL = self::accessTokenURL();
  211. $url = "{$accessTokenURL}?grant_type=client_credentials&client_id={$clientID}&client_secret={$clientSecret}";
  212. $result = self::http($url);
  213. $access_token = json_decode($result, TRUE);
  214. if (empty($access_token) || isset($access_token['error'])) {
  215. $this->_setOAuthError($access_token);
  216. return FALSE;
  217. } else {
  218. return $access_token;
  219. }
  220. }
  221. public static function generate_nonce ()
  222. {
  223. $mt = microtime();
  224. $rand = mt_rand();
  225. return md5($mt . $rand); // md5s look nicer than numbers
  226. }
  227. /**
  228. * request apipool
  229. */
  230. public function request ($method = 'TCP')
  231. {
  232. static $tcpField = array(
  233. 'method' => 1 ,
  234. 'oauth_consumer_key' => 1 ,
  235. 'oauth_token' => 1 ,
  236. 'oauth_nonce' => 1 ,
  237. 'oauth_timestamp' => 1 ,
  238. 'oauth_version' => 1 ,
  239. 'oauth_signature_method' => 1 ,
  240. 'oauth_signature' => 1 ,
  241. 'call_id' => 1 ,
  242. 'version' => 1
  243. );
  244. $this->_clearError();
  245. $param = $this->params;
  246. $this->params = array();
  247. $url = self::apiPoolURL();
  248. $parameters['oauth_token'] = 'null';
  249. $parameters['oauth_consumer_key'] = $this->appId;
  250. $parameters['oauth_nonce'] = self::generate_nonce();
  251. $parameters['oauth_timestamp'] = (string) time();
  252. $parameters['oauth_version'] = '2.0';
  253. $parameters['oauth_signature_method'] = 'HMAC-SHA1';
  254. if ($method == 'TCP') {
  255. $parameters['call_id'] = 0;
  256. }
  257. // data merging
  258. foreach ($parameters as $key => $value) {
  259. if (! isset($param[$key])) {
  260. $param[$key] = $parameters[$key];
  261. }
  262. }
  263. if ($method == 'TCP') {
  264. $tcpParams = array();
  265. foreach ($param as $key => $value) {
  266. if (! isset($tcpField[$key])) {
  267. $tcpParams[$key] = $value;
  268. unset($param[$key]);
  269. }
  270. }
  271. $param['params'] = $tcpParams;
  272. }
  273. if (! isset($param['oauth_signature'])) {
  274. $param['oauth_signature'] = self::generateSig($param);
  275. }
  276. $result = '';
  277. if ($this->oauth_debug) {
  278. $this->apiStart();
  279. }
  280. switch ($method) {
  281. case 'TCP':
  282. $result = self::tcp($param);
  283. break;
  284. case 'GET':
  285. $url = $url . '?' . http_build_query($param);
  286. $result = self::http($url, $method);
  287. break;
  288. case 'POST':
  289. $postdata = http_build_query($param);
  290. $result = self::http($url, $method, $postdata);
  291. break;
  292. default:
  293. return FALSE;
  294. break;
  295. }
  296. if ($this->oauth_debug) {
  297. $this->apiStop();
  298. $this->apiSpent($this->appId, $param['method']);
  299. }
  300. $result = json_decode($result, TRUE);
  301. if (empty($result)) {
  302. $this->_setGWError();
  303. return FALSE;
  304. }
  305. $response = array();
  306. if ($method == 'TCP') {
  307. $response = $result['response'];
  308. } else {
  309. $response = $result;
  310. }
  311. //check error
  312. if (! isset($response['return_code']) || $response['return_code'] != 0) {
  313. $this->_setGWError($response);
  314. return FALSE;
  315. }
  316. return $response;
  317. }
  318. private function generateSig ($params, $secret = '')
  319. {
  320. if (empty($secret)) {
  321. $secret = $this->appSecret;
  322. }
  323. $str = '';
  324. ksort($params);
  325. foreach ($params as $k => $v) {
  326. if (! is_array($v)) {
  327. $str .= "$k=$v";
  328. } else {
  329. ksort($v);
  330. $str .= "$k=" . json_encode($v);
  331. }
  332. }
  333. return bin2hex(hash_hmac('sha1', $str, $secret, TRUE));
  334. }
  335. public function setParam ($key, $value)
  336. {
  337. $this->params[$key] = $value;
  338. }
  339. public function tcp ($param)
  340. {
  341. $sock = socket_create(AF_INET, SOCK_STREAM, 0);
  342. if (FALSE === $sock) {
  343. return FALSE;
  344. }
  345. socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array(
  346. 'sec' => $this->systemParam['timeout'] ,
  347. 'usec' => 0
  348. ));
  349. socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array(
  350. 'sec' => $this->systemParam['timeout'] ,
  351. 'usec' => 0
  352. ));
  353. $result = socket_connect($sock, $this->systemParam['gatewayHost'], $this->systemParam['gatewayPort']);
  354. if (FALSE === $result) {
  355. socket_close($sock);
  356. return FALSE;
  357. }
  358. $data = json_encode($param);
  359. $len = dechex(strlen($data));
  360. $data = sprintf('%06s%s', $len, $data);
  361. $result = socket_write($sock, $data);
  362. if (FALSE === $sock) {
  363. socket_close($sock);
  364. return FALSE;
  365. }
  366. $data = socket_read($sock, 6);
  367. if (FALSE === $data) {
  368. socket_close($sock);
  369. return FALSE;
  370. }
  371. $len = hexdec($data);
  372. $data = socket_read($sock, $len);
  373. if (FALSE === $data) {
  374. socket_close($sock);
  375. return FALSE;
  376. }
  377. socket_close($sock);
  378. return $data;
  379. }
  380. /**
  381. * Make an HTTP request
  382. *
  383. * @return string API results
  384. */
  385. public function http ($url, $method = 'GET', $postfields = FALSE)
  386. {
  387. $this->http_info = array();
  388. $ci = curl_init();
  389. /* Curl settings */
  390. curl_setopt($ci, CURLOPT_USERAGENT, $this->useragent);
  391. curl_setopt($ci, CURLOPT_CONNECTTIMEOUT, $this->systemParam['connectTimeout']);
  392. curl_setopt($ci, CURLOPT_TIMEOUT, $this->systemParam['timeout']);
  393. curl_setopt($ci, CURLOPT_RETURNTRANSFER, TRUE);
  394. curl_setopt($ci, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
  395. curl_setopt($ci, CURLOPT_SSL_VERIFYPEER, $this->ssl_verifypeer);
  396. curl_setopt($ci, CURLOPT_HEADERFUNCTION, array(
  397. $this ,
  398. 'getHeader'
  399. ));
  400. curl_setopt($ci, CURLOPT_HEADER, FALSE);
  401. switch ($method) {
  402. case 'POST':
  403. curl_setopt($ci, CURLOPT_POST, TRUE);
  404. if (! empty($postfields)) {
  405. curl_setopt($ci, CURLOPT_POSTFIELDS, $postfields);
  406. //echo "=====post data======\r\n";
  407. //echo $postfields;
  408. }
  409. break;
  410. case 'DELETE':
  411. curl_setopt($ci, CURLOPT_CUSTOMREQUEST, 'DELETE');
  412. if (! empty($postfields)) {
  413. $url = "{$url}?{$postfields}";
  414. }
  415. break;
  416. }
  417. $header_array = array();
  418. $header_array2 = array();
  419. foreach ($header_array as $k => $v)
  420. array_push($header_array2, $k . ': ' . $v);
  421. curl_setopt($ci, CURLOPT_HTTPHEADER, $header_array2);
  422. curl_setopt($ci, CURLINFO_HEADER_OUT, FALSE);
  423. //echo $url."<hr/>";
  424. curl_setopt($ci, CURLOPT_URL, $url);
  425. $response = curl_exec($ci);
  426. $this->http_code = curl_getinfo($ci, CURLINFO_HTTP_CODE);
  427. $this->http_info = array_merge($this->http_info, curl_getinfo($ci));
  428. $this->url = $url;
  429. curl_close($ci);
  430. return $response;
  431. }
  432. /**
  433. * Get the header info to store.
  434. *
  435. * @return int
  436. */
  437. public function getHeader ($ch, $header)
  438. {
  439. $i = strpos($header, ':');
  440. if (! empty($i)) {
  441. $key = str_replace('-', '_', strtolower(substr($header, 0, $i)));
  442. $value = trim(substr($header, $i + 2));
  443. $this->http_header[$key] = $value;
  444. }
  445. return strlen($header);
  446. }
  447. private function _setOAuthError ($err = null)
  448. {
  449. if (empty($err)) {
  450. $this->lastErrorCode = 'unknow';
  451. $this->lastErrorMsg = 'unkonw';
  452. } else {
  453. $this->lastErrorCode = @$err['error'];
  454. $this->lastErrorMsg = @$err['error_description'];
  455. }
  456. }
  457. private function _setGWError ($response = null)
  458. {
  459. if (empty($response)) {
  460. $this->lastErrorCode = 'unknow';
  461. $this->lastErrorMsg = 'unkonw';
  462. } else {
  463. $this->lastErrorCode = @$response['return_code'];
  464. $this->lastErrorMsg = @$response['return_message'];
  465. }
  466. }
  467. private function _clearError ()
  468. {
  469. $this->lastErrorCode = 0;
  470. $this->lastErrorMsg = '';
  471. }
  472. public function getLastErrCode ()
  473. {
  474. return $this->lastErrorCode;
  475. }
  476. public function getLastErrMsg ()
  477. {
  478. return $this->lastErrorMsg;
  479. }
  480. public function getExecTime ()
  481. {
  482. return $this->execTime;
  483. }
  484. private function apiStart ()
  485. {
  486. $this->apiStartTime = microtime(TRUE);
  487. }
  488. private function apiStop ()
  489. {
  490. $this->apiStopTime = microtime(TRUE);
  491. }
  492. private function apiSpent ($appid, $api)
  493. {
  494. $url = 'http://log.ibw.sdo.com/apipool.jpg?';
  495. $spent = round(($this->apiStopTime - $this->apiStartTime) * 1000, 1);
  496. $this->execTime = $spent;
  497. $params = array();
  498. $params['appid'] = $appid;
  499. $params['api'] = $api;
  500. $params['time'] = $spent;
  501. $url .= http_build_query($params);
  502. @file_get_contents($url);
  503. }
  504. }
  505. ?>