// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Helpers\Jwt; use App\Models\DossierModel; use App\Models\MemberModel; use App\Services\BaseService; use App\Services\Common\CityService; use App\Services\ConfigService; use App\Services\EmailService; use App\Services\RedisService; use App\Services\SmsService; use App\Services\ToolService; use Illuminate\Support\Facades\DB; use phpqrcode\QRcode; /** * 会员管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class MemberService * @package App\Services\Api */ class MemberService extends BaseService { public static $instance = null; /** * 构造函数 * @since 2020/11/11 * MemberService constructor. */ public function __construct() { $this->model = new MemberModel(); } /** * @return static|null */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } /** * 用户登录 * @param $params * @return array|false */ public function login($params) { // 授权 $account = isset($params['account']) ? $params['account'] : ''; $smsCode = isset($params['sms_code']) ? $params['sms_code'] : ''; // 短信验证码或邮箱验证码 $type = isset($params['type']) ? $params['type'] : 1; $password = isset($params['password']) ? $params['password'] : ''; $appSources = isset($params['app_sources']) ? $params['app_sources'] : ''; $incode = isset($params['incode']) ? $params['incode'] : ''; if (empty($params) || empty($account)) { $this->error = 2014; return false; } $userInfo = $this->model->where(['mark' => 1]) ->where(function ($query) use ($account, $type) { if ($type == 1 || $type == 2) { $query->where(['username' => $account])->orWhere(['mobile' => $account])->orWhere(['email' => $account]); } else if ($type == 3) { $query->orWhere(['email' => $account]); } }) ->select(['id', 'openid', 'username', 'email', 'mobile', 'password', 'parent_id', 'vip', 'code', 'status', 'mark']) ->first(); $userInfo = $userInfo ? $userInfo->toArray() : []; $userId = isset($userInfo['id']) ? $userInfo['id'] : 0; $status = isset($userInfo['status']) ? $userInfo['status'] : 0; if ($userInfo && $status != 1) { $this->error = '账号已被冻结,请联系客服'; return false; } // 账号密码 if ($type == 1) { // 未注册 if (empty($userInfo)) { $this->error = '账号未注册,请选择其他方式登录注册'; return false; } // 已注册验证密码 $userPassword = isset($userInfo['password']) ? $userInfo['password'] : ''; if ($userInfo && $userPassword != get_password($password)) { $this->error = '登录密码错误'; return false; } } else if ($type == 2) { // 验证短信验证码 if (!SmsService::make()->check($account, $smsCode, 'login')) { $this->error = SmsService::make()->getError(); return false; } } else if ($type == 3) { // 已注册验证邮箱验证码 if (!EmailService::make()->check($account, $smsCode, 'login')) { $this->error = EmailService::make()->getError(); return false; } } // 未注册 $ip = get_client_ip(); $system = isset($params['system']) ? $params['system'] : []; if (empty($userInfo)) { // 推荐人 $parentId = 0; $parents = ''; if ($incode) { $inviteInfo = $this->model->where(['code' => $incode, 'mark' => 1]) ->select(['id', 'parents', 'parent_id']) ->first(); $parentId = isset($inviteInfo['id']) ? $inviteInfo['id'] : 0; $parents = isset($inviteInfo['parents']) ? $parentId . ',' . $inviteInfo['parents'] : ($parentId ? $parentId . ',' : ''); if(empty($parentId)){ $this->error = '邀请码错误'; return false; } } // 账号注册 DB::beginTransaction(); $userId = $this->model->max('id') + 1; $userInfo = [ 'username' => $type == 1 ? $account : '', 'mobile' => $type == 2 ? $account : '', 'email' => $type == 3 ? $account : '', 'nickname' => get_nickname('T'), 'password' => $type == 1 ? get_password($password) : '', 'member_level' => 0, 'parent_id' => $parentId, 'parents' => $parents, 'app_uuid' => isset($system['uuid']) ? $system['uuid'] : '', 'device' => $appSources == 'android' ? 2 : 1, 'source' => 1, 'status' => 1, 'login_ip' => $ip, 'code' => strtoupper(get_random_code(9, 'X', "{$userId}")), 'create_time' => time(), 'login_time' => time(), 'mark' => 1 ]; if (!$this->model->insert($userInfo)) { DB::rollBack(); $this->error = EmailService::make()->getError(); return false; } // 资料 $ipData = ToolService::make()->getIpAddress($ip, ''); $province = isset($ipData['regionName']) ? $ipData['regionName'] : ''; $city = isset($ipData['city']) ? $ipData['city'] : ''; $provinceId = CityService::make()->getFieldByName($province); $cityId = CityService::make()->getFieldByName($city); $birthday = date('Y-m-d'); $starData = getStar($birthday); $dossier = [ 'user_id'=> $userId, 'nickname'=> '自己', 'type'=>1, 'birthday'=> $birthday, 'province_id' => $provinceId, 'city_id' => $cityId, 'city' => $city, 'star'=> isset($starData['code'])? $starData['code'] : '', 'star_text'=> isset($starData['name'])? $starData['name'] : '', 'status'=>1, 'is_default'=>1, ]; if (!DossierModel::insert($dossier)) { DB::rollBack(); $this->error = EmailService::make()->getError(); return false; } // TODO 邀请注册奖励 DB::commit(); unset($userInfo['password']); unset($userInfo['parents']); unset($userInfo['parents']); } else { $this->model->where(['id' => $userId])->update([ 'app_uuid' => isset($system['uuid']) ? $system['uuid'] : '', 'login_ip' => $ip, 'update_time' => time(), 'login_time' => time(), ]); } // 获取登录授权token $jwt = new Jwt('jwt_star_app'); $token = $jwt->getToken($userId); // 结果返回 $result = [ 'access_token' => $token, 'info' => ['uid' => $userId, 'parent_id' => $userInfo['parent_id'], 'account' => $account, 'code' => $userInfo['code']], ]; $this->error = 2004; RedisService::set("auths:info:{$userId}", $userInfo, 2 * 24 * 3600); return $result; } /** * 邀请注册 * @param $params * @return array|false */ public function register($params) { // 授权 $account = isset($params['account']) ? $params['account'] : ''; $smsCode = isset($params['sms_code']) ? $params['sms_code'] : ''; // 短信验证码或邮箱验证码 $type = isset($params['type']) ? $params['type'] : 1; $password = isset($params['password']) ? $params['password'] : ''; $appSources = isset($params['app_sources']) ? $params['app_sources'] : ''; $incode = isset($params['incode']) ? $params['incode'] : ''; if (empty($params) || empty($account) || empty($incode)) { $this->error = 2014; return false; } $userInfo = $this->model->where(['mark' => 1]) ->where(function ($query) use ($account, $type) { if ($type == 1 || $type == 2) { $query->where(['username' => $account])->orWhere(['mobile' => $account])->orWhere(['email' => $account]); } else if ($type == 3) { $query->orWhere(['email' => $account]); } }) ->select(['id', 'openid', 'username', 'email', 'mobile', 'password', 'parent_id', 'vip', 'code', 'status', 'mark']) ->first(); $userInfo = $userInfo ? $userInfo->toArray() : []; if ($userInfo) { $this->error = '账号已注册,请直接下载APP或到小程序内登录使用'; return false; } // 账号密码 if ($type == 2) { // 已注册验证短信验证码 if (!SmsService::make()->check($account, $smsCode, 'reg')) { $this->error = SmsService::make()->getError(); return false; } } else if ($type == 3) { // 已注册验证邮箱验证码 if (!EmailService::make()->check($account, $smsCode, 'reg')) { $this->error = EmailService::make()->getError(); return false; } } // 推荐人 $parentId = 0; $parents = ''; if ($incode) { $inviteInfo = $this->model->where(['code' => $incode, 'mark' => 1]) ->select(['id', 'parents', 'parent_id']) ->first(); $parentId = isset($inviteInfo['id']) ? $inviteInfo['id'] : 0; $parents = isset($inviteInfo['parents']) ? $parentId . ',' . $inviteInfo['parents'] : ($parentId ? $parentId . ',' : ''); } if(empty($parentId)){ $this->error = '邀请码错误'; return false; } // 未注册 $ip = get_client_ip(); $ipData = ToolService::make()->getIpAddress($ip, ''); $province = isset($ipData['regionName']) ? $ipData['regionName'] : ''; $city = isset($ipData['city']) ? $ipData['city'] : ''; $provinceId = CityService::make()->getFieldByName($province); $cityId = CityService::make()->getFieldByName($city); $system = isset($params['system']) ? $params['system'] : []; // 账号注册 DB::beginTransaction(); $userId = $this->model->max('id') + 1; $userInfo = [ 'username' => $type == 1 ? $account : '', 'mobile' => $type == 2 ? $account : '', 'email' => $type == 3 ? $account : '', 'nickname' => get_nickname('T'), 'password' => $type == 1 ? get_password($password) : '', 'member_level' => 0, 'parent_id' => $parentId, 'parents' => $parents, 'app_uuid' => isset($system['uuid']) ? $system['uuid'] : '', 'device' => $appSources == 'android' ? 2 : 1, 'source' => 1, 'status' => 1, 'login_ip' => $ip, 'code' => strtoupper(get_random_code(9, 'X', "{$userId}")), 'create_time' => time(), 'login_time' => time(), 'mark' => 1 ]; if (!$this->model->insert($userInfo)) { DB::rollBack(); $this->error = EmailService::make()->getError(); return false; } // 资料 $birthday = date('Y-m-d'); $starData = getStar($birthday); $dossier = [ 'user_id'=> $userId, 'nickname'=> '自己', 'type'=>1, 'birthday'=> $birthday, 'star'=> isset($starData['code'])? $starData['code'] : '', 'star_text'=> isset($starData['name'])? $starData['name'] : '', 'province_id' => $provinceId, 'city_id' => $cityId, 'city' => $city, 'status'=>1, 'is_default'=>1, ]; if (!DossierModel::insert($dossier)) { DB::rollBack(); $this->error = EmailService::make()->getError(); return false; } // TODO 邀请注册奖励 DB::commit(); unset($userInfo['password']); unset($userInfo['parents']); unset($userInfo['parents']); // 结果返回 $siteInfo = ConfigService::make()->getConfigByGroup(1); $result = [ 'app_urls'=>[ 'android'=> isset($siteInfo['android_app_url']['value'])? $siteInfo['android_app_url']['value'] : '', 'ios'=> isset($siteInfo['ios_app_url']['value'])? $siteInfo['ios_app_url']['value'] : '', ], 'info' => ['uid' => $userId, 'parent_id' => $userInfo['parent_id'], 'account' => $account, 'code' => $userInfo['code']], ]; $this->error = 2004; RedisService::set("auths:info:{$userId}", $userInfo, 2 * 24 * 3600); return $result; } /** * 用户信息 * @param int $userId 用户ID * @param false $refresh * @return array|mixed */ public function getInfo(int $userId, $refresh = false) { $cacheKey = "caches:member:info_{$userId}"; $info = RedisService::get($cacheKey); if ($info && !$refresh) { return $info; } $info = $this->model->with(['parent','profile']) ->where(['id' => $userId, 'mark' => 1]) ->select(['id', 'nickname', 'avatar', 'code', 'member_level','stars', 'beans', 'vip', 'profit', 'balance', 'view_ads', 'ads_beans', 'mobile', 'parent_id', 'email', 'username', 'status']) ->first(); $info = $info ? $info->toArray() : []; if (empty($info)) { $this->error = 2016; return false; } $profile = isset($info['profile'])? $info['profile'] : []; if ($info['avatar']) { $info['avatar'] = get_image_url($info['avatar']); } else { $star = isset($profile['star']) && $profile['star'] ? $profile['star'] : ''; $gender = isset($profile['gender']) && $profile['gender'] ? $profile['gender'] : 0; $name = intval($info['id'] % 3) + 1; if ($star && $gender) { $name = "{$star}/" . ($gender == 1 ? 'f_' : 'm_') . $name; } $avatar = "/images/avatar/{$name}.jpeg"; $info['avatar'] = get_image_url($avatar); } $info['birthday'] = isset($profile['birthday']) && $profile['birthday']? $profile['birthday'] : date('Y-m-d'); $info['star'] = isset($profile['star']) && $profile['star']? $profile['star'] : ''; $info['star_text'] = isset($profile['star_text']) && $profile['star_text']? $profile['star_text'] : ''; if(empty($info['star'])){ $starData = getStar($info['birthday']); $info['star'] = isset($starData['code']) ? $starData['code'] : ''; $info['star_text'] = isset($starData['name']) ? $starData['name'] : ''; } $info['share_url'] = env('WEB_URL').'#/pages/share/index?incode='.$info['code']; $info['share_qrcode'] = get_image_url($this->makeQrcode($info['share_url'])); $info['orders'] = [ ]; RedisService::set($cacheKey, $info, rand(3, 5)); return $info; } /** * @param $userId */ public function getProfile($userId) { $cacheKey = "caches:profiles:info_{$userId}"; $info = RedisService::get($cacheKey); if(empty($info)){ $info = DossierModel::with(['dossier_type'])->where(['user_id'=> $userId,'status'=>1,'mark'=>1]) ->orderBy('is_default', 'asc') ->first(); $info = $info? $info->toArray() : []; if($info){ RedisService::set($cacheKey, $info, rand(300, 600)); }else{ $birthday =date('Y-m-d'); $starData = getStar($birthday); $info = [ 'nickname'=> '-示例', 'gender'=> 2, 'birthday'=> $birthday, 'star'=> isset($starData['code'])? $starData['code'] : '', 'star_text'=> isset($starData['name'])? $starData['name'] : '', 'dossier_type'=> [ 'id'=>1, 'name'=> '其他' ] ]; } } } /** * 生成普通参数二维码 * @param $str 参数 * @param bool $refresh 是否重新生成 * @return bool */ public function makeQrcode($str, $refresh = false, $size = 4, $margin = 2, $level = 2) { $basePath = base_path() . '/public'; $qrFile = '/images/qrcode/'; if (!is_dir($basePath . '/uploads' . $qrFile)) { @mkdir($basePath . '/uploads' . $qrFile, 0755, true); } $key = date('Ymd') . strtoupper(md5($str . '_' . $size . $margin . $level)); $qrFile = $qrFile . "C_{$key}.png"; $cacheKey = "caches:qrcodes:member_" . $key; if (RedisService::get($cacheKey) && is_file($basePath . '/uploads' . $qrFile) && !$refresh) { return $qrFile; } QRcode::png($str, $basePath . '/uploads' . $qrFile, $level, $size, $margin); if (!file_exists($basePath . '/uploads' . $qrFile)) { return false; } RedisService::set($cacheKey, ['str' => $str, 'qrcode' => $qrFile, 'date' => date('Y-m-d H:i:s')], 7 * 24 * 3600); return $qrFile; } }