ConnectOAuth.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. <?php
  2. /**
  3. * [Discuz!] (C)2001-2099 Comsenz Inc.
  4. * This is NOT a freeware, use is subject to license terms
  5. *
  6. * $Id: ConnectOAuth.php 34191 2013-10-30 08:07:15Z nemohou $
  7. */
  8. if(!defined('IN_DISCUZ')) {
  9. exit('Access Denied');
  10. }
  11. Cloud::loadFile('Service_Connect');
  12. Cloud::loadFile('Service_Client_OAuth');
  13. class Cloud_Service_Client_ConnectOAuth extends Cloud_Service_Client_OAuth {
  14. private $_requestTokenURL = 'http://openapi.qzone.qq.com/oauth/qzoneoauth_request_token';
  15. private $_oAuthAuthorizeURL = 'http://openapi.qzone.qq.com/oauth/qzoneoauth_authorize';
  16. private $_accessTokenURL = 'http://openapi.qzone.qq.com/oauth/qzoneoauth_access_token';
  17. private $_getUserInfoURL = 'http://openapi.qzone.qq.com/user/get_user_info';
  18. private $_addShareURL = 'http://openapi.qzone.qq.com/share/add_share';
  19. private $_addWeiBoURL = 'http://openapi.qzone.qq.com/wb/add_weibo';
  20. private $_addTURL = 'http://openapi.qzone.qq.com/t/add_t';
  21. private $_addPicTURL = 'http://openapi.qzone.qq.com/t/add_pic_t';
  22. private $_getReportListURL = 'http://openapi.qzone.qq.com/t/get_repost_list';
  23. private $_oAuthAuthorizeURL_V2 = 'https://graph.qq.com/oauth2.0/authorize';
  24. private $_accessTokenURL_V2 = 'https://graph.qq.com/oauth2.0/token';
  25. private $_openIdURL_V2 = 'https://graph.qq.com/oauth2.0/me';
  26. private $_getUserInfoURL_V2 = 'https://graph.qq.com/user/get_user_info';
  27. private $_addShareURL_V2 = 'https://graph.qq.com/share/add_share';
  28. private $_addTURL_V2 = 'https://graph.qq.com/t/add_t';
  29. private $_addPicTURL_V2 = 'https://graph.qq.com/t/add_pic_t';
  30. const RESPONSE_ERROR = 999;
  31. const RESPONSE_ERROR_MSG = 'request failed';
  32. protected static $_instance;
  33. public static function getInstance($connectAppId = '', $connectAppKey = '', $apiIp = '') {
  34. if (!(self::$_instance instanceof self)) {
  35. self::$_instance = new self($connectAppId = '', $connectAppKey = '', $apiIp = '');
  36. }
  37. return self::$_instance;
  38. }
  39. public function __construct($connectAppId = '', $connectAppKey = '', $apiIp = '') {
  40. if(!$connectAppId || !$connectAppKey) {
  41. global $_G;
  42. $connectAppId = $_G['setting']['connectappid'];
  43. $connectAppKey = $_G['setting']['connectappkey'];
  44. }
  45. $this->setAppkey($connectAppId, $connectAppKey);
  46. if(!$this->_appKey || !$this->_appSecret) {
  47. throw new Exception('connectAppId/connectAppKey Invalid', __LINE__);
  48. }
  49. if(!$apiIp) {
  50. global $_G;
  51. $apiIp = $_G['setting']['connect_api_ip'] ? $_G['setting']['connect_api_ip'] : '';
  52. }
  53. if($apiIp && !$_G['setting']['connect']['oauth2']) {
  54. $this->setApiIp($apiIp);
  55. }
  56. }
  57. public function connectGetRequestToken($callback, $clientIp = '') {
  58. $extra = array();
  59. $extra['oauth_callback'] = rawurlencode($callback);
  60. if ($clientIp) {
  61. $extra['oauth_client_ip'] = $clientIp;
  62. }
  63. $this->setTokenSecret('');
  64. $response = $this->_request($this->_requestTokenURL, $extra);
  65. parse_str($response, $params);
  66. if($params['oauth_token'] && $params['oauth_token_secret']) {
  67. return $params;
  68. } else {
  69. $params['error_code'] = $params['error_code'] ? $params['error_code'] : self::RESPONSE_ERROR;
  70. throw new Exception($params['error_code'], __LINE__);
  71. }
  72. }
  73. public function getOAuthAuthorizeURL($requestToken) {
  74. $params = array(
  75. 'oauth_consumer_key' => $this->_appKey,
  76. 'oauth_token' => $requestToken,
  77. );
  78. $utilService = Cloud::loadClass('Service_Util');
  79. $oAuthAuthorizeURL = $this->_oAuthAuthorizeURL.'?'.$utilService->httpBuildQuery($params, '', '&');
  80. return $oAuthAuthorizeURL;
  81. }
  82. private function _connectIsValidOpenid($openId, $timestamp, $sig) {
  83. $key = $this->_appSecret;
  84. $str = $openId.$timestamp;
  85. $signature = $this->customHmac($str, $key);
  86. return $sig == $signature;
  87. }
  88. public function connectGetAccessToken($params, $requestTokenSecret) {
  89. if(!$this->_connectIsValidOpenid($params['openid'], $params['timestamp'], $params['oauth_signature'])) {
  90. throw new Exception('openId signature invalid', __LINE__);
  91. }
  92. if(!$params['oauth_token'] || !$params['oauth_vericode']) {
  93. throw new Exception('requestToken/vericode invalid', __LINE__);
  94. }
  95. $extra = array(
  96. 'oauth_token' => $params['oauth_token'],
  97. 'oauth_vericode' => $params['oauth_vericode'],
  98. );
  99. $this->setTokenSecret($requestTokenSecret);
  100. $response = $this->_request($this->_accessTokenURL, $extra);
  101. parse_str($response, $result);
  102. if($result['oauth_token'] && $result['oauth_token_secret'] && $result['openid']) {
  103. return $result;
  104. } else {
  105. $result['error_code'] = $result['error_code'] ? $result['error_code'] : self::RESPONSE_ERROR;
  106. throw new Exception($result['error_code'], __LINE__);
  107. }
  108. }
  109. public function connectGetUserInfo($openId, $accessToken, $accessTokenSecret) {
  110. $extra = array(
  111. 'oauth_token' => $accessToken,
  112. 'openid' => $openId,
  113. 'format' => 'xml',
  114. );
  115. $this->setTokenSecret($accessTokenSecret);
  116. $response = $this->_request($this->_getUserInfoURL, $extra);
  117. $data = $this->_xmlParse($response);
  118. if(isset($data['ret']) && $data['ret'] == 0) {
  119. return $data;
  120. } else {
  121. throw new Exception($data['msg'], $data['ret']);
  122. }
  123. }
  124. private function _request($requestURL, $extra = array(), $oauthMethod = 'GET', $multi) {
  125. if(!$this->_appKey || !$this->_appSecret) {
  126. throw new Exception('appKey or appSecret not init');
  127. }
  128. if(strtoupper(CHARSET) != 'UTF-8') {
  129. foreach((array)$extra as $k => $v) {
  130. $extra[$k] = diconv($v, CHARSET, 'UTF-8');
  131. }
  132. }
  133. return $this->getRequest($requestURL, $extra, $oauthMethod, $multi);
  134. }
  135. private function _xmlParse($data) {
  136. $connectService = Cloud::loadClass('Service_Connect');
  137. $data = $connectService->connectParseXml($data);
  138. if (strtoupper(CHARSET) != 'UTF-8') {
  139. $data = $this->_iconv($data, 'UTF-8', CHARSET);
  140. }
  141. if(!isset($data['ret']) && !isset($data['errcode'])) {
  142. $data = array(
  143. 'ret' => self::RESPONSE_ERROR,
  144. 'msg' => self::RESPONSE_ERROR_MSG
  145. );
  146. }
  147. return $data;
  148. }
  149. private function _iconv($data, $inputCharset, $outputCharset) {
  150. if (is_array($data)) {
  151. foreach($data as $key => $val) {
  152. $value = array_map(array(__CLASS__, '_iconv'), array($val), array($inputCharset), array($outputCharset));
  153. $result[$key] = $value[0];
  154. }
  155. } else {
  156. $result = diconv($data, $inputCharset, $outputCharset);
  157. }
  158. return $result;
  159. }
  160. public function connectAddShare($openId, $accessToken, $accessTokenSecret, $params) {
  161. if(!$params['title'] || !$params['url']) {
  162. throw new Exception('Required Parameter Missing');
  163. }
  164. $paramsName = array('title', 'url', 'comment', 'summary', 'images', 'source', 'type', 'playurl', 'nswb');
  165. if($params['title']) {
  166. $params['title'] = cutstr($params['title'], 72, '');
  167. }
  168. if($params['comment']) {
  169. $params['comment'] = cutstr($params['comment'], 80, '');
  170. }
  171. if($params['summary']) {
  172. $params['summary'] = cutstr($params['summary'], 160, '');
  173. }
  174. if($params['images']) {
  175. $params['images'] = cutstr($params['images'], 255, '');
  176. }
  177. if($params['playurl']) {
  178. $params['playurl'] = cutstr($params['playurl'], 256, '');
  179. }
  180. $extra = array(
  181. 'oauth_token' => $accessToken,
  182. 'openid' => $openId,
  183. 'format' => 'xml',
  184. );
  185. foreach($paramsName as $name) {
  186. if($params[$name]) {
  187. $extra[$name] = $params[$name];
  188. }
  189. }
  190. $this->setTokenSecret($accessTokenSecret);
  191. $response = $this->_request($this->_addShareURL, $extra, 'POST');
  192. $data = $this->_xmlParse($response);
  193. if(isset($data['ret']) && $data['ret'] == 0) {
  194. return $data;
  195. } else {
  196. throw new Exception($data['msg'], $data['ret']);
  197. }
  198. }
  199. public function connectAddPicT($openId, $accessToken, $accessTokenSecret, $params) {
  200. if(!$params['content'] || !$params['pic']) {
  201. throw new Exception('Required Parameter Missing');
  202. }
  203. $paramsName = array('content', 'pic', 'clientip', 'jing', 'wei', 'syncflag');
  204. $extra = array(
  205. 'oauth_token' => $accessToken,
  206. 'openid' => $openId,
  207. 'format' => 'xml',
  208. );
  209. foreach($paramsName as $name) {
  210. if($params[$name]) {
  211. $extra[$name] = $params[$name];
  212. }
  213. }
  214. $pic = $extra['pic'];
  215. unset($extra['pic']);
  216. $this->setTokenSecret($accessTokenSecret);
  217. $response = $this->_request($this->_addPicTURL, $extra, 'POST', array('pic' => $pic, 'remote' => $params['remote'] ? true : false));
  218. $data = $this->_xmlParse($response);
  219. if(isset($data['ret']) && $data['ret'] == 0) {
  220. return $data;
  221. } else {
  222. throw new Exception($data['msg'], $data['ret']);
  223. }
  224. }
  225. public function connectAddT($openId, $accessToken, $accessTokenSecret, $params) {
  226. if(!$params['content']) {
  227. throw new Exception('Required Parameter Missing');
  228. }
  229. $paramsName = array('content', 'clientip', 'jing', 'wei');
  230. $extra = array(
  231. 'oauth_token' => $accessToken,
  232. 'openid' => $openId,
  233. 'format' => 'xml',
  234. );
  235. foreach($paramsName as $name) {
  236. if($params[$name]) {
  237. $extra[$name] = $params[$name];
  238. }
  239. }
  240. $this->setTokenSecret($accessTokenSecret);
  241. $response = $this->_request($this->_addTURL, $extra, 'POST');
  242. $data = $this->_xmlParse($response);
  243. if(isset($data['ret']) && $data['ret'] == 0) {
  244. return $data;
  245. } else {
  246. throw new Exception($data['msg'], $data['ret']);
  247. }
  248. }
  249. public function connectGetRepostList($openId, $accessToken, $accessTokenSecret, $params) {
  250. if(!isset($params['flag']) || !$params['rootid'] || !isset($params['pageflag']) || !isset($params['pagetime']) || !$params['reqnum'] || !isset($params['twitterid'])) {
  251. throw new Exception('Required Parameter Missing');
  252. }
  253. $paramsName = array('flag', 'rootid', 'pageflag', 'pagetime', 'reqnum', 'twitterid');
  254. $extra = array(
  255. 'oauth_token' => $accessToken,
  256. 'openid' => $openId,
  257. 'format' => 'xml',
  258. );
  259. foreach($paramsName as $name) {
  260. if($params[$name]) {
  261. $extra[$name] = $params[$name];
  262. }
  263. }
  264. $this->setTokenSecret($accessTokenSecret);
  265. $response = $this->_request($this->_getReportListURL, $extra, 'GET');
  266. $data = $this->_xmlParse($response);
  267. if(isset($data['ret']) && $data['ret'] == 0) {
  268. return $data;
  269. } else {
  270. throw new Exception($data['msg'], $data['ret']);
  271. }
  272. }
  273. public function getOAuthAuthorizeURL_V2($redirect_uri) {
  274. $params = array(
  275. 'response_type' => 'code',
  276. 'client_id' => $this->_appKey,
  277. 'redirect_uri' => $redirect_uri,
  278. 'state' => md5(FORMHASH),
  279. 'scope' => 'get_user_info,add_share,add_t,add_pic_t,get_repost_list',
  280. );
  281. $utilService = Cloud::loadClass('Service_Util');
  282. return $this->_oAuthAuthorizeURL_V2.'?'.$utilService->httpBuildQuery($params, '', '&');
  283. }
  284. public function connectGetOpenId_V2($redirect_uri, $code) {
  285. $params = array(
  286. 'grant_type' => 'authorization_code',
  287. 'client_id' => $this->_appKey,
  288. 'redirect_uri' => $redirect_uri,
  289. 'client_secret' => $this->_appSecret,
  290. 'code' => $code
  291. );
  292. $utilService = Cloud::loadClass('Service_Util');
  293. $response = $this->dfsockopen($this->_accessTokenURL_V2.'?'.$utilService->httpBuildQuery($params, '', '&'));
  294. parse_str($response, $result);
  295. if($result['access_token'] && $result['refresh_token']) {
  296. $params = array(
  297. 'access_token' => $result['access_token']
  298. );
  299. $response = $this->callback($this->dfsockopen($this->_openIdURL_V2.'?'.$utilService->httpBuildQuery($params, '', '&')));
  300. if($response->openid) {
  301. $result = array(
  302. 'openid' => $response->openid,
  303. 'access_token' => $result['access_token']
  304. );
  305. return $result;
  306. } else {
  307. $result->error = $result->error ? $result->error : self::RESPONSE_ERROR;
  308. throw new Exception($result->error, __LINE__);
  309. }
  310. } else {
  311. $result = $this->callback($response);
  312. $result->error = $result->error ? $result->error : self::RESPONSE_ERROR;
  313. throw new Exception($result->error, __LINE__);
  314. }
  315. }
  316. public function connectGetUserInfo_V2($openId, $accessToken) {
  317. $params = array(
  318. 'access_token' => $accessToken,
  319. 'oauth_consumer_key' => $this->_appKey,
  320. 'openid' => $openId,
  321. 'format' => 'xml'
  322. );
  323. $utilService = Cloud::loadClass('Service_Util');
  324. $response = $this->dfsockopen($this->_getUserInfoURL_V2.'?'.$utilService->httpBuildQuery($params, '', '&'));
  325. $data = $this->_xmlParse($response);
  326. if(isset($data['ret']) && $data['ret'] == 0) {
  327. return $data;
  328. } else {
  329. throw new Exception($data['msg'], $data['ret']);
  330. }
  331. }
  332. public function connectAddShare_V2($openId, $accessToken, $params) {
  333. if(!$params['title'] || !$params['url']) {
  334. throw new Exception('Required Parameter Missing');
  335. }
  336. $paramsName = array('title', 'url', 'comment', 'summary', 'images', 'source', 'type', 'playurl', 'nswb');
  337. if($params['title']) {
  338. $params['title'] = diconv(cutstr($params['title'], 72, ''), CHARSET, 'UTF-8');
  339. }
  340. if($params['comment']) {
  341. $params['comment'] = diconv(cutstr($params['comment'], 80, ''), CHARSET, 'UTF-8');
  342. }
  343. if($params['summary']) {
  344. $params['summary'] = diconv(cutstr($params['summary'], 160, ''), CHARSET, 'UTF-8');
  345. }
  346. if($params['images']) {
  347. $params['images'] = cutstr($params['images'], 255, '');
  348. }
  349. if($params['playurl']) {
  350. $params['playurl'] = cutstr($params['playurl'], 256, '');
  351. }
  352. $extra = array(
  353. 'access_token' => $accessToken,
  354. 'oauth_consumer_key' => $this->_appKey,
  355. 'openid' => $openId,
  356. 'format' => 'xml',
  357. );
  358. foreach($paramsName as $name) {
  359. if($params[$name]) {
  360. $extra[$name] = $params[$name];
  361. }
  362. }
  363. $response = $this->dfsockopen($this->_addShareURL_V2, $extra);
  364. $data = $this->_xmlParse($response);
  365. if(isset($data['ret']) && $data['ret'] == 0) {
  366. return $data;
  367. } else {
  368. throw new Exception($data['msg'], $data['ret']);
  369. }
  370. }
  371. public function connectAddPicT_V2($openId, $accessToken, $params) {
  372. if(!$params['content'] || !$params['pic']) {
  373. throw new Exception('Required Parameter Missing');
  374. }
  375. $extra = array(
  376. 'access_token' => $accessToken,
  377. 'oauth_consumer_key' => $this->_appKey,
  378. 'openid' => $openId,
  379. 'content' => diconv($params['content'], CHARSET, 'UTF-8'),
  380. 'format' => 'xml',
  381. );
  382. $response = $this->dfsockopen($this->_addPicTURL_V2, $extra, array('pic' => $params['pic']));
  383. $data = $this->_xmlParse($response);
  384. if(isset($data['ret']) && $data['ret'] == 0) {
  385. return $data;
  386. } else {
  387. throw new Exception($data['msg'], $data['ret']);
  388. }
  389. }
  390. public function connectAddT_V2($openId, $accessToken, $params) {
  391. if(!$params['content']) {
  392. throw new Exception('Required Parameter Missing');
  393. }
  394. $extra = array(
  395. 'access_token' => $accessToken,
  396. 'oauth_consumer_key' => $this->_appKey,
  397. 'openid' => $openId,
  398. 'content' => diconv($params['content'], CHARSET, 'UTF-8'),
  399. 'format' => 'xml',
  400. );
  401. $response = $this->dfsockopen($this->_addTURL_V2, $extra);
  402. $data = $this->_xmlParse($response);
  403. if(isset($data['ret']) && $data['ret'] == 0) {
  404. return $data;
  405. } else {
  406. throw new Exception($data['msg'], $data['ret']);
  407. }
  408. }
  409. }