463 lines
14 KiB
PHP
Executable File
463 lines
14 KiB
PHP
Executable File
<?php
|
||
|
||
namespace app\api\controller;
|
||
|
||
use app\MyController;
|
||
use app\common\model\User;
|
||
use app\common\model\UserAccount;
|
||
use think\facade\Request;
|
||
use app\common\model\User as UserModel;
|
||
|
||
header('Access-Control-Allow-Origin: *');
|
||
|
||
/**
|
||
* 商户后台控制器基类
|
||
*/
|
||
class Base extends MyController
|
||
{
|
||
public $page = '10';
|
||
|
||
/**
|
||
* 获取当前用户信息
|
||
*/
|
||
protected function getUser()
|
||
{
|
||
$token = request()->header('token', '');
|
||
|
||
// 先从Redis中获取用户账户信息
|
||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||
$redis_key = 'user_account_token:' . $token;
|
||
$user_account = $redis->get($redis_key);
|
||
|
||
if ($user_account) {
|
||
// Redis中存在数据,直接使用
|
||
$user_account = json_decode($user_account, true);
|
||
} else {
|
||
// Redis中不存在,从数据库获取
|
||
$user_account = UserAccount::getInfo(['account_token' => $token]);
|
||
|
||
// 如果数据库中存在该用户账户信息,则存入Redis
|
||
if ($user_account) {
|
||
$redis->set($redis_key, json_encode($user_account));
|
||
$redis->expire($redis_key, 600); // 设置过期时间为10分钟(600秒)
|
||
}
|
||
}
|
||
|
||
if (!$user_account) {
|
||
$data['status'] = '-1';
|
||
$data['msg'] = "没有找到用户信息1";
|
||
exit(json_encode($data, 1));
|
||
}
|
||
|
||
$user_account_is = user_md5($user_account['user_id'] . $user_account['token_num'] . $user_account['token_time']);
|
||
if ($token !== $user_account_is) {
|
||
$data['status'] = '-1';
|
||
$data['msg'] = "没有找到用户信息2";
|
||
exit(json_encode($data, 1));
|
||
}
|
||
|
||
$user = User::where(['id' => $user_account['user_id']])->find();
|
||
if (!$user) {
|
||
$data['status'] = '-1';
|
||
$data['msg'] = "没有找到用户信息3";
|
||
exit(json_encode($data, 1));
|
||
}
|
||
if ($user['status'] != 1) {
|
||
$data['status'] = '-1';
|
||
$data['msg'] = "该账户已被封号,请联系客服解封";
|
||
exit(json_encode($data, 1));
|
||
}
|
||
|
||
// 检查用户是否有UID,如果没有则生成
|
||
if (empty($user['uid'])) {
|
||
// 获取用户uid配置
|
||
$user_config = getConfig('user_config');
|
||
if (!empty($user_config) && isset($user_config['uid_type'])) {
|
||
// 生成UID
|
||
$uid = $this->generateUidForUser($user['id']);
|
||
if ($uid) {
|
||
// 更新用户UID
|
||
User::where('id', $user['id'])->update(['uid' => $uid]);
|
||
$user['uid'] = $uid;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $user;
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取当前登录用户ID
|
||
*
|
||
* @return int 用户ID,未登录或状态异常时返回0
|
||
*/
|
||
protected function getUserId()
|
||
{
|
||
$token = request()->header('token', '');
|
||
// 尝试从请求参数中获取token
|
||
if (empty($token)) {
|
||
$token = $this->request->param('token', '');
|
||
}
|
||
|
||
if (empty($token)) {
|
||
return 0;
|
||
}
|
||
|
||
// 先从Redis中获取用户账户信息
|
||
$redis = (new \app\common\server\RedisHelper())->getRedis();
|
||
$redis_key = 'user_account_token:' . $token;
|
||
$user_account = $redis->get($redis_key);
|
||
|
||
if ($user_account) {
|
||
// Redis中存在数据,直接使用
|
||
$user_account = json_decode($user_account, true);
|
||
} else {
|
||
// Redis中不存在,从数据库获取
|
||
$user_account = UserAccount::getInfo(['account_token' => $token]);
|
||
|
||
// 如果数据库中存在该用户账户信息,则存入Redis
|
||
if ($user_account) {
|
||
$redis->set($redis_key, json_encode($user_account));
|
||
$redis->expire($redis_key, 600); // 设置过期时间为10分钟(600秒)
|
||
}
|
||
}
|
||
|
||
if (!$user_account) {
|
||
return 0;
|
||
}
|
||
|
||
// 验证token有效性
|
||
$user_account_is = user_md5($user_account['user_id'] . $user_account['token_num'] . $user_account['token_time']);
|
||
if ($token !== $user_account_is) {
|
||
return 0;
|
||
}
|
||
|
||
// 检查用户状态
|
||
$user = User::where(['id' => $user_account['user_id']])->find();
|
||
if (!$user || $user['status'] != 1) {
|
||
return 0;
|
||
}
|
||
|
||
return $user['id'];
|
||
}
|
||
|
||
/**
|
||
* 为用户生成UID
|
||
*
|
||
* @param int $user_id 用户ID
|
||
* @return string 生成的UID
|
||
*/
|
||
protected function generateUidForUser($user_id)
|
||
{
|
||
// 获取用户uid配置
|
||
$user_config = getConfig('user_config');
|
||
if (empty($user_config) || !isset($user_config['uid_type'])) {
|
||
return (string) $user_id; // 默认使用真实ID
|
||
}
|
||
|
||
$uid_type = (int) $user_config['uid_type'];
|
||
$uid_length = isset($user_config['uid_length']) ? (int) $user_config['uid_length'] : 6;
|
||
|
||
// 限制长度范围
|
||
if ($uid_length < 4) {
|
||
$uid_length = 4;
|
||
} elseif ($uid_length > 16) {
|
||
$uid_length = 16;
|
||
}
|
||
|
||
// 根据不同类型生成UID
|
||
switch ($uid_type) {
|
||
case 0: // 真实ID
|
||
return (string) $user_id;
|
||
|
||
case 1: // 数字ID
|
||
// 生成不以0开头的随机数字
|
||
$max_attempts = 10;
|
||
$attempt = 0;
|
||
|
||
while ($attempt < $max_attempts) {
|
||
// 生成随机数字
|
||
$min = pow(10, $uid_length - 1);
|
||
$max = pow(10, $uid_length) - 1;
|
||
$uid = (string) mt_rand($min, $max);
|
||
|
||
// 检查是否唯一
|
||
$exists = User::where('uid', $uid)->count();
|
||
if ($exists == 0) {
|
||
return $uid;
|
||
}
|
||
|
||
$attempt++;
|
||
}
|
||
|
||
// 如果多次尝试后仍无法生成唯一ID,则使用更可靠的方法
|
||
return $this->generateUniqueNumericId($uid_length);
|
||
|
||
case 2: // 随机字符和数字
|
||
$length = max(8, $uid_length); // 字母数字混合至少8位
|
||
|
||
$max_attempts = 10;
|
||
$attempt = 0;
|
||
|
||
while ($attempt < $max_attempts) {
|
||
// 生成随机字母数字
|
||
$characters = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ'; // 排除容易混淆的字符
|
||
$uid = '';
|
||
|
||
// 确保第一个字符不是数字
|
||
$uid .= $characters[mt_rand(8, strlen($characters) - 1)]; // 从字母开始
|
||
|
||
// 生成剩余字符
|
||
for ($i = 1; $i < $length; $i++) {
|
||
$uid .= $characters[mt_rand(0, strlen($characters) - 1)];
|
||
}
|
||
|
||
// 检查是否唯一
|
||
$exists = User::where('uid', $uid)->count();
|
||
if ($exists == 0) {
|
||
return $uid;
|
||
}
|
||
|
||
$attempt++;
|
||
}
|
||
|
||
// 如果多次尝试后仍无法生成唯一ID,使用时间戳+随机数确保唯一性
|
||
return $this->generateUniqueAlphaNumId($length);
|
||
|
||
default:
|
||
return (string) $user_id;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成唯一的数字ID(备用方法)
|
||
*/
|
||
private function generateUniqueNumericId($length)
|
||
{
|
||
// 使用时间微秒 + 随机数的方式保证唯一性
|
||
$base = microtime(true) * 10000 . mt_rand(1000, 9999);
|
||
$uid = substr(preg_replace('/[^0-9]/', '', $base), 0, $length);
|
||
|
||
// 确保不以0开头且长度正确
|
||
while (strlen($uid) < $length || $uid[0] == '0') {
|
||
$uid = mt_rand(1, 9) . substr($uid, 1);
|
||
$uid = substr($uid, 0, $length);
|
||
}
|
||
|
||
return $uid;
|
||
}
|
||
|
||
/**
|
||
* 生成唯一的字母数字ID(备用方法)
|
||
*/
|
||
private function generateUniqueAlphaNumId($length)
|
||
{
|
||
// 使用时间戳 + 随机字符
|
||
$base = time() . mt_rand(1000, 9999);
|
||
$hash = md5($base);
|
||
|
||
// 转换为字母数字混合
|
||
$uid = '';
|
||
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; // 排除容易混淆的字符
|
||
|
||
// 确保第一个字符是字母
|
||
$uid .= $chars[mt_rand(0, 25)]; // 前26个是字母
|
||
|
||
// 生成剩余字符
|
||
for ($i = 1; $i < $length; $i++) {
|
||
$uid .= $chars[mt_rand(0, strlen($chars) - 1)];
|
||
}
|
||
|
||
return $uid;
|
||
}
|
||
|
||
/**
|
||
*
|
||
* 是否H5客户端
|
||
* @return bool
|
||
*/
|
||
protected function ish5()
|
||
{
|
||
$client = $this->getPlatform();
|
||
if ($client == "h5") {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
protected function getPlatform()
|
||
{
|
||
$client = request()->header('client', '');
|
||
if($client==""){
|
||
$client = request()->header('platform', '');
|
||
}
|
||
return $client;
|
||
}
|
||
|
||
|
||
/*
|
||
* 判断优惠券是否领过
|
||
*/
|
||
protected function getUserid1($is_force = true)
|
||
{
|
||
$header = Request::header();
|
||
if ($header['token'] == '') {
|
||
$token = $this->request->param('token');
|
||
} else {
|
||
$token = $header['token'];
|
||
}
|
||
$header['logintype'] = 1;
|
||
if (!isset($header['logintype']) or !in_array($header['logintype'], [1, 2])) {
|
||
return false;
|
||
}
|
||
if (!$token) {
|
||
if ($is_force) {
|
||
return false;
|
||
}
|
||
|
||
}
|
||
$user_account = UserAccount::getInfo(['account_token' => $token]);
|
||
if (empty($user_account)) {
|
||
if ($is_force) {
|
||
return false;
|
||
}
|
||
return false;
|
||
}
|
||
$user = UserModel::getInfo(['id' => $user_account['user_id']]);
|
||
if (empty($user)) {
|
||
return false;
|
||
}
|
||
if ($user['status'] != 1) {
|
||
return false;
|
||
}
|
||
#判断优惠券是否领过
|
||
if ($user['is_use_coupon'] == 1) {
|
||
return false;
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断用户是否已登录
|
||
*
|
||
* @param bool $returnUserId 是否返回用户ID而不是布尔值
|
||
* @return bool|int 如果$returnUserId为true,返回用户ID(未登录时为0);否则返回布尔值
|
||
*/
|
||
protected function isLogin($returnUserId = false)
|
||
{
|
||
$token = request()->header('token', '');
|
||
if (empty($token)) {
|
||
$token = $this->request->param('token', '');
|
||
}
|
||
|
||
if (empty($token)) {
|
||
return $returnUserId ? 0 : false;
|
||
}
|
||
|
||
$user_account = UserAccount::getInfo(['account_token' => $token]);
|
||
if (!$user_account) {
|
||
return $returnUserId ? 0 : false;
|
||
}
|
||
|
||
// 验证token有效性
|
||
$user_account_is = user_md5($user_account['user_id'] . $user_account['token_num'] . $user_account['token_time']);
|
||
if ($token !== $user_account_is) {
|
||
return $returnUserId ? 0 : false;
|
||
}
|
||
|
||
// 检查用户状态
|
||
$user = User::where(['id' => $user_account['user_id']])->find();
|
||
if (!$user || $user['status'] != 1) {
|
||
return $returnUserId ? 0 : false;
|
||
}
|
||
|
||
return $returnUserId ? $user['id'] : true;
|
||
}
|
||
|
||
/**
|
||
* 检查用户登录状态,未登录时返回JSON错误响应
|
||
*
|
||
* @param string $msg 自定义错误消息
|
||
* @return array|bool 登录时返回用户信息数组,未登录时输出JSON并终止执行
|
||
*/
|
||
protected function checkLogin($msg = '请先登录')
|
||
{
|
||
$user = $this->getUser();
|
||
if (!$user) {
|
||
$data = [
|
||
'status' => -1,
|
||
'msg' => $msg
|
||
];
|
||
echo json_encode($data, JSON_UNESCAPED_UNICODE);
|
||
exit;
|
||
}
|
||
return $user;
|
||
}
|
||
|
||
/**
|
||
* 检查用户是否满足解锁盒子的条件
|
||
*
|
||
* @param int $unlock_amount 解锁所需金额
|
||
* @return bool 是否满足解锁条件
|
||
*/
|
||
protected function checkUnlockCondition($unlock_amount)
|
||
{
|
||
if ($unlock_amount <= 0) {
|
||
return true; // 无需解锁
|
||
}
|
||
|
||
// 获取用户ID
|
||
$userId = $this->isLogin(true);
|
||
if (!$userId) {
|
||
return false; // 未登录
|
||
}
|
||
|
||
// 获取用户消费总额
|
||
$user = User::where('id', $userId)->find();
|
||
if (!$user) {
|
||
return false;
|
||
}
|
||
|
||
// 用户消费总额大于等于解锁金额时可以解锁
|
||
return isset($user['total_consumption']) && $user['total_consumption'] >= $unlock_amount;
|
||
}
|
||
|
||
|
||
/**
|
||
* 获取真实客户端IP地址
|
||
* 支持从代理服务器转发的请求
|
||
*/
|
||
protected function getRealIp()
|
||
{
|
||
$ip = request()->ip();
|
||
|
||
// 检查常见的代理服务器IP头信息
|
||
$headers = [
|
||
'HTTP_X_FORWARDED_FOR',
|
||
'HTTP_X_REAL_IP',
|
||
'HTTP_CLIENT_IP',
|
||
'HTTP_X_CLIENT_IP',
|
||
'HTTP_X_CLUSTER_CLIENT_IP',
|
||
'REMOTE_ADDR'
|
||
];
|
||
|
||
foreach ($headers as $header) {
|
||
if (isset($_SERVER[$header]) && !empty($_SERVER[$header])) {
|
||
// 可能包含多个IP,取第一个
|
||
$ips = explode(',', $_SERVER[$header]);
|
||
$client_ip = trim($ips[0]);
|
||
|
||
// 验证IP格式是否合法
|
||
if (filter_var($client_ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||
return $client_ip;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $ip;
|
||
}
|
||
|
||
}
|