You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
7.7 KiB
256 lines
7.7 KiB
<?php
|
|
declare (strict_types = 1);
|
|
|
|
namespace app\service\user;
|
|
|
|
|
|
use app\model\WechatUser;
|
|
use app\service\BaseService;
|
|
use fast\Http;
|
|
use think\facade\Cookie;
|
|
use think\facade\Session;
|
|
|
|
class LoginService extends BaseService
|
|
{
|
|
|
|
/**
|
|
* 判断登录状态
|
|
* @return bool
|
|
*/
|
|
public function isLogin()
|
|
{
|
|
if (!$this->user) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* 登录凭证校验
|
|
* @param $code
|
|
* @param $iv
|
|
* @param $encryptedData
|
|
* @return array
|
|
* @throws \fast\FuncException
|
|
*/
|
|
public function code2session($code, $iv, $encryptedData)
|
|
{
|
|
|
|
$http = new Http();
|
|
$url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . env("app.appid") . "&secret=" . env("app.appsecret") . "&js_code={$code}&grant_type=authorization_code";
|
|
$res = $http::get($url);
|
|
if ($res['code'] != 200) {
|
|
throw new \fast\FuncException($res['msg']);
|
|
}
|
|
$res['data'] = json_decode($res['data'], true);
|
|
if (isset($res['data']['errcode'])) {
|
|
throw new \fast\FuncException($res['data']['errmsg']);
|
|
}
|
|
session('app_openid', $res['data']['openid']);
|
|
session('app_session_key', $res['data']['session_key']);
|
|
$res['userInfo'] = json_decode($this->decodeWechatIv($iv, $encryptedData), true);
|
|
|
|
$result = [];
|
|
$result['openid'] = $res['data']['openid'];
|
|
if (isset($res['data']['unionid'])) $result['unionid'] = $res['data']['unionid'];
|
|
$result['phone'] = $res['userInfo']['phoneNumber'];
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* 解密微信的iv和encryptedData
|
|
* @param $iv
|
|
* @param $encryptedData
|
|
* @return false|string
|
|
* @throws \fast\FuncException
|
|
*/
|
|
public function decodeWechatIv($iv, $encryptedData)
|
|
{
|
|
$openid = session('app_openid');
|
|
$session_key = session('app_session_key');
|
|
if (!$openid || !$session_key) {
|
|
throw new \fast\FuncException('缺少主要参数');
|
|
}
|
|
if (strlen($session_key) != 24) {
|
|
throw new \fast\FuncException('sessionkey长度错误');
|
|
}
|
|
if (strlen($iv) != 24) {
|
|
throw new \fast\FuncException('iv长度错误');
|
|
}
|
|
$aesKey = base64_decode($session_key);
|
|
$aesIV = base64_decode($iv);
|
|
$aesCipher = base64_decode($encryptedData);
|
|
$result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
|
|
$dataObj = json_decode($result);
|
|
if ($dataObj == NULL) {
|
|
throw new \fast\FuncException('登录失败,请稍候再试');
|
|
}
|
|
if ($dataObj->watermark->appid != env("app.appid")) {
|
|
throw new \fast\FuncException('小程序appid不一致,登录失败');
|
|
}
|
|
return $result;
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 用户端登录
|
|
* @param $phone
|
|
* @param $openid
|
|
* @param $unionid
|
|
* @return WechatUser|mixed
|
|
* @throws \fast\FuncException
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function userLogin($phone, $openid, $unionid)
|
|
{
|
|
$field = 'id,openid,phone,nickname,sex,headimgurl';
|
|
$user = WechatUser::where('phone', $phone)->where('delete_time', 0)->field($field)->find();
|
|
if ($openid != $user->openid) {
|
|
WechatUser::where('id', $user->id)->save(['openid' => $user->openid]);
|
|
}
|
|
if ($user) {
|
|
return $this->userSuccess($user);
|
|
}
|
|
return $this->register($phone, $openid, $unionid);
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param $phone
|
|
* @return WechatUser|array|mixed
|
|
* @throws \fast\FuncException
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function userPhoneLogin($phone)
|
|
{
|
|
$field = 'id,openid,phone,nickname,sex,headimgurl';
|
|
$user = WechatUser::where('phone', $phone)->where('delete_time', 0)->field($field)->find();
|
|
if ($user) {
|
|
return $this->userSuccess($user);
|
|
}
|
|
return $this->register($phone);
|
|
}
|
|
|
|
/**
|
|
* 用户登录成功
|
|
* @param WechatUser $user
|
|
* @return array
|
|
*/
|
|
public function userSuccess(WechatUser $user)
|
|
{
|
|
session('user', $user->toArray());
|
|
$this->userKeeplogin($user->id,$user->openid,3600 * 24 * 7);
|
|
// $user->visible(['id', 'name', 'logo']);
|
|
return $user->toArray();
|
|
}
|
|
|
|
/**
|
|
* 保持登录
|
|
* @param $user_id
|
|
* @param $token
|
|
* @param $keeptime
|
|
* @return bool
|
|
*/
|
|
protected function userKeeplogin($user_id, $token, $keeptime = 0)
|
|
{
|
|
if ($keeptime) {
|
|
$expiretime = time() + $keeptime;
|
|
|
|
$key = md5(md5(strval($user_id)) . md5(strval($keeptime)) . md5(strval($expiretime)) . $token);
|
|
error_reporting(E_ALL);
|
|
ini_set('display_errors', '1');
|
|
$data = [$user_id, $keeptime, $expiretime, $key];
|
|
|
|
Cookie::set('userKeeplogin', implode('|', $data), 86400 * 30);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* 用户端注册
|
|
* @param $phone
|
|
* @param string $openid
|
|
* @param string $unionid
|
|
* @return WechatUser|mixed
|
|
* @throws \fast\FuncException
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function register($phone, string $openid = '', string $unionid = '')
|
|
{
|
|
|
|
$add = [
|
|
'phone' => $phone,
|
|
'openid' => $openid,
|
|
'nickname' => '微信用户',
|
|
'unionid' => $unionid ?? '',
|
|
];
|
|
$id = (new WechatUser())->insertGetId($add);
|
|
|
|
if (!$id) {
|
|
throw new \fast\FuncException('注册失败,请稍候再试');
|
|
}
|
|
$user = WechatUser::where('id', $id)->find();
|
|
return $this->userSuccess($user);
|
|
|
|
}
|
|
|
|
/**
|
|
* 自动登录
|
|
* @return WechatUser|array|false|mixed|\think\Model
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function userAutologin() {
|
|
$keeplogin = Cookie::get('userKeeplogin');
|
|
if (!$keeplogin) {
|
|
return false;
|
|
}
|
|
[$id, $keeptime, $expiretime, $key] = explode('|', $keeplogin);
|
|
if ($id && $keeptime && $expiretime && $key && $expiretime > time()) {
|
|
$user = WechatUser::where('id', $id)->find();
|
|
if (!$user || !$user->token) {
|
|
return false;
|
|
}
|
|
unset($user->password);
|
|
//token有变更
|
|
if ($key != md5(md5($id) . md5($keeptime) . md5($expiretime) . $user->token)) {
|
|
return false;
|
|
}
|
|
Session::set('user', $user->toArray());
|
|
//刷新自动登录的时效
|
|
$this->userKeeplogin($id,$user->token,$keeptime);
|
|
return $user;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 登出
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\DbException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
*/
|
|
public function userLogout() {
|
|
$user = WechatUser::find($this->user_id);
|
|
if ($user) {
|
|
$user->token = '';
|
|
$user->save();
|
|
}
|
|
Session::delete('user');
|
|
Cookie::delete('userKeeplogin');
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|