Login.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Models\Api\Personnel\Employee as EmployeeModel;
  4. use App\Http\Requests\Api\Login as Request;
  5. use App\Facades\Servers\Sms\VerifyCode as Sms;
  6. use Illuminate\Support\Facades\Cache;
  7. use App\Facades\Servers\Wechat\Mini;
  8. use App\Models\Api\Personnel\EmployeeOpenid as EmployeeOpenidModel;
  9. use Illuminate\Support\Facades\DB;
  10. /**
  11. * API登录控制器
  12. * @author 唐远望
  13. * @version 1.0
  14. * @date 2025-12-09
  15. *
  16. */
  17. class Login extends Api
  18. {
  19. /**
  20. * 登录方法 /manager/login/index
  21. * @author 唐远望
  22. * @version 1.0
  23. * @date 2025-12-09
  24. * @param string employee_code 登录账号
  25. * @param string password 登录密码
  26. *
  27. * */
  28. public function index(Request $Request, EmployeeModel $EmployeeModel)
  29. {
  30. // 验证规则
  31. $Request->scene('login')->validate();
  32. // 接收数据
  33. $employee_code = $Request->input('employee_code', '');
  34. // 接收数据
  35. $password = $Request->input('password', '');
  36. // 查询用户
  37. $admin = $EmployeeModel->Where('employee_code', $employee_code)->first(['company_id', 'id', 'name', 'mobile', 'status', 'password', 'insert_time', 'update_time']);
  38. // 用户不存在
  39. if (!$admin || $admin['status']) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  40. // 用户不存在
  41. if ($admin['status']) return json_send(['code' => 'error', 'msg' => '该账号已停用']);
  42. // 转数组
  43. $admin = $admin->toArray();
  44. // 比对密码
  45. if (md5($password) != $admin['password']) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  46. // 登录
  47. $accessToken = $EmployeeModel->Login($admin['id'], $admin['company_id'], 'api');
  48. if (isset($accessToken['error'])) return json_send(['code' => 'error', 'msg' => '登录失败', 'data' => $accessToken['data']]);
  49. $accessToken['username'] = $admin['name'];
  50. $accessToken['is_system_admin'] = 0;
  51. // 表单令牌
  52. return json_send(['code' => 'success', 'msg' => '登录成功', 'data' => $accessToken]);
  53. }
  54. /**
  55. * 退出方法 /manager/login/out
  56. * @author 唐远望
  57. * @version 1.0
  58. * @date 2025-12-09
  59. * @param string authcode 用户令牌
  60. *
  61. */
  62. public function out(EmployeeModel $EmployeeModel)
  63. {
  64. $user_info = $this->checkLogin();
  65. // 验证规则
  66. $uid = $user_info['uid'];
  67. // 退出登录
  68. $EmployeeModel->LoginOut($uid, 'api');
  69. // 表单令牌
  70. return json_send(['code' => 'success', 'msg' => '退出成功', 'data' => '']);
  71. }
  72. /**
  73. * 手机号码登录 /manager/login/mobile
  74. * @author 唐远望
  75. * @version 1.0
  76. * @date 2025-12-04
  77. * @param string mobile 手机号码
  78. * @param string password 登录密码
  79. *
  80. */
  81. public function mobile(Request $Request, EmployeeModel $EmployeeModel)
  82. {
  83. // 验证规则
  84. $Request->scene('mobile')->validate();
  85. // 接收数据
  86. $phone = $Request->input('phone', '');
  87. // 接收数据
  88. $password = $Request->input('password', '');
  89. // 查询用户
  90. $user_info = $EmployeeModel->where('mobile', $phone)->first(['company_id', 'id', 'name', 'mobile', 'status', 'password', 'insert_time', 'update_time']);
  91. // 用户不存在
  92. if (!$user_info || $user_info['status']) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  93. // 用户不存在
  94. if ($user_info['status']) return json_send(['code' => 'error', 'msg' => '该账号已停用']);
  95. // 转数组
  96. $user_info = $user_info->toArray();
  97. // 比对密码
  98. if (md5($password) != $user_info['password']) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  99. // 登录
  100. $accessToken = $EmployeeModel->Login($user_info['id'], $user_info['company_id'], 'api');
  101. if (isset($accessToken['error'])) return json_send(['code' => 'error', 'msg' => '登录失败', 'data' => $accessToken['data']]);
  102. $accessToken['username'] = $user_info['name'];
  103. $accessToken['is_system_admin'] = 0;
  104. // 表单令牌
  105. return json_send(['code' => 'success', 'msg' => '登录成功', 'data' => $accessToken]);
  106. }
  107. /**
  108. * 发送验证码
  109. * @author 唐远望
  110. * @version 1.0
  111. * @date 2026-01-16
  112. * @param string phone 手机号码
  113. *
  114. */
  115. public function send_code(Request $Request, EmployeeModel $EmployeeModel)
  116. {
  117. // 验证规则
  118. $Request->scene('send_code')->validate();
  119. // 接收数据
  120. $mobile = request('phone', '');
  121. if (!$mobile) return json_send(['code' => 'error', 'msg' => '请先填写手机号']);
  122. // 获取数据
  123. $session = Cache::get('loginSmsCode_' . $mobile);
  124. // 如果有数据,并且验证码创建的时间在一分钟之内
  125. if ($session && time() - $session['create_time'] < 60) return json_send(['code' => 'error', 'msg' => '请稍后再试']);
  126. // 查询用户
  127. $admin = $EmployeeModel->query()->where('mobile', $mobile)->first(['status']);
  128. if ($admin && $admin['status']) return json_send(['code' => 'error', 'msg' => '用户已被停用']);
  129. $code = strval(rand(100000, 999999));
  130. $result = Sms::sendCode($mobile, $code);
  131. if (isset($result['error'])) return json_send(['code' => 'error', 'msg' => $result['error']]);
  132. $session = ['code' => $code, 'mobile' => $mobile, 'create_time' => time()];
  133. Cache::put('loginSmsCode_' . $mobile, $session, 120);
  134. return json_send(['code' => 'success', 'msg' => '发送成功', 'data' => '']);
  135. }
  136. /**
  137. * 邮箱登录 /manager/login/email
  138. * @author 唐远望
  139. * @version 1.0
  140. * @date 2026-01-16
  141. * @param string email 邮箱号码
  142. * @param string password 登录密码
  143. *
  144. */
  145. public function email(Request $Request, EmployeeModel $EmployeeModel)
  146. {
  147. // 验证规则
  148. $Request->scene('email')->validate();
  149. // 接收数据
  150. $email = $Request->input('email', '');
  151. // 接收数据
  152. $password = $Request->input('password', '');
  153. // 查询用户
  154. $admin = $EmployeeModel->where('email', $email)->first(['company_id', 'id', 'name', 'mobile', 'status', 'password', 'insert_time', 'update_time']);
  155. // 用户不存在
  156. if (!$admin) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  157. // 用户不存在
  158. if ($admin['status']) return json_send(['code' => 'error', 'msg' => '该账号已停用']);
  159. // 转数组
  160. $admin = $admin->toArray();
  161. // 比对密码
  162. if (md5($password) != $admin['password']) return json_send(['code' => 'error', 'msg' => '密码错误或账号不存在']);
  163. // 登录
  164. $accessToken = $EmployeeModel->Login($admin['id'], $admin['company_id'], 'api');
  165. if (isset($accessToken['error'])) return json_send(['code' => 'error', 'msg' => '登录失败', 'data' => $accessToken['data']]);
  166. $accessToken['username'] = $admin['name'];
  167. $accessToken['is_system_admin'] = 0;
  168. // 表单令牌
  169. return json_send(['code' => 'success', 'msg' => '登录成功', 'data' => $accessToken]);
  170. }
  171. /**
  172. * 手机验证码登录 /manager/login/mobile_code
  173. * @author 唐远望
  174. * @version 1.0
  175. * @date 2026-01-16
  176. * @param string mobile 手机号码
  177. * @param string code 验证码
  178. *
  179. */
  180. public function mobile_code(Request $Request, EmployeeModel $EmployeeModel)
  181. {
  182. // 验证规则
  183. $Request->scene('mobile_code')->validate();
  184. // 接收数据
  185. $phone = $Request->input('phone', '');
  186. // 接收数据
  187. $code = $Request->input('code', '');
  188. // 获取数据
  189. $session = Cache::get('loginSmsCode_' . $phone);
  190. if (!$session) return json_send(['code' => 'error', 'msg' => '请先获取手机号验证码']);
  191. if ($session['code'] != $code || $session['mobile'] != $phone) return json_send(['code' => 'error', 'msg' => '验证码错误']);
  192. // 查询用户
  193. $admin = $EmployeeModel->where('mobile', $phone)->first(['company_id', 'id', 'name', 'mobile', 'status', 'password', 'insert_time', 'update_time']);
  194. // 用户不存在
  195. if (!$admin) return json_send(['code' => 'error', 'msg' => '账号不存在']);
  196. // 用户不存在
  197. if ($admin['status']) return json_send(['code' => 'error', 'msg' => '该账号已停用']);
  198. // 转数组
  199. $admin = $admin->toArray();
  200. // 登录
  201. $accessToken = $EmployeeModel->Login($admin['id'], $admin['company_id'], 'api');
  202. if (isset($accessToken['error'])) return json_send(['code' => 'error', 'msg' => '登录失败', 'data' => $accessToken['data']]);
  203. $accessToken['username'] = $admin['name'];
  204. $accessToken['is_system_admin'] = 0;
  205. // 表单令牌
  206. return json_send(['code' => 'success', 'msg' => '登录成功', 'data' => $accessToken]);
  207. }
  208. /**
  209. * 小程序手机号授权
  210. * @author 唐远望
  211. * @version 1.0
  212. * @date 2026-03-10
  213. * @param string auth_code 授权code
  214. * @param string open_code 开放平台code
  215. *
  216. */
  217. public function wechat_phone(Request $Request, EmployeeModel $EmployeeModel, EmployeeOpenidModel $EmployeeOpenidModel)
  218. {
  219. // 验证规则
  220. $Request->scene('wechat_phone')->validate();
  221. // 接收数据
  222. $auth_code = request('auth_code', '');
  223. $open_code = $Request->input('open_code', '');
  224. $appId = config('wechat.mini.app_id', ''); //小程序APPID
  225. // 授权结果
  226. $result = Mini::getUserPhone($auth_code, $appId);
  227. // 如果所需字段不存在
  228. if (isset($result['error'])) return json_send(['code' => 'error', 'msg' => '授权失败', 'data' => ['error' => $result['error']]]);
  229. // 如果所需字段不存在
  230. if (empty($result['purePhoneNumber'])) return json_send(['code' => 'error', 'msg' => '未获取到手机号', 'data' => ['error' => '未获取到手机号']]);
  231. $phone = $result['purePhoneNumber'];
  232. // 查询用户
  233. $phone_user_data = $EmployeeModel->where(['mobile' => $phone])->first(['company_id', 'id as uid', 'name as username', 'mobile as phone', 'status', 'password', 'insert_time', 'update_time']);
  234. if (!$phone_user_data) return json_send(['code' => 'error', 'msg' => '手机号码未授权']);
  235. if ($phone_user_data['status']) return json_send(['code' => 'error', 'msg' => '该账号已停用']);
  236. $company_id = $phone_user_data->company_id;
  237. $uid = $phone_user_data->uid;
  238. //获取用户的openid
  239. $tokenData = Mini::jscode2session($open_code, $appId);
  240. if (!isset($tokenData['openid']) || !$tokenData['openid']) return json_send(['code' => 'error', 'msg' => '获取openid失败', 'data' => $tokenData]);
  241. if (!isset($tokenData['unionid']) || !$tokenData['unionid']) return json_send(['code' => 'error', 'msg' => '获取unionid失败', 'data' => $tokenData]);
  242. $user_open_data = $EmployeeOpenidModel->where(['mini_openid' => $tokenData['openid']])->first();
  243. if (!$user_open_data) {
  244. //自动绑定手机号码用户
  245. try {
  246. $phone_user_data->band_wechat = 1; //绑定微信0=未绑定1=已绑定
  247. $phone_user_data->save();
  248. $unionid = $tokenData['unionid'] ?? '';
  249. $official_user_info = $EmployeeOpenidModel->where(['unionid' => $unionid])->first();
  250. if ($official_user_info) {
  251. $official_user_info->employee_id = $uid;
  252. $official_user_info->mini_openid = $tokenData['openid'];
  253. $official_user_info->update_time = time();
  254. $official_user_info->save();
  255. } else {
  256. $EmployeeOpenidModel->insertGetId([
  257. 'company_id' => $company_id,
  258. 'employee_id' => $uid,
  259. 'unionid' => $tokenData['unionid'] ?? '',
  260. 'mini_openid' => $tokenData['openid'],
  261. 'insert_time' => time()
  262. ]);
  263. }
  264. DB::commit();
  265. } catch (\Exception $e) {
  266. DB::rollBack();
  267. return json_send(['code' => 'error', 'msg' => '绑定失败', 'data' => $e->getMessage()]);
  268. }
  269. } else {
  270. $user_open_data->unionid = $tokenData['unionid'] ?? '';
  271. $user_open_data->mini_openid = $tokenData['openid'];
  272. $user_open_data->update_time = time();
  273. $user_open_data->save();
  274. }
  275. // 转数组
  276. $admin = $phone_user_data->toArray();
  277. // 登录
  278. $accessToken = $EmployeeModel->Login($admin['uid'], $admin['company_id'], 'api');
  279. if (isset($accessToken['error'])) return json_send(['code' => 'error', 'msg' => '登录失败', 'data' => $accessToken['data']]);
  280. $accessToken['username'] = $admin['username'];
  281. $accessToken['is_system_admin'] = 0;
  282. // 表单令牌
  283. return json_send(['code' => 'success', 'msg' => '登录成功', 'data' => $accessToken]);
  284. }
  285. }