diff --git a/application/common/Model/Member.php b/application/common/Model/Member.php index 3e556b2..5dd0a92 100644 --- a/application/common/Model/Member.php +++ b/application/common/Model/Member.php @@ -2,6 +2,7 @@ namespace app\common\Model; +use PDOStatement; use service\JwtService; use service\NodeService; use service\RandomService; @@ -124,27 +125,60 @@ class Member extends CommonModel return $result; } + /** + * 钉钉登录 + * @param $userInfo + * @return Member|array|PDOStatement|string|\think\Model|null + * @throws \think\db\exception\DataNotFoundException + * @throws \think\db\exception\ModelNotFoundException + * @throws \think\exception\DbException + */ public static function dingtalkLogin($userInfo) { + $currentMember = getCurrentMember(); + $where = ['code' => $currentMember['code']]; + $currentMember = self::where($where)->find(); + $unionid = $userInfo['unionid']; $openid = $userInfo['openid']; $member = self::where(['dingtalk_unionid' => $unionid])->find(); + $memberData = [ + 'dingtalk_openid' => $openid, + 'dingtalk_unionid' => $unionid, + 'dingtalk_userid' => isset($userInfo['userId']) ? $userInfo['userId'] : '', + ]; if (!$member) { - $memberData = [ - 'dingtalk_openid' => $openid, - 'dingtalk_unionid' => $unionid, - 'name' => $userInfo['nick'], - 'dingtalk_userid' => isset($userInfo['userId']) ? $userInfo['userId'] : '', - 'avatar' => isset($userInfo['avatar']) ? $userInfo['avatar'] : '', - 'mobile' => isset($userInfo['mobile']) ? $userInfo['mobile'] : '', - 'email' => isset($userInfo['email']) ? $userInfo['email'] : '', - ]; - $member = self::createMember($memberData); + $memberData['name'] = $userInfo['nick']; + $memberData['avatar'] = isset($userInfo['avatar']) ? $userInfo['avatar'] : ''; + $memberData['mobile'] = isset($userInfo['mobile']) ? $userInfo['mobile'] : ''; + $memberData['email'] = isset($userInfo['email']) ? $userInfo['email'] : ''; + if (!$currentMember) { + $member = self::createMember($memberData); + } else { + //已登录 + $member = $currentMember; + //且未绑定,则绑定 + if (!$member['dingtalk_unionid']) { + self::update($memberData, $where); + } + } + } else { + if ($member['dingtalk_unionid'] != $currentMember['dingtalk_unionid']) { + return error('1', '您想要绑定的第三方帐号已经被绑定给其他帐号,请先用该第三方帐号登录后,解绑释放它,再切回当前帐号发起绑定'); + } } self::login($member); return $member; } + public static function logout() + { + !empty($_SESSION) && $_SESSION = []; + [session_unset(), session_destroy()]; + setCurrentMember(null); + session('loginInfo', null); + } + /** * @param File $file * @return array|bool diff --git a/application/index/controller/Oauth.php b/application/index/controller/Oauth.php index f6e3377..4352ba8 100644 --- a/application/index/controller/Oauth.php +++ b/application/index/controller/Oauth.php @@ -13,6 +13,9 @@ use app\common\Model\Member; use controller\BasicApi; use EasyDingTalk\Application; use Symfony\Component\HttpFoundation\RedirectResponse; +use think\db\exception\DataNotFoundException; +use think\db\exception\ModelNotFoundException; +use think\exception\DbException; use think\facade\Log; use think\facade\Request; use think\response\Redirect; @@ -24,20 +27,24 @@ class Oauth extends BasicApi { } + /** + * 获取钉钉登录授权 + * @return Redirect + */ public function dingTalkOauth() { + $redirectPath = Request::param('redirectPath', ''); + $bindDingtalk = Request::param('bindDingtalk', ''); $currentMember = getCurrentMember(); - if (!$currentMember) { + if (!$currentMember || $bindDingtalk) { $app = new Application(config('dingtalk.')); // $response = $app->oauth->use('app-01')->redirect(); $response = $app->oauth->use('app-01')->withQrConnect()->redirect(); $redirect = $response->getTargetUrl(); - if ($redirect) { - if ($redirect == 'undefined') { - $redirect = '/'; - } - $_SESSION['target_url'] = $redirect; + if ($redirectPath) { + session('redirectPath', $redirectPath); } + $redirectPath && $redirect .= '&$redirectPath=' . $redirectPath; return redirect($redirect); } else { //已登录跳转 @@ -45,10 +52,47 @@ class Oauth extends BasicApi } } + /** + * 钉钉应用内免密登录 + * @throws DataNotFoundException + * @throws ModelNotFoundException + * @throws DbException + */ + public function dingTalkLoginByCode() + { + $code = Request::param('code'); + logRecord($code); + $app = new Application(config('dingtalk.')); + $result = $app->user->getUserByCode($code); + logRecord($result); + if (!$result['errcode']) { + $userId = $result['userid']; + $user = $app->user->get($userId, $lang = null); + logRecord($user); + if (!$user['errcode']) { + $userInfo = [ + 'unionid' => $user['unionid'], + 'openid' => $user['openId'], + 'userId' => $user['userid'], + 'name' => $user['name'], + 'avatar' => $user['avatar'], + 'mobile' => $user['mobile'], + 'email' => $user['email'], + ]; + Member::dingtalkLogin($userInfo); + $loginInfo = session('loginInfo'); + $this->success('', $loginInfo); + } + } + $this->error($result['errmsg']); + } /** - * 获取钉钉授权 + * 钉钉授权回调 * @return RedirectResponse|Redirect + * @throws DataNotFoundException + * @throws ModelNotFoundException + * @throws DbException */ public function dingTalkOauthCallback() { @@ -60,8 +104,17 @@ class Oauth extends BasicApi $redirect = $response->getTargetUrl(); logRecord($redirect); logRecord($user); - //用户注册/绑定微信 - $targetUrl = '/index.html#/member/login?logged=1'; + //用户注册/绑定钉钉 + $redirectPath = session('redirectPath'); + $targetUrl = '/index.html#/member/login'; + if ($redirectPath) { + $targetUrl = '/index.html#' . $redirectPath; + } + if (strpos($targetUrl, '?') === false) { + $targetUrl .= '?logged=1'; + } else { + $targetUrl .= '&logged=1'; + } if (!$user['errcode']) { $result = $app->user->getUseridByUnionid($user['user_info']['unionid']); if (!$result['errcode']) { @@ -74,8 +127,15 @@ class Oauth extends BasicApi $user['user_info']['userId'] = $userId; } } - Member::dingtalkLogin($user['user_info']); - }else{ + $result = Member::dingtalkLogin($user['user_info']); + //跳转地址携带message可以在应用内展示通知消息 + //logged=1表示业务处理成功 + if (isError($result)) { + Member::logout(); + $targetUrl .= '&message=' . $result['msg']; +// $targetUrl = '/index.html#/member/login?logged=0&message='.$result['msg']; + } + } else { $targetUrl = '/index.html#/member/login?logged=0&message=钉钉登录失败,请重试'; } // 登录成功跳转 diff --git a/application/project/controller/Login.php b/application/project/controller/Login.php index 63bbcd0..2374600 100644 --- a/application/project/controller/Login.php +++ b/application/project/controller/Login.php @@ -256,6 +256,31 @@ class Login extends BasicApi $this->success('发送邮件成功'); } + /** + * 解绑钉钉 + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + */ + public function _unbindDingtalk() + { + $currentMember = getCurrentMember(); + $memberCode = $currentMember['code']; + $member = Member::where(['code' => $memberCode])->find(); + if (!$member['mobile'] && !$member['email']) { + $this->error('您未绑定手机或邮箱,无法解绑 '); + } + $member->dingtalk_openid = ''; + $member->dingtalk_unionid = ''; + $member->dingtalk_userid = ''; + $member->save(); + $currentMember['dingtalk_openid'] = ''; + $currentMember['dingtalk_unionid'] = ''; + $currentMember['dingtalk_userid'] = ''; + setCurrentMember($currentMember); + $this->success('解除绑定成功', $currentMember); + } + /** * 验证绑定邮箱 * @throws DataNotFoundException @@ -281,22 +306,30 @@ class Login extends BasicApi } + /** + * 检测登陆信息 + */ public function _checkLogin() { $loginInfo = session('loginInfo'); $this->success('', $loginInfo); } + /* + * 获取当前用户信息 + */ + public function _currentMember() + { + $this->success('', getCurrentMember()); + } + /** * 退出登录 */ public function _out() { - session('member') && LogService::write('系统管理', '用户退出系统成功'); - !empty($_SESSION) && $_SESSION = []; - [session_unset(), session_destroy()]; - session('loginInfo', null); + Member::logout(); $this->success(''); }