- 按 docs/renew-code-comment.md 将 PHP 文件头改为带边框的 Author 注释\n- 注释中的 crmeb.com 替换为 uj345.cn(代码字符串中的外链未改)\n- 新增 docs/renew-code-comment.md 说明 Made-with: Cursor
520 lines
17 KiB
PHP
520 lines
17 KiB
PHP
<?php
|
|
// +----------------------------------------------------------------------
|
|
// | Author: ScottPan Team
|
|
// +----------------------------------------------------------------------
|
|
|
|
namespace app\controller\api\v1;
|
|
|
|
|
|
use app\Request;
|
|
use app\services\wechat\WechatServices as WechatAuthServices;
|
|
use Psr\SimpleCache\InvalidArgumentException;
|
|
use think\annotation\Inject;
|
|
use think\db\exception\DataNotFoundException;
|
|
use think\db\exception\DbException;
|
|
use think\db\exception\ModelNotFoundException;
|
|
use think\facade\Config;
|
|
use crmeb\services\CacheService;
|
|
use app\services\user\LoginServices;
|
|
use think\exception\ValidateException;
|
|
use app\validate\api\user\RegisterValidates;
|
|
use think\Response;
|
|
|
|
/**
|
|
* 登录
|
|
* Class Login
|
|
* @package app\api\controller
|
|
*/
|
|
class Login
|
|
{
|
|
|
|
/**
|
|
* @var LoginServices
|
|
*/
|
|
#[Inject]
|
|
protected LoginServices $services;
|
|
|
|
/**
|
|
* H5账号登陆
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
* @throws DbException
|
|
*/
|
|
public function login(Request $request)
|
|
{
|
|
[$account, $password, $spread_spid] = $request->postMore([
|
|
'account', 'password', 'spread_spid'
|
|
], true);
|
|
if (!$account || !$password) {
|
|
return app('json')->fail('请输入账号和密码');
|
|
}
|
|
validate(\app\validate\api\LoginValidate::class)->check(['account' => $account, 'pwd' => $password]);
|
|
|
|
return app('json')->success('登录成功', $this->services->login($account, $password, $spread_spid));
|
|
}
|
|
|
|
/**
|
|
* apple快捷登陆
|
|
* @param Request $request
|
|
* @param WechatAuthServices $services
|
|
* @return mixed
|
|
* @throws InvalidArgumentException
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function appleLogin(Request $request, WechatAuthServices $services)
|
|
{
|
|
[$openId, $phone, $email, $captcha] = $request->postMore([
|
|
['openId', ''],
|
|
['phone', ''],
|
|
['email', ''],
|
|
['captcha', '']
|
|
], true);
|
|
if ($phone) {
|
|
if (!$captcha) {
|
|
return app('json')->fail('请输入验证码');
|
|
}
|
|
//验证验证码
|
|
$verifyCode = CacheService::get('code_' . $phone);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->fail('验证码错误');
|
|
}
|
|
} else {
|
|
if (!$openId) {
|
|
return app('json')->fail('参数错误');
|
|
}
|
|
}
|
|
$userInfo = [
|
|
'openId' => $openId,
|
|
'unionid' => '',
|
|
'avatarUrl' => sys_config('h5_avatar'),
|
|
'nickName' => $email
|
|
];
|
|
if (!$userInfo['nickName']) {
|
|
mt_srand();
|
|
$userInfo['nickname'] = 'wx' . rand(100000, 999999);
|
|
}
|
|
$token = $services->appAuth($userInfo, $phone, 'apple');
|
|
if ($token) {
|
|
return app('json')->success('登录成功', $token);
|
|
} else if ($token === false) {
|
|
return app('json')->success('请绑定手机号', ['isbind' => true]);
|
|
} else {
|
|
return app('json')->fail('登陆失败');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* 退出登录
|
|
* @param Request $request
|
|
*/
|
|
public function logout(Request $request)
|
|
{
|
|
$key = trim(ltrim($request->header(Config::get('cookie.token_name')), 'Bearer'));
|
|
CacheService::redisHandler()->delete(md5($key));
|
|
return app('json')->success('成功');
|
|
}
|
|
|
|
public function verifyCode()
|
|
{
|
|
$unique = password_hash(uniqid(true), PASSWORD_BCRYPT);
|
|
CacheService::set('sms.key.' . $unique, 0, 300);
|
|
$time = sys_config('verify_expire_time', 1);
|
|
return app('json')->success(['key' => $unique, 'expire_time' => $time]);
|
|
}
|
|
|
|
public function captcha(Request $request)
|
|
{
|
|
ob_clean();
|
|
$rep = captcha();
|
|
$key = app('session')->get('captcha.key');
|
|
$uni = $request->get('key');
|
|
if ($uni)
|
|
CacheService::set('sms.key.cap.' . $uni, $key, 300);
|
|
|
|
return $rep;
|
|
}
|
|
|
|
/**
|
|
* 验证验证码是否正确
|
|
*
|
|
* @param $uni
|
|
* @param string $code
|
|
* @return bool
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
protected function checkCaptcha($uni, string $code): bool
|
|
{
|
|
$cacheName = 'sms.key.cap.' . $uni;
|
|
if (!CacheService::has($cacheName)) {
|
|
return false;
|
|
}
|
|
|
|
$key = CacheService::get($cacheName);
|
|
|
|
$code = mb_strtolower($code, 'UTF-8');
|
|
|
|
$res = password_verify($code, $key);
|
|
|
|
if ($res) {
|
|
CaCacheServiceche::delete($cacheName);
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* @return mixed
|
|
*/
|
|
public function ajcaptcha(Request $request)
|
|
{
|
|
$captchaType = $request->get('captchaType');
|
|
return app('json')->success(aj_captcha_create($captchaType));
|
|
}
|
|
|
|
/**
|
|
* 一次验证
|
|
* @return mixed
|
|
*/
|
|
public function ajcheck(Request $request)
|
|
{
|
|
[$token, $pointJson, $captchaType] = $request->postMore([
|
|
['token', ''],
|
|
['pointJson', ''],
|
|
['captchaType', ''],
|
|
], true);
|
|
try {
|
|
aj_captcha_check_one($captchaType, $token, $pointJson);
|
|
return app('json')->success();
|
|
} catch (\Throwable $e) {
|
|
return app('json')->fail(400336);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 验证码发送
|
|
* @param Request $request
|
|
* @return mixed
|
|
*/
|
|
public function verify(Request $request)
|
|
{
|
|
[$phone, $type, $key, $captchaType, $captchaVerification] = $request->postMore([
|
|
['phone', 0],
|
|
['type', ''],
|
|
['key', ''],
|
|
['captchaType', ''],
|
|
['captchaVerification', ''],
|
|
], true);
|
|
|
|
$keyName = 'sms.key.' . $key;
|
|
$nowKey = 'sms.' . date('YmdHi');
|
|
|
|
if (!CacheService::has($keyName))
|
|
return app('json')->make(401, '发送验证码失败,请刷新页面重新获取');
|
|
|
|
|
|
$total = 1;
|
|
if (CacheService::has($nowKey)) {
|
|
$total = CacheService::get($nowKey);
|
|
if ($total > Config::get('sms.maxMinuteCount', 20))
|
|
return app('json')->success('已发送');
|
|
}
|
|
|
|
//二次验证
|
|
// try {
|
|
// aj_captcha_check_two($captchaType, $captchaVerification);
|
|
// } catch (\Throwable $e) {
|
|
// return app('json')->fail($e->getError());
|
|
// }
|
|
|
|
try {
|
|
validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
$time = sys_config('verify_expire_time', 1);
|
|
$smsCode = $this->services->verify($phone, $type, $time, app()->request->ip());
|
|
if ($smsCode) {
|
|
CacheService::set('code_' . $phone, $smsCode, $time * 60);
|
|
CacheService::set($nowKey, $total, 61);
|
|
event('sms.sendAfter', [$smsCode, $phone]);
|
|
return app('json')->success('发送成功');
|
|
} else {
|
|
return app('json')->fail('发送失败');
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* H5注册新用户
|
|
* @param Request $request
|
|
* @return mixed
|
|
*/
|
|
public function register(Request $request)
|
|
{
|
|
[$account, $captcha, $password, $spread_spid] = $request->postMore([['account', ''], ['captcha', ''], ['password', ''], ['spread_spid', 0]], true);
|
|
try {
|
|
validate(RegisterValidates::class)->scene('register')->check(['account' => $account, 'captcha' => $captcha, 'password' => $password]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
$verifyCode = CacheService::get('code_' . $account);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha)
|
|
return app('json')->fail('验证码错误');
|
|
if (strlen(trim($password)) < 6 || strlen(trim($password)) > 16)
|
|
return app('json')->fail('密码必须是在6到16位之间');
|
|
if ($password == '123456') return app('json')->fail('密码太过简单,请输入较为复杂的密码');
|
|
$user_type = $request->getFromType() ? $request->getFromType() : 'h5';
|
|
$registerStatus = $this->services->register($account, $password, $spread_spid, $user_type);
|
|
if ($registerStatus) {
|
|
return app('json')->success('注册成功');
|
|
}
|
|
return app('json')->fail('注册失败');
|
|
}
|
|
|
|
/**
|
|
* 密码修改
|
|
* @param Request $request
|
|
* @return mixed
|
|
*/
|
|
public function reset(Request $request)
|
|
{
|
|
[$account, $captcha, $password] = $request->postMore([['account', ''], ['captcha', ''], ['password', '']], true);
|
|
try {
|
|
validate(RegisterValidates::class)->scene('register')->check(['account' => $account, 'captcha' => $captcha, 'password' => $password]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
$verifyCode = CacheService::get('code_' . $account);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha) {
|
|
return app('json')->fail('验证码错误');
|
|
}
|
|
if (strlen(trim($password)) < 6 || strlen(trim($password)) > 16)
|
|
return app('json')->fail('密码必须是在6到16位之间');
|
|
if ($password == '123456') return app('json')->fail('密码太过简单,请输入较为复杂的密码');
|
|
$resetStatus = $this->services->reset($account, $password);
|
|
if ($resetStatus) return app('json')->success('修改成功');
|
|
return app('json')->fail('修改失败');
|
|
}
|
|
|
|
/**
|
|
* 手机号登录
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
* @throws \think\exception\DbException
|
|
*/
|
|
public function mobile(Request $request)
|
|
{
|
|
[$phone, $captcha, $spread_spid] = $request->postMore([['phone', ''], ['captcha', ''], ['spread_spid', 0]], true);
|
|
|
|
//验证手机号
|
|
try {
|
|
validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
|
|
//验证验证码
|
|
$verifyCode = CacheService::get('code_' . $phone);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha) {
|
|
return app('json')->fail('验证码错误');
|
|
}
|
|
$user_type = $request->getFromType() ? $request->getFromType() : 'h5';
|
|
$token = $this->services->mobile($phone, $spread_spid, $user_type);
|
|
if ($token) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->success('登录成功', $token);
|
|
} else {
|
|
return app('json')->fail('登录失败');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* H5切换登陆
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
* @throws \think\exception\DbException
|
|
*/
|
|
public function switch_h5(Request $request)
|
|
{
|
|
$from = $request->post('from', 'wechat');
|
|
$user = $request->user();
|
|
$token = $this->services->switchAccount($user, $from);
|
|
if ($token) {
|
|
$token['userInfo'] = $user;
|
|
return app('json')->success('登录成功', $token);
|
|
} else
|
|
return app('json')->fail('登录失败');
|
|
}
|
|
|
|
/**
|
|
* 绑定手机号
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
* @throws \think\exception\DbException
|
|
*/
|
|
public function binding_phone(Request $request)
|
|
{
|
|
[$phone, $captcha, $key] = $request->postMore([
|
|
['phone', ''],
|
|
['captcha', ''],
|
|
['key', '']
|
|
], true);
|
|
//验证手机号
|
|
try {
|
|
validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
if (!$key) {
|
|
return app('json')->fail('参数错误');
|
|
}
|
|
if (!$phone) {
|
|
return app('json')->fail('请输入手机号');
|
|
}
|
|
//验证验证码
|
|
$verifyCode = CacheService::get('code_' . $phone);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->fail('验证码错误');
|
|
}
|
|
$re = $this->services->bindind_phone($phone, $key);
|
|
if ($re) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->success('绑定成功', $re);
|
|
} else
|
|
return app('json')->fail('绑定失败');
|
|
}
|
|
|
|
/**
|
|
* 绑定手机号
|
|
* @param Request $request
|
|
* @return mixed
|
|
* @throws DataNotFoundException
|
|
* @throws ModelNotFoundException
|
|
* @throws \think\exception\DbException
|
|
*/
|
|
public function user_binding_phone(Request $request)
|
|
{
|
|
[$phone, $captcha, $step] = $request->postMore([
|
|
['phone', ''],
|
|
['captcha', ''],
|
|
['step', 0]
|
|
], true);
|
|
|
|
//验证手机号
|
|
try {
|
|
validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
if (!$step) {
|
|
//验证验证码
|
|
$verifyCode = CacheService::get('code_' . $phone);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha)
|
|
return app('json')->fail('验证码错误');
|
|
}
|
|
$uid = (int)$request->uid();
|
|
$re = $this->services->userBindindPhone($uid, $phone, $step);
|
|
if ($re) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->success($re['msg'] ?? '绑定成功', $re['data'] ?? []);
|
|
} else
|
|
return app('json')->fail('绑定失败');
|
|
}
|
|
|
|
public function update_binding_phone(Request $request)
|
|
{
|
|
[$phone, $captcha] = $request->postMore([
|
|
['phone', ''],
|
|
['captcha', ''],
|
|
], true);
|
|
|
|
//验证手机号
|
|
try {
|
|
validate(RegisterValidates::class)->scene('code')->check(['phone' => $phone]);
|
|
} catch (ValidateException $e) {
|
|
return app('json')->fail($e->getError());
|
|
}
|
|
//验证验证码
|
|
$verifyCode = CacheService::get('code_' . $phone);
|
|
if (!$verifyCode)
|
|
return app('json')->fail('请先获取验证码');
|
|
$verifyCode = substr($verifyCode, 0, 6);
|
|
if ($verifyCode != $captcha)
|
|
return app('json')->fail('验证码错误');
|
|
$uid = (int)$request->uid();
|
|
$re = $this->services->updateBindindPhone($uid, $phone);
|
|
if ($re) {
|
|
CacheService::delete('code_' . $phone);
|
|
return app('json')->success($re['msg'] ?? '修改成功', $re['data'] ?? []);
|
|
} else
|
|
return app('json')->fail('修改失败');
|
|
}
|
|
|
|
/**
|
|
* 设置扫描二维码状态
|
|
* @param string $code
|
|
* @return mixed
|
|
*/
|
|
public function setLoginKey(string $code)
|
|
{
|
|
if (!$code) {
|
|
return app('json')->fail('登录CODE不存在');
|
|
}
|
|
$cacheCode = CacheService::get($code);
|
|
if ($cacheCode === false || $cacheCode === null) {
|
|
return app('json')->fail('二维码已过期请重新扫描');
|
|
}
|
|
CacheService::set($code, '0', 600);
|
|
return app('json')->success();
|
|
}
|
|
|
|
/**
|
|
* 远程登录接口
|
|
* @param Request $request
|
|
* @return Response
|
|
* User: liusl
|
|
* DateTime: 2024/10/26 14:48
|
|
* @throws DataNotFoundException
|
|
* @throws DbException
|
|
* @throws ModelNotFoundException
|
|
*/
|
|
public function remoteRegister(Request $request)
|
|
{
|
|
[$remote_token] = $request->getMore([
|
|
['remote_token', ''],
|
|
], true);
|
|
if ($remote_token == '') return app('json')->success('登录失败', ['get_remote_login_url' => sys_config('get_remote_login_url')]);
|
|
return app('json')->success('登录成功', $this->services->remoteRegister($remote_token));
|
|
}
|
|
}
|