LoginController.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\controller\api\v1;
  12. use app\Request;
  13. use app\services\wechat\WechatServices as WechatAuthServices;
  14. use think\facade\Config;
  15. use crmeb\services\CacheService;
  16. use app\services\user\LoginServices;
  17. use think\exception\ValidateException;
  18. use app\validate\api\user\RegisterValidates;
  19. /**
  20. * 登录
  21. * Class AuthController
  22. * @package app\controller\api
  23. */
  24. class LoginController
  25. {
  26. protected $services = NUll;
  27. /**
  28. * LoginController constructor.
  29. * @param LoginServices $services
  30. */
  31. public function __construct(LoginServices $services)
  32. {
  33. $this->services = $services;
  34. }
  35. /**
  36. * H5账号登陆
  37. * @param Request $request
  38. * @return mixed
  39. * @throws \think\db\exception\DataNotFoundException
  40. * @throws \think\db\exception\ModelNotFoundException
  41. * @throws \think\exception\DbException
  42. */
  43. public function login(Request $request)
  44. {
  45. [$account, $password, $spread_spid] = $request->postMore([
  46. 'account', 'password', 'spread_spid'
  47. ], true);
  48. if (!$account || !$password) {
  49. return app('json')->fail('请输入账号和密码');
  50. }
  51. validate(\app\validate\api\LoginValidate::class)->check(['account' => $account, 'pwd' => $password]);
  52. return app('json')->success('登录成功', $this->services->login($account, $password, $spread_spid));
  53. }
  54. /**
  55. * apple快捷登陆
  56. * @param Request $request
  57. * @param WechatAuthServices $services
  58. * @return mixed
  59. * @throws \Psr\SimpleCache\InvalidArgumentException
  60. * @throws \think\db\exception\DataNotFoundException
  61. * @throws \think\db\exception\ModelNotFoundException
  62. */
  63. public function appleLogin(Request $request, WechatAuthServices $services)
  64. {
  65. [$openId, $phone, $email, $captcha] = $request->postMore([
  66. ['openId', ''],
  67. ['phone', ''],
  68. ['email', ''],
  69. ['captcha', '']
  70. ], true);
  71. if ($phone) {
  72. if (!$captcha) {
  73. return app('json')->fail('请输入验证码');
  74. }
  75. //验证验证码
  76. $verifyCode = CacheService::get('code_' . $phone);
  77. if (!$verifyCode)
  78. return app('json')->fail('请先获取验证码');
  79. $verifyCode = substr($verifyCode, 0, 6);
  80. if ($verifyCode != $captcha) {
  81. CacheService::delete('code_' . $phone);
  82. return app('json')->fail('验证码错误');
  83. }
  84. }
  85. $userInfo = [
  86. 'openId' => $openId,
  87. 'unionid' => '',
  88. 'avatarUrl' => sys_config('h5_avatar'),
  89. 'nickName' => $email
  90. ];
  91. if (!$userInfo['nickName']) {
  92. mt_srand();
  93. $userInfo['nickname'] = 'wx' . rand(100000, 999999);
  94. }
  95. $token = $services->appAuth($userInfo, $phone, 'apple');
  96. if ($token) {
  97. return app('json')->success('登录成功', $token);
  98. } else if ($token === false) {
  99. return app('json')->success('登录成功', ['isbind' => true]);
  100. } else {
  101. return app('json')->fail('登陆失败');
  102. }
  103. }
  104. /**
  105. * 退出登录
  106. * @param Request $request
  107. */
  108. public function logout(Request $request)
  109. {
  110. $key = trim(ltrim($request->header(Config::get('cookie.token_name')), 'Bearer'));
  111. CacheService::redisHandler()->delete(md5($key));
  112. return app('json')->success('成功');
  113. }
  114. public function verifyCode()
  115. {
  116. $unique = password_hash(uniqid(true), PASSWORD_BCRYPT);
  117. CacheService::set('sms.key.' . $unique, 0, 300);
  118. $time = sys_config('verify_expire_time', 1);
  119. return app('json')->success(['key' => $unique, 'expire_time' => $time]);
  120. }
  121. public function captcha(Request $request)
  122. {
  123. ob_clean();
  124. $rep = captcha();
  125. $key = app('session')->get('captcha.key');
  126. $uni = $request->get('key');
  127. if ($uni)
  128. CacheService::set('sms.key.cap.' . $uni, $key, 300);
  129. return $rep;
  130. }
  131. /**
  132. * 验证验证码是否正确
  133. *
  134. * @param $uni
  135. * @param string $code
  136. * @return bool
  137. * @throws \Psr\SimpleCache\InvalidArgumentException
  138. */
  139. protected function checkCaptcha($uni, string $code): bool
  140. {
  141. $cacheName = 'sms.key.cap.' . $uni;
  142. if (!CacheService::has($cacheName)) {
  143. return false;
  144. }
  145. $key = CacheService::get($cacheName);
  146. $code = mb_strtolower($code, 'UTF-8');
  147. $res = password_verify($code, $key);
  148. if ($res) {
  149. CaCacheServiceche::delete($cacheName);
  150. }
  151. return $res;
  152. }
  153. /**
  154. * @return mixed
  155. */
  156. public function ajcaptcha(Request $request)
  157. {
  158. $captchaType = $request->get('captchaType');
  159. return app('json')->success(aj_captcha_create($captchaType));
  160. }
  161. /**
  162. * 一次验证
  163. * @return mixed
  164. */
  165. public function ajcheck(Request $request)
  166. {
  167. [$token, $pointJson, $captchaType] = $request->postMore([
  168. ['token', ''],
  169. ['pointJson', ''],
  170. ['captchaType', ''],
  171. ], true);
  172. try {
  173. aj_captcha_check_one($captchaType, $token, $pointJson);
  174. return app('json')->success();
  175. } catch (\Throwable $e) {
  176. return app('json')->fail(400336);
  177. }
  178. }
  179. /**
  180. * 验证码发送
  181. * @param Request $request
  182. * @return mixed
  183. */
  184. public function verify(Request $request)
  185. {
  186. [$phone, $type, $key, $captchaType, $captchaVerification] = $request->postMore([
  187. ['phone', 0],
  188. ['type', ''],
  189. ['key', ''],
  190. ['captchaType', ''],
  191. ['captchaVerification', ''],
  192. ], true);
  193. $keyName = 'sms.key.' . $key;
  194. $nowKey = 'sms.' . date('YmdHi');
  195. if (!CacheService::has($keyName))
  196. return app('json')->make(401, '发送验证码失败,请刷新页面重新获取');
  197. $total = 1;
  198. if (CacheService::has($nowKey)) {
  199. $total = CacheService::get($nowKey);
  200. if ($total > Config::get('sms.maxMinuteCount', 20))
  201. return app('json')->success('已发送');
  202. }
  203. //二次验证
  204. try {
  205. aj_captcha_check_two($captchaType, $captchaVerification);
  206. } catch (\Throwable $e) {
  207. return app('json')->fail($e->getError());
  208. }
  209. try {
  210. validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
  211. } catch (ValidateException $e) {
  212. return app('json')->fail($e->getError());
  213. }
  214. $time = sys_config('verify_expire_time', 1);
  215. $smsCode = $this->services->verify($phone, $type, $time, app()->request->ip());
  216. if ($smsCode) {
  217. CacheService::set('code_' . $phone, $smsCode, $time * 60);
  218. CacheService::set($nowKey, $total, 61);
  219. event('sms.sendAfter', [$smsCode, $phone]);
  220. return app('json')->success('发送成功');
  221. } else {
  222. return app('json')->fail('发送失败');
  223. }
  224. }
  225. /**
  226. * H5注册新用户
  227. * @param Request $request
  228. * @return mixed
  229. */
  230. public function register(Request $request)
  231. {
  232. [$account, $captcha, $password, $spread_spid] = $request->postMore([
  233. ['account', ''],
  234. ['captcha', ''],
  235. ['password', ''],
  236. ['spread_spid', 0]
  237. ], true);
  238. try {
  239. validate(RegisterValidates::class)->scene('register')->check(['account' => $account, 'captcha' => $captcha, 'password' => $password]);
  240. } catch (ValidateException $e) {
  241. return app('json')->fail($e->getError());
  242. }
  243. $verifyCode = CacheService::get('code_' . $account);
  244. if (!$verifyCode)
  245. return app('json')->fail('请先获取验证码');
  246. $verifyCode = substr($verifyCode, 0, 6);
  247. if ($verifyCode != $captcha)
  248. return app('json')->fail('验证码错误');
  249. if (strlen(trim($password)) < 4 || strlen(trim($password)) > 64)
  250. return app('json')->fail('密码必须是在4到64位之间');
  251. if ($password == '123456') return app('json')->fail('密码太过简单,请输入较为复杂的密码');
  252. $user_type = $request->getFromType() ? $request->getFromType() : 'h5';
  253. $registerStatus = $this->services->register($account, $password, $spread_spid, $user_type);
  254. if ($registerStatus) {
  255. CacheService::delete('code_' . $account);
  256. return app('json')->success('注册成功');
  257. }
  258. return app('json')->fail('注册失败');
  259. }
  260. /**
  261. * 密码修改
  262. * @param Request $request
  263. * @return mixed
  264. */
  265. public function reset(Request $request)
  266. {
  267. [$account, $captcha, $password] = $request->postMore([['account', ''], ['captcha', ''], ['password', '']], true);
  268. try {
  269. validate(RegisterValidates::class)->scene('register')->check(['account' => $account, 'captcha' => $captcha, 'password' => $password]);
  270. } catch (ValidateException $e) {
  271. return app('json')->fail($e->getError());
  272. }
  273. $verifyCode = CacheService::get('code_' . $account);
  274. if (!$verifyCode)
  275. return app('json')->fail('请先获取验证码');
  276. $verifyCode = substr($verifyCode, 0, 6);
  277. if ($verifyCode != $captcha) {
  278. return app('json')->fail('验证码错误');
  279. }
  280. if (strlen(trim($password)) < 4 || strlen(trim($password)) > 64)
  281. return app('json')->fail('密码必须是在4到64位之间');
  282. if ($password == '123456') return app('json')->fail('密码太过简单,请输入较为复杂的密码');
  283. $resetStatus = $this->services->reset($account, $password);
  284. if ($resetStatus) {
  285. CacheService::delete('code_' . $account);
  286. return app('json')->success('修改成功');
  287. }
  288. return app('json')->fail('修改失败');
  289. }
  290. /**
  291. * 手机号登录
  292. * @param Request $request
  293. * @return mixed
  294. * @throws \think\db\exception\DataNotFoundException
  295. * @throws \think\db\exception\ModelNotFoundException
  296. * @throws \think\exception\DbException
  297. */
  298. public function mobile(Request $request)
  299. {
  300. [$phone, $captcha, $spread_spid] = $request->postMore([['phone', ''], ['captcha', ''], ['spread_spid', 0]], true);
  301. //验证手机号
  302. try {
  303. validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
  304. } catch (ValidateException $e) {
  305. return app('json')->fail($e->getError());
  306. }
  307. //验证验证码
  308. // $verifyCode = CacheService::get('code_' . $phone);
  309. // if (!$verifyCode)
  310. // return app('json')->fail('请先获取验证码');
  311. // $verifyCode = substr($verifyCode, 0, 6);
  312. // if ($verifyCode != $captcha) {
  313. // return app('json')->fail('验证码错误');
  314. // }
  315. $user_type = $request->getFromType() ? $request->getFromType() : 'h5';
  316. $token = $this->services->mobile($phone, $spread_spid, $user_type);
  317. if ($token) {
  318. CacheService::delete('code_' . $phone);
  319. return app('json')->success('登录成功', $token);
  320. } else {
  321. return app('json')->fail('登录失败');
  322. }
  323. }
  324. /**
  325. * H5切换登陆
  326. * @param Request $request
  327. * @return mixed
  328. * @throws \think\db\exception\DataNotFoundException
  329. * @throws \think\db\exception\ModelNotFoundException
  330. * @throws \think\exception\DbException
  331. */
  332. public function switch_h5(Request $request)
  333. {
  334. $from = $request->post('from', 'wechat');
  335. $user = $request->user();
  336. $token = $this->services->switchAccount($user, $from);
  337. if ($token) {
  338. $token['userInfo'] = $user;
  339. return app('json')->success('登录成功', $token);
  340. } else
  341. return app('json')->fail('登录失败');
  342. }
  343. /**
  344. * 绑定手机号
  345. * @param Request $request
  346. * @return mixed
  347. * @throws \think\db\exception\DataNotFoundException
  348. * @throws \think\db\exception\ModelNotFoundException
  349. * @throws \think\exception\DbException
  350. */
  351. public function binding_phone(Request $request)
  352. {
  353. [$phone, $captcha, $key] = $request->postMore([
  354. ['phone', ''],
  355. ['captcha', ''],
  356. ['key', '']
  357. ], true);
  358. //验证手机号
  359. try {
  360. validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
  361. } catch (ValidateException $e) {
  362. return app('json')->fail($e->getError());
  363. }
  364. if (!$key) {
  365. return app('json')->fail('参数错误');
  366. }
  367. if (!$phone) {
  368. return app('json')->fail('请输入手机号');
  369. }
  370. //验证验证码
  371. $verifyCode = CacheService::get('code_' . $phone);
  372. if (!$verifyCode)
  373. return app('json')->fail('请先获取验证码');
  374. $verifyCode = substr($verifyCode, 0, 6);
  375. if ($verifyCode != $captcha) {
  376. CacheService::delete('code_' . $phone);
  377. return app('json')->fail('验证码错误');
  378. }
  379. $re = $this->services->bindind_phone($phone, $key);
  380. if ($re) {
  381. CacheService::delete('code_' . $phone);
  382. return app('json')->success('绑定成功', $re);
  383. } else
  384. return app('json')->fail('绑定失败');
  385. }
  386. /**
  387. * 绑定手机号
  388. * @param Request $request
  389. * @return mixed
  390. * @throws \think\db\exception\DataNotFoundException
  391. * @throws \think\db\exception\ModelNotFoundException
  392. * @throws \think\exception\DbException
  393. */
  394. public function user_binding_phone(Request $request)
  395. {
  396. [$phone, $captcha, $step] = $request->postMore([
  397. ['phone', ''],
  398. ['captcha', ''],
  399. ['step', 0]
  400. ], true);
  401. //验证手机号
  402. try {
  403. validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
  404. } catch (ValidateException $e) {
  405. return app('json')->fail($e->getError());
  406. }
  407. if (!$step) {
  408. //验证验证码
  409. $verifyCode = CacheService::get('code_' . $phone);
  410. if (!$verifyCode)
  411. return app('json')->fail('请先获取验证码');
  412. $verifyCode = substr($verifyCode, 0, 6);
  413. if ($verifyCode != $captcha)
  414. return app('json')->fail('验证码错误');
  415. }
  416. $uid = (int)$request->uid();
  417. $re = $this->services->userBindindPhone($uid, $phone, $step);
  418. if ($re) {
  419. CacheService::delete('code_' . $phone);
  420. return app('json')->success($re['msg'] ?? '绑定成功', $re['data'] ?? []);
  421. } else
  422. return app('json')->fail('绑定失败');
  423. }
  424. public function update_binding_phone(Request $request)
  425. {
  426. [$phone, $captcha] = $request->postMore([
  427. ['phone', ''],
  428. ['captcha', ''],
  429. ], true);
  430. //验证手机号
  431. try {
  432. validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
  433. } catch (ValidateException $e) {
  434. return app('json')->fail($e->getError());
  435. }
  436. //验证验证码
  437. $verifyCode = CacheService::get('code_' . $phone);
  438. if (!$verifyCode)
  439. return app('json')->fail('请先获取验证码');
  440. $verifyCode = substr($verifyCode, 0, 6);
  441. if ($verifyCode != $captcha)
  442. return app('json')->fail('验证码错误');
  443. $uid = (int)$request->uid();
  444. $re = $this->services->updateBindindPhone($uid, $phone);
  445. if ($re) {
  446. CacheService::delete('code_' . $phone);
  447. return app('json')->success($re['msg'] ?? '修改成功', $re['data'] ?? []);
  448. } else
  449. return app('json')->fail('修改失败');
  450. }
  451. /**
  452. * 设置扫描二维码状态
  453. * @param string $code
  454. * @return mixed
  455. */
  456. public function setLoginKey(string $code)
  457. {
  458. if (!$code) {
  459. return app('json')->fail('登录CODE不存在');
  460. }
  461. $cacheCode = CacheService::get($code);
  462. if ($cacheCode === false || $cacheCode === null) {
  463. return app('json')->fail('二维码已过期请重新扫描');
  464. }
  465. CacheService::set($code, '0', 600);
  466. return app('json')->success();
  467. }
  468. }