UserController.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. <?php
  2. /**
  3. * 用户登录相关
  4. * User: benzhan
  5. * Date: 2018/10/18
  6. * Time: 10:41
  7. */
  8. class UserController extends BaseController {
  9. protected $ajaxLoginActions = [
  10. 'eosBind',
  11. 'ethBind',
  12. 'tronBind',
  13. 'tgBind',
  14. 'unbind',
  15. 'changeUserName',
  16. 'changeNickName',
  17. 'changePhoto',
  18. 'setVisible',
  19. ];
  20. public function __construct() {
  21. parent::__construct(false);
  22. }
  23. /**
  24. * 获取随机数【不需要登录】
  25. * @author benzhan
  26. */
  27. public function actionRandom($args) {
  28. $rules = [
  29. 'account' => ['string', 'reg' => '/^([a-z0-9\.]{1,13})$|^(0x[a-z0-9]{40})$|^[a-zA-Z0-9]{34}$/i', 'desc' => 'eos账号|eth账号|tron账号'],
  30. ];
  31. Param::checkParam2($rules, $args);
  32. $random = Account::getRandom($args['account']);
  33. Response::success($random);
  34. }
  35. /**
  36. * 获取随机数【不需要登录】
  37. * @author benzhan
  38. */
  39. public function actionRandom2($args) {
  40. $rules = [
  41. 'account' => ['string', 'reg' => '/^([a-z0-9\.]{1,13})$|^(0x[a-z0-9]{40})$|^[a-zA-Z0-9]{34}$/i', 'desc' => 'eos账号|eth账号'],
  42. ];
  43. Param::checkParam2($rules, $args);
  44. $random = Account::getRandom($args['account'], true);
  45. Response::success($random);
  46. }
  47. private function _getUserBaseInfo($user_id) {
  48. $objUserInfo = new TableHelper('user_info', 'dw_chat');
  49. $row = $objUserInfo->getRow(['user_id' => $user_id], ['_field' => 'user_id, user_name, nick_name, cover_photo']);
  50. return $row;
  51. }
  52. /**
  53. * Eos账号登录【不需要登录】
  54. * @author benzhan
  55. */
  56. public function actionEosLogin($args, $orginStr = null) {
  57. $rules = [
  58. 'account' => ['string', 'reg' => '/^[a-z0-9\.]{1,13}$/', 'desc' => 'eos账号'],
  59. 'pubkey' => ['string', 'nullable' => true, '公钥'],
  60. 'authority' => ['string', 'nullable' => true, 'enum' => ['owner', 'active'], '权限'],
  61. 'sign' => ['string', 'desc' => '私钥加密后的签名']
  62. ];
  63. Param::checkParam2($rules, $args);
  64. $info = User::getInfo();
  65. if ($info) {
  66. $info['info'] = $this->_getUserBaseInfo($info['user_id']);
  67. return $info;
  68. }
  69. if (!$args['pubkey'] && $args['authority']) {
  70. $args['pubkey'] = $this->_getPublicKey($args['account'], $args['authority']);
  71. }
  72. if (!$args['pubkey']) {
  73. Response::error(CODE_PARAM_ERROR, 'pubkey is empty.');
  74. }
  75. $account = $args['account'];
  76. if ($orginStr) {
  77. $data = $orginStr;
  78. } else {
  79. $data = Account::getRandom($account);
  80. if (!$data) {
  81. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  82. }
  83. }
  84. $flag = false;
  85. try {
  86. $flag = Account::verifyMsg($args['pubkey'], $account, $data, $args['sign']);
  87. } catch (Exception $e) {
  88. Response::error($e->getCode(), $e->getMessage());
  89. }
  90. if ($flag) {
  91. $user_id = User::login($args['account'], Account::TYPE_EOS);
  92. $info = Account::setCookie($user_id);
  93. $info['info'] = $this->_getUserBaseInfo($info['user_id']);
  94. return $info;
  95. } else {
  96. if ($orginStr) {
  97. return false;
  98. } else {
  99. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  100. }
  101. }
  102. }
  103. /**
  104. * 校验登录 (合约方式
  105. * @author solu
  106. * @param $args
  107. * @return array
  108. */
  109. public function actionEosLogin2($args) {
  110. $rules = [
  111. 'account' => ['string', 'reg' => '/^[a-z0-9\.]{1,13}$/', 'desc' => 'eos账号'],
  112. 'access_token' => ['string', 'len' => 36, 'desc' => 'access_token'],
  113. 'trx_id' => ['string', 'desc' => '交易id'],
  114. 'group_id' => ['int', 'nullable' => true, 'desc' => '群id'],
  115. ];
  116. Param::checkParam2($rules, $args);
  117. $objSync = new Sync_LoginLog();
  118. $objLoginLog = new TableHelper('login_log', 'dw_chat');
  119. $_where = ['trx_id' => $args['trx_id']];
  120. $row = $objLoginLog->getRow($_where);
  121. $maxTry = 3;
  122. $i = 0;
  123. // 没有数据请求同步再尝试
  124. while ($i < $maxTry && !$row) {
  125. sleep($i + 1);
  126. $objSync->pubSubscribe();
  127. $row = $objLoginLog->getRow($_where);
  128. $i++;
  129. }
  130. if (!$row) {
  131. Response::error(CODE_NORMAL_ERROR, 'trx_id not in log!');
  132. }
  133. $account = $args['account'];
  134. $random = Account::getRandom($account);
  135. if (!$random) {
  136. Response::error(CODE_NORMAL_ERROR, 'can not find random data, please refresh.');
  137. }
  138. if ($row['account'] != $account) {
  139. Response::error(CODE_NORMAL_ERROR, 'account unmatch');
  140. }
  141. if ($random != $row['memo']) {
  142. Response::error(CODE_NORMAL_ERROR, 'random unmatch');
  143. }
  144. $data = [];
  145. try {
  146. $data = Account::verifyPlayer($row['account'], $random, $args['access_token']);
  147. } catch (Exception $e) {
  148. Response::error($e->getCode(), $e->getMessage());
  149. }
  150. // 带群id检测是否加入群
  151. if ($args['group_id']) {
  152. try {
  153. (new GroupInfo())->joinGroup($data['user_id'], $args['group_id']);
  154. } catch (Exception $e) {
  155. var_log($e->getMessage());
  156. }
  157. }
  158. return $data;
  159. }
  160. private function _getPublicKey($account, $authority) {
  161. $accountInfo = EosBase::getAccount($account);
  162. $accountInfo = json_decode($accountInfo, true);
  163. foreach ($accountInfo['permissions'] as $p) {
  164. if ($p['perm_name'] == $authority) {
  165. return $p['required_auth']['keys'][0]['key'];
  166. }
  167. }
  168. return null;
  169. }
  170. /**
  171. * Eos账号绑定
  172. * @author benzhan
  173. */
  174. public function actionEosBind($args) {
  175. $rules = [
  176. 'account' => ['string', 'reg' => '/^[a-z0-9\.]{1,13}$/', 'desc' => 'eos账号'],
  177. 'pubkey' => ['string', '公钥'],
  178. 'sign' => ['string', 'desc' => '私钥加密后的签名'],
  179. ];
  180. Param::checkParam2($rules, $args);
  181. $account = $args['account'];
  182. $data = Account::getRandom($account);
  183. if (!$data) {
  184. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  185. }
  186. $flag = Account::verifyMsg($args['pubkey'], $account, $data, $args['sign']);
  187. if ($flag) {
  188. $user_id = User::getUserId();
  189. User::bind($user_id, $args['account'], Account::TYPE_EOS);
  190. } else {
  191. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  192. }
  193. }
  194. /**
  195. * Eth账号登录【不需要登录】
  196. * @author solu
  197. */
  198. public function actionEthLogin($args) {
  199. $rules = [
  200. 'account' => ['string', 'reg' => '/^0x[a-z0-9]{40}$/i', 'desc' => 'eos账号'],
  201. 'sign' => ['string', 'desc' => '私钥加密后的签名']
  202. ];
  203. Param::checkParam2($rules, $args);
  204. $info = User::getInfo();
  205. if ($info) {
  206. return $info;
  207. }
  208. $account = $args['account'];
  209. $data = Account::getRandom($account);
  210. if (!$data) {
  211. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  212. }
  213. $flag = false;
  214. try {
  215. $flag = Account::verifyEth($args['account'], $data, $args['sign']);
  216. } catch (Exception $e) {}
  217. if (!$flag) {
  218. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  219. }
  220. $user_id = User::login($args['account'], Account::TYPE_ETH);
  221. return Account::setCookie($user_id);
  222. }
  223. /**
  224. * ETH账号绑定
  225. * @author solu
  226. * @param $args
  227. */
  228. public function actionEthBind($args) {
  229. $rules = [
  230. 'account' => ['string', 'reg' => '/^0x[a-z0-9]{40}$/i', 'desc' => 'eos账号'],
  231. 'sign' => ['string', 'desc' => '私钥加密后的签名']
  232. ];
  233. Param::checkParam2($rules, $args);
  234. $account = $args['account'];
  235. $data = Account::getRandom($account);
  236. if (!$data) {
  237. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  238. }
  239. $flag = false;
  240. try {
  241. $flag = Account::verifyEth($args['account'], $data, $args['sign']);
  242. } catch (Exception $e) {}
  243. if (!$flag) {
  244. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  245. }
  246. $user_id = User::getUserId();
  247. User::bind($user_id, $account, Account::TYPE_ETH);
  248. }
  249. /**
  250. * Tron账号登录【不需要登录】
  251. * @param $args
  252. * @return array
  253. */
  254. public function actionTronLogin($args) {
  255. $rules = [
  256. 'account' => ['string', 'reg' => '/^[a-zA-Z0-9]{34}$/', 'desc' => 'tron账号'],
  257. 'sign' => ['string', 'desc' => '私钥加密后的签名']
  258. ];
  259. Param::checkParam2($rules, $args);
  260. $info = User::getInfo();
  261. if ($info) {
  262. return $info;
  263. }
  264. $account = $args['account'];
  265. $data = Account::getRandom($account);
  266. if (!$data) {
  267. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  268. }
  269. $flag = false;
  270. try {
  271. $flag = Account::verifyTron($args['account'], $data, $args['sign']);
  272. } catch (Exception $e) {}
  273. if (!$flag) {
  274. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  275. }
  276. $user_id = User::login($args['account'], Account::TYPE_TRON);
  277. return Account::setCookie($user_id);
  278. }
  279. /**
  280. * Tron账号绑定
  281. * @author solu
  282. * @param $args
  283. */
  284. public function actionTronBind($args) {
  285. $rules = [
  286. 'account' => ['string', 'reg' => '/^[a-zA-Z0-9]{34}$/', 'desc' => 'tron账号'],
  287. 'sign' => ['string', 'desc' => '私钥加密后的签名']
  288. ];
  289. Param::checkParam2($rules, $args);
  290. $account = $args['account'];
  291. $data = Account::getRandom($account);
  292. if (!$data) {
  293. Response::error(CODE_NO_PERMITION, 'can not find random data, please refresh.');
  294. }
  295. $flag = false;
  296. try {
  297. $flag = Account::verifyTron($args['account'], $data, $args['sign']);
  298. } catch (Exception $e) {}
  299. if (!$flag) {
  300. Response::error(CODE_NORMAL_ERROR, 'Verify failure, please retry.');
  301. }
  302. $user_id = User::getUserId();
  303. User::bind($user_id, $account, Account::TYPE_TRON);
  304. }
  305. /**
  306. * 解绑账号
  307. * @author solu
  308. * @param $args
  309. */
  310. public function actionUnbind($args) {
  311. $typeRule = array_keys(Account::getAllType());
  312. $rules = [
  313. 'type' => ['string', 'enum' => $typeRule, 'desc' => '类型 eos,eth, tron'],
  314. ];
  315. Param::checkParam2($rules, $args);
  316. $userId = User::getUserId();
  317. try {
  318. User::unbind($userId, $args['type']);
  319. } catch (Exception $e) {
  320. Response::error($e->getCode(), $e->getMessage());
  321. }
  322. }
  323. /**
  324. * 修改用户名【只能修改一次】
  325. * @author benzhan
  326. */
  327. public function actionChangeUserName($args) {
  328. $rules = [
  329. 'user_name' => ['string', 'reg' => '/^[a-zA-Z_0-9]{5,20}$/i', 'desc' => '用户名'],
  330. ];
  331. Param::checkParam2($rules, $args);
  332. $user_id = User::getUserId();
  333. User::saveInfo($user_id, $args);
  334. }
  335. /**
  336. * 修改昵称
  337. * @author benzhan
  338. */
  339. public function actionChangeNickName($args) {
  340. $rules = [
  341. 'nick_name' => ['string', 'len' => [1, 20], 'desc' => '用户名'],
  342. ];
  343. Param::checkParam2($rules, $args);
  344. $user_id = User::getUserId();
  345. User::saveInfo($user_id, $args);
  346. User::setUserNameById($user_id, $args['nick_name']);
  347. }
  348. /**
  349. * 修改头像
  350. * @author benzhan
  351. */
  352. public function actionChangePhoto($args) {
  353. $args = array_merge($args, $_FILES);
  354. $rules = [
  355. 'cover_photo' => ['array', 'desc' => '头像文件'],
  356. ];
  357. Param::checkParam2($rules, $args);
  358. $file = $args['cover_photo'];
  359. $cover_photo = '';
  360. try {
  361. $cover_photo = (new FileUrl())->getFileUrl($file['tmp_name'], $file['name'], $file['type'], true);
  362. } catch (Exception $e) {
  363. Response::error($e->getCode(), $e->getMessage());
  364. }
  365. $user_id = User::getUserId();
  366. User::saveInfo($user_id, compact('cover_photo'));
  367. }
  368. /**
  369. * 第三方账号的是否可见
  370. * @author benzhan
  371. */
  372. public function actionSetVisible($args) {
  373. $rules = [
  374. 'type' => ['string', 'enum' => ['eos', 'eth', 'tron'], 'desc' => '类型'],
  375. 'is_visible' => ['int', 'desc' => '是否可见'],
  376. ];
  377. Param::checkParam2($rules, $args);
  378. $user_id = User::getUserId();
  379. $type = $args['type'];
  380. $is_visible = (int) $args['is_visible'];
  381. $objUserBindInfo = new TableHelper('user_bind_info', 'dw_chat');
  382. $objUserBindInfo->updateObject(compact('is_visible'), compact('user_id', 'type'));
  383. }
  384. /**
  385. * 用户信息接口
  386. * @author solu
  387. * @param $args
  388. * @return array
  389. */
  390. public function actionInfo($args) {
  391. $rules = [
  392. 'target_id' => ['int', 'desc' => '用户id'],
  393. 'group_id' => ['int', 'nullable' => true, '群id'],
  394. ];
  395. Param::checkParam2($rules, $args);
  396. $self = User::getUserId();
  397. $userId = (int)$args['target_id'];
  398. $groupId = (int)$args['group_id'];
  399. // 如果是自己调用,则刷新token的有效期
  400. if ($userId == $self) {
  401. Account::refreshToken();
  402. }
  403. return User::getUserInfo($userId, $self, $groupId);
  404. }
  405. /**
  406. * Simplewallet 协议登录
  407. * @param $args
  408. * @param string $authority
  409. *
  410. * @return array|bool|null
  411. */
  412. public function actionSimplewallet($args, $authority = 'active') {
  413. if (!$args) {
  414. $json = file_get_contents('php://input');
  415. $data = json_decode($json, true);
  416. $args += $data;
  417. }
  418. $rules = [
  419. 'account' => ['string', 'desc' => 'Eos账号'],
  420. 'chainId' => ['string', 'desc' => '链id'],
  421. 'protocol' => ['string', 'desc' => '协议', 'enum' => ['SimpleWallet']],
  422. 'ref' => ['string', 'desc' => '来源'],
  423. 'sign' => ['string', 'desc' => '签名'],
  424. 'timestamp' => ['string', 'desc' => '时间戳'],
  425. 'uuID' => ['string', 'desc' => '随机数'],
  426. 'version' => ['string', 'desc' => '版本号'],
  427. ];
  428. Param::checkParam($rules, $args);
  429. $pubkey = $this->_getPublicKey($args['account'], $authority);
  430. $newArgs = [
  431. 'account' => $args['account'],
  432. 'pubkey' => $pubkey,
  433. 'authority' => $authority,
  434. 'sign' => $args['sign'],
  435. ];
  436. $orginStr = "{$args['timestamp']}{$args['account']}{$args['uuID']}{$args['ref']}";
  437. $info = $this->actionEosLogin($newArgs, $orginStr);
  438. if ($info) {
  439. $objRedis = dwRedis::init();
  440. $info['account'] = $args['account'];
  441. $uuid = $this->_getUuid($args['uuID']);
  442. $objRedis->setex($uuid, 60, json_encode($info));
  443. } else if ($authority == 'active') {
  444. // 再尝试一次 owner
  445. $this->actionSimplewallet($args, 'owner');
  446. }
  447. }
  448. /**
  449. * Simplewallet 协议登录
  450. * @param $args
  451. * @param string $authority
  452. *
  453. * @return array|bool|null
  454. */
  455. public function actionSimplewalletCheck($args) {
  456. $rules = [
  457. 'uuID' => ['string', 'desc' => '随机数']
  458. ];
  459. Param::checkParam($rules, $args);
  460. $objRedis = dwRedis::init();
  461. $uuid = $this->_getUuid($args['uuID']);
  462. $json = $objRedis->get($uuid);
  463. if ($json) {
  464. $info = json_decode($json, true);
  465. return $info;
  466. } else {
  467. Response::error(CODE_NORMAL_ERROR, 'no found');
  468. }
  469. }
  470. private function _getUuid($uuid) {
  471. return "globals:simple_wallet:{$uuid}";
  472. }
  473. /**
  474. * Telegram登录
  475. * @author solu
  476. * @param $args
  477. * @return array
  478. */
  479. public function actionTgLogin($args) {
  480. $rules = [
  481. 'id' => ['int', 'desc' => 'telegram user id'],
  482. 'first_name' => 'string',
  483. 'last_name' => 'string',
  484. 'auth_date' => ['int', 'desc' => 'timestamp'],
  485. 'hash' => ['string', 'desc' => 'verify hash'],
  486. ];
  487. Param::checkParam2($rules, $args);
  488. $data = [];
  489. try {
  490. $data = ThirdApi::checkTelegramAuthorization($args);
  491. } catch (Exception $e) {
  492. Response::error(CODE_SIGN_ERROR, $e->getMessage());
  493. }
  494. $name = $data['first_name'] . '_' . $data['last_name'];
  495. $user_id = User::login($data['id'], Account::TYPE_TG, $name);
  496. return Account::setCookie($user_id);
  497. }
  498. /**
  499. * Telegram绑定
  500. * @author solu
  501. * @param $args
  502. */
  503. public function actionTgBind($args) {
  504. $rules = [
  505. 'id' => ['int', 'desc' => 'telegram user id'],
  506. 'first_name' => 'string',
  507. 'last_name' => 'string',
  508. 'auth_date' => ['int', 'desc' => 'timestamp'],
  509. 'hash' => ['string', 'desc' => 'verify hash'],
  510. ];
  511. Param::checkParam2($rules, $args);
  512. $data = [];
  513. try {
  514. $data = ThirdApi::checkTelegramAuthorization($args);
  515. } catch (Exception $e) {
  516. Response::error(CODE_SIGN_ERROR, $e->getMessage());
  517. }
  518. $user_id = User::getUserId();
  519. User::bind($user_id, $data['id'], Account::TYPE_TG);
  520. }
  521. public function actionTg($args) {
  522. $this->tpl = Template::init();
  523. $this->tpl->display('tg');
  524. }
  525. }