Login.php 12 KB

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