<?php namespace addons\shopro\controller; use app\common\library\Ems; use app\common\library\Sms; use fast\Random; use think\Validate; use addons\shopro\library\Wechat; use think\Db; use addons\shopro\model\UserOauth; use addons\shopro\model\User as UserModel; use addons\shopro\model\UserStore; /** * 会员接口 */ class User extends Base { protected $noNeedLogin = ['login', 'mobilelogin', 'accountLogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third', 'wxMiniProgramLogin', 'getWxMiniProgramSessionKey', 'wxOfficialAccountLogin', 'wxOfficialAccountBaseLogin', 'wxOpenPlatformLogin', 'getUserDefaultFields']; protected $noNeedRight = '*'; public function _initialize() { return parent::_initialize(); } /** * 会员中心 */ public function index() { $auth = \app\common\library\Auth::instance(); $auth->setAllowFields(['id', 'username', 'nickname', 'mobile', 'avatar', 'score', 'birthday', 'money', 'group', 'group_id']); $data = $auth->getUserinfo(); if (!isset($data['group'])) { $data['group'] = \addons\shopro\model\UserGroup::get($data['group_id']); } // 查询用户优惠券数量 $userCoupons = \addons\shopro\model\Coupons::getCouponsList(1); $data['coupons_num'] = count($userCoupons); // 查询用户是否是门店管理员 $userStores = UserStore::where('user_id', $data['id'])->select(); $data['is_store'] = $userStores ? 1 : 0; $data['store_id'] = 0; if (count($userStores) == 1) { // 只有一个店铺 直接进入店铺 $data['store_id'] = $userStores[0]['store_id']; } $this->success('用户信息', $data); } /** * 会员登录 * * @param string $account 账号 * @param string $password 密码 */ public function accountLogin() { $account = $this->request->post('account'); $password = $this->request->post('password'); if (!$account || !$password) { $this->error(__('Invalid parameters')); } $ret = $this->auth->login($account, $password); if ($ret) { $data = ['userinfo' => $this->auth->getUserinfo()]; $this->success(__('Logged in successful'), $data); } else { $this->error($this->auth->getError()); } } /** * 获取微信小程序session_key * * @param string $code 加密code */ public function getWxMiniProgramSessionKey() { $post = $this->request->post(); $wechat = new Wechat('wxMiniProgram'); $decryptSession = $wechat->code($post['code']); $this->success('获取session_key', $decryptSession); } /** * 微信小程序登录 * * @param string $code 加密code */ public function wxMiniProgramLogin() { $post = $this->request->post(); $wechat = new Wechat('wxMiniProgram'); $decryptUserInfo = $wechat->decryptData($post['session_key'], $post['iv'], $post['encryptedData']); // array(10) { // ["openId"] => string(28) "oD9ko40ZEoru7bjzN2f0Wnm3uNmA" // ["nickName"] => string(12) "Civilization" // ["gender"] => int(1) // ["language"] => string(5) "zh_CN" // ["city"] => string(0) "" // ["province"] => string(0) "" // ["country"] => string(7) "Iceland" // ["avatarUrl"] => string(124) "https://wx.qlogo.cn/mmopen/vi_32/bKchg38ErVBnuJBb4NfCOYkMsxgzZ3vZGu7y7V0BQG8clImsyvZge2HzGGYfxXKBNv8dbQOvyvmjKPEtRyrniaA/132" // ["unionId"] => string(28) "odsYQ1MLsGSGL6Gp5f6y3at2j7Hg" // ["watermark"] => array(2) { // ["timestamp"] => int(1590344429) // ["appid"] => string(18) "wx39cd0799d4567dd0" // } // } //组装decryptData $decryptData = array_change_key_case($decryptUserInfo, CASE_LOWER); $decryptData['headimgurl'] = $decryptData['avatarurl']; $decryptData['sex'] = $decryptData['gender']; $decryptData['session_key'] = $post['session_key']; if (empty($decryptData['openid'])) { $this->error(__('code错误'), $decryptData); } $ret = $this->oauthLoginOrRegister($decryptData, 'wxMiniProgram', 'Wechat'); if ($ret) { $data = $ret->getUserinfo(); if (!isset($data['group'])) { $data['group'] = \addons\shopro\model\UserGroup::get($data['group_id']); } $this->success(__('Logged in successful'), $data); } $this->error($this->auth->getError()); } /** * 微信APP登录 * * @param string $authResult id信息 * @param string $userInfo 用户信息 */ public function wxOpenPlatformLogin() { $params = $this->request->post(); //App // 'authResult' => // array ( // 'access_token' => '32_WlLV5jxPoZuHWi7fnnxNPhun8Dj_igJPWOOxkP_WyEkHHc6pLpBz-13F3uu8KvS2HI0ei0l64Js8TD_W7A16JSr7PA16gwcDeU7RWd35gzQ', // 'expires_in' => 7200, // 'refresh_token' => '32_uvVpEiwt9q4ZmzDZgyF7jv8e4XxXValLOsuux4-GG7PIgywjnVL8Ovzzw-H1sKUd__X9NJko2lB49ZMo1ubYL4DT0Hv0C33yKkZDq8K0J9Y', // 'openid' => 'oO01HuKtCFucLFr-Q9vwCLMGHO08', // 'scope' => 'snsapi_userinfo', // 'unionid' => 'odsYQ1IOJtHfVIK9KqPdy1U0uMBo', // ), // 'userInfo' => // array ( // 'openId' => 'oO01HuKtCFucLFr-Q9vwCLMGHO08', // 'nickName' => 'RogerD', // 'gender' => 1, // 'city' => '中山', // 'province' => '广东', // 'country' => '中国', // 'avatarUrl' => 'http://thirdwx.qlogo.cn/mmopen/vi_32/PiajxSqBRaEK5uWViaPyje54F39j2FZYgvVicB0sQV1zLQ4ia41DYm7bqLlygCYu5sH8Y4MvfFWicNRUP4by7l1yhkg/132', // 'unionId' => 'odsYQ1IOJtHfVIK9KqPdy1U0uMBo', // ), //组装decryptData $userInfo = array_change_key_case($params['userInfo'], CASE_LOWER); $userInfo['headimgurl'] = $userInfo['avatarurl']; $userInfo['sex'] = $userInfo['gender']; $decryptData = array_merge($params['authResult'], $userInfo); $ret = $this->oauthLoginOrRegister($decryptData, 'App', 'Wechat'); if ($ret) { $data = $ret->getUserinfo(); if (!isset($data['group'])) { $data['group'] = \addons\shopro\model\UserGroup::get($data['group_id']); } $this->success(__('Logged in successful'), $data); } $this->error($this->auth->getError()); } /** * 微信公众号登录 * * @param string $code 加密code */ public function wxOfficialAccountLogin() { $wechat = new Wechat('wxOfficialAccount'); $oauth = $wechat->oauth(); //解析来源页面 $oUrl = input('get.state'); $url = explode('/', $oUrl); $procotol = $url[0] . '//'; $host = $url[2]; $decryptData = $oauth->user()->getOriginal(); // ["openid"] => string(28) "oUgIVxASHEWU0wHd_ypNhJAdH088" // ["nickname"] => string(6) "東浩" // ["sex"] => int(1) // ["language"] => string(5) "zh_CN" // ["city"] => string(6) "郑州" // ["province"] => string(6) "河南" // ["country"] => string(6) "中国" // ["headimgurl"] => string(133) "http://thirdwx.qlogo.cn/mmopen/vi_32/PiajxSqBRaEI3EldP4TQicjoF7utibMMRP08vfC9AOWia3WYmUWAGyI9GjWVkzMiahVYo2ef4KTNvVwLfhvKA3W0iccQ/132" // ["privilege"] => array(0) { // } // ["unionid"] => string(28) "odsYQ1CI3j4CK8_NmWdz0HuKsajY" $ret = $this->oauthLoginOrRegister($decryptData, 'wxOfficialAccount', 'Wechat'); if ($ret) { //登录页接参Token header('Location:' . $procotol . $host . '/pages/public/login?token=' . $ret->getToken()); exit; } $this->error($ret->getError()); } /** * 微信公众号静默登录 * * @param string $code 加密code */ public function wxOfficialAccountBaseLogin() { $wechat = new Wechat('wxOfficialAccount'); $oauth = $wechat->oauth(); $oUrl = input('get.state'); $url = explode('/', $oUrl); $decryptData = $oauth->user()->getOriginal(); if ($decryptData) { header('Location:' . $oUrl . '&openid=' . $decryptData['openid']); } else { $this->error('未获取到OPENID'); } } /** * 第三方登录或自动注册 * * @param string $decryptData 解密参数 * @param string $platform 平台名称 * @param string $provider 厂商名称 * @param string $keeptime 有效时长 */ private function oauthLoginOrRegister($decryptData, $platform, $provider, $keeptime = 0) { extract($decryptData); @$oauthData = compact('provider', 'unionid', 'platform', 'openid', 'nickname', 'sex', 'city', 'province', 'country', 'headimgurl', 'session_key', 'refresh_token', 'access_token'); $oauthData['logintime'] = time(); $oauthData['logincount'] = 1; if ($platform === 'wxMiniProgram' || $platform === 'App') { $oauthData['expire_in'] = 7200; $oauthData['expiretime'] = time() + 7200; } $auth = \app\common\library\Auth::instance(); $auth->keeptime($keeptime); $auth->setAllowFields(['id', 'username', 'nickname', 'mobile', 'avatar', 'score', 'money', 'group', 'group_id']); $userOauth = UserOauth::get(['openid' => $openid]); if (isset($decryptData['nickname'])) { $fields['nickname'] = $decryptData['nickname']; } if (isset($decryptData['headimgurl'])) { $fields['avatar'] = $decryptData['headimgurl']; } //开启事务 Db::startTrans(); try { if ($userOauth) { //找到对应已注册用户,更新oauthData数据和用户数据直接发起登录 $user_id = $userOauth->user_id; $user = UserModel::get($user_id); $oauthData['logincount'] = $userOauth->logincount + 1; $userOauth->save($oauthData); } else { //添加新的oauthData数据 //默认创建新用户 $createNewUser = true; // 判断是否有unionid 并且已存在oauth数据中 if (isset($unionid)) { //存在同厂商信息,添加oauthData数据,合并用户 $user_id = UserOauth::where(['unionid' => $unionid])->value('user_id'); $user = UserModel::get($user_id); if ($user) { $createNewUser = false; } } if ($createNewUser) { // 创建空用户 $username = Random::alnum(20); $password = ''; $domain = request()->host(); $extend = $this->getUserDefaultFields(); $result = $auth->register($username, $password, $username . '@' . $domain, '', $extend, $keeptime); if (!$result) { return false; } $user = $auth->getUser(); if (!isset($fields['nickname'])) { //默认昵称 $fields['nickname'] = $extend['nickname'] . $user->id; } // 更新会员资料 $user = UserModel::get($user->id); // 保存第三方信息 $user_id = $user->id; } $oauthData['user_id'] = $user_id; UserOauth::create($oauthData); } if (isset($fields)) $user->save($fields); Db::commit(); } catch (\Exception $e) { Db::rollback(); $auth->logout(); $this->error($e->getMessage()); return false; } $auth->direct($user_id); return $auth; } /** * 手机验证码登录 * * @param string $mobile 手机号 * @param string $code 验证码 */ public function mobileLogin() { $mobile = $this->request->post('mobile'); $code = $this->request->post('code'); if (!$mobile || !$code) { $this->error(__('Invalid parameters')); } if (!Validate::regex($mobile, "^1\d{10}$")) { $this->error(__('Mobile is incorrect')); } if (!Sms::check($mobile, $code, 'mobilelogin')) { $this->error(__('Captcha is incorrect')); } $user = \app\common\model\User::getByMobile($mobile); if ($user) { if ($user->status != 'normal') { $this->error(__('Account is locked')); } //如果已经有账号则直接登录 $ret = $this->auth->direct($user->id); } if ($ret) { Sms::flush($mobile, 'mobilelogin'); $data = ['userinfo' => $this->auth->getUserinfo()]; $this->success(__('Logged in successful'), $data); } else { $this->error($this->auth->getError()); } } /** * 注册会员 * * @param string $username 用户名 * @param string $password 密码 * @param string $email 邮箱 * @param string $mobile 手机号 * @param string $code 验证码 */ public function register() { $username = $this->request->post('mobile'); $password = $this->request->post('password'); $email = $this->request->post('mobile') . '@' . request()->host(); $mobile = $this->request->post('mobile'); $code = $this->request->post('code'); if (!$password) { $this->error(__('请填写密码')); //TODO:密码规则校验 } if (strlen($password) < 6 || strlen($password) > 16) { $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验 } if ($email && !Validate::is($email, "email")) { $this->error(__('邮箱填写错误')); } if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) { $this->error(__('手机号填写错误')); } $ret = Sms::check($mobile, $code, 'register'); if (!$ret) { $this->error(__('Captcha is incorrect')); } $extend = $this->getUserDefaultFields(); $ret = $this->auth->register($username, $password, $email, $mobile, $extend); if ($ret) { $user = $this->auth->getUser(); $user->nickname = $user->nickname . $user->id; $user->save(); $data = ['userinfo' => $this->auth->getUserinfo()]; $this->success(__('注册成功'), $data); } else { $this->error($this->auth->getError()); } } /** * 注销登录 */ public function logout() { $this->auth->logout(); $this->success(__('Logout successful')); } /** * 修改会员个人信息 * * @param string $avatar 头像地址 * @param string $username 用户名 * @param string $nickname 昵称 * @param string $birthday 生日 * @param string $bio 个人简介 */ public function profile() { $user = $this->auth->getUser(); $username = $this->request->post('username'); $nickname = $this->request->post('nickname'); $bio = $this->request->post('bio', ''); $birthday = $this->request->post('birthday'); $avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars'); if ($username) { $exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find(); if ($exists) { $this->error(__('Username already exists')); } $user->username = $username; } $user->nickname = $nickname; $user->bio = $bio; $user->birthday = $birthday; $user->avatar = $avatar; $user->save(); $this->success(); } /** * 修改邮箱 * * @param string $email 邮箱 * @param string $captcha 验证码 */ public function changeemail() { $user = $this->auth->getUser(); $email = $this->request->post('email'); $captcha = $this->request->request('captcha'); if (!$email || !$captcha) { $this->error(__('Invalid parameters')); } if (!Validate::is($email, "email")) { $this->error(__('Email is incorrect')); } if (\app\common\model\User::where('email', $email)->where('id', '<>', $user->id)->find()) { $this->error(__('Email already exists')); } $result = Ems::check($email, $captcha, 'changeemail'); if (!$result) { $this->error(__('Captcha is incorrect')); } $verification = $user->verification; $verification->email = 1; $user->verification = $verification; $user->email = $email; $user->save(); Ems::flush($email, 'changeemail'); $this->success(); } /** * 修改手机号 * * @param string $mobile 手机号 * @param string $captcha 验证码 */ public function changemobile() { $user = $this->auth->getUser(); $mobile = $this->request->post('mobile'); $captcha = $this->request->post('captcha'); if (!$mobile || !$captcha) { $this->error(__('Invalid parameters')); } if (!Validate::regex($mobile, "^1\d{10}$")) { $this->error(__('Mobile is incorrect')); } if (\app\common\model\User::where('mobile', $mobile)->where('id', '<>', $user->id)->find()) { $this->error(__('Mobile already exists')); } $result = Sms::check($mobile, $captcha, 'changemobile'); if (!$result) { $this->error(__('Captcha is incorrect')); } $verification = $user->verification; $verification->mobile = 1; $user->verification = $verification; $user->mobile = $mobile; $user->save(); Sms::flush($mobile, 'changemobile'); $this->success(); } /** * 重置密码 * * @param string $mobile 手机号 * @param string $newpassword 新密码 * @param string $captcha 验证码 */ public function resetpwd() { $type = $this->request->post("type", 'mobile'); $mobile = $this->request->post("mobile"); $email = $this->request->post("email"); $newpassword = $this->request->post("newpassword"); $captcha = $this->request->post("captcha"); if (!$newpassword || !$captcha) { $this->error(__('Invalid parameters')); } if (strlen($newpassword) < 6 || strlen($newpassword) > 16) { $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验 } if ($type == 'mobile') { if (!Validate::regex($mobile, "^1\d{10}$")) { $this->error(__('Mobile is incorrect')); } $user = \app\common\model\User::getByMobile($mobile); if (!$user) { $this->error(__('User not found')); } $ret = Sms::check($mobile, $captcha, 'resetpwd'); if (!$ret) { $this->error(__('Captcha is incorrect')); } Sms::flush($mobile, 'resetpwd'); } else { if (!Validate::is($email, "email")) { $this->error(__('Email is incorrect')); } $user = \app\common\model\User::getByEmail($email); if (!$user) { $this->error(__('User not found')); } $ret = Ems::check($email, $captcha, 'resetpwd'); if (!$ret) { $this->error(__('Captcha is incorrect')); } Ems::flush($email, 'resetpwd'); } //模拟一次登录 $this->auth->direct($user->id); $ret = $this->auth->changepwd($newpassword, '', true); if ($ret) { $this->success(__('Reset password successful')); } else { $this->error($this->auth->getError()); } } public function changepwd() { $user = $this->auth->getUser(); $oldpassword = $this->request->post("oldpassword"); $newpassword = $this->request->post("newpassword"); if (!$newpassword || !$oldpassword) { $this->error(__('Invalid parameters')); } if (strlen($newpassword) < 6 || strlen($newpassword) > 16) { $this->error(__('密码长度 6-16 位')); //TODO:密码规则校验 } $ret = $this->auth->changepwd($newpassword, $oldpassword); if ($ret) { $this->auth->direct($user->id); $data = ['userinfo' => $this->auth->getUserinfo()]; $this->success(__('Change password successful'), $data); } else { $this->error($this->auth->getError()); } } private function getUserDefaultFields() { $userConfig = json_decode(\addons\shopro\model\Config::get(['name' => 'user'])->value,true); return $userConfig; } }