vr-shopxo-plugin/shopxo/app/service/UserService.php

3645 lines
126 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;
use think\facade\Db;
use app\service\SystemService;
use app\service\RegionService;
use app\service\SafetyService;
use app\service\ResourcesService;
use app\service\SystemBaseService;
use app\service\ConfigService;
use app\service\ApiService;
/**
* 用户服务层
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-01T21:51:08+0800
*/
class UserService
{
// user登录session key
public static $user_login_key = 'user_login_info';
public static $user_token_key = 'user_token_data';
/**
* 用户列表
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-06T21:31:53+0800
* @param [array] $params [输入参数]
*/
public static function UserList($params = [])
{
$where = empty($params['where']) ? [] : $params['where'];
$field = empty($params['field']) ? '*' : $params['field'];
$order_by = empty($params['order_by']) ? 'id desc' : trim($params['order_by']);
$m = isset($params['m']) ? intval($params['m']) : 0;
$n = isset($params['n']) ? intval($params['n']) : 10;
// 用户列表读取前钩子
$hook_name = 'plugins_service_user_list_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'where' => &$where,
'field' => &$field,
'order_by' => &$order_by,
'm' => &$m,
'n' => &$n,
]);
// 获取用户列表
$data = Db::name('User')->where($where)->order($order_by)->field($field)->limit($m, $n)->select()->toArray();
return DataReturn(MyLang('handle_success'), 0, self::UserListHandle($data, $params));
}
/**
* 列表数据处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-01
* @desc description
* @param [array] $data [数据列表]
* @param [array] $params [输入参数]
*/
public static function UserListHandle($data, $params = [])
{
if(!empty($data))
{
// 用户列表钩子-前面
$hook_name = 'plugins_service_user_list_handle_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'data' => &$data,
]);
// 字段列表
$keys = ArrayKeys($data);
// 邀请用户列表
$referrer_data = [];
if(in_array('referrer', $keys))
{
$referrer_data = self::GetUserViewInfo(array_column($data, 'referrer'));
}
// 用户平台信息
$platform_data = [];
if(in_array('id', $keys))
{
$platform = Db::name('UserPlatform')->where(['user_id'=>array_column($data, 'id')])->select()->toArray();
if(!empty($platform))
{
$common_platform_type = MyConst('common_platform_type');
foreach($platform as $v)
{
if(!array_key_exists($v['user_id'], $platform_data))
{
$platform_data[$v['user_id']] = ['data'=>[], 'system'=>[], 'platform'=>[]];
}
$v['platform_name'] = isset($common_platform_type[$v['platform']]) ? $common_platform_type[$v['platform']]['name'] : $v['platform'];
$platform_data[$v['user_id']]['data'][] = $v;
if(!in_array($v['system_type'], $platform_data[$v['user_id']]['system']))
{
$platform_data[$v['user_id']]['system'][] = $v['system_type'];
}
if(!in_array($v['platform_name'], $platform_data[$v['user_id']]['platform']))
{
$platform_data[$v['user_id']]['platform'][] = $v['platform_name'];
}
}
}
}
// 开始处理数据
$common_gender_list = MyConst('common_gender_list');
$common_user_status_list = MyConst('common_user_status_list');
foreach($data as &$v)
{
// 生日
if(array_key_exists('birthday', $v))
{
$v['birthday'] = empty($v['birthday']) ? '' : date('Y-m-d', $v['birthday']);
}
// 头像
if(array_key_exists('avatar', $v))
{
if(!empty($v['avatar']))
{
$v['avatar'] = ResourcesService::AttachmentPathViewHandle($v['avatar']);
} else {
$v['avatar'] = UserDefaultAvatar();
}
}
// 邀请用户信息
if(array_key_exists('referrer', $v))
{
$v['referrer_info'] = (!empty($referrer_data) && is_array($referrer_data) && array_key_exists($v['referrer'], $referrer_data)) ? $referrer_data[$v['referrer']] : [];
}
// 用户平台信息
if(array_key_exists('id', $v))
{
$temp = (empty($platform_data) || empty($platform_data[$v['id']])) ? [] : $platform_data[$v['id']];
$v['user_platform_data'] = empty($temp['data']) ? [] : $temp['data'];
$v['system_type_list'] = empty($temp['system']) ? [] : $temp['system'];
$v['platform_list'] = empty($temp['platform']) ? [] : $temp['platform'];
$v['system_type_text'] = empty($v['system_type_list']) ? '' : implode('', $v['system_type_list']);
$v['platform_text'] = empty($v['platform_list']) ? '' : implode('', $v['platform_list']);
}
// 时间
if(array_key_exists('add_time', $v))
{
$v['add_time'] = date('Y-m-d H:i:s', $v['add_time']);
}
if(array_key_exists('upd_time', $v))
{
$v['upd_time'] = empty($v['upd_time']) ? '' : date('Y-m-d H:i:s', $v['upd_time']);
}
// 性别
if(array_key_exists('gender', $v))
{
$v['gender_text'] = isset($common_gender_list[$v['gender']]) ? $common_gender_list[$v['gender']]['name'] : '';
}
// 状态
if(array_key_exists('status', $v))
{
$v['status_text'] = $common_user_status_list[$v['status']]['name'];
}
}
// 用户列表钩子-后面
$hook_name = 'plugins_service_user_list_handle_end';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'data' => &$data,
]);
}
return $data;
}
/**
* 用户总数
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-10T22:16:29+0800
* @param [array] $where [条件]
*/
public static function UserTotal($where)
{
// 用户总数读取前钩子
$hook_name = 'plugins_service_user_total_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'where' => &$where,
]);
// 获取总数
return (int) Db::name('User')->where($where)->count();
}
/**
* 获取用户登录信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-12-06
* @desc description
* @param [boolean] $is_cache [是否缓存读取]
*/
public static function LoginUserInfo($is_cache = true)
{
// 静态数据避免重复读取
static $user_login_info = null;
if($user_login_info === null && $is_cache)
{
$user_login_info = self::CacheLoginUserInfo();
}
// 缓存为空则重新读取
if(empty($user_login_info))
{
if(APPLICATION == 'web')
{
// web用户session
$user_login_info = MySession(self::$user_login_key);
}
if(empty($user_login_info))
{
$params = input();
if(!empty($params['token']))
{
$user_login_info = self::UserTokenData($params['token']);
}
}
}
return $user_login_info;
}
/**
* 获取用户token用户数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2019-08-18T19:01:59+0800
* @desc description
* @param [string] $token [用户token]
*/
public static function UserTokenData($token)
{
// token缓存数据
$user = self::CacheUserTokenData($token);
if(!empty($user) && isset($user['id']))
{
return $user;
}
// 数据库校验
return self::AppUserInfoHandle(['where_field'=>'token', 'where_value'=>$token, 'is_refresh_token'=>0]);
}
/**
* 用户登录缓存数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-03-28
* @desc description
*/
public static function CacheLoginUserInfo()
{
// 静态数据避免重复读取
static $user_cache_login_info = null;
if($user_cache_login_info === null)
{
// 参数
$params = input();
// 用户数据处理
if(APPLICATION == 'web')
{
// web用户session
$user_cache_login_info = MySession(self::$user_login_key);
// 用户信息为空指定了token则设置登录信息
if(empty($user_cache_login_info))
{
$token = empty($params['token']) ? MyCookie(self::$user_token_key) : $params['token'];
if(!empty($token))
{
$user_cache_login_info = self::CacheUserTokenData($token);
// 存在token用户信息则记录session
if(!empty($user_cache_login_info))
{
self::UserLoginRecord(0, $user_cache_login_info);
}
}
}
} else {
if(!empty($params['token']))
{
$user_cache_login_info = self::CacheUserTokenData($params['token']);
}
}
}
return $user_cache_login_info;
}
/**
* 获取用户token缓存用户数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @datetime 2019-08-18T19:01:59+0800
* @desc description
* @param [string] $token [用户token]
*/
public static function CacheUserTokenData($token)
{
return MyCache(SystemService::CacheKey('shopxo.cache_user_info').$token);
}
/**
* 用户状态校验
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-02-27
* @desc description
* @param [int] $user_id [用户id]
* @param [array] $valid_status [有效状态]
*/
public static function UserStatusCheck($user_id, $valid_status = [0])
{
// 查询用户状态是否正常
$user = self::UserBaseInfo('id', $user_id);
if(empty($user))
{
return DataReturn(MyLang('common_service.user.user_no_exist_tips'), -110);
}
if(!is_array($valid_status))
{
$valid_status = explode(',', $valid_status);
}
if(!in_array($user['status'], $valid_status))
{
$common_user_status_list = MyConst('common_user_status_list');
if(isset($common_user_status_list[$user['status']]))
{
return DataReturn($common_user_status_list[$user['status']]['tips'], -110);
} else {
return DataReturn(MyLang('common_service.user.user_status_error_tips'), -110);
}
}
return DataReturn(MyLang('check_success'), 0);
}
/**
* 根据字段获取用户基础信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-01-25
* @desc description
* @param [string] $where_field [字段名称]
* @param [string] $where_value [字段值]
* @param [string] $field [指定字段]
*/
public static function UserBaseInfo($where_field, $where_value, $field = '*')
{
$where = [
[$where_field, '=', $where_value],
['is_delete_time', '=', 0],
['is_logout_time', '=', 0],
];
return Db::name('User')->where($where)->field($field)->find();
}
/**
* 根据字段获取用户平台信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-01-25
* @desc description
* @param [string] $where_field [字段名称]
* @param [string] $where_value [字段值]
* @param [string] $field [指定字段]
* @param [array] $params [输入参数]
*/
public static function UserPlatformInfo($where_field, $where_value, $field = '*', $params = [])
{
$system_type = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
$platform = empty($params['platform']) ? APPLICATION_CLIENT_TYPE : $params['platform'];
$where = [
[$where_field, '=', $where_value],
['system_type', '=', $system_type],
['platform', '=', $platform],
];
return Db::name('UserPlatform')->where($where)->field($field)->find();
}
/**
* 根据字段获取用户信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-01-25
* @desc description
* @param [string] $where_field [字段名称]
* @param [string] $where_value [字段值]
* @param [string] $field [指定字段]
* @param [array] $params [输入参数]
*/
public static function UserInfo($where_field, $where_value, $field = '*', $params = [])
{
// 用户平台表结构
$platform_structure = ResourcesService::TableStructureData('UserPlatform');
unset($platform_structure['id'], $platform_structure['user_id'], $platform_structure['add_time'], $platform_structure['upd_time']);
$platform_structure = array_keys($platform_structure);
// 用户基础和平台条件
$where_field_arr = explode('|', $where_field);
foreach($where_field_arr as $k=>$v)
{
$where_field_arr[$k] = (in_array($v, $platform_structure) ? 'up.' : 'u.').$v;
}
$where_field = implode('|', $where_field_arr);
// 查询字段处理
if($field == '*')
{
$field = 'u.*, up.'.implode(', up.', $platform_structure);
} else {
$field_arr = explode(',', $field);
$u_arr = array_diff($field_arr, $platform_structure);
$up_arr = array_intersect($field_arr, $platform_structure);
$field = 'u.'.implode(', u.', $u_arr).(empty($up_arr) ? '' : ', up.'.implode(', up.', $up_arr));
}
// 查询用户信息
$system_type = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
$platform = empty($params['platform']) ? APPLICATION_CLIENT_TYPE : $params['platform'];
$where = [
[$where_field, '=', $where_value],
['up.system_type', '=', $system_type],
['up.platform', '=', $platform],
['u.is_delete_time', '=', 0],
['u.is_logout_time', '=', 0],
];
$user = Db::name('User')->alias('u')->join('user_platform up', 'u.id=up.user_id')->where($where)->field($field)->find();
// 如果当前系统类型和平台 用户和平台表没有对应数据,则先读取用户基础信息在匹配平台数据
if(empty($user))
{
// 是否存在条件字段.指定前缀,则去除
if(stripos($where_field, '.') !== false)
{
$temp = explode('.', $where_field);
$where_field = $temp[1];
}
// 如果当前条件字段是平台表字段则先从平台表读取数据
if(in_array($where_field, $platform_structure))
{
$user_platform = self::MatchingUserPlatformData($where_field, $where_value, $params);
if(!empty($user_platform))
{
$user = self::UserBaseInfo('id', $user_platform['user_id'], '*', $params);
if(!empty($user))
{
$user = array_merge($user, $user_platform);
}
}
} else {
$user = self::UserBaseInfo($where_field, $where_value, '*', $params);
if(!empty($user))
{
$user_platform = self::MatchingUserPlatformData('user_id', $user['id'], $params);
if(!empty($user_platform))
{
$user = array_merge($user, $user_platform);
}
}
}
}
return $user;
}
/**
* 匹配用户平台数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-12-29
* @desc description
* @param [string] $where_field [字段名称]
* @param [string] $where_value [字段值]
* @param [array] $params [输入参数]
*/
public static function MatchingUserPlatformData($where_field, $where_value, $params = [])
{
$temp_platform = [];
$user_platform = Db::name('UserPlatform')->where([$where_field=>$where_value])->select()->toArray();
if(!empty($user_platform))
{
$platform = empty($params['platform']) ? APPLICATION_CLIENT_TYPE : $params['platform'];
foreach($user_platform as $pv)
{
// 优先取当前平台类型的数据
if($pv['platform'] == $platform)
{
$temp_platform = $pv;
break;
}
}
if(empty($temp_platform))
{
$temp_platform = $user_platform[0];
}
unset($temp_platform['id'], $temp_platform['add_time'], $temp_platform['upd_time']);
}
return $temp_platform;
}
/**
* 根据字段获取用户系统信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-01-25
* @desc description
* @param [string] $where_field [字段名称]
* @param [string] $where_value [字段值]
* @param [string] $field [指定字段]
* @param [array] $params [输入参数]
*/
public static function UserSystemInfo($where_field, $where_value, $field = 'u.*', $params = [])
{
$system_type = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
$where = [
[$where_field, '=', $where_value],
['up.system_type', '=', $system_type],
['u.is_delete_time', '=', 0],
['u.is_logout_time', '=', 0],
];
return Db::name('User')->alias('u')->join('user_platform up', 'u.id=up.user_id')->where($where)->field($field)->find();
}
/**
* 用户平台信息添加
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-03-15
* @desc description
* @param [array] $data [用户平台信息]
* @param [array] $params [输入参数]
*/
public static function UserPlatformInsert($data, $params = [])
{
// 系统标识
if(empty($data['system_type']))
{
$data['system_type'] = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
}
// 平台
if(empty($data['platform']))
{
$data['platform'] = APPLICATION_CLIENT_TYPE;
}
$data['add_time'] = time();
return Db::name('UserPlatform')->insertGetId($data) > 0;
}
/**
* 用户平台信息更新
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-03-15
* @desc description
* @param [string] $where_field [条件字段]
* @param [string] $where_value [条件值]
* @param [array] $data [更新数据]
* @param [array] $params [输入参数]
*/
public static function UserPlatformUpdate($where_field, $where_value, $data, $params = [])
{
$where = [
[$where_field, '=', $where_value],
];
// 非自增id则增加更多条件
if($where_field != 'id')
{
$system_type = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
$platform = empty($params['platform']) ? APPLICATION_CLIENT_TYPE : $params['platform'];
$where[] = ['system_type', '=', $system_type];
$where[] = ['platform', '=', $platform];
}
$data['upd_time'] = time();
return Db::name('UserPlatform')->where($where)->update($data);
}
/**
* 用户信息保存
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-10T22:16:29+0800
* @param [array] $params [输入参数]
*/
public static function UserSave($params = [])
{
// 请求参数
$p = [
[
'checked_type' => 'empty',
'key_name' => 'admin',
'error_msg' => MyLang('common_service.user.save_admin_info_error_tips'),
],
[
'checked_type' => 'length',
'key_name' => 'username',
'checked_data' => '30',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_username_message'),
],
[
'checked_type' => 'unique',
'key_name' => 'username',
'checked_data' => 'User',
'checked_key' => 'id',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.save_user_already_exist_tips'),
],
[
'checked_type' => 'length',
'key_name' => 'nickname',
'checked_data' => '30',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_nickname_message'),
],
[
'checked_type' => 'fun',
'key_name' => 'mobile',
'checked_data' => 'CheckMobile',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_mobile_message'),
],
[
'checked_type' => 'fun',
'key_name' => 'email',
'checked_data' => 'CheckEmail',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_email_message'),
],
[
'checked_type' => 'in',
'key_name' => 'gender',
'checked_data' => array_column(MyConst('common_gender_list'), 'id'),
'error_msg' => MyLang('common_service.user.save_gender_range_error_tips'),
],
[
'checked_type' => 'in',
'key_name' => 'status',
'checked_data' => array_column(MyConst('common_user_status_list'), 'id'),
'error_msg' => MyLang('common_service.user.save_status_range_error_tips'),
],
[
'checked_type' => 'length',
'key_name' => 'address',
'checked_data' => '80',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_address_message'),
],
[
'checked_type' => 'fun',
'key_name' => 'pwd',
'checked_data' => 'CheckLoginPwd',
'is_checked' => 1,
'error_msg' => MyLang('common_service.user.form_item_pwd_message'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 附件
$attachment = ResourcesService::AttachmentParams($params, ['avatar']);
if($attachment['code'] != 0)
{
return $attachment;
}
// 更新数据
$data = [
'avatar' => $attachment['data']['avatar'],
'username' => isset($params['username']) ? $params['username'] : '',
'nickname' => isset($params['nickname']) ? $params['nickname'] : '',
'mobile' => isset($params['mobile']) ? $params['mobile'] : '',
'email' => isset($params['email']) ? $params['email'] : '',
'province' => empty($params['province']) ? '' : $params['province'],
'city' => empty($params['city']) ? '' : $params['city'],
'county' => empty($params['county']) ? '' : $params['county'],
'address' => empty($params['address']) ? '' : $params['address'],
'gender' => intval($params['gender']),
'integral' => intval($params['integral']),
'locking_integral' => intval($params['locking_integral']),
'status' => intval($params['status']),
'birthday' => empty($params['birthday']) ? 0 : strtotime($params['birthday']),
'referrer' => empty($params['referrer']) ? 0 : intval($params['referrer']),
];
// 邀请人处理
if(!empty($data['referrer']) && !empty($params['id']))
{
// 邀请人不能为当前用户id、相同则去掉
if($data['referrer'] == $params['id'])
{
$data['referrer'] = 0;
}
// 对方的邀请是否是当前用户
if(!empty($data['referrer']))
{
$referrer = Db::name('User')->where(['id'=>$data['referrer']])->value('referrer');
if(!empty($referrer) && $referrer == $params['id'])
{
$data['referrer'] = 0;
}
}
}
// 用户保存处理钩子
$hook_name = 'plugins_service_user_save_handle';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'data' => &$data,
'user_id' => isset($params['id']) ? intval($params['id']) : 0,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 密码
if(!empty($params['pwd']))
{
$data['salt'] = GetNumberCode(6);
$data['pwd'] = LoginPwdEncryption(trim($params['pwd']), $data['salt']);
}
// 更新/添加
if(!empty($params['id']))
{
// 获取用户信息
$user = Db::name('User')->where(['id'=>intval($params['id'])])->field('id,integral')->find();
if(empty($user))
{
return DataReturn(MyLang('common_service.user.save_user_info_no_exist_tips'), -10);
}
$ret = self::UserUpdateHandle($data, $params['id'], $params);
if($ret['code'] == 0)
{
$user_id = $params['id'];
}
} else {
$ret = self::UserInsert($data);
if($ret['code'] != 0)
{
return $ret;
}
$user_id = $ret['data']['user_id'];
}
// 添加用户后处理钩子
$hook_name = 'plugins_service_user_save_success_handle';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'data' => &$data,
'user_id' => &$user_id,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 状态
if(isset($user_id))
{
if(($data['integral'] > 0 && empty($user)) || (isset($user['integral']) && $user['integral'] != $data['integral']))
{
$integral_type = 1;
$old_integral = 0;
$opt_integral = $data['integral'];
if(!empty($params['id']))
{
$old_integral = $user['integral'];
$integral_type = ($user['integral'] > $data['integral']) ? 0 : 1;
$opt_integral = ($integral_type == 1) ? $data['integral']-$user['integral'] : $user['integral']-$data['integral'];
}
IntegralService::UserIntegralLogAdd($user_id, $old_integral, $opt_integral, MyLang('common_service.user.admin_operate_name'), $integral_type, $params['admin']['id']);
}
return DataReturn(MyLang('operate_success'), 0);
}
return DataReturn(MyLang('operate_fail'), -100);
}
/**
* 用户信息更新
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-02-13
* @desc description
* @param [array] $data [用户更新信息]
* @param [int] $user_id [用户id]
* @param [array] $params [输入参数]
*/
public static function UserUpdateHandle($data, $user_id, $params = [])
{
// 注册数据分离处理
// 用户平台表结构
$structure = ResourcesService::TableStructureData('UserPlatform');
unset($structure['id'], $structure['user_id'], $structure['add_time'], $structure['upd_time']);
$user_base = [];
$user_platform = [];
foreach($data as $k=>$v)
{
if(array_key_exists($k, $structure))
{
$user_platform[$k] = $v;
} else {
$user_base[$k] = $v;
}
}
// 用户信息更新
$user_base['upd_time'] = time();
if(Db::name('User')->where(['id'=>$user_id])->update($user_base) === false)
{
return DataReturn(MyLang('update_fail'), -100);
}
// 用户平台信息更新
$user_platform['user_id'] = $user_id;
if(self::UserPlatformUpdate('user_id', $user_id, $user_platform, $params) === false)
{
return DataReturn(MyLang('update_fail'), -100);
}
// 更新成功后钩子
$hook_name = 'plugins_service_user_update_success';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user_id' => $user_id,
'data' => $data,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
return DataReturn(MyLang('update_success'), 0);
}
/**
* 用户删除
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-10T22:16:29+0800
* @param [array] $params [输入参数]
*/
public static function UserDelete($params = [])
{
// 参数是否有误
if(empty($params['ids']))
{
return DataReturn(MyLang('data_id_error_tips'), -1);
}
// 是否数组
if(!is_array($params['ids']))
{
$params['ids'] = explode(',', $params['ids']);
}
// 用户表
if(!Db::name('User')->where(['id'=>$params['ids']])->delete())
{
return DataReturn(MyLang('delete_fail'), -100);
}
// 用户平台信息表
if(Db::name('UserPlatform')->where(['user_id'=>$params['ids']])->delete() === false)
{
return DataReturn(MyLang('delete_fail'), -100);
}
return DataReturn(MyLang('delete_success'), 0);
}
/**
* 用户登录记录
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-09T11:37:43+0800
* @param [int] $user_id [用户id]
* @param [array] $user [用户信息]
* @param [array] $params [输入参数]
* @return [boolean] [记录成功true, 失败false]
*/
public static function UserLoginRecord($user_id = 0, $user = [], $params = [])
{
if(!empty($user_id) && empty($user))
{
$user = self::UserHandle(self::UserInfo('id', $user_id, '*', $params));
}
if(!empty($user))
{
// 用户id处理
if(empty($user_id))
{
$user_id = $user['id'];
}
// 用户登录成功信息纪录钩子
$hook_name = 'plugins_service_user_login_success_record';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user' => &$user,
'user_id' => $user_id
]);
// 通过token存储用户缓存信息
if(!empty($user['token']))
{
MyCache(SystemService::CacheKey('shopxo.cache_user_info').$user['token'], $user);
}
// web端设置session
if(APPLICATION == 'web')
{
// 存储session
MySession(self::$user_login_key, $user);
// 设置cookie数据
MyCookie('user_info', json_encode($user, JSON_UNESCAPED_UNICODE), false);
}
return true;
}
return false;
}
/**
* 用户数据处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-01-23
* @desc description
* @param [ array] $user [用户数据]
*/
public static function UserHandle($user)
{
if(!empty($user))
{
// 基础数据处理
if(isset($user['add_time']))
{
$user['add_time_text'] = date('Y-m-d H:i:s', $user['add_time']);
}
if(isset($user['upd_time']))
{
$user['upd_time_text'] = date('Y-m-d H:i:s', $user['upd_time']);
}
if(isset($user['gender']))
{
$user['gender_text'] = MyConst('common_gender_list')[$user['gender']]['name'];
}
if(isset($user['birthday']))
{
$user['birthday'] = empty($user['birthday']) ? '' : date('Y-m-d', $user['birthday']);
}
// 邮箱/手机
if(isset($user['mobile']))
{
$user['mobile_security'] = empty($user['mobile']) ? '' : mb_substr($user['mobile'], 0, 3, 'utf-8').'***'.mb_substr($user['mobile'], -3, null, 'utf-8');
}
if(isset($user['email']))
{
$user['email_security'] = empty($user['email']) ? '' : mb_substr($user['email'], 0, 3, 'utf-8').'***'.mb_substr($user['email'], -3, null, 'utf-8');
}
// 地址信息
if(isset($user['province']) && isset($user['city']) && isset($user['county']) && isset($user['address']))
{
$user['address_info'] = $user['province'].$user['city'].$user['county'].$user['address'];
}
// 显示名称,根据规则优先展示
$user['user_name_view'] = isset($user['nickname']) ? $user['nickname'] : '';
if(empty($user['user_name_view']) && isset($user['username']))
{
$user['user_name_view'] = $user['username'];
}
if(empty($user['user_name_view']) && isset($user['mobile_security']))
{
$user['user_name_view'] = $user['mobile_security'];
}
if(empty($user['user_name_view']) && isset($user['email_security']))
{
$user['user_name_view'] = $user['email_security'];
}
// 头像
if(isset($user['avatar']))
{
if(!empty($user['avatar']))
{
$user['avatar'] = ResourcesService::AttachmentPathViewHandle($user['avatar']);
} else {
$user['avatar'] = UserDefaultAvatar();
}
}
// 是否设置了密码
$user['is_setup_pwd'] = empty($user['pwd']) ? 0 : 1;
// 移除特殊数据
unset($user['pwd'], $user['salt']);
}
return $user;
}
/**
* 用户头像更新
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-10-16
* @desc description
* @param [array] $params [输入参数]
*/
public static function UserAvatarUpload($params = [])
{
// 用户id
$user_id = (empty($params['user']) || empty($params['user']['id'])) ? 0 : $params['user']['id'];
// 唯一标识
$unique = md5(empty($user_id) ? ResourcesService::UserUniqueId() : $user_id);
// 缓存key、是否操作频繁
$cache_key = 'cache_user_avatar_upload_frequency_'.$unique;
$cache_value = MyCache($cache_key);
if(!empty($cache_value) && $cache_value['time']+3600 > time() && $cache_value['count'] >= 5)
{
return DataReturn(MyLang('operate_frequent_tips'), -1);
}
// 开始处理图片存储
// 定义图片目录
$root_path = ROOT.'public'.DS;
$img_path = 'static'.DS.'upload'.DS.'images'.DS.'user_avatar'.DS;
$date = DS.date('Y').DS.date('m').DS.date('d').DS;
// 图像类库
$images_obj = \base\Images::Instance(['is_new_name'=>false]);
// 文件上传校验、仅表单$_FILES的方式验证
$is_file_url = !empty($params[$params['img_field']]) && substr($params[$params['img_field']], 0, 4) == 'http';
if(!$is_file_url)
{
$error = FileUploadError($params['img_field']);
if($error !== true)
{
return DataReturn($error, -2);
}
}
// 头像处理前钩子
$hook_name = 'plugins_service_user_avatar_upload_begin';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user_id' => $user_id,
'unique' => $unique,
'params' => $params,
'files' => $_FILES,
'root_path' => $root_path,
'img_path' => $img_path,
'date' => $date,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 是否指定裁剪信息
$original_dir = $root_path.$img_path.'original'.$date;
// 是否url链接地址
if($is_file_url)
{
$original = $images_obj->DownloadImageSave($params[$params['img_field']], $original_dir);
} else {
if(!empty($params['img_width']) && !empty($params['img_height']) && isset($params['img_x']) && isset($params['img_y']))
{
$original = $images_obj->GetCompressCut($_FILES[$params['img_field']], $original_dir, 800, 800, $params['img_x'], $params['img_y'], $params['img_width'], $params['img_height']);
} else {
$original = $images_obj->GetOriginal($_FILES[$params['img_field']], $original_dir);
}
}
if(!empty($original))
{
$compr = $images_obj->GetBinaryCompress($root_path.$img_path.'original'.$date.$original, $root_path.$img_path.'compr'.$date, 200, 200);
$small = $images_obj->GetBinaryCompress($root_path.$img_path.'original'.$date.$original, $root_path.$img_path.'small'.$date, 50, 50);
}
if(empty($compr) || empty($small))
{
return DataReturn(MyLang('images_format_error_tips'), -3);
}
$avatar = DS.$img_path.'compr'.$date.$compr;
// 缓存记录
if(empty($cache_value))
{
$cache_value = ['count'=>1, 'time'=>time()];
} else {
$cache_value['count']++;
}
MyCache($cache_key, $cache_value, 3600);
// 头像处理后钩子
$hook_name = 'plugins_service_user_avatar_upload_end';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user_id' => $user_id,
'unique' => $unique,
'params' => $params,
'files' => $_FILES,
'root_path' => $root_path,
'img_path' => $img_path,
'date' => $date,
'avatar' => $avatar,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// app则直接返回图片地址
if(APPLICATION == 'app')
{
return DataReturn(MyLang('upload_success'), 0, ResourcesService::AttachmentPathViewHandle($avatar));
}
// 更新用户头像
$data = [
'avatar' => $avatar,
'upd_time' => time(),
];
if(Db::name('User')->where(['id'=>$user_id])->update($data))
{
// 头像处理成功钩子
$hook_name = 'plugins_service_user_avatar_upload_success';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user_id' => $user_id,
'unique' => $unique,
'params' => $params,
'files' => $_FILES,
'root_path' => $root_path,
'img_path' => $img_path,
'date' => $date,
'avatar' => $avatar,
]);
// web端用户登录纪录处理
if(self::UserLoginRecord($params['user']['id']))
{
return DataReturn(MyLang('upload_success'), 0);
}
}
return DataReturn(MyLang('upload_fail'), -100);
}
/**
* 用户登录
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-03
* @desc description
* @param [array] $params [输入参数]
*/
public static function Login($params = [])
{
// 用户登录前校验钩子
$hook_name = 'plugins_service_user_login_begin_check';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 请求参数
$p = [
[
'checked_type' => 'in',
'key_name' => 'type',
'checked_data' => array_column(MyConst('common_login_type_list'), 'value'),
'error_msg' => MyLang('login_type_error_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'accounts',
'error_msg' => MyLang('accounts_empty_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 是否开启用户登录
if(!in_array($params['type'], MyC('home_user_login_type', [], true)))
{
return DataReturn(MyLang('login_close_tips'), -1);
}
// 账户校验
$ac = self::UserLoginAccountsCheck($params);
if($ac['code'] != 0)
{
return $ac;
}
// 验证参数
$verify_params = [
'key_prefix' => 'user_login_'.md5($params['accounts']),
'expire_time' => MyC('common_verify_expire_time'),
];
// 帐号密码登录需要校验密码
if($params['type'] == 'username')
{
// 请求参数
$p = [
[
'checked_type' => 'fun',
'key_name' => 'pwd',
'checked_data' => 'CheckLoginPwd',
'error_msg' => MyLang('common_service.user.form_item_pwd_message'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 帐号密码登录是否开启图片验证码
$verify_params['key_prefix'] = 'user_login';
$verify = self::IsImaVerify($params, $verify_params, MyC('home_user_login_img_verify_state'));
if($verify['code'] != 0)
{
return $verify;
}
} else {
// 账户类型
$obj = null;
switch($params['type'])
{
// 短信
case 'sms' :
$obj = new \base\Sms($verify_params);
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
break;
// 未知的字段
default :
return DataReturn(MyLang('verify_type_error_tips'), -1);
}
// 验证码校验
// sms, email
if(isset($obj) && is_object($obj))
{
// 是否已过期
if(!$obj->CheckExpire())
{
return DataReturn(MyLang('verify_code_expire_tips'), -10);
}
// 是否正确
if(!$obj->CheckCorrect($params['verify']))
{
return DataReturn(MyLang('verify_code_error_tips'), -11);
}
}
}
// 获取用户账户信息
$method = self::UserUniqueMethod();
$user = self::$method($ac['data'], $params['accounts']);
if(empty($user))
{
return DataReturn(MyLang('accounts_error_tips'), -3);
}
// 密码校验
// 帐号密码登录需要校验密码
if($params['type'] == 'username')
{
if(empty($user['pwd']) || empty($user['salt']))
{
return DataReturn(MyLang('password_no_setup_tips'), -4);
}
$pwd = LoginPwdEncryption($params['pwd'], $user['salt']);
if($pwd != $user['pwd'])
{
return DataReturn(MyLang('password_error_tips'), -4);
}
}
// 用户平台信息、不存在则添加
$user_platform = self::UserPlatformInfo('user_id', $user['id']);
if(empty($user_platform))
{
if(!self::UserPlatformInsert(['user_id' => $user['id']], $params))
{
return DataReturn(MyLang('insert_fail'), -1);
}
}
// 用户状态
if(in_array($user['status'], [2,3]))
{
return DataReturn(MyConst('common_user_status_list')[$user['status']]['tips'], -10);
}
// 用户登录前钩子
$hook_name = 'plugins_service_user_login_begin';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'user_id' => $user['id']
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 返回数据,更新数据库
$upd_data = [];
if($params['type'] == 'username')
{
$salt = GetNumberCode(6);
$upd_data['salt'] = $salt;
$upd_data['pwd'] = LoginPwdEncryption($params['pwd'], $salt);
}
// 用户openid
if(empty($user_platform[APPLICATION_CLIENT_TYPE.'_openid']))
{
$openid = self::UserOpenidHandle($params);
if(!empty($openid['field']) && !empty($openid['value']))
{
// openid放入用户data中
$upd_data[$openid['field']] = $openid['value'];
}
}
// 用户unionid
if(empty($user_platform[APPLICATION_CLIENT_TYPE.'_unionid']))
{
$unionid = self::UserUnionidHandle($params);
if(!empty($unionid['field']) && !empty($unionid['value']))
{
// unionid放入用户data中
$upd_data[$unionid['field']] = $unionid['value'];
}
}
// 昵称和头像
if(empty($user['nickname']) && !empty($params['nickname']))
{
$upd_data['nickname'] = $params['nickname'];
}
if((empty($user['avatar']) || stripos($user['avatar'], 'default-user-avatar') !== false) && !empty($params['avatar']))
{
$upd_data['avatar'] = $params['avatar'];
}
// 更新用户信息
if(!empty($upd_data))
{
$ret = self::UserUpdateHandle($upd_data, $user['id'], $params);
if($ret['code'] != 0)
{
return DataReturn(MyLang('login_failure_tips'), -100);
}
}
// 清除图片验证码
if(isset($verify) && isset($verify['data']) && is_object($verify['data']))
{
$verify['data']->Remove();
}
return self::UserLoginHandle($user['id'], $params);
}
/**
* 登录处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-05-24
* @desc description
* @param [int] $user_id [用户id]
* @param [array] $params [输入参数]
*/
public static function UserLoginHandle($user_id, $params = [])
{
// 返回前端html代码
$body_html = [];
// 用户登录后钩子
$user = self::UserHandle(self::UserInfo('id', $user_id, '*', $params));
// 会员码生成处理
if(empty($user['number_code']))
{
$user['number_code'] = self::UserNumberCodeCreatedHandle($user_id);
}
// token
$user['token'] = self::UserTokenUpdate($user_id, $user);
// 登录钩子
$hook_name = 'plugins_service_user_login_end';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'user_id' => $user_id,
'user' => $user,
'body_html' => &$body_html,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 登录记录
if(self::UserLoginRecord(0, $user))
{
// 成功返回
if(APPLICATION == 'app')
{
$result = self::AppUserInfoHandle(['user'=>$user, 'is_refresh_token'=>0]);
} else {
$result = [
'body_html' => is_array($body_html) ? implode(' ', $body_html) : $body_html,
'user_id' => $user_id,
];
}
return DataReturn(MyLang('login_success'), 0, $result);
}
return DataReturn(MyLang('login_failure_tips'), -100);
}
/**
* 用户注册
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-03
* @desc description
* @param [array] $params [输入参数]
*/
public static function Reg($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => 'accounts',
'error_msg' => MyLang('accounts_empty_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'pwd',
'error_msg' => MyLang('password_empty_tips'),
],
[
'checked_type' => 'in',
'key_name' => 'type',
'checked_data' => array_column(MyConst('common_user_reg_type_list'), 'value'),
'error_msg' => MyLang('register_type_error_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'verify',
'is_checked' => 2,
'error_msg' => MyLang('verify_code_empty_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 用户注册前校验钩子
$hook_name = 'plugins_service_user_register_begin_check';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 是否开启用户注册
if(!in_array($params['type'], MyC('home_user_reg_type', [], true)))
{
return DataReturn(MyLang('register_close_tips'), -1);
}
// 账户校验
$ret = self::UserRegAccountsCheck($params);
if($ret['code'] != 0)
{
return $ret;
}
// 是否需要审核
$common_register_is_enable_audit = MyC('common_register_is_enable_audit', 0);
// 用户数据
$salt = GetNumberCode(6);
$data = [
'upd_time' => time(),
'salt' => $salt,
'pwd' => LoginPwdEncryption($params['pwd'], $salt),
'status' => ($common_register_is_enable_audit == 1) ? 3 : 0,
];
// 验证码校验
$verify_params = [
'key_prefix' => 'user_reg_'.md5($params['accounts']),
'expire_time' => MyC('common_verify_expire_time'),
];
// 账户类型
$obj = null;
switch($params['type'])
{
// 短信
case 'sms' :
$data['mobile'] = $params['accounts'];
$obj = new \base\Sms($verify_params);
break;
// 邮箱
case 'email' :
$data['email'] = $params['accounts'];
$obj = new \base\Email($verify_params);
break;
// 默认 账号
default :
$data['username'] = $params['accounts'];
// 是否开启图片验证码
// user_reg 由前端图片验证码传递的 type 一致
$verify_params['key_prefix'] = 'user_reg';
$verify = self::IsImaVerify($params, $verify_params, MyC('home_user_register_img_verify_state'));
if($verify['code'] != 0)
{
return $verify;
}
}
// 验证码校验
// sms, email
if(isset($obj) && is_object($obj))
{
// 是否已过期
if(!$obj->CheckExpire())
{
return DataReturn(MyLang('verify_code_expire_tips'), -10);
}
// 是否正确
if(!$obj->CheckCorrect($params['verify']))
{
return DataReturn(MyLang('verify_code_error_tips'), -11);
}
}
// 数据添加
$user_ret = self::UserInsert($data, $params);
if($user_ret['code'] == 0)
{
// 清除验证码
if(isset($obj) && is_object($obj))
{
$obj->Remove();
}
// 是否需要审核
if($common_register_is_enable_audit == 1)
{
return DataReturn(MyLang('common_service.user.user_not_audit_tips'), -110);
}
// 用户登录session纪录
if(self::UserLoginRecord($user_ret['data']['user_id']))
{
// 成功返回
if(APPLICATION == 'app')
{
$result = self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$user_ret['data']['user_id'], 'is_refresh_token'=>0]);
} else {
$result = $user_ret['data'];
}
return DataReturn(MyLang('register_success'), 0, $result);
}
return DataReturn(MyLang('common_service.user.user_register_success_no_login_tips'));
}
return $user_ret;
}
/**
* 用户注册账户校验
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T10:06:29+0800
* @param [array] $params [输入参数]
*/
public static function UserRegAccountsCheck($params = [])
{
switch($params['type'])
{
// 手机
case 'sms' :
// 手机号码格式
if(!CheckMobile($params['accounts']))
{
return DataReturn(MyLang('mobile_format_error_tips'), -2);
}
// 手机号码是否已存在
if(self::IsExistAccounts($params['accounts'], 'mobile'))
{
return DataReturn(MyLang('common_service.user.mobile_already_exist_tips'), -3);
}
break;
// 邮箱
case 'email' :
// 电子邮箱格式
if(!CheckEmail($params['accounts']))
{
return DataReturn(MyLang('email_format_error_tips'), -2);
}
// 电子邮箱是否已存在
if(self::IsExistAccounts($params['accounts'], 'email'))
{
return DataReturn(MyLang('common_service.user.email_already_exist_tips'), -3);
}
break;
// 用户名
case 'username' :
// 用户名格式
if(!CheckUserName($params['accounts']))
{
return DataReturn(MyLang('common_service.user.username_format_error_tips'), -2);
}
// 用户名是否已存在
if(self::IsExistAccounts($params['accounts'], 'username'))
{
return DataReturn(str_replace('{$var}', $params['accounts'], MyLang('common_service.user.save_user_already_exist_tips')), -3);
}
break;
}
return DataReturn(MyLang('operate_success'), 0);
}
/**
* 账户是否存在
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-08T10:27:14+0800
* @param [string] $accounts [账户名称]
* @param [string] $field [字段名称]
* @return [boolean] [存在true, 不存在false]
*/
public static function IsExistAccounts($accounts, $field = 'mobile')
{
$method = self::UserUniqueMethod();
$temp = self::$method($field, $accounts);
return !empty($temp);
}
/**
* 用户校验唯一方法
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-03-22
* @desc description
*/
public static function UserUniqueMethod()
{
return (MyC('common_user_unique_system_type_model') == 1) ? 'UserSystemInfo' : 'UserBaseInfo';
}
/**
* 是否开启图片验证码校验
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-22T15:48:31+0800
* @param [array] $params [输入参数]
* @param [array] $verify_params [配置参数]
* @param [int] $status [状态 0未开启, 1已开启]
* @return [object] [图片验证码类对象]
*/
public static function IsImaVerify($params, $verify_params, $status = 0)
{
if($status == 1)
{
if(empty($params['verify']))
{
return DataReturn(MyLang('verify_images_empty_tips'), -10);
}
$verify = new \base\Verify($verify_params);
if(!$verify->CheckExpire())
{
return DataReturn(MyLang('verify_code_expire_tips'), -11);
}
if(!$verify->CheckCorrect($params['verify']))
{
return DataReturn(MyLang('verify_code_error_tips'), -12);
}
return DataReturn(MyLang('operate_success'), 0, $verify);
}
return DataReturn(MyLang('operate_success'), 0);
}
/**
* 用户登录账户校验
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T10:06:29+0800
* @param [array] $params [输入参数]
*/
public static function UserLoginAccountsCheck($params = [])
{
$field = '';
switch($params['type'])
{
// 手机
case 'sms' :
// 手机号码格式
if(!CheckMobile($params['accounts']))
{
return DataReturn(MyLang('mobile_format_error_tips'), -2);
}
// 手机号码是否不存在
if(!self::IsExistAccounts($params['accounts'], 'mobile'))
{
return DataReturn(MyLang('mobile_no_exist_error_tips'), -3);
}
$field = 'mobile';
break;
// 邮箱
case 'email' :
// 电子邮箱格式
if(!CheckEmail($params['accounts']))
{
return DataReturn(MyLang('email_format_error_tips'), -2);
}
// 电子邮箱是否不存在
if(!self::IsExistAccounts($params['accounts'], 'email'))
{
return DataReturn(MyLang('email_no_exist_error_tips'), -3);
}
$field = 'email';
break;
// 用户名
case 'username' :
// 帐号是否不存在
if(!self::IsExistAccounts($params['accounts'], 'username|mobile|email'))
{
return DataReturn(MyLang('accounts_error_tips'), -3);
}
$field = 'username|mobile|email';
break;
}
return DataReturn(MyLang('operate_success'), 0, $field);
}
/**
* 用户登录-验证码发送
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T10:06:29+0800
* @param [array] $params [输入参数]
*/
public static function LoginVerifySend($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => 'accounts',
'error_msg' => MyLang('accounts_empty_tips'),
],
[
'checked_type' => 'in',
'key_name' => 'type',
'checked_data' => array_column(MyConst('common_login_type_list'), 'value'),
'error_msg' => MyLang('login_type_error_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 是否开启用户登录
if(!in_array($params['type'], MyC('home_user_login_type', [], true)))
{
return DataReturn(MyLang('login_close_tips'), -1);
}
// 验证码基础参数
$verify_params = [
'key_prefix' => 'user_login',
'expire_time' => MyC('common_verify_expire_time'),
'interval_time' => MyC('common_verify_interval_time'),
];
// 是否开启图片验证码
$verify = self::IsImaVerify($params, $verify_params, MyC('common_img_verify_state'));
if($verify['code'] != 0)
{
return $verify;
}
// 账户校验
$ac = self::UserLoginAccountsCheck($params);
if($ac['code'] != 0)
{
return $ac;
}
// 验证码基础参数 key
$verify_params['key_prefix'] = 'user_login_'.md5($params['accounts']);
// 发送验证码
$code = GetNumberCode(4);
switch($params['type'])
{
// 短信
case 'sms' :
$obj = new \base\Sms($verify_params);
$status = $obj->SendCode($params['accounts'], $code, ConfigService::SmsTemplateValue('home_sms_login_template'));
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
$email_params = [
'email' => $params['accounts'],
'content' => MyC('home_email_login_template'),
'title' => MyC('home_site_name').' - '.MyLang('common_service.user.login_email_send_title'),
'code' => $code,
];
$status = $obj->SendHtml($email_params);
break;
// 默认
default :
return DataReturn(MyLang('verify_code_not_support_send_error_tips'), -2);
}
if($status)
{
// 清除验证码
if(isset($verify['data']) && is_object($verify['data']))
{
$verify['data']->Remove();
}
return DataReturn(MyLang('send_success'), 0);
}
return DataReturn(MyLang('send_fail').'['.$obj->error.']', -100);
}
/**
* 用户注册-验证码发送
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T10:06:29+0800
* @param [array] $params [输入参数]
*/
public static function RegVerifySend($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => 'accounts',
'error_msg' => MyLang('accounts_empty_tips'),
],
[
'checked_type' => 'in',
'key_name' => 'type',
'checked_data' => array_column(MyConst('common_user_reg_type_list'), 'value'),
'error_msg' => MyLang('register_type_error_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 是否开启用户注册
if(!in_array($params['type'], MyC('home_user_reg_type', [], true)))
{
return DataReturn(MyLang('register_close_tips'), -1);
}
// 验证码基础参数
$verify_params = [
'key_prefix' => 'user_reg',
'expire_time' => MyC('common_verify_expire_time'),
'interval_time' => MyC('common_verify_interval_time'),
];
// 是否开启图片验证码
$verify = self::IsImaVerify($params, $verify_params, MyC('common_img_verify_state'));
if($verify['code'] != 0)
{
return $verify;
}
// 账户校验
$ret = self::UserRegAccountsCheck($params);
if($ret['code'] != 0)
{
return $ret;
}
// 验证码基础参数 key
$verify_params['key_prefix'] = 'user_reg_'.md5($params['accounts']);
// 发送验证码
$code = GetNumberCode(4);
switch($params['type'])
{
// 短信
case 'sms' :
$obj = new \base\Sms($verify_params);
$status = $obj->SendCode($params['accounts'], $code, ConfigService::SmsTemplateValue('home_sms_user_reg_template'));
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
$email_params = [
'email' => $params['accounts'],
'content' => MyC('home_email_user_reg_template'),
'title' => MyC('home_site_name').' - '.MyLang('common_service.user.register_email_send_title'),
'code' => $code,
];
$status = $obj->SendHtml($email_params);
break;
// 默认
default :
return DataReturn(MyLang('verify_code_not_support_send_error_tips'), -2);
}
if($status)
{
// 清除验证码
if(isset($verify['data']) && is_object($verify['data']))
{
$verify['data']->Remove();
}
return DataReturn(MyLang('send_success'), 0);
}
return DataReturn(MyLang('send_fail').'['.$obj->error.']', -100);
}
/**
* 密码找回验证码发送
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T17:35:03+0800
* @param [array] $params [输入参数]
*/
public static function ForgetPwdVerifySend($params = [])
{
// 参数
if(empty($params['accounts']))
{
return DataReturn(MyLang('params_error_tips'), -10);
}
// 验证码基础参数
$verify_params = [
'key_prefix' => 'user_forget',
'expire_time' => MyC('common_verify_expire_time'),
'interval_time' => MyC('common_verify_interval_time'),
];
// 是否开启图片验证码
$verify = self::IsImaVerify($params, $verify_params, MyC('common_img_verify_state'));
if($verify['code'] != 0)
{
return $verify;
}
// 账户是否存在,并返回账户格式类型
$ret = self::UserForgetAccountsCheck($params['accounts']);
if($ret['code'] != 0)
{
return $ret;
}
// 验证码基础参数 key
$verify_params['key_prefix'] = 'user_forget_'.md5($params['accounts']);
// 验证码
$code = GetNumberCode(4);
// 账户字段类型
switch($ret['data'])
{
// 手机
case 'mobile' :
$obj = new \base\Sms($verify_params);
$status = $obj->SendCode($params['accounts'], $code, ConfigService::SmsTemplateValue('home_sms_user_forget_pwd_template'));
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
$email_params = [
'email' => $params['accounts'],
'content' => MyC('home_email_user_forget_pwd_template'),
'title' => MyC('home_site_name').' - '.MyLang('common_service.user.forget_pwd_email_send_title'),
'code' => $code,
];
$status = $obj->SendHtml($email_params);
break;
// 默认
default :
return DataReturn(MyLang('common_service.user.mobile_or_email_format_error_tips'), -1);
}
if($status)
{
// 清除图片验证码
if(isset($verify) && isset($verify['data']) && is_object($verify['data']))
{
$verify['data']->Remove();
}
return DataReturn(MyLang('send_success'), 0);
}
return DataReturn(MyLang('send_fail').'['.$obj->error.']', -100);
}
/**
* 帐号校验
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T17:59:53+0800
* @param [string] $accounts [账户名称]
* @return [string] [账户字段 mobile, email]
*/
public static function UserForgetAccountsCheck($accounts)
{
if(CheckMobile($accounts))
{
if(!self::IsExistAccounts($accounts, 'mobile'))
{
return DataReturn(MyLang('mobile_no_exist_error_tips'), -3);
}
return DataReturn(MyLang('operate_success'), 0, 'mobile');
} else if(CheckEmail($accounts))
{
if(!self::IsExistAccounts($accounts, 'email'))
{
return DataReturn(MyLang('email_no_exist_error_tips'), -3);
}
return DataReturn(MyLang('operate_success'), 0, 'email');
}
return DataReturn(MyLang('common_service.user.mobile_or_email_format_error_tips'), -4);
}
/**
* 密码找回
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2017-03-10T17:35:03+0800
* @param [array] $params [输入参数]
*/
public static function ForgetPwd($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => 'accounts',
'error_msg' => MyLang('accounts_empty_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'pwd',
'error_msg' => MyLang('password_empty_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'verify',
'error_msg' => MyLang('verify_code_empty_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 账户是否存在
$ret = self::UserForgetAccountsCheck($params['accounts']);
if($ret['code'] != 0)
{
return $ret;
}
// 验证码校验
$verify_params = [
'key_prefix' => 'user_forget_'.md5($params['accounts']),
'expire_time' => MyC('common_verify_expire_time'),
'interval_time' => MyC('common_verify_interval_time'),
];
switch($ret['data'])
{
// 手机
case 'mobile' :
$obj = new \base\Sms($verify_params);
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
break;
// 默认
default :
return DataReturn(MyLang('common_service.user.mobile_or_email_format_error_tips'), -1);
}
// 是否已过期
if(!$obj->CheckExpire())
{
return DataReturn(MyLang('verify_code_expire_tips'), -10);
}
// 是否正确
if(!$obj->CheckCorrect($params['verify']))
{
return DataReturn(MyLang('verify_code_error_tips'), -11);
}
// 获取用户信息
$user = self::UserInfo($ret['data'], $params['accounts']);
if(empty($user))
{
return DataReturn(MyLang('common_service.user.save_user_info_no_exist_tips'), -12);
}
// 密码修改
$ret = SafetyService::UserLoginPwdUpdate($params['accounts'], $user['id'], $params['pwd']);
if($ret['code'] == 0)
{
// 清除验证码
if(isset($obj) && is_object($obj))
{
$obj->Remove();
}
return DataReturn(MyLang('operate_success'), 0);
}
return $ret;
}
/**
* 用户资料保存
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-04
* @desc description
* @param [array] $params [输入参数]
*/
public static function PersonalSave($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'length',
'checked_data' => '1,60',
'key_name' => 'nickname',
'is_checked' => 2,
'error_msg' => MyLang('common_service.user.save_nickname_format_error_tips'),
],
[
'checked_type' => 'in',
'checked_data' => [0,1,2],
'key_name' => 'gender',
'is_checked' => 2,
'error_msg' => MyLang('common_service.user.save_gender_range_error_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'user',
'error_msg' => MyLang('user_info_incorrect_tips'),
],
[
'checked_type' => 'length',
'key_name' => 'address',
'checked_data' => '80',
'is_checked' => 2,
'error_msg' => MyLang('common_service.user.form_item_address_message'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 更新的字段
$fields = [
'avatar',
'birthday',
'nickname',
'gender',
'province',
'city',
'county',
'address',
'mobile',
];
$data = [];
foreach($fields as $k)
{
if(array_key_exists($k, $params))
{
switch($k)
{
// 头像
case 'avatar' :
$data[$k] = empty($params['avatar']) ? '' : ResourcesService::AttachmentPathHandle($params['avatar']);
break;
// 生日
case 'birthday' :
$data[$k] = empty($params['birthday']) ? '' : strtotime($params['birthday']);
break;
// 手机、用户基础信息填写一键授权手机号码
case 'mobile' :
if(!empty($params['mobile']))
{
// 手机号码不存在则绑定到当前账号下
$method = self::UserUniqueMethod();
$temp = self::$method('mobile', $params['mobile']);
if(empty($temp))
{
$data[$k] = $params['mobile'];
}
}
break;
default :
$data[$k] = empty($params[$k]) ? '' : $params[$k];
}
}
}
if(empty($data))
{
return DataReturn(MyLang('content_params_empty_tips'), -1);
}
// 更新用户信息
if(self::UserUpdateHandle($data, $params['user']['id'], $params))
{
// 重新获取用户信息
$user = self::UserHandle(self::UserInfo('id', $params['user']['id']));
// 重新更新用户缓存
self::UserLoginRecord(0, $user);
// 去除
if(!empty($user['token']))
{
MyCache(SystemService::CacheKey('shopxo.cache_user_info').$user['token'], $user);
}
return DataReturn(MyLang('change_success'), 0, $user);
}
return DataReturn(MyLang('change_fail'), -100);
}
/**
* 用户授权数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-11-06
* @desc description
* @param [array] $params [用户数据]
* @param [string] $field [平台字段名称]
*/
public static function AuthUserProgram($params, $field)
{
// 用户信息
$data = [
$field => $params['openid'],
'nickname' => empty($params['nickname']) ? '' : $params['nickname'],
'avatar' => empty($params['avatar']) ? '' : $params['avatar'],
'gender' => empty($params['gender']) ? 0 : intval($params['gender']),
'province' => empty($params['province']) ? '' : $params['province'],
'city' => empty($params['city']) ? '' : $params['city'],
'county' => empty($params['county']) ? '' : $params['county'],
'mobile' => empty($params['mobile']) ? '' : $params['mobile'],
'referrer' => isset($params['referrer']) ? $params['referrer'] : 0,
];
// 用户唯一方法
$method = self::UserUniqueMethod();
// 是否需要添加用户
$is_insert_user = false;
// 用户信息处理
$user_platform = self::UserPlatformInfo($field, $params['openid']);
if(!empty($user_platform))
{
// 用户信息
$user = self::UserBaseInfo('id', $user_platform['user_id']);
if(empty($user))
{
$is_insert_user = true;
} else {
// 用户状态
if($user['status'] != 0)
{
return DataReturn(MyLang('common_service.user.user_not_audit_tips'), -301);
}
// 如果有手机号码、如当前用户不存在手机号码则绑定
if(empty($user['mobile']) && !empty($data['mobile']))
{
// 手机号码不存在则绑定到当前账号下
$temp = self::$method('mobile', $data['mobile']);
if(empty($temp))
{
// 是否被禁止
$ret = self::UserRegForbidCheck($data['mobile'], 'mobile');
if($ret['code'] != 0)
{
return $ret;
}
// 绑定手机
$upd_data = [
'mobile' => $data['mobile'],
'upd_time' => time(),
];
if(Db::name('User')->where(['id'=>$user['id']])->update($upd_data))
{
return DataReturn(MyLang('bind_success'), 0, self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$user['id']]));
}
} else {
if($user['id'] != $temp['id'])
{
return DataReturn(MyLang('common_service.user.mobile_already_bind_account_tips'), -1);
}
}
}
return DataReturn(MyLang('auth_success'), 0, $user);
}
} else {
// 用户unionid
$unionid = self::UserUnionidHandle($params);
if(!empty($unionid['field']) && !empty($unionid['value']))
{
// unionid字段是否存在用户
$unionid_user_platform = self::UserPlatformInfo($unionid['field'], $unionid['value']);
if(!empty($unionid_user_platform))
{
// 用户信息
$unionid_user_base = self::UserBaseInfo('id', $unionid_user_platform['user_id']);
if(empty($user))
{
$is_insert_user = true;
} else {
// 用户状态
if($unionid_user_base['status'] != 0)
{
return DataReturn(MyLang('common_service.user.user_not_audit_tips'), -301);
}
// openid绑定
if(!self::UserPlatformUpdate('id', $unionid_user_platform['id'], [$field => $params['openid']], $params))
{
return DataReturn(MyLang('bind_fail'), -1);
}
// 如果有手机号码、如当前用户不存在手机号码则绑定
if(empty($unionid_user_base['mobile']) && !empty($data['mobile']))
{
// 手机号码不存在则绑定到当前账号下
$temp = self::$method('mobile', $data['mobile']);
if(empty($temp))
{
// 是否被禁止
$ret = self::UserRegForbidCheck($data['mobile'], 'mobile');
if($ret['code'] != 0)
{
return $ret;
}
// 绑定手机
$upd_data = [
'mobile' => $data['mobile'],
'upd_time' => time(),
];
if(!Db::name('User')->where(['id'=>$unionid_user_base['id']])->update($upd_data))
{
return DataReturn(MyLang('bind_fail'), -1);
}
} else {
if($unionid_user_base['id'] != $temp['id'])
{
return DataReturn(MyLang('common_service.user.mobile_already_bind_account_tips'), -1);
}
}
}
return DataReturn(MyLang('bind_success'), 0, self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$unionid_user_base['id']]));
}
}
// 如果用户不存在数据库中则unionid放入用户data中
$data[$unionid['field']] = $unionid['value'];
}
// 不强制绑定手机则写入用户信息
if(intval(MyC('common_user_is_mandatory_bind_mobile')) != 1)
{
$is_insert_user = true;
} else {
// 绑定手机号码
if(!empty($data['mobile']))
{
// 如果手机号码存在则直接绑定openid
// 不存在添加存在更新openid
$user = self::$method('mobile', $data['mobile']);
if(!empty($user))
{
// 上面openid和unionid都没存在信息但是存在手机号码信息则增加用户平台数据
$user_platform_insert = [
'user_id' => $user['id'],
$field => $params['openid'],
];
if(!empty($unionid['field']) && !empty($unionid['value']))
{
$user_platform_insert[$unionid['field']] = $unionid['value'];
}
if(self::UserPlatformInsert($user_platform_insert, $params))
{
return DataReturn(MyLang('bind_success'), 0, self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$user['id']]));
}
} else {
$is_insert_user = true;
}
}
}
}
// 添加用户
if($is_insert_user)
{
// 是否需要审核
$common_register_is_enable_audit = MyC('common_register_is_enable_audit', 0);
$data['status'] = ($common_register_is_enable_audit == 1) ? 3 : 0;
// 添加用户
$ret = self::UserInsert($data, $params);
if($ret['code'] == 0)
{
// 是否需要审核
if($common_register_is_enable_audit == 1)
{
return DataReturn(MyLang('common_service.user.user_not_audit_tips'), -110);
}
return DataReturn(MyLang('auth_success'), 0, self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$ret['data']['user_id'], 'is_refresh_token'=>0]));
}
return $ret;
}
return DataReturn(MyLang('auth_success'), 0, self::AppUserInfoHandle(['user'=>$data]));
}
/**
* 用户openid绑定
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-06-21
* @desc description
* @param [int] $user_id [用户id]
* @param [string] $openid [openid]
* @param [string] $field [openid 字段]
*/
public static function UserOpenidBind($user_id, $openid, $field)
{
return self::UserPlatformUpdate('user_id', $user_id, [$field => $openid]);
}
/**
* 用户openid处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-02-11
* @desc description
* @param [array] $params [输入参数]
*/
public static function UserOpenidHandle($params = [])
{
$field = null;
$value = null;
$fields_arr = array_column(MyConst('common_appmini_type'), 'value');
foreach($fields_arr as $type)
{
$openid = $type.'_openid';
if(!empty($params[$openid]))
{
$field = $openid;
$value = $params[$openid];
break;
}
}
return ['field'=>$field, 'value'=>$value];
}
/**
* 用户unionid处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-02-11
* @desc description
* @param [array] $params [输入参数]
*/
public static function UserUnionidHandle($params = [])
{
// 用户unionid列表
// 微信用户unionid
// QQ用户unionid
// 头条用户unionid
$field = null;
$value = null;
$fields_arr = ['weixin_unionid', 'qq_unionid', 'toutiao_unionid'];
foreach($fields_arr as $unionid)
{
if(!empty($params[$unionid]))
{
$field = $unionid;
$value = $params[$unionid];
break;
}
}
return ['field'=>$field, 'value'=>$value];
}
/**
* app用户信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-11-06
* @desc description
* @param [array] $params [输入参数]
*/
public static function AppUserInfoHandle($params = [])
{
// 获取用户信息
if(!empty($params['user_id']))
{
$params['user'] = self::UserHandle(self::UserInfo('id', $params['user_id']));
} elseif(!empty($params['where_field']) && !empty($params['where_value']) && empty($params['user']))
{
$params['user'] = self::UserHandle(self::UserInfo($params['where_field'], $params['where_value']));
}
if(!empty($params['user']))
{
// 是否强制绑定手机号码
$params['user']['is_mandatory_bind_mobile'] = intval(MyC('common_user_is_mandatory_bind_mobile'));
// 基础处理
if(!empty($params['user']['id']))
{
// 会员码生成处理
if(empty($params['user']['number_code']))
{
$params['user']['number_code'] = self::UserNumberCodeCreatedHandle($params['user']['id']);
}
// 重新生成token更新到数据库并缓存
if(!isset($params['is_refresh_token']) || $params['is_refresh_token'] == 1)
{
$params['user']['token'] = self::UserTokenUpdate($params['user']['id'], $params['user']);
}
}
// token读取没有缓存则记录缓存
if(!empty($params['where_field']) && !empty($params['where_value']) && $params['where_field'] == 'token')
{
$user_cache_login_info = self::CacheUserTokenData($params['where_value']);
if(empty($user_cache_login_info))
{
MyCache(SystemService::CacheKey('shopxo.cache_user_info').$params['where_value'], $params['user']);
}
}
// 用户信息钩子
$hook_name = 'plugins_service_user_app_info_handle';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'user_id' => (empty($params['user']) || empty($params['user']['id'])) ? 0 : $params['user']['id'],
'user' => &$params['user'],
'params' => $params,
]);
}
return $params['user'];
}
/**
* 用户 token更新
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-07-01
* @desc description
* @param [int] $user_id [用户id]
* @param [array] $user [指定用户信息]
*/
public static function UserTokenUpdate($user_id, $user = [])
{
// 未指定用户则读取用户信息、并处理数据
if(empty($user) && !empty($user_id))
{
$user = self::UserHandle(self::UserInfo('id', $user_id));
}
if(!empty($user))
{
// token生成并存储缓存
$user['token'] = ApiService::CreatedUserToken($user['id']);
if(self::UserPlatformUpdate('user_id', $user['id'], ['token'=>$user['token'], 'upd_time'=>time()]) !== false)
{
MyCache(SystemService::CacheKey('shopxo.cache_user_info').$user['token'], $user);
}
}
return (empty($user) || empty($user['token'])) ? '' : $user['token'];
}
/**
* 用户添加
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-04-03
* @desc description
* @param [array] $data [用户添加数据]
* @param [array] $params [输入参数]
*/
public static function UserInsert($data, $params = [])
{
// 用户唯一方法
$method = self::UserUniqueMethod();
// 用户名、手机、邮箱不允许重复注册
if(!empty($data['username']))
{
// 是否被禁止
$ret = self::UserRegForbidCheck($data['username'], 'username');
if($ret['code'] != 0)
{
return $ret;
}
// 唯一验证
$temp = self::$method('username', $data['username']);
if(!empty($temp))
{
return DataReturn(str_replace('{$var}', $data['username'], MyLang('common_service.user.save_user_already_exist_tips')), -10);
}
} else if(!empty($data['mobile']))
{
// 是否被禁止
$ret = self::UserRegForbidCheck($data['mobile'], 'mobile');
if($ret['code'] != 0)
{
return $ret;
}
// 唯一验证
$temp = self::$method('mobile', $data['mobile']);
if(!empty($temp))
{
return DataReturn(MyLang('common_service.user.mobile_already_exist_tips'), -10);
}
} else if(!empty($data['email']))
{
// 是否被禁止
$ret = self::UserRegForbidCheck($data['email'], 'email');
if($ret['code'] != 0)
{
return $ret;
}
// 唯一验证
$temp = self::$method('email', $data['email']);
if(!empty($temp))
{
return DataReturn(MyLang('common_service.user.email_already_exist_tips'), -10);
}
}
// 用户基础信息处理
$data = self::UserBaseHandle($data, $params);
// 用户openid
$openid = self::UserOpenidHandle($params);
if(!empty($openid['field']) && !empty($openid['value']))
{
// openid放入用户data中
$data[$openid['field']] = $openid['value'];
}
// 用户unionid
$unionid = self::UserUnionidHandle($params);
if(!empty($unionid['field']) && !empty($unionid['value']))
{
// unionid放入用户data中
$data[$unionid['field']] = $unionid['value'];
}
// 推荐人id
$data['referrer'] = self::UserReferrerDecrypt($params);
// 注册数据分离处理
// 用户平台表结构
$structure = ResourcesService::TableStructureData('UserPlatform');
unset($structure['id'], $structure['user_id'], $structure['add_time'], $structure['upd_time']);
$user_base = [];
$user_platform = [];
foreach($data as $k=>$v)
{
if(array_key_exists($k, $structure))
{
$user_platform[$k] = $v;
} else {
$user_base[$k] = $v;
}
}
// 注册添加之前钩子
$hook_name = 'plugins_service_user_register_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'user_base' => &$user_base,
'user_platform' => &$user_platform,
]);
// 用户信息以手机或邮箱、不存在则添加
$user_base['add_time'] = time();
$user_id = Db::name('User')->insertGetId($user_base);
if($user_id <= 0)
{
return DataReturn(MyLang('insert_fail'), -100);
}
// 用户平台信息添加
$user_platform['user_id'] = $user_id;
if(!self::UserPlatformInsert($user_platform, $params))
{
return DataReturn(MyLang('insert_fail'), -100);
}
// 会员码生成处理
self::UserNumberCodeCreatedHandle($user_id);
// token
self::UserTokenUpdate($user_id);
// 清除推荐id
if(!empty($user_base['referrer']))
{
MySession('share_referrer_id', null);
MyCookie('share_referrer_id', null);
}
// 返回前端html代码
$body_html = [];
// 注册成功后钩子
$user = self::UserHandle(self::UserInfo('id', $user_id, 'id,number_code,system_type,token,status,username,nickname,mobile,email,gender,avatar,province,city,county,birthday,add_time'));
$hook_name = 'plugins_service_user_register_end';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
'user_id' => $user_id,
'user' => $user,
'body_html' => &$body_html,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 登录返回
$result = [
'body_html' => is_array($body_html) ? implode(' ', $body_html) : $body_html,
'user_id' => $user_id,
];
return DataReturn(MyLang('insert_success'), 0, $result);
}
/**
* 会员码生成处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-11-09
* @desc description
* @param [int] $user_id [用户id]
*/
public static function UserNumberCodeCreatedHandle($user_id)
{
// 会员码
$max = 10;
$len = strlen($user_id);
$number_code = '8888'.(($len < $max) ? GetNumberCode($max-$len).$user_id : $user_id);
// 更新数据库
Db::name('User')->where(['id'=>$user_id])->update(['number_code'=>$number_code]);
return $number_code;
}
/**
* 用户基础信息处理、注册绑定的时候处理外部传入的基础信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-11-13
* @desc description
* @param [array] $data [用户信息]
* @param [array] $params [输入参数]
*/
public static function UserBaseHandle($data, $params = [])
{
// 系统类型
if(empty($data['system_type']))
{
$data['system_type'] = empty($params['system_type_name']) ? SYSTEM_TYPE : $params['system_type_name'];
}
// 基础参数处理
if(!empty($params) && is_array($params))
{
// 是否存在基信息
// 参数key => dbkey
$base_fields = [
'nickname' => [
'key' => 'nickname',
'type' => 'string'
],
'avatar' => [
'key' => 'avatar',
'type' => 'url'
],
'province' => [
'key' => 'province',
'type' => 'string'
],
'city' => [
'key' => 'city',
'type' => 'string'
],
'county' => [
'key' => 'county',
'type' => 'string'
],
'gender' => [
'key' => 'gender',
'type' => 'int',
'isset' => 1
],
];
foreach($base_fields as $k=>$v)
{
if(!empty($params[$k]) || (isset($v['isset']) && isset($params[$k])))
{
switch($v['type'])
{
// url处理
case 'url' :
$params[$k] = str_replace(['&amp;'], ['&'], $params[$k]);
// 头像如果是默认则置空
if($k == 'avatar' && !empty($params[$k]) && stripos($params[$k], 'default-user-avatar') !== false)
{
$params[$k] = '';
}
break;
// 整数
case 'int' :
$params[$k] = intval($params[$k]);
break;
}
$data[$v['key']] = $params[$k];
}
}
}
return $data;
}
/**
* app用户手机绑定
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-27
* @desc description
* @param [array] $params [输入参数]
*/
public static function AppMobileBind($params = [])
{
return self::AppAccountsBindhHandle('mobile', $params);
}
/**
* app用户邮箱绑定
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-27
* @desc description
* @param [array] $params [输入参数]
*/
public static function AppEmailBind($params = [])
{
return self::AppAccountsBindhHandle('email', $params);
}
/**
* app用户手机或邮箱绑定
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-03-11
* @desc description
* @param [string] $type [字段每次类型mobile, email]
* @param [array] $params [输入参数]
*/
public static function AppAccountsBindhHandle($type, $params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => $type,
'error_msg' => MyLang('common_service.user.'.$type.'_empty_tips'),
],
[
'checked_type' => 'empty',
'key_name' => 'verify',
'error_msg' => MyLang('verify_code_empty_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 用户手机或邮箱绑定前校验钩子
$hook_name = 'plugins_service_user_app_'.$type.'_bind_begin_check';
$ret = EventReturnHandle(MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => &$params,
]));
if(isset($ret['code']) && $ret['code'] != 0)
{
return $ret;
}
// 格式验证
$check_fun = 'Check'.ucfirst($type);
if(!$check_fun($params[$type]))
{
return DataReturn(MyLang($type.'_format_error_tips'), -2);
}
// 验证码校验
$verify_params = [
'key_prefix' => 'user_bind_'.md5($params[$type]),
'expire_time' => MyC('common_verify_expire_time')
];
$obj = new \base\Sms($verify_params);
// 是否已过期
if(!$obj->CheckExpire())
{
return DataReturn(MyLang('verify_code_expire_tips'), -10);
}
// 是否正确
if(!$obj->CheckCorrect($params['verify']))
{
return DataReturn(MyLang('verify_code_error_tips'), -11);
}
// 用户更新数据
$data = [
$type => $params[$type],
];
// 是否小程序请求
$is_appmini = array_key_exists(APPLICATION_CLIENT_TYPE, MyConst('common_appmini_type'));
// 根据绑定账户类型【手机或邮箱】获取用户信息
$method = self::UserUniqueMethod();
$db_user = self::$method($type, $data[$type]);
// 额外信息
if(empty($db_user))
{
if(empty($db_user['nickname']) && !empty($params['nickname']))
{
$data['nickname'] = $params['nickname'];
}
if(empty($db_user['avatar']) && !empty($params['avatar']))
{
$data['avatar'] = $params['avatar'];
}
if(empty($db_user['province']) && !empty($params['province']))
{
$data['province'] = $params['province'];
}
if(empty($db_user['city']) && !empty($params['city']))
{
$data['city'] = $params['city'];
}
if(empty($db_user['county']) && !empty($params['county']))
{
$data['county'] = $params['county'];
}
if(empty($db_user) && isset($params['gender']))
{
$data['gender'] = intval($params['gender']);
}
}
// 小程序请求处理
if($is_appmini)
{
// openid必须存在
$accounts_field = APPLICATION_CLIENT_TYPE.'_openid';
if(empty($params[$accounts_field]))
{
return DataReturn(MyLang('common_service.user.user_openid_empty_tips'), -20);
}
// openid数据
$data[$accounts_field] = $params[$accounts_field];
// 小程序请求获取用户信息
$user_platform = self::UserPlatformInfo($accounts_field, $params[$accounts_field]);
$current_user = empty($user_platform) ? [] : self::UserBaseInfo('id', $user_platform['user_id']);
} else {
// 当前登录用户
$current_user = self::LoginUserInfo();
}
// 用户是否存在已登录
if(!empty($current_user))
{
// 手机帐号信息是否存在
if(!empty($db_user))
{
// id不一致则提示错误
if($current_user['id'] != $db_user['id'])
{
return DataReturn(MyLang('common_service.user.'.$type.'_already_bind_account_tips'), -50);
}
// 是否与当前帐号的手机号码一致
if(!empty($current_user[$type]) && $current_user[$type] == $db_user[$type])
{
return DataReturn(MyLang('common_service.user.'.$type.'_current_mobile_identical_tips'), -51);
}
}
// 当前用户赋值手机帐号信息
$db_user = $current_user;
}
// 不存在添加/则更新
if(empty($db_user))
{
// 如果用户不存在则新增用户状态字段
// 是否需要审核
$common_register_is_enable_audit = MyC('common_register_is_enable_audit', 0);
$data['status'] = ($common_register_is_enable_audit == 1) ? 3 : 0;
// 新增用户
$user_ret = self::UserInsert($data, $params);
if($user_ret['code'] != 0)
{
return $user_ret;
}
$user_id = $user_ret['data']['user_id'];
} else {
// 小程序请求处理
if($is_appmini)
{
// 用户unionid
$unionid = self::UserUnionidHandle($params);
if(!empty($unionid['field']) && !empty($unionid['value']))
{
if(empty($db_user[$unionid['field']]))
{
// unionid放入用户data中
$data[$unionid['field']] = $unionid['value'];
}
}
}
// 帐号信息更新
$ret = self::UserUpdateHandle($data, $db_user['id'], $params);
if($ret['code'] != 0)
{
return $ret;
}
$user_id = $db_user['id'];
}
if(isset($user_id) && $user_id > 0)
{
// 用户平台信息、不存在则添加
$user_platform = self::UserPlatformInfo('user_id', $user_id);
if(empty($user_platform))
{
if(!self::UserPlatformInsert(['user_id' => $user_id], $params))
{
return DataReturn(MyLang('insert_fail'), -1);
}
}
// 清除验证码
$obj->Remove();
return DataReturn(MyLang('bind_success'), 0, self::AppUserInfoHandle(['where_field'=>'id', 'where_value'=>$user_id]));
}
return DataReturn(MyLang('bind_fail'), -100);
}
/**
* app用户手机绑定验证码发送
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-27
* @desc description
* @param [array] $params [输入参数]
*/
public static function AppMobileBindVerifySend($params = [])
{
return self::AppAccountsBindVerifySendHandle('mobile', $params);
}
/**
* app用户邮箱绑定验证码发送
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2018-12-27
* @desc description
* @param [array] $params [输入参数]
*/
public static function AppEmailBindVerifySend($params = [])
{
return self::AppAccountsBindVerifySendHandle('email', $params);
}
/**
* app用户手机或邮箱绑定验证码发送处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-03-11
* @desc description
* @param [string] $type [字段每次类型mobile, email]
* @param [array] $params [输入参数]
*/
public static function AppAccountsBindVerifySendHandle($type, $params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => $type,
'error_msg' => MyLang('common_service.user.'.$type.'_empty_tips'),
],
[
'checked_type' => 'fun',
'key_name' => $type,
'checked_data' => 'Check'.ucfirst($type),
'error_msg' => MyLang($type.'_format_error_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 验证码公共基础参数
$verify_params = [
'key_prefix' => 'user_bind_'.md5($params[$type]),
'expire_time' => MyC('common_verify_expire_time'),
'interval_time' => MyC('common_verify_interval_time'),
];
// 发送验证码
$code = GetNumberCode(4);
switch($type)
{
// 短信
case 'mobile' :
$obj = new \base\Sms($verify_params);
$status = $obj->SendCode($params[$type], $code, ConfigService::SmsTemplateValue('home_sms_user_mobile_binding_template'));
break;
// 邮箱
case 'email' :
$obj = new \base\Email($verify_params);
$email_params = [
'email' => $params[$type],
'content' => MyC('home_email_user_email_binding_template'),
'title' => MyC('home_site_name').' - '.MyLang('common_service.safety.send_verify_email_title'),
'code' => $code,
];
$status = $obj->SendHtml($email_params);
break;
// 默认
default :
return DataReturn(MyLang('verify_code_not_support_send_error_tips'), -2);
}
if($status)
{
return DataReturn(MyLang('send_success'), 0);
}
return DataReturn(MyLang('send_fail').'['.$obj->error.']', -100);
}
/**
* 根据token获取用户信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-12-06
* @desc description
* @param [array] $params [输入参数]
*/
public static function TokenUserinfo($params = [])
{
// 数据验证
$p = [
[
'checked_type' => 'empty',
'key_name' => 'token',
'error_msg' => MyLang('common_service.user.token_empty_tips'),
],
];
$ret = ParamsChecked($params, $p);
if($ret !== true)
{
return DataReturn($ret, -1);
}
// 获取用户信息并处理
$user = self::UserHandle(self::UserInfo('token', $params['token']));
if(empty($user))
{
return DataReturn(MyLang('common_service.user.save_user_info_no_exist_tips'), -1);
}
return DataReturn('success', 0, $user);
}
/**
* 用户退出
* @author Devil
* @blog http://gong.gg/
* @version 0.0.1
* @datetime 2016-12-05T14:31:23+0800
* @param [array] $params [输入参数]
*/
public static function Logout($params = [])
{
// 用户信息
$user = self::CacheLoginUserInfo();
// 清除session
MySession(self::$user_login_key, null);
// html代码
$body_html = [];
// 用户退出钩子
$hook_name = 'plugins_service_user_logout_handle';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => [],
'user_id' => isset($user['id']) ? $user['id'] : 0,
'user' => $user,
'body_html' => &$body_html,
]);
// 数据返回
$result = [
'body_html' => is_array($body_html) ? implode(' ', $body_html) : $body_html,
];
return DataReturn(MyLang('quit_success'), 0, $result);
}
/**
* 获取用户展示信息
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-05-05
* @desc description
* @param [array|int] $user_ids [用户id]
* @param [array] $user [指定用户信息]
*/
public static function GetUserViewInfo($user_ids, $user = [])
{
// 是否指定用户信息
if(empty($user) && !empty($user_ids))
{
// 参数处理查询数据
if(is_array($user_ids))
{
$user_ids = array_filter(array_unique($user_ids));
}
// 静态数据容器,确保每一个用户只读取一次,避免重复读取浪费资源
static $user_view_info_static_data = [];
if(!empty($user_ids))
{
$temp_user_ids = [];
$params_user_ids = is_array($user_ids) ? $user_ids : explode(',', $user_ids);
foreach($params_user_ids as $uid)
{
if(empty($user_view_info_static_data) || !array_key_exists($uid, $user_view_info_static_data))
{
$temp_user_ids[] = $uid;
}
}
// 存在未读取的规格咋数据库读取
if(!empty($temp_user_ids))
{
$data = Db::name('User')->where(['id'=>$temp_user_ids])->column('id,number_code,username,nickname,mobile,email,avatar,gender,birthday,province,city,county,address,integral,locking_integral,add_time', 'id');
if(!empty($data))
{
foreach($data as $uid=>$uv)
{
$user_view_info_static_data[$uid] = self::UserHandle($uv);
}
}
// 空数据记录、避免重复查询
foreach($temp_user_ids as $uid)
{
if(!array_key_exists($uid, $user_view_info_static_data))
{
$user_view_info_static_data[$uid] = null;
}
}
}
}
// 用户id是否数组
if(is_array($user_ids))
{
$user = isset($user_view_info_static_data) ? $user_view_info_static_data : [];
} else {
$user = (!empty($user_view_info_static_data) && array_key_exists($user_ids, $user_view_info_static_data)) ? $user_view_info_static_data[$user_ids] : [];
}
} else {
if(!empty($user))
{
$user = self::UserHandle($user);
}
}
return $user;
}
/**
* 用户登录,密码找回左侧数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-05-17
* @desc description
* @param [array] $params [输入参数]
*/
public static function UserEntranceLeftData($params = [])
{
// 从缓存获取
$data = empty($params['cache_key']) ? [] : MyCache($params['cache_key']);
// 获取数据
if(empty($data))
{
$data = [];
if(!empty($params['left_key']))
{
for($i=1; $i<=3; $i++)
{
$images_value = MyC('home_site_user_'.$params['left_key'].'_ad'.$i.'_images');
$url_value = MyC('home_site_user_'.$params['left_key'].'_ad'.$i.'_url');
$bg_color_value = MyC('home_site_user_'.$params['left_key'].'_ad'.$i.'_bg_color');
if(!empty($images_value))
{
$data[] = [
'images' => ResourcesService::AttachmentPathViewHandle($images_value),
'url' => empty($url_value) ? null : $url_value,
'bg_color' => empty($bg_color_value) ? null : $bg_color_value,
];
}
}
// 存储缓存
if(!empty($params['cache_key']))
{
MyCache($params['cache_key'], $data);
}
}
}
return DataReturn(MyLang('operate_success'), 0, $data);
}
/**
* 用户推荐id加密
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-06-21
* @desc description
* @param [int] $user_id [用户id]
*/
public static function UserReferrerEncryption($user_id)
{
return StrToAscii(base64_encode($user_id));
}
/**
* 用户推荐id解密
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2019-06-21
* @desc description
* @param [array] $params [输入参数, referrer 参数用户推荐id, 会员码, 手机, 邮箱]
*/
public static function UserReferrerDecrypt($params = [])
{
// 推荐人
if(empty($params['referrer']))
{
$referrer = MySession('share_referrer_id');
if(empty($referrer))
{
$referrer = MyCookie('share_referrer_id');
}
} else {
$referrer = $params['referrer'];
}
if(!empty($referrer))
{
// 用户验证、默认用户id和会员码
$field = 'id|number_code';
// 是否手机号码
if(CheckMobile($referrer))
{
$field = 'mobile';
// 是否电子邮箱
} else if(CheckEmail($referrer))
{
$field = 'email';
} else {
// 查看用户id是否已加密
if(preg_match('/[a-zA-Z]/', $referrer))
{
$referrer = intval(base64_decode(AsciiToStr($referrer)));
}
}
$referrer = Db::name('User')->where([$field=>$referrer, 'status'=>0])->value('id');
}
return empty($referrer) ? 0 : intval($referrer);
}
/**
* 用户登录注册后跳转页面地址
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2021-03-04
* @desc description
*/
public static function UserLoginOrRegBackRefererUrl()
{
// 上一个页面, 空则用户中心
$referer_url = empty($_SERVER['HTTP_REFERER']) ? MyUrl('index/user/index') : htmlentities($_SERVER['HTTP_REFERER']);
if(!empty($_SERVER['HTTP_REFERER']))
{
// 是否是指定页面,则赋值用户中心
$all = ['login', 'register', 'forget', 'logininfo', 'reginfo', 'smsreginfo', 'emailreginfo', 'forgetpwdinfo', 'logout'];
$status = false;
foreach($all as $v)
{
if(strpos($_SERVER['HTTP_REFERER'], $v) !== false)
{
$referer_url = MyUrl('index/user/index');
$status = true;
break;
}
}
// 未匹配到指定页面
if(!$status)
{
// 非商城域名,则赋值用户中心
if(GetUrlHost($referer_url) != GetUrlHost(__MY_URL__))
{
$referer_url = MyUrl('index/user/index');
}
}
}
return $referer_url;
}
/**
* 用户名、手机、邮箱注册是否禁止
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-12-18
* @desc description
* @param [string] $value [用户名、手机、邮箱]
* @param [string] $type [类型 username用户名、mobile手机、email邮箱]
*/
public static function UserRegForbidCheck($value, $type)
{
$forbid = MyC('home_userregister_unique_forbid_value');
if(!empty($forbid))
{
if(!is_array($forbid))
{
$forbid = explode(',', $forbid);
}
if(in_array($value, $forbid))
{
return DataReturn(MyLang('register_'.$type.'_forbid_error_tips').'('.$value.')', -1);
}
}
return DataReturn('success', 0);
}
}
?>