OpenAuth.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. <?php
  2. /**
  3. * OpenAuth class file.
  4. * @author Jack Chen <captain_jacky@163.com>
  5. * @copyright Copyright &copy; WEBZING 2013-
  6. * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  7. * @version 1.0.0
  8. */
  9. namespace app\components\OpenAuth;
  10. use app\common\components\SiteUrl;
  11. use app\common\helpers\Identify;
  12. use app\common\helpers\Session;
  13. use app\components\WeiXin\WeiXin;
  14. use app\modules\ucenter\models\UserOpenAuth;
  15. use Yii;
  16. class OpenAuth extends \yii\base\Component
  17. {
  18. public $weibo;
  19. public $wx;
  20. public $qq;
  21. public $dd;
  22. public $mp;
  23. public $method;
  24. public $app;
  25. private $wbAppId;
  26. private $wbAppSecret;
  27. public $wbScope;
  28. public $wbCallBackUrl;
  29. private $wxAppId;
  30. private $wxAppSecret;
  31. public $wxCallBackUrl;
  32. private $qqAppId;
  33. private $qqAppKey;
  34. public $qqScope;
  35. public $qqCallBackUrl;
  36. private $mpAppId;
  37. private $mpAppSecret;
  38. private $mpToken;
  39. private $dingtalkAppKey;
  40. private $dingtalkAppSecret;
  41. public $dingtalkCallBackUrl;
  42. public $apps = array('weibo','wx','qq','dd','mp');
  43. public function __construct()
  44. {
  45. $this->qqScope = 'get_user_info,add_share,list_album,add_album,upload_pic,add_topic,add_one_blog,add_weibo,check_page_fans,add_t,add_pic_t,del_t,get_repost_list,get_info,get_other_info,get_fanslist,get_idolist,add_idol,del_idol,get_tenpay_addr';
  46. $this->wbScope = '';
  47. $keys = array('wbAppId','wbAppSecret','wbCallBackUrl','wxAppId','wxAppSecret','wxCallBackUrl','qqAppId','qqAppKey','qqCallBackUrl','dingtalkAppKey','dingtalkAppSecret','dingtalkCallBackUrl','mpAppId','mpAppSecret','mpToken','openWbLogin','openWxLogin','openQqLogin','openMpLogin','mpAutoLoginWap','openMpSubLogin','dingtalkLogin');
  48. foreach($keys as $key)
  49. {
  50. if(is_wap_site())
  51. {
  52. $tempArgs[$key] = in_array($key,array('mpAppId','mpAppSecret','mpToken','openMpLogin','mpAutoLoginWap','openMpSubLogin'))?Yii::$app->params['openauth'][$key]:Yii::$app->params['openauth']['m_'.$key];
  53. }
  54. else
  55. {
  56. $tempArgs[$key] = Yii::$app->params['openauth'][$key];
  57. }
  58. $tempArgs[$key] = $tempArgs[$key]? $tempArgs[$key]:'';
  59. }
  60. if(isset($tempArgs))$args = $tempArgs;
  61. extract($args);
  62. if(isset($wbAppId)&&!defined('WB_APPID')) define("WB_APPID", $wbAppId);
  63. if(isset($wbAppSecret)&&!defined('WB_APPSECRET')) define("WB_APPSECRET", $wbAppSecret);
  64. if(empty($wbScope))$wbScope = $this->wbScope;
  65. if(isset($wbScope)&&!defined('WB_SCOPE')) define("WB_SCOPE", $wbScope);
  66. if(isset($wbCallBackUrl)) $this->wbCallBackUrl = $wbCallBackUrl;
  67. if(isset($wxAppId)&&!defined('WX_APPID')) define("WX_APPID", $wxAppId);
  68. if(isset($wxAppSecret)&&!defined('WX_APPSECRET')) define("WX_APPSECRET", $wxAppSecret);
  69. if(isset($wxCallBackUrl)) $this->wxCallBackUrl = $wxCallBackUrl;
  70. if(isset($qqAppId)&&!defined('QQ_APPID')) define("QQ_APPID", $qqAppId);
  71. if(isset($qqAppKey)&&!defined('QQ_APPKEY')) define("QQ_APPKEY", $qqAppKey);
  72. if(empty($qqScope))$qqScope = $this->qqScope;
  73. if(isset($qqScope)&&!defined('QQ_SCOPE')) define("QQ_SCOPE", $qqScope);
  74. if(isset($qqCallBackUrl)) $this->qqCallBackUrl = $qqCallBackUrl;
  75. if(isset($dingtalkAppKey)&&!defined('DD_APPKEY')) define("DD_APPKEY", $dingtalkAppKey);
  76. if(isset($dingtalkAppSecret)&&!defined('DD_APPSECRET')) define("DD_APPSECRET", $dingtalkAppSecret);
  77. if(isset($dingtalkCallBackUrl)) $this->dingtalkCallBackUrl = $dingtalkCallBackUrl;
  78. if(isset($mpAppId)&&!defined('MP_APPID')) define("MP_APPID", $mpAppId);
  79. if(isset($mpAppSecret)&&!defined('MP_APPSECRET')) define("MP_APPSECRET", $mpAppSecret);
  80. if(isset($mpToken)&&!defined('MP_TOKEN')) define("MP_TOKEN", $mpToken);
  81. $this->weibo = new \app\components\OpenAuth\core\weibo();
  82. $this->qq = new \app\components\OpenAuth\core\qq();
  83. $this->wx = new \app\components\OpenAuth\core\wx();
  84. $this->dd = new \app\components\OpenAuth\core\dd();
  85. Session::set('app',[]);
  86. }
  87. public function init()
  88. {
  89. parent::init();
  90. }
  91. //获取微信授权链接
  92. public function getWxLoginUrl()
  93. {
  94. $state = uniqid('wx_', true);
  95. $url = $this->wx->codeUrl($this->wxCallBackUrl,$state);
  96. Session::set('wx_state',$state);
  97. return $url;
  98. }
  99. //微信验证
  100. public function wxAuth()
  101. {
  102. $state = $_REQUEST['state'];
  103. $code = $_REQUEST['code'];
  104. if (Session::get('wx_state')==null || $state !== Session::get('wx_state'))
  105. exit("参数错误!请返回重新使用微信登录!");
  106. $token = $this->wx->getAccessToken($code);
  107. if (isset($token['errcode']))
  108. {
  109. exit("验证错误!请返回重新使用微信登录!");
  110. }
  111. Session::set('wx_token',array('access_token' => $token['access_token'], 'openid' => $token['openid'], 'uid' => $token['openid'], 'expires_in' => $token['expires_in']));
  112. $this->_callback('wx');
  113. return true;
  114. }
  115. //获取QQ授权链接地址
  116. public function getQqLoginUrl()
  117. {
  118. $state = uniqid('qq_', true);
  119. $url = $this->qq->getAuthorizeURL($this->qqCallBackUrl, 'code', $state, $this->qqScope);
  120. Session::set('qq_state',$state);
  121. return $url;
  122. }
  123. //QQ授权验证
  124. public function qqAuth()
  125. {
  126. $state = $_REQUEST['state'];
  127. $code = $_REQUEST['code'];
  128. if (Session::get('qq_state')==null || $state !== Session::get('qq_state'))
  129. exit("参数错误!请返回重新使用QQ登录!");
  130. $keys = array('code' => $code, 'redirect_uri' => $this->qqCallBackUrl);
  131. $token = $this->qq->getAccessToken('code', $keys);
  132. if (isset($token['error']))
  133. exit("验证错误!请返回重新使用QQ登录!");
  134. Session::set('qq_token',$token);
  135. $openid = $this->qq->getOpenID();
  136. Session::set('qq_token',array('access_token' => $token['access_token'], 'openid' => $openid, 'uid' => $openid, 'expires_in' => $token['expires_in']));
  137. $this->_callback('qq');
  138. return true;
  139. }
  140. //获取微博授权链接地址
  141. public function getWbLoginUrl()
  142. {
  143. $state = uniqid('weibo_', true);
  144. $url = $this->weibo->getAuthorizeURL($this->wbCallBackUrl, 'code', $state);
  145. Session::set('weibo_state',$state);
  146. return $url;
  147. }
  148. //微博授权验证
  149. public function wbAuth()
  150. {
  151. $state = $_REQUEST['state'];
  152. $code = $_REQUEST['code'];
  153. if (Session::get('weibo_state')==null || $state !== Session::get('weibo_state'))
  154. exit("参数错误!请返回重新使用新浪微博登录!");
  155. $keys = array('code' => $code, 'redirect_uri' => $this->wbCallBackUrl);
  156. $token = $this->weibo->getAccessToken('code', $keys);
  157. if (isset($token['error']))
  158. exit("验证错误!请返回重新使用新浪微博登录!");
  159. Session::set('weibo_token',$token);
  160. $this->_callback('weibo');
  161. return true;
  162. }
  163. //获取钉钉授权链接
  164. public function getDdLoginUrl()
  165. {
  166. $state = uniqid('dd_', true);
  167. $url = $this->dd->authUrl($this->dingtalkCallBackUrl,$state);
  168. Session::set('dd_state',$state);
  169. return $url;
  170. }
  171. //钉钉验证
  172. public function ddAuth()
  173. {
  174. $state = $_REQUEST['state'];
  175. $code = $_REQUEST['authCode'];
  176. if (Session::get('dd_state')==null || $state !== Session::get('dd_state'))
  177. exit("参数错误!请返回重新使用钉钉登录!");
  178. $token = $this->dd->getAccessToken($code);
  179. if (isset($token['errcode']))
  180. {
  181. exit("验证错误!请返回重新使用钉钉登录!");
  182. }
  183. Session::set('dd_token',array('access_token' => $token['access_token'], 'expires_in' => $token['expires_in'], 'refresh_token' => $token['refresh_token']));
  184. return true;
  185. }
  186. //生成登录公众号二维码
  187. public function mpLogin()
  188. {
  189. $scene_id = mt_rand(100000000,999999999).rand(0,9).rand(0,9);
  190. if(Yii::$app->params['openauth']['openMpSubLogin']&&!IN_WAP)
  191. {
  192. $args = array(
  193. 'appId'=>MP_APPID,
  194. 'appSecret'=>MP_APPSECRET,
  195. 'token'=>MP_TOKEN,
  196. );
  197. $weixin = new WeiXin($args);
  198. $weixin->init();
  199. $scene_id = 'mplogin_'.$scene_id;
  200. $result = $weixin->createQrcode($scene_id,3);
  201. $returnResult = [
  202. 'error' => 0,
  203. 'msg' => '请求成功',
  204. 'data' => ['codeUrl'=>$result['codeUrl'],'scene_id'=>$scene_id,'expire'=>Yii::$app->params['qrcodeExpire']],
  205. 'code'=>200
  206. ];
  207. echo_json($returnResult);
  208. }
  209. else
  210. {
  211. //通过进入H5微信授权登录
  212. $expireTime = TIMESTAMP-30*60;
  213. UserOpenAuth::deleteAll("app_uid='0' and app='mp' and bind_time<$expireTime");
  214. $openAuth = new UserOpenAuth();
  215. $openAuth->app = 'mp';
  216. $openAuth->app_uid = '0';
  217. $openAuth->scene_id = (defined('IN_WAP')&&IN_WAP==TRUE)?'wap_'.$scene_id:'pc_'.$scene_id;
  218. $openAuth->app_unionid = '';
  219. $openAuth->app_unionname = 'wx';
  220. $openAuth->bind_time = TIMESTAMP;
  221. $openAuth->share_no = \app\common\helpers\Cookie::getCookie(Yii::$app->params['shareArgName'])? \app\common\helpers\Cookie::getCookie(Yii::$app->params['shareArgName']):'';
  222. $openAuth->hash = '';
  223. if($openAuth->save())
  224. {
  225. //如果仅仅绑定,应该传个标识符到手机端
  226. if(Identify::hasLogined())$uauth = sys_auth(Identify::getUserInfo(NULL,'user_id'));
  227. $url = (defined('IN_WAP')&&IN_WAP==TRUE)?SiteUrl::mpLogin($scene_id,1):(Identify::hasLogined()?SiteUrl::mpLogin($scene_id,0,$uauth):SiteUrl::mpLogin($scene_id));
  228. $url = str_replace(WEB_URL,WAP_URL,$url);
  229. $codeUrl =APP_URL.'ajax/qrcode/?url='.urlencode($url);
  230. $returnResult = [
  231. 'error' => 0,
  232. 'msg' => '请求成功',
  233. 'data' => ['codeUrl'=>$codeUrl,'scene_id'=>$scene_id,'expire'=>Yii::$app->params['qrcodeExpire'],'url'=>$url],
  234. 'code'=>200
  235. ];
  236. if(defined('IN_WAP')&&IN_WAP==TRUE)
  237. {
  238. return $returnResult;
  239. }
  240. else
  241. {
  242. echo_json($returnResult);
  243. }
  244. }
  245. }
  246. }
  247. /**
  248. * 获取指定应用的用户UID
  249. * @param string $app 应用名称 weibo/qq 默认qq
  250. * @return mixed
  251. */
  252. function getAppUserId($app = 'qq') {
  253. $uid = 0;
  254. if ($app == 'weibo') {
  255. $uid = Session::get('weibo_token.uid')? Session::get('weibo_token.uid'): 0;
  256. } else if ($app == 'qq') {
  257. $uid = Session::get('qq_token.uid')? Session::get('qq_token.uid'): 0;
  258. }
  259. else if ($app == 'wx') {
  260. $uid =Session::get('wx_token.uid')? Session::get('wx_token.uid'): 0;
  261. }
  262. return $uid;
  263. }
  264. /**
  265. * 判断应用是否已经登录
  266. * @param string $app 应用名称 weibo/qq qq
  267. * @return bool
  268. */
  269. function checkAppLogin($app = 'qq') {
  270. if (!in_array($app, $this->apps)) return false;
  271. return $this->$app->verify() ? true : false;
  272. }
  273. /**
  274. * 退出/注销
  275. */
  276. public function logout() {
  277. $app = isset($_GET['app']) ? $_GET['app'] : '';
  278. if (in_array($app,$this->apps)) {
  279. Session::set('app.'.$app,'');
  280. Session::set("{$app}_token",'');
  281. }
  282. }
  283. /**
  284. * 获取应用的中文名称
  285. * @param string $app /weibo/qq 默认renren
  286. * @return string
  287. */
  288. function getAppName($app = 'qq') {
  289. $app_array = array( 'weibo' => '新浪微博', 'qq' => '腾讯QQ', 'wx' => '微信', 'dd' => '钉钉', 'mp' => '微信公众号');
  290. $app_name = isset($app_array[$app]) ? $app_array[$app] : '';
  291. return $app_name;
  292. }
  293. //验证成功后的处理跳转地址
  294. private function _callback($app) {
  295. if (in_array($app,$this->apps)) {
  296. //todo
  297. }
  298. }
  299. /**
  300. * 获取指定应用的用户信息
  301. * @param string $app 应用名称 renren/weibo/qq 默认renren
  302. * @return mixed
  303. */
  304. public function getAppUserInfo($app = 'qq') {
  305. $result = array();
  306. if ($app == 'weibo') {
  307. $weiboclient = new \app\components\OpenAuth\core\Weiboclient(Session::get('weibo_token.access_token'));
  308. $result = $weiboclient->show_user_by_id(Session::get('weibo_token.uid'));
  309. $result['name'] = $result['name'];
  310. $result['nick_name'] = $result['screen_name'];
  311. $result['uid'] = Session::get('weibo_token.uid');
  312. unset($result['id']);
  313. $result['avatar'] = $result['profile_image_url'];
  314. $result['unionid'] = Session::get('weibo_token.uid');
  315. $result['sex'] = $result['gender'] == 'm' ? 1: 2;
  316. $result['birthday'] = '';
  317. } else if ($app == 'qq') {
  318. $qqclient = new \app\components\OpenAuth\core\qqclient(Session::get('qq_token.access_token'), Session::get('qq_token.openid'));
  319. $result = $qqclient->get_user_info();
  320. $result['name'] = $result['nickname'];
  321. $result['nick_name'] = $result['nickname'];
  322. $result['uid'] = Session::get('qq_token.openid');
  323. $result['avatar'] = $result['figureurl_qq_2']?$result['figureurl_qq_2']:$result['figureurl_qq_1'];
  324. $result['unionid'] = Session::get('qq_token.openid');
  325. $result['sex'] = $result['gender']=='男'?1:2;
  326. $result['birthday'] = '';
  327. }else if ($app == 'wx') {
  328. $wxclient = new \app\components\OpenAuth\core\wxclient();
  329. $result = $wxclient->get_user_info();
  330. $result = json_decode($result[0],true);
  331. $result['name'] = $result['nickname'];
  332. $result['nick_name'] = $result['nickname'];
  333. $result['uid'] = Session::get('wx_token.openid');
  334. $result['avatar'] = $result['headimgurl'];
  335. $result['unionid'] = $result['unionid'];
  336. $result['sex'] = $result['sex'];
  337. $result['birthday'] = '';
  338. }
  339. else if ($app == 'dd') {
  340. $ddclient = new \app\components\OpenAuth\core\ddclient(Session::get('dd_token.access_token'));
  341. $result = $ddclient->get_user_info();
  342. $result = json_decode($result,true);
  343. $result['name'] = $result['nick'];
  344. $result['nick_name'] = $result['nick'];
  345. $result['uid'] = $result['openId'];
  346. $result['unionid'] = $result['unionId'];
  347. $result['avatar'] = $result['avatarUrl'];
  348. $result['mobile'] = $result['mobile'];
  349. }
  350. return $result;
  351. }
  352. //生成开启接收微信消息通知二维码
  353. public function mpMsg()
  354. {
  355. $scene_id = mt_rand(100000000,999999999).rand(0,9).rand(0,9);
  356. if(Yii::$app->params['mp']['openmsg'])
  357. {
  358. $args = array(
  359. 'appId'=>Yii::$app->params['mp']['mpAppId'],
  360. 'appSecret'=>Yii::$app->params['mp']['mpAppSecret'],
  361. 'token'=>Yii::$app->params['mp']['mpToken'],
  362. );
  363. $weixin = new WeiXin($args);
  364. $weixin->init();
  365. $scene_id = 'mpmsg_'.$scene_id;
  366. $result = $weixin->createQrcode($scene_id,3);
  367. $returnResult= ([
  368. 'error' => 0,
  369. 'msg' => '请求成功',
  370. 'data' => ['codeUrl'=>$result['codeUrl'],'scene_id'=>$scene_id,'expire'=>Yii::$app->params['qrcodeExpire']],
  371. 'code'=>200
  372. ]);
  373. if(defined('IN_WAP')&&IN_WAP==TRUE)
  374. {
  375. $expireTime = TIMESTAMP-30*60;
  376. UserOpenAuth::deleteAll("app_uid='0' and app='mpmsg' and bind_time<$expireTime");
  377. $openAuth = new UserOpenAuth();
  378. $openAuth->app = 'mpmsg';
  379. $openAuth->app_uid = '0';
  380. $openAuth->scene_id = $scene_id;
  381. $openAuth->app_unionid = '';
  382. $openAuth->app_unionname = 'mpmsg';
  383. $openAuth->bind_time = TIMESTAMP;
  384. $openAuth->save();
  385. return $returnResult;
  386. }
  387. else
  388. {
  389. echo_json($returnResult);
  390. }
  391. }
  392. }
  393. //生成关注公众号二维码
  394. public function mpSub()
  395. {
  396. $scene_id = mt_rand(100000000,999999999).rand(0,9).rand(0,9);
  397. if(Yii::$app->params['mp']['mpAppId'])
  398. {
  399. $args = array(
  400. 'appId'=>Yii::$app->params['mp']['mpAppId'],
  401. 'appSecret'=>Yii::$app->params['mp']['mpAppSecret'],
  402. 'token'=>Yii::$app->params['mp']['mpToken'],
  403. );
  404. $weixin = new WeiXin($args);
  405. $weixin->init();
  406. $scene_id = 'mpsub_'.$scene_id;
  407. $result = $weixin->createQrcode($scene_id,3);
  408. if($result['codeUrl'])
  409. {
  410. ob_clean();
  411. echo https_request($result['codeUrl']);
  412. }
  413. }
  414. }
  415. //生成下载文档二维码
  416. public function freeDowncode()
  417. {
  418. $id = Yii::$app->request->get('id');
  419. if(!empty($id))
  420. {
  421. if(Yii::$app->params['mp']['mpAppId'])
  422. {
  423. $args = array(
  424. 'appId'=>Yii::$app->params['mp']['mpAppId'],
  425. 'appSecret'=>Yii::$app->params['mp']['mpAppSecret'],
  426. 'token'=>Yii::$app->params['mp']['mpToken'],
  427. );
  428. $weixin = new WeiXin($args);
  429. $weixin->init();
  430. $scene_id ='freedowndoc_'.$id;
  431. $result = $weixin->createQrcode($scene_id,3);
  432. echo_json([
  433. 'error' => 0,
  434. 'msg' => '请求成功',
  435. 'data' => ['codeUrl'=>$result['codeUrl'],'scene_id'=>$scene_id],
  436. 'code'=>200
  437. ]);
  438. }
  439. }
  440. }
  441. }