// +---------------------------------------------------------------------- namespace App\Services\Api; use App\Models\AccountStatisticsModel; use App\Models\ActionLogModel; use App\Models\MemberBankModel; use App\Models\MemberModel; use App\Services\BaseService; use App\Services\JwtService; use App\Services\MpService; use App\Services\RedisService; use Illuminate\Support\Facades\DB; use phpQrcode\QRcode; /** * 会员管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class MemberService * @package App\Services\Api */ class MemberService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * MemberService constructor. */ public function __construct() { $this->model = new MemberModel(); } /** * 静态入口 * @return MemberService|static|null */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } /** * 授权登录 * @param $code * @param array $params * @return array|false */ public function login($code, $params = []) { // 账号登录 if (empty($code)) { $this->error = 1041; return false; } // 获取用户信息 $result = MpService::make()->getUserInfo($code); $openid = isset($result['openid']) ? $result['openid'] : ''; if (empty($openid)) { $this->error = 1042; return false; } // 验证是否注册,没有则注册 $where = ['openid' => $openid]; $data = $this->model->where($where) ->select(['id', 'openid', 'mobile', 'user_type', 'nickname', 'avatar', 'code', 'status', 'mark']) ->first(); $data = $data ? $data->toArray() : []; $userId = isset($data['id']) ? $data['id'] : 0; $avatar = isset($data['avatar']) ? $data['avatar'] : ''; $mobile = isset($data['mobile']) ? $data['mobile'] : ''; $nickName = isset($data['nickname']) ? $data['nickname'] : ''; $status = isset($data['status']) ? $data['status'] : 0; $mark = isset($data['mark']) ? $data['mark'] : 0; if ($data && $userId && $status != 1 && $mark == 1) { $this->error = 2015; return false; } $system = isset($params['system']) ? $params['system'] : []; $system = $system && !is_array($system) ? json_decode($system, true) : $system; $appSources = isset($system['app_sources']) && $system['app_sources'] ? $system['app_sources'] : 'ios'; $uuid = isset($system['uuid']) ? $system['uuid'] : ''; $version = isset($system['app_version']) ? $system['app_version'] : ''; if (empty($data)) { $userId = $this->model->max('id') + 1; // 推荐人 $rid = isset($params['rid']) ? intval($params['rid']) : 0; $parents = ''; if ($rid) { $inviteInfo = $this->model->where(['id' => $rid, 'mark' => 1]) ->select(['id', 'parent_id', 'parents', 'status']) ->first(); $parents = isset($inviteInfo['parents']) ? $inviteInfo['parents'] : ''; if ($inviteInfo) { $parents = $parents ? $parents . $rid . ',' : ",{$rid},"; } } $data = [ 'nickname' => '', 'openid' => $openid, 'mobile' => '', 'avatar' => '', 'parent_id' => $rid, 'parents' => $parents, 'code' => get_random_code(9, 'S', $userId), 'password' => get_password('a123456'), 'login_ip' => get_client_ip(), 'create_time' => time(), 'login_time' => time(), 'login_count' => DB::raw("login_count+1"), 'app_version' => $version, 'app_uuid' => $uuid, 'device' => $appSources == 'ios' ? 1 : 2, ]; if (!$userId = $this->model->insertGetId($data)) { $this->error = 2018; return false; } } // 更新登录信息 else if ($mark == 0 || !RedisService::get("caches:members:login_{$userId}")) { $updateData = [ 'login_ip' => get_client_ip(), 'create_time' => time(), 'login_time' => time(), 'app_uuid' => $uuid, 'login_count' => DB::raw("login_count+1"), 'app_version' => $version, 'device' => $appSources == 'ios' ? 1 : 2, 'mark' => 1, ]; if ($mark == 0) { $data['nickname'] = ''; $data['avatar'] = ''; $data['mobile'] = ''; $data['openid'] = $openid; $nickName = ''; $avatar = ''; $mobile = ''; } $this->model->where(['id' => $userId])->update($updateData); RedisService::set("caches:members:login_{$userId}", $updateData, rand(30, 60)); } // 如果未生成佣金账户则创建 if(!$accountId = AccountStatisticsModel::where(['user_id'=>$userId])->value('id')){ AccountStatisticsModel::insert(['user_id'=>$userId]); } // 获取登录授权token $token = JwtService::make()->encode($userId); // 结果返回 $result = [ 'access_token' => $token, 'info' => ['uid' => $userId, 'openid' => $openid, 'has_info' => $avatar && $nickName ? 1 : 0, 'mobile' => $mobile], ]; // 用户缓存信息 $this->error = 2019; $data['token'] = $token; unset($data['mobile']); RedisService::set("auths:info:{$userId}", $data, 24 * 3600); return $result; } /** * 完善资料 * @param $params * @return array|false */ public function setProfile($params) { $id = isset($params['id'])? $params['id'] : 0; $code = isset($params['code'])? $params['code'] : ''; $avatar = isset($params['avatar'])? $params['avatar'] : ''; $nickname = isset($params['nickname'])? $params['nickname'] : ''; if($id<=0 || empty($code)){ $this->error = '授权参数错误,请刷新重试'; return false; } if(empty($avatar) || empty($nickname)){ $this->error = '请先获取用户授权信息'; return false; } $userInfo = $this->model->where(['id'=>$id,'mark'=>1]) ->select(['id as uid', 'nickname', 'openid','avatar']) ->first(); if(empty($userInfo)){ $this->error = '授权登录失败,请刷新重试'; return false; } // 获取手机号信息 $phoneData = MpService::make()->getPhoneNumber($code); $phoneData = isset($phoneData['phone_info']) ? $phoneData['phone_info'] : []; $phone = isset($phoneData['phoneNumber']) ? $phoneData['phoneNumber'] : ''; if (empty($phone)) { $this->error = MpService::make()->getError(); return false; } $avatar = save_base64_image($avatar, 'avatar'); if(!$this->model->where(['id'=>$id])->update(['mobile'=>$phone,'nickname'=>$nickname,'avatar'=>$avatar,'update_time'=>time()])){ $this->error = '获取授权信息失败'; return false; } $this->error = '登录成功'; // 获取登录授权token $token = JwtService::make()->encode($id); return [ 'access_token'=> $token, 'info'=> $userInfo ]; } /** * 重置密码 * @param $params * @return array|false */ public function forget($params) { // 账号登录 $mobile = isset($params['mobile']) ? trim($params['mobile']) : ''; $password = isset($params['password']) ? trim($params['password']) : ''; if (empty($params) || empty($mobile) || empty($password)) { $this->error = 1041; return false; } // 验证是否注册 if (!$userId = $this->model->where(['mobile' => $mobile, 'mark' => 1])->value('id')) { $this->error = 1038; return false; } if (!$this->model->where(['id' => $userId])->update(['password' => get_password($password), 'update_time' => time()])) { $this->error = 2030; return false; } // 操作日志 ActionLogModel::setRecord($userId, ['type' => 2, 'title' => '重置密码', 'content' => '重置登录密码', 'module' => 'member']); ActionLogModel::record(); $this->error = 2031; return true; } /** * 获取资料详情 * @param $where * @param array $field */ public function getInfo($where, array $field = [], $refresh = true) { if (empty($where)) { return false; } $fieldKey = $field ? '_' . md5(json_encode($field)) : ''; $cacheKey = "caches:members:info_" . (!is_array($where) ? $where . $fieldKey : md5(json_encode($where) . $fieldKey)); $info = RedisService::get($cacheKey); if ($info && !$refresh) { return $info; } $defaultField = ['id', 'user_type', 'realname', 'mobile','is_auth', 'nickname','company','position','department', 'balance', 'code', 'openid','create_time', 'status', 'avatar']; $field = $field ? $field : $defaultField; if (is_array($where)) { $info = $this->model->with(['account'])->where(['mark' => 1])->where($where)->select($field)->first(); } else { $info = $this->model->with(['account'])->where(['mark' => 1])->where(['id' => (int)$where])->select($field)->first(); } $info = $info ? $info->toArray() : []; if ($info) { $info['create_time'] = $info['create_time']?datetime(strtotime($info['create_time']),'Y-m-d H:i') : ''; $info['position_text'] = $info['department'] && $info['position']? $info['department'].'/'.$info['position'] : ''; if (isset($info['avatar'])) { $info['avatar'] = $info['avatar'] ? get_image_url($info['avatar']) : ''; } if (isset($info['mobile'])) { $info['mobile_text'] = $info['mobile'] ? format_mobile($info['mobile']) : ''; } $params = request()->all(); $type = isset($params['type'])?$params['type']:''; if($type == 'qrcode'){ $info['qrcode'] = MpService::make()->getMiniQrcode('pages/login/login',"rid={$info['id']}"); $info['qrcode'] = $info['qrcode']? get_image_url($info['qrcode']):''; } if($type == 'center'){ $info['uppers'] = [ ['id'=>1,'name'=>'11','avatar'=>get_image_url('/images/member/logo.png')], ['id'=>2,'name'=>'11','avatar'=>get_image_url('/images/member/logo.png')], ]; $info['users'] = [ ['id'=>1,'name'=>'11','avatar'=>get_image_url('/images/member/logo.png')], ['id'=>2,'name'=>'11','avatar'=>get_image_url('/images/member/logo.png')], ['id'=>3,'name'=>'11','avatar'=>get_image_url('/images/member/logo.png')], ]; $info['upper_count'] = 2; $info['user_count'] = 3; } RedisService::set($cacheKey, $info, rand(30, 60)); } return $info; } /** * 认证资料 * @param $userId * @return array|mixed */ public function authInfo($userId) { $cacheKey = "caches:members:authInfo:{$userId}"; $info = RedisService::get($cacheKey); if ($info) { return $info; } $info = $this->model->where(['id' => $userId, 'mark' => 1]) ->select(['id', 'realname','idcard','bank_name','bank_card','bank_branch','is_auth', 'status']) ->first(); if($info){ RedisService::set($cacheKey, $info, rand(300,600)); } return $info; } /** * 绑定收款账户 * @param $userId * @return array|mixed */ public function bindAccount($userId, $params) { if($params['type']==1){ $alipay = MemberBankModel::where(['type'=>1,'user_id'=>$userId,'mark'=>1]) ->select(['id','user_id','type','realname','account','account_remark','status']) ->first(); $alipayId = isset($alipay['id'])?$alipay['id'] : 0; $data = [ 'type'=> 1, 'user_id'=> $userId, 'realname'=>$params['realname'], 'account'=>$params['account'], 'account_remark'=>isset($params['account_remark']) && $params['account_remark']?$params['account_remark']:'支付宝', 'status'=>1 ]; if($alipayId){ $data['update_time']=time(); MemberBankModel::where(['id'=>$alipayId])->update($data); }else { $data['create_time']=time(); MemberBankModel::insertGetId($data); } } else if($params['type']==2){ $banks = MemberBankModel::where(['type'=>2,'user_id'=>$userId,'mark'=>1]) ->select(['id','user_id','type','realname','account','account_remark','status']) ->first(); $bankId = isset($banks['id'])?$banks['id'] : 0; $data = [ 'type'=>2, 'user_id'=> $userId, 'realname'=>$params['realname'], 'account'=>$params['account'], 'account_remark'=>$params['account_remark'], 'status'=>1 ]; if($bankId){ $data['update_time']=time(); MemberBankModel::where(['id'=>$bankId])->update($data); }else { $data['create_time']=time(); MemberBankModel::insertGetId($data); } }else{ $this->error = '账号类型错误'; return false; } RedisService::keyDel("caches:members:account:{$userId}*"); $this->error = '绑定收款账号成功'; return true; } /** * 团队人数 * @param $uid * @return array|int|mixed */ public function getTeamCount($uid) { $cacheKey = "caches:members:teamCount:{$uid}"; $data = RedisService::get($cacheKey); if ($data) { return $data; } $data = $this->model->from('member as a') ->where('a.parents', 'like', "%,{$uid},%") ->where(['a.status' => 1, 'a.mark' => 1]) ->count('id'); if($data){ RedisService::set($cacheKey, $data, rand(5,10)); } return $data; } /** * 生成普通参数二维码 * @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; } /** * 修改信息 * @param $userId * @param $params * @return bool */ public function modify($userId, $params) { $cacheLockKey = "caches:members:modify_{$userId}"; if (RedisService::get($cacheLockKey)) { $this->error = 1034; return false; } // 用户验证 RedisService::set($cacheLockKey, ['user_id' => $userId, 'params' => $params], rand(2, 3)); $info = $this->model->where(['id' => $userId, 'mark' => 1]) ->select(['id', 'nickname','avatar','company','position','department', 'status']) ->first(); if (!$info || $info['status'] != 1) { $this->error = 2016; RedisService::clear($cacheLockKey); return false; } // 修改数据 $data = ['update_time' => time()]; $nickname = isset($params['nickname']) ? $params['nickname'] : ''; if (isset($params['nickname']) && $nickname) { $data['nickname'] = $nickname; } $mobile = isset($params['mobile']) ? $params['mobile'] : ''; if (isset($params['mobile']) && $mobile) { $data['mobile'] = $mobile; } $company = isset($params['company']) ? $params['company'] : ''; if (isset($params['company']) && $company) { $data['company'] = $company; } $department = isset($params['department']) ? $params['department'] : ''; if (isset($params['department']) && $department) { $data['department'] = $department; } $position = isset($params['position']) ? $params['position'] : ''; if (isset($params['position']) && $position) { $data['position'] = $position; } // 头像 $avatar = isset($params['avatar']) ? $params['avatar'] : ''; if (isset($params['avatar']) && $avatar) { $data['avatar'] = save_base64_image($avatar, 'avatar'); } if (!$this->model->where(['id' => $userId])->update($data)) { $this->error = 1014; RedisService::clear($cacheLockKey); return false; } $oldAvatar = isset($info['avatar']) ? $info['avatar'] : ''; if ($avatar && $oldAvatar && ($avatar != $oldAvatar) && file_exists(ATTACHMENT_PATH . $oldAvatar)) { @unlink(ATTACHMENT_PATH . $oldAvatar); } $this->error = 1013; RedisService::clear($cacheLockKey); return true; } /** * 认证 * @param $userId * @param $params * @return bool */ public function auth($userId, $params) { $cacheLockKey = "caches:members:auth_{$userId}"; if (RedisService::get($cacheLockKey)) { $this->error = 1034; return false; } // 用户验证 RedisService::set($cacheLockKey, ['user_id' => $userId, 'params' => $params], rand(2, 3)); $info = $this->model->where(['id' => $userId, 'mark' => 1]) ->select(['id', 'realname','idcard','bank_name','bank_card','bank_branch','is_auth', 'status']) ->first(); if (!$info || $info['status'] != 1) { $this->error = '账号或已被冻结,请联系客服'; RedisService::clear($cacheLockKey); return false; } if($info['is_auth'] == 1 && $info['idcard'] && $info['realname'] && $info['bank_name'] && $info['bank_card'] && $info['bank_branch']){ $this->error = '抱歉,您已完成认证'; RedisService::clear($cacheLockKey); return false; } // 认证数据 $data = [ 'realname'=> isset($params['realname'])?$params['realname'] : '', 'idcard'=> isset($params['idcard'])?$params['idcard'] : '', 'bank_name'=> isset($params['bank_name'])?$params['bank_name'] : '', 'bank_card'=> isset($params['bank_card'])?$params['bank_card'] : '', 'bank_branch'=> isset($params['bank_branch'])?$params['bank_branch'] : '', 'is_auth'=> 1, 'update_time' => time() ]; if (!$this->model->where(['id' => $userId])->update($data)) { $this->error = '认证提交失败'; RedisService::clear($cacheLockKey); return false; } $this->error = '恭喜您,已完成认证'; RedisService::clear($cacheLockKey); RedisService::clear("caches:members:authInfo:{$userId}"); return true; } /** * 账号注销 * @param $userId * @return bool */ public function logOff($userId) { $info = $this->model->where(['id' => $userId, 'mark' => 1]) ->select(['id', 'password', 'status']) ->first(); $status = isset($info['status']) ? $info['status'] : 0; if (empty($info)) { $this->error = 2044; return false; } if ($status != 1) { $this->error = 2044; return false; } if (!$this->model->where(['id' => $userId])->update(['status' => 3, 'update_time' => time()])) { $this->error = 2049; return false; } $this->error = 2048; RedisService::clear("auths:info:" . $userId); return true; } }