Login.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <?php
  2. namespace addons\shop\controller\api;
  3. use addons\third\model\Third;
  4. use app\common\library\Auth;
  5. use app\common\library\Sms;
  6. use app\common\library\Ems;
  7. use fast\Random;
  8. use think\Validate;
  9. use fast\Http;
  10. use addons\third\library\Service;
  11. use think\Config;
  12. use think\Env;
  13. use think\Session;
  14. class Login extends Base
  15. {
  16. protected $noNeedLogin = ['*'];
  17. public function _initialize()
  18. {
  19. parent::_initialize();
  20. if (!$this->request->isPost()) {
  21. $this->error('请求错误');
  22. }
  23. Auth::instance()->setAllowFields(array_merge(['username'], $this->allowFields));
  24. }
  25. /**
  26. * 会员登录
  27. *
  28. * @param string $account 账号
  29. * @param string $password 密码
  30. */
  31. public function login()
  32. {
  33. $account = $this->request->post('account', '');
  34. $password = $this->request->post('password', '');
  35. if (!$account || !$password) {
  36. $this->error(__('Invalid parameters'));
  37. }
  38. $ret = $this->auth->login($account, $password);
  39. if ($ret) {
  40. $user = $this->auth->getUserinfo();
  41. $user['avatar'] = cdnurl($user['avatar'], true);
  42. $this->success(__('Logged in successful'), [
  43. 'token' => $this->auth->getToken(),
  44. 'user' => $user
  45. ]);
  46. } else {
  47. $this->error($this->auth->getError());
  48. }
  49. }
  50. /**
  51. * 重置密码
  52. *
  53. * @param string $mobile 手机号
  54. * @param string $newpassword 新密码
  55. * @param string $captcha 验证码
  56. */
  57. public function resetpwd()
  58. {
  59. $type = $this->request->param("type");
  60. $mobile = $this->request->param("mobile");
  61. $email = $this->request->param("email");
  62. $newpassword = $this->request->param("newpassword");
  63. $captcha = $this->request->param("captcha");
  64. if (!$newpassword || !$captcha) {
  65. $this->error(__('Invalid parameters'));
  66. }
  67. if ($type == 'mobile') {
  68. if (!Validate::regex($mobile, "^1\d{10}$")) {
  69. $this->error(__('Mobile is incorrect'));
  70. }
  71. $user = \app\common\model\User::getByMobile($mobile);
  72. if (!$user) {
  73. $this->error(__('User not found'));
  74. }
  75. $ret = Sms::check($mobile, $captcha, 'resetpwd');
  76. if (!$ret) {
  77. $this->error(__('Captcha is incorrect'));
  78. }
  79. Sms::flush($mobile, 'resetpwd');
  80. } else {
  81. if (!Validate::is($email, "email")) {
  82. $this->error(__('Email is incorrect'));
  83. }
  84. $user = \app\common\model\User::getByEmail($email);
  85. if (!$user) {
  86. $this->error(__('User not found'));
  87. }
  88. $ret = Ems::check($email, $captcha, 'resetpwd');
  89. if (!$ret) {
  90. $this->error(__('Captcha is incorrect'));
  91. }
  92. Ems::flush($email, 'resetpwd');
  93. }
  94. //模拟一次登录
  95. $this->auth->direct($user->id);
  96. $ret = $this->auth->changepwd($newpassword, '', true);
  97. if ($ret) {
  98. $this->success(__('Reset password successful'));
  99. } else {
  100. $this->error($this->auth->getError());
  101. }
  102. }
  103. /**
  104. * 手机验证码登录
  105. *
  106. * @param string $mobile 手机号
  107. * @param string $captcha 验证码
  108. */
  109. public function mobilelogin()
  110. {
  111. $mobile = $this->request->post('mobile');
  112. $captcha = $this->request->post('captcha');
  113. $invite_id = $this->request->post('invite_id');
  114. if ($invite_id) {
  115. \think\Cookie::set('inviter', $invite_id);
  116. }
  117. if (!$mobile || !$captcha) {
  118. $this->error(__('Invalid parameters'));
  119. }
  120. if (!Validate::regex($mobile, "^1\d{10}$")) {
  121. $this->error(__('Mobile is incorrect'));
  122. }
  123. // 这里需要处理 测试环境 env('app_debug') 为 true 时,不进行验证码验证 校验 验证码固定为env的配置 DEFAULT_SMSCODE: 123456
  124. if (!Env::get('app.app_debug') && $captcha != Env::get('app.DEFAULT_SMSCODE')) {
  125. if (!Sms::check($mobile, $captcha, 'mobilelogin')) {
  126. $this->error(__('Captcha is incorrect'));
  127. }
  128. }
  129. $user = \app\common\model\User::getByMobile($mobile);
  130. if ($user) {
  131. if ($user->status != 'normal') {
  132. $this->error(__('Account is locked'));
  133. }
  134. //如果已经有账号则直接登录
  135. $ret = $this->auth->direct($user->id);
  136. } else {
  137. $ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, []);
  138. }
  139. if ($ret) {
  140. Sms::flush($mobile, 'mobilelogin');
  141. $user = $this->auth->getUserinfo();
  142. $user['avatar'] = cdnurl($user['avatar'], true);
  143. $data = ['token' => $this->auth->getToken(), 'user' => $user];
  144. $this->success(__('Logged in successful'), $data);
  145. } else {
  146. $this->error($this->auth->getError());
  147. }
  148. }
  149. /**
  150. * 注册会员
  151. *
  152. * @param string $username 用户名
  153. * @param string $password 密码
  154. * @param string $email 邮箱
  155. * @param string $mobile 手机号
  156. * @param string $code 验证码
  157. */
  158. public function register()
  159. {
  160. $username = $this->request->post('username');
  161. $password = $this->request->post('password');
  162. $mobile = $this->request->post('mobile');
  163. $code = $this->request->post('code');
  164. $invite_id = $this->request->post('invite_id');
  165. if ($invite_id) {
  166. \think\Cookie::set('inviter', $invite_id);
  167. }
  168. if (!$username || !$password) {
  169. $this->error(__('Invalid parameters'));
  170. }
  171. if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
  172. $this->error(__('Mobile is incorrect'));
  173. }
  174. $ret = Sms::check($mobile, $code, 'register');
  175. if (!$ret) {
  176. $this->error(__('Captcha is incorrect'));
  177. }
  178. $ret = $this->auth->register($username, $password, '', $mobile, []);
  179. if ($ret) {
  180. $user = $this->auth->getUserinfo();
  181. $user['avatar'] = cdnurl($user['avatar'], true);
  182. $this->success(__('Sign up successful'), [
  183. 'token' => $this->auth->getToken(),
  184. 'user' => $user
  185. ]);
  186. } else {
  187. $this->error($this->auth->getError());
  188. }
  189. }
  190. /**
  191. * 第三方登录[绑定] 小程序
  192. */
  193. public function wxLogin()
  194. {
  195. $code = $this->request->post("code");
  196. $rawData = $this->request->post("rawData/a", '', 'trim');
  197. if (!$code) {
  198. $this->error("参数不正确");
  199. }
  200. $rawData = $rawData ?: ['nickName' => '微信用户'];
  201. $third = get_addon_info('third');
  202. if (!$third || !$third['state']) {
  203. $this->error("请在后台插件管理安装第三方登录插件并启用");
  204. }
  205. if (!config('shop.wx_appid') || !config('shop.wx_app_secret')) {
  206. $this->error("请在后台配置微信小程序参数");
  207. }
  208. $json = (new \addons\shop\library\Wechat\Service())->getWechatSession($code);
  209. if (isset($json['openid'])) {
  210. $userinfo = [
  211. 'platform' => 'wechat',
  212. 'apptype' => 'miniapp',
  213. 'openid' => $json['openid'],
  214. 'userinfo' => [
  215. 'nickname' => $rawData['nickName'] ?? '',
  216. 'avatar' => $rawData['avatarUrl'] ?? ''
  217. ],
  218. 'openname' => $rawData['nickName'] ?? '',
  219. 'access_token' => $json['session_key'],
  220. 'refresh_token' => '',
  221. 'expires_in' => $json['expires_in'] ?? 0,
  222. 'unionid' => $json['unionid'] ?? ''
  223. ];
  224. $third = [
  225. 'nickname' => $rawData['nickName'] ?? '',
  226. 'avatar' => $rawData['avatarUrl'] ?? ''
  227. ];
  228. $user = null;
  229. if ($this->auth->isLogin() || Service::isBindThird($userinfo['platform'], $userinfo['openid'])) {
  230. Service::connect($userinfo['platform'], $userinfo);
  231. } else {
  232. // 是否自动创建账号
  233. if (config('shop.wechatautocreate')) {
  234. Service::connect($userinfo['platform'], $userinfo);
  235. } else {
  236. Session::set('third-userinfo', $userinfo);
  237. $this->success('授权成功!', ['third' => $third, 'openid' => $json['openid'], 'bind' => true]);
  238. }
  239. }
  240. $user = $this->auth->getUserinfo();
  241. $this->success('授权成功!', ['user' => $user, 'third' => $third, 'openid' => $json['openid']]);
  242. }
  243. $this->error("授权失败," . ($json['errmsg'] ?? "未知错误"));
  244. }
  245. /**
  246. * 微信手机号授权登录
  247. */
  248. public function wechatMobileLogin()
  249. {
  250. $code = $this->request->post("code");
  251. $logincode = $this->request->post("logincode");
  252. $bind = $this->request->post("bind");
  253. $data = (new \addons\shop\library\Wechat\Service())->getWechatMobile($code);
  254. if ($data) {
  255. $mobile = $data['phoneNumber'];
  256. //获取openid和unionid
  257. $json = (new \addons\shop\library\Wechat\Service())->getWechatSession($logincode);
  258. $openid = $json['openid'] ?? '';
  259. $unionid = $json['unionid'] ?? '';
  260. $user = \app\common\model\User::getByMobile($mobile);
  261. if ($user) {
  262. if ($user->status != 'normal') {
  263. $this->error(__('Account is locked'));
  264. }
  265. //如果已经有账号则直接登录
  266. $ret = $this->auth->direct($user->id);
  267. } else {
  268. $ret = $this->auth->register($mobile, Random::alnum(), '', $mobile, ['nickname' => substr_replace($mobile, '****', 3, 4)]);
  269. }
  270. //判断是否绑定模式,openid是否有关联,没有关联的情况下手动进行关联
  271. if ($bind && $openid) {
  272. if (Service::isBindThird('wechat', $openid)) {
  273. $this->error("手机号已经绑定其它账号");
  274. }
  275. // 在第三方登录表中创建关联
  276. $values = ['user_id' => $this->auth->id, 'platform' => 'wechat', 'openid' => $openid, 'unionid' => $unionid, 'openname' => '微信用户', 'apptype' => 'miniapp'];
  277. Third::create($values, true);
  278. }
  279. if ($ret) {
  280. $data = ['user' => $this->auth->getUserinfo(), 'token' => $this->auth->getToken(), 'openid' => $openid];
  281. $this->success('授权成功!', $data);
  282. } else {
  283. $this->error($this->auth->getError());
  284. }
  285. } else {
  286. $this->error("授权失败,请重试");
  287. }
  288. }
  289. /**
  290. * APP登录
  291. */
  292. public function appLogin()
  293. {
  294. $code = $this->request->post("code");
  295. $scope = $this->request->post("scope");
  296. if (!$code) {
  297. $this->error("参数不正确");
  298. }
  299. $third = get_addon_info('third');
  300. if (!$third || !$third['state']) {
  301. $this->error("请在后台插件管理安装第三方登录插件并启用");
  302. }
  303. Session::set('state', $code);
  304. $config = [
  305. 'app_id' => Config::get('shop.app_id'),
  306. 'app_secret' => Config::get('shop.app_secret'),
  307. 'scope' => $scope
  308. ];
  309. if (!$config['app_id'] || !$config['app_secret']) {
  310. $this->error("请在后台配置移动端APP参数");
  311. }
  312. $wechat = new \addons\third\library\Wechat($config);
  313. $userinfo = $wechat->getUserInfo(['code' => $code, 'state' => $code]);
  314. if (!$userinfo) {
  315. $this->error(__('操作失败'));
  316. }
  317. //判断是否需要绑定
  318. $userinfo['apptype'] = 'native';
  319. $userinfo['platform'] = 'wechat';
  320. $third = [
  321. 'avatar' => $userinfo['userinfo']['avatar'],
  322. 'nickname' => $userinfo['userinfo']['nickname']
  323. ];
  324. $user = null;
  325. if ($this->auth->isLogin() || Service::isBindThird($userinfo['platform'], $userinfo['openid'], $userinfo['apptype'], $userinfo['unionid'])) {
  326. Service::connect($userinfo['platform'], $userinfo);
  327. $user = $this->auth->getUserinfo();
  328. } else {
  329. Session::set('third-userinfo', $userinfo);
  330. }
  331. $this->success('授权成功!', ['user' => $user, 'third' => $third]);
  332. }
  333. /**
  334. * 获取Openid(仅用于微信小程序)
  335. */
  336. public function getWechatOpenid()
  337. {
  338. $code = $this->request->post("logincode");
  339. $json = (new \addons\shop\library\Wechat\Service())->getWechatSession($code);
  340. $this->success('获取成功!', ['openid' => $json['openid'] ?? '']);
  341. }
  342. }