This commit is contained in:
2025-08-14 17:19:26 +08:00
parent 30abda5ba7
commit 281248fd04
245 changed files with 21051 additions and 61 deletions

View File

@@ -0,0 +1,255 @@
<?php
namespace app\czg\app\controller;
use ba\Date;
use Throwable;
use ba\Captcha;
use ba\Random;
use app\common\model\User;
use think\facade\Validate;
use app\common\facade\Token;
use app\common\model\UserScoreLog;
use app\common\model\UserMoneyLog;
use app\common\controller\Frontend;
use app\api\validate\Account as AccountValidate;
class AccountController extends Frontend
{
protected array $noNeedLogin = ['retrievePassword'];
protected array $noNeedPermission = ['verification', 'changeBind'];
public function initialize(): void
{
parent::initialize();
}
public function overview(): void
{
$sevenDays = Date::unixTime('day', -6);
$score = $money = $days = [];
for ($i = 0; $i < 7; $i++) {
$days[$i] = date("Y-m-d", $sevenDays + ($i * 86400));
$tempToday0 = strtotime($days[$i]);
$tempToday24 = strtotime('+1 day', $tempToday0) - 1;
$score[$i] = UserScoreLog::where('user_id', $this->auth->id)
->where('create_time', 'BETWEEN', $tempToday0 . ',' . $tempToday24)
->sum('score');
$userMoneyTemp = UserMoneyLog::where('user_id', $this->auth->id)
->where('create_time', 'BETWEEN', $tempToday0 . ',' . $tempToday24)
->sum('money');
$money[$i] = bcdiv($userMoneyTemp, 100, 2);
}
$this->success('', [
'days' => $days,
'score' => $score,
'money' => $money,
]);
}
/**
* 会员资料
* @throws Throwable
*/
public function profile(): void
{
if ($this->request->isPost()) {
$data = $this->request->only(['id', 'avatar', 'username', 'nickname', 'gender', 'birthday', 'motto']);
if (!isset($data['birthday'])) $data['birthday'] = null;
try {
$validate = new AccountValidate();
$validate->scene('edit')->check($data);
} catch (Throwable $e) {
$this->error($e->getMessage());
}
$model = $this->auth->getUser();
$model->startTrans();
try {
$model->save($data);
$model->commit();
} catch (Throwable $e) {
$model->rollback();
$this->error($e->getMessage());
}
$this->success(__('Data updated successfully~'));
}
$this->success('', [
'accountVerificationType' => get_account_verification_type()
]);
}
/**
* 通过手机号或邮箱验证账户
* 此处检查的验证码是通过 api/Ems或api/Sms发送的
* 验证成功后,向前端返回一个 email-pass Token或着 mobile-pass Token
* 在 changBind 方法中,通过 pass Token来确定用户已经通过了账户验证用户未绑定邮箱/手机时通过账户密码验证)
* @throws Throwable
*/
public function verification(): void
{
$captcha = new Captcha();
$params = $this->request->only(['type', 'captcha']);
if ($captcha->check($params['captcha'], ($params['type'] == 'email' ? $this->auth->email : $this->auth->mobile) . "user_{$params['type']}_verify")) {
$uuid = Random::uuid();
Token::set($uuid, $params['type'] . '-pass', $this->auth->id, 600);
$this->success('', [
'type' => $params['type'],
'accountVerificationToken' => $uuid,
]);
}
$this->error(__('Please enter the correct verification code'));
}
/**
* 修改绑定信息(手机号、邮箱)
* 通过 pass Token来确定用户已经通过了账户验证也就是以上的 verification 方法,同时用户未绑定邮箱/手机时通过账户密码验证
* @throws Throwable
*/
public function changeBind(): void
{
$captcha = new Captcha();
$params = $this->request->only(['type', 'captcha', 'email', 'mobile', 'accountVerificationToken', 'password']);
$user = $this->auth->getUser();
if ($user[$params['type']]) {
if (!Token::check($params['accountVerificationToken'], $params['type'] . '-pass', $user->id)) {
$this->error(__('You need to verify your account before modifying the binding information'));
}
} elseif (!isset($params['password']) || !verify_password($params['password'], $user->password, ['salt' => $user->salt])) {
$this->error(__('Password error'));
}
// 检查验证码
if ($captcha->check($params['captcha'], $params[$params['type']] . "user_change_{$params['type']}")) {
if ($params['type'] == 'email') {
$validate = Validate::rule(['email' => 'require|email|unique:user'])->message([
'email.require' => 'email format error',
'email.email' => 'email format error',
'email.unique' => 'email is occupied',
]);
if (!$validate->check(['email' => $params['email']])) {
$this->error(__($validate->getError()));
}
$user->email = $params['email'];
} elseif ($params['type'] == 'mobile') {
$validate = Validate::rule(['mobile' => 'require|mobile|unique:user'])->message([
'mobile.require' => 'mobile format error',
'mobile.mobile' => 'mobile format error',
'mobile.unique' => 'mobile is occupied',
]);
if (!$validate->check(['mobile' => $params['mobile']])) {
$this->error(__($validate->getError()));
}
$user->mobile = $params['mobile'];
}
Token::delete($params['accountVerificationToken']);
$user->save();
$this->success();
}
$this->error(__('Please enter the correct verification code'));
}
public function changePassword(): void
{
if ($this->request->isPost()) {
$model = $this->auth->getUser();
$params = $this->request->only(['oldPassword', 'newPassword']);
if (!verify_password($params['oldPassword'], $model->password, ['salt' => $model->salt])) {
$this->error(__('Old password error'));
}
$model->startTrans();
try {
$validate = new AccountValidate();
$validate->scene('changePassword')->check(['password' => $params['newPassword']]);
$model->resetPassword($this->auth->id, $params['newPassword']);
$model->commit();
} catch (Throwable $e) {
$model->rollback();
$this->error($e->getMessage());
}
$this->auth->logout();
$this->success(__('Password has been changed, please login again~'));
}
}
/**
* 积分日志
* @throws Throwable
*/
public function integral(): void
{
$limit = $this->request->request('limit');
$integralModel = new UserScoreLog();
$res = $integralModel->where('user_id', $this->auth->id)
->order('create_time desc')
->paginate($limit);
$this->success('', [
'list' => $res->items(),
'total' => $res->total(),
]);
}
/**
* 余额日志
* @throws Throwable
*/
public function balance(): void
{
$limit = $this->request->request('limit');
$moneyModel = new UserMoneyLog();
$res = $moneyModel->where('user_id', $this->auth->id)
->order('create_time desc')
->paginate($limit);
$this->success('', [
'list' => $res->items(),
'total' => $res->total(),
]);
}
/**
* 找回密码
* @throws Throwable
*/
public function retrievePassword(): void
{
$params = $this->request->only(['type', 'account', 'captcha', 'password']);
try {
$validate = new AccountValidate();
$validate->scene('retrievePassword')->check($params);
} catch (Throwable $e) {
$this->error($e->getMessage());
}
if ($params['type'] == 'email') {
$user = User::where('email', $params['account'])->find();
} else {
$user = User::where('mobile', $params['account'])->find();
}
if (!$user) {
$this->error(__('Account does not exist~'));
}
$captchaObj = new Captcha();
if (!$captchaObj->check($params['captcha'], $params['account'] . 'user_retrieve_pwd')) {
$this->error(__('Please enter the correct verification code'));
}
if ($user->resetPassword($user->id, $params['password'])) {
$this->success(__('Password has been changed~'));
} else {
$this->error(__('Failed to modify password, please try again later~'));
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\Frontend;
use app\utils\RedisUtils;
use think\facade\Db;
class AdController extends Frontend
{
public function state()
{
$params = $this->request->get();
$info = Db::name('uni_ad_callback_record')->where([
'user_id' => $this->getUserId(),
'extra' => $params['extraKey']
])->find();
if (!$info && RedisUtils::isCanCash($this->getUserId()) && str_contains($params['extraKey'], 'cash')) {
RedisUtils::setCanCashFlag($this->getUserId(), -1);
}
$this->success();
}
}

View File

@@ -0,0 +1,70 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\Frontend;
use ba\Random;
use OSS\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;
use OSS\Core\OssException;
use think\facade\Db;
use support\Log;
class AliossController extends Frontend
{
protected array $noNeedLogin = ['*'];
public function upload()
{
$file = request()->file('file');
if(empty($file)) {
$this->error('参数不能为空');
}
$commoninfo = Db::connect(config('database.search_library'));
$endpoint = $commoninfo->name('common_info')->where(['type' => 68])->find()['value'];
$accessKeyId = $commoninfo->name('common_info')->where(['type' => 69])->find()['value'];
$secretAccessKey = $commoninfo->name('common_info')->where(['type' => 70])->find()['value'];
$bucket = $commoninfo->name('common_info')->where(['type' => 71])->find()['value'];
$befor_url = $commoninfo->name('common_info')->where(['type' => 72])->find()['value'];
putenv('OSS_ACCESS_KEY_ID=' . $accessKeyId);
putenv('OSS_ACCESS_KEY_SECRET='. $secretAccessKey);
$provider = new EnvironmentVariableCredentialsProvider();
$object = date('Ymd') . '/' . uniqid() . '.' .$file->getOriginalExtension();
try{
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
"signatureVersion" => OssClient::OSS_SIGNATURE_VERSION_V1,
);
$ossClient = new OssClient($config);
// 以二进制模式读取文件内容
$handle = fopen($file->getRealPath(), 'rb');
$content = stream_get_contents($handle);
fclose($handle);
// 上传二进制内容明确指定Content-Type
$options = [
OssClient::OSS_CONTENT_LENGTH => strlen($content),
OssClient::OSS_CONTENT_TYPE => $file->getMime(),
// 禁用字符编码转换
'Content-Encoding' => 'binary',
];
$res = $ossClient->putObject($bucket, $object, $content, $options);
Log::write('上传文件结果' . json_encode($res));
if(!empty($res['info'])) {
return $this->ApiDataReturn(['data' => $befor_url . '/' . $object, 'msg' => 'success', 'code' => 0]);
}else {
$this->error('上传失败');
}
} catch(OssException $e) {
$this->error($e->getMessage());
}
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\Frontend;
use app\czg\app\model\TbUser;
class AnnouncementController extends Frontend
{
protected array $noNeedLogin = ['*'];
// 忘记密码
public function index()
{
$get = $this->request->get();
return $this->ApiDataReturn(\app\czg\app\model\Announcement::list($get['type']));
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace app\czg\app\controller;
use app\czg\app\model\CommonInfo;
use app\czg\app\model\Orders;
use app\common\controller\Frontend;
class BannerController extends Frontend
{
protected array $noNeedLogin = ['selectBannerList', 'test'];
// 查询所有banner图
public function selectBannerList()
{
$get = $this->request->get();
if(empty($get['classify'])) {
$this->error('参数不完整');
}
$banner = \app\api\model\Banner::where(['classify' => $get['classify'], 'state' => 1])->order('sort', 'desc')->select()->toArray();
$this->success('ok', convertToCamelCase($banner));
}
public function test()
{
$qdAward = (new CommonInfo())->getByCode(915)['value'];
$this->successWithData(bccomp($qdAward, "0") > 0);
}
}

View File

@@ -0,0 +1,94 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\WithDraw;
use app\common\controller\Frontend;
use app\exception\SysException;
use app\utils\RedisUtils;
use support\think\Cache;
use app\api\model\Cash as CashModel;
class CashController extends Frontend
{
protected array $noNeedLogin = ['*'];
public function canCash()
{
$user_id = $this->auth->getUser()['user_id'];
$comm = CommonInfo::where(['type' => 928])->find()->value;
if($comm == 0) {
$this->success('ok', true);
}
$redis_can_cash = Cache::get('cash:canCash:' . $user_id);
if($redis_can_cash) {
$this->success('ok', true);
}
}
private function checkCanCash($userId)
{
$canCash = RedisUtils::isCanCash($userId);
if (!$canCash) {
$val = (new CommonInfo())->getByCode(928)['value'];
if ($val == '1') {
throw new SysException("您未观看激励广告,请先观看");
}
}
}
/**
* 提现接口
*/
public function withdraw()
{
$amount = $this->request->get('amount');
$isAlipay = $this->request->get('isAlipay/d');
$userId = $this->getUserId();
self::checkCanCash($userId);
$info = (new CommonInfo())->getByCode(930);
if (!$info) {
$this->error("当前时间段未开启提现功能");
}
$timeScope = explode('~', $info['value']); // 如 08:30~17:30
$today = date('Y-m-d');
// 拼接今日的开始和结束时间
$beginTime = strtotime($today . ' ' . $timeScope[0]);
$endTime = strtotime($today . ' ' . $timeScope[1]);
$now = time();
// 判断是否在时间范围内
if ($now < $beginTime || $now > $endTime) {
throw new SysException("提现时间为每天" . $info['value']);
}
debounce("withdraw:".$userId, 30);
runWithLock("lock:withdraw:{$userId}", 300, function () use ($userId, $amount, $isAlipay) {
WithDraw::goWithDraw($userId, $amount, '', false, $isAlipay == 1);
});
$this->success('提现成功,将在三个工作日内到账,请耐心等待!');
}
/**
* 查询提现记录列表
*/
public function selectPayDetails()
{
$get = $this->request->get();
$cashOut[ 'user_id'] = $this->auth->user_id;
return $this->ApiDataReturn(CashModel::selectPayDetails($cashOut, $get, true, $this->auth->getUser()));
}
}

View File

@@ -0,0 +1,110 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\Frontend;
use ba\Random;
use think\facade\Db;
use Throwable;
use ba\Captcha;
use think\Response;
use ba\ClickCaptcha;
use think\facade\Config;
use app\common\facade\Token;
use app\common\library\Auth as UserAuth;
class CommonController extends Frontend
{
protected array $noNeedLogin = ['getAppUseKv', 'getAppUseKv'];
/**
* 图形验证码
* @throws Throwable
*/
public function captcha(): Response
{
$captchaId = $this->request->request('id');
$config = array(
'codeSet' => '123456789', // 验证码字符集合
'fontSize' => 22, // 验证码字体大小(px)
'useCurve' => false, // 是否画混淆曲线
'useNoise' => true, // 是否添加杂点
'length' => 4, // 验证码位数
'bg' => array(255, 255, 255), // 背景颜色
);
$captcha = new Captcha($config);
return $captcha->entry($captchaId);
}
/**
* 点选验证码
*/
public function clickCaptcha(): void
{
$id = $this->request->request('id/s');
$captcha = new ClickCaptcha();
$this->success('', $captcha->creat($id));
}
/**
* 点选验证码检查
* @throws Throwable
*/
public function checkClickCaptcha(): void
{
$id = $this->request->post('id/s');
$info = $this->request->post('info/s');
$unset = $this->request->post('unset/b', false);
$captcha = new ClickCaptcha();
if ($captcha->check($id, $info, $unset)) $this->success();
$this->error();
}
/**
* 刷新 token
* 无需主动删除原 token由 token 驱动自行实现过期 token 清理,可避免并发场景下无法获取到过期 token 数据
*/
public function refreshToken(): void
{
$refreshToken = $this->request->post('refreshToken');
$refreshToken = Token::get($refreshToken);
if (!$refreshToken || $refreshToken['expire_time'] < time()) {
$this->error(__('Login expired, please login again.'));
}
$newToken = Random::uuid();
// 管理员token刷新
if ($refreshToken['type'] == AdminAuth::TOKEN_TYPE . '-refresh') {
Token::set($newToken, AdminAuth::TOKEN_TYPE, $refreshToken['user_id'], (int)Config::get('buildadmin.admin_token_keep_time'));
}
// 会员token刷新
if ($refreshToken['type'] == UserAuth::TOKEN_TYPE . '-refresh') {
Token::set($newToken, UserAuth::TOKEN_TYPE, $refreshToken['user_id'], (int)Config::get('buildadmin.user_token_keep_time'));
}
$this->success('', [
'type' => $refreshToken['type'],
'token' => $newToken
]);
}
public function getAppUseKv()
{
return $this->resultApi(\app\common\model\Common::getAppUseKv());
}
public function type()
{
$type = $this->request->route('num');
$data = convertToCamelCase(Db::connect(config('think-orm.search_library'))->name('common_info')->where('type', $type)->find());
$this->success('ok', $data, 0);
}
}

View File

@@ -0,0 +1,153 @@
<?php
namespace app\czg\app\controller;
use app\api\validate\CourseCollectValidate;
use app\common\library\DatabaseRoute;
use app\common\model\BaseModel;
use think\facade\Db;
use app\common\controller\Frontend;
class CourseCollectController extends Frontend
{
protected array $noNeedPermission = [];
public function initialize(): void
{
parent::initialize();
}
private function insertOrder($params)
{
$userId = $this->getUserId();
$model = DatabaseRoute::getDb('course_collect', $userId, true);
$info = $model->where([
'user_id' => $userId,
'classify' => 3,
'course_id' => $params['courseId'],
])->order('create_time', 'desc')->limit(1)->find();
if ($info) {
// 更新记录
$model
->where([
'course_collect_id' => $info['course_collect_id'],
'user_id' => $userId,
])
->update([
'update_time' => date('Y-m-d H:i:s'),
'course_details_id' => $params['courseDetailsId'],
]);
} else {
// 插入新记录
$model->insert([
'user_id' => $userId,
'course_id' => $params['courseId'],
'course_details_id' => $params['courseDetailsId'],
'classify' => 3,
'create_time' => date('Y-m-d H:i:s'),
'update_time' => date('Y-m-d H:i:s'),
]);
}
}
public function upGoodNum($params, $isAdd)
{
$courseDetails = $course_d = DatabaseRoute::getDb('course_details', ['course_id' => $params['courseId']]);
$courseDetails = $courseDetails->where([
'course_id' => $params['courseId'],
'course_details_id' => $params['courseDetailsId'],
])->find();
if (!$courseDetails) {
return; // 数据不存在,不处理
}
$goodNum = isset($courseDetails['good_num']) ? (int)$courseDetails['good_num'] : 0;
if ($isAdd) {
$goodNum += 1; // 点赞
} else {
$goodNum -= 1; // 取消点赞
}
if ($goodNum < 0) {
return; // 防止出现负数
}
Db::connect(DatabaseRoute::getConnection('course_details', ['course_id' => $params['courseId']], true))->name('course_details')->where([
'course_id' => $params['courseId'],
'course_details_id' => $params['courseDetailsId'],
])->update(['good_num' => $goodNum]);
}
public function insertCourseCollect()
{
$userId = $this->getUserId();
$data = $this->request->only(['classify', 'courseDetailsId', 'courseId', 'type']);
// classify 1收藏 2点赞 3订单
(new CourseCollectValidate())->scene('insertCourseCollect')->check($data);
if ($data['classify'] === 3) {
$this->insertOrder($data);
} else {
$where = [
'user_id' => $userId,
'classify' => $data['classify'],
'course_id' => $data['courseId'],
];
if ($data['classify'] === 2) {
if(empty($data['courseDetailsId'])) {
$this->error('courseDetailsId不能为空', [], -1);
}
$where[] = ['course_details_id', 'eq', $data['courseDetailsId']];
}
$model = DatabaseRoute::getDb('course_collect', $this->getUserId());
$info = $model->where($where)->find();
if ($data['type'] == 1) {
if ($info == null) {
$model = DatabaseRoute::getDb('course_collect', $this->getUserId(), true);
$model->insert([
'user_id' => $this->getUserId(),
'create_time' => getNormalDate(),
'update_time' => getNormalDate(),
'course_id' => $data['courseId'],
'course_details_id' => !empty($data['courseDetailsId'])?$data['courseDetailsId']:null,
'classify' => $data['classify'],
]);
}
}else{
if ($info) {
DatabaseRoute::getDb('course_collect', $this->getUserId(), true)->where([
'course_collect_id' => $info['course_collect_id']
])->delete();
}
}
}
if ($data['classify'] == 2) {
$this->upGoodNum($data, $data['type']);
}
$this->success();
}
// app查询收藏短剧信息
public function selectByUserId()
{
$get = $this->request->get();
return $this->ApiDataReturn(\app\api\model\Course::selectByUserId($get, $this->auth->user_id));
}
// 我的追剧和我的喜欢数量
public function collectVideoSummary()
{
return $this->ApiDataReturn(\app\api\model\Course::collectVideoSummary($this->auth->user_id));
}
}

View File

@@ -1,16 +1,51 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\BaseController;
use app\common\library\DatabaseRoute;
use app\czg\app\model\Course;
use app\model\Test;
use support\Request;
use think\facade\Db;
use app\common\controller\Frontend;
use app\api\model\Course;
class CourseController extends BaseController
class CourseController extends Frontend
{
protected array $noNeedLogin = ['selectCourse', 'selectCourseDetailsList', 'viewCourse'];
public function selectCourse()
{
$post = $this->request->get();
$res = Course::selectCourse($post);
return $this->ApiDataReturn($res);
}
// 推荐视频
public function selectCourseDetailsList()
{
if($this->auth->isLogin()) {
$user_id = $this->auth->user_id;
}else {
$user_id = 0;
}
$post = $this->request->get();
$res = Course::selectCourseDetailsList($post, $user_id);
return $this->ApiDataReturn($res);
}
// 获取抽奖红包提示
public function getRedEnvelopeTips()
{
$user_id = $this->auth->user_id;
$res = Course::getRedEnvelopeTips($user_id);
return $this->ApiDataReturn($res);
}
// 查看视频
public function viewCourse()
{
$get = $this->request->get();
$res = Course::viewCourse($get);
return $this->ApiDataReturn($res);
}
// 根据id查询短剧集数列表
public function courseSets()
{
$get = $this->request->get();

View File

@@ -0,0 +1,316 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\DiscSpinningRecord;
use app\api\model\Orders;
use app\api\model\TbUser;
use app\api\model\UserMoney;
use app\common\controller\Frontend;
use app\common\library\DatabaseRoute;
use app\exception\CzgException;
use app\exception\SysException;
use app\queue\DiscReceiveQueue;
use ba\Random;
use think\facade\Db;
use support\Log;
use think\facade\Queue;
class DiscSpinningController extends Frontend
{
protected array $noNeedLogin = ['draw'];
protected array $noNeedPermission = [];
public function initialize(): void
{
parent::initialize();
}
/**
* 抽奖
*/
public function draw()
{
$params = $this->request->get();
$userInfo = $this->auth->getUser();
Log::info('抽奖'. json_encode($userInfo));
debounce("user:disc-spinning:draw:".$userInfo['user_id'], 1);
$userId = $userInfo['user_id'];
$resp = [];
runWithLock("user:disc-spinning:limit:user:lock:".$this->getUserId(), 60, function () use ($params, $userId, &$resp, $userInfo) {
DatabaseRoute::transactionXa(function () use ($params, $userId, &$resp, $userInfo) {
// 查询抽奖次数
$count = DiscSpinningRecord::countDraw($userId);
// 免费两次之后校验实名
if ($count == 2 && !TbUser::checkEnable($userInfo)) {
$this->error('请实名认证后继续抽奖');
}
Log::info("用户id: $userId, 抽奖次数: $count");
// 订单抽奖
if (!isset($params['source']) || $params['source'] == 1) {
$drawCount = (new CommonInfo())->getByCodeToInt(901);
if ($count >= $drawCount) {
$this->error('当日可抽奖次数已超限');
}
// 校验订单笔数
$orders = Orders::selectOrdersByDay($userId);
if (!$orders) {
throw new SysException("无可用抽奖机会");
}
$params['sourceId'] = $orders['orders_id'];
}else{
$this->error("八嘎");
}
if (!isset($params['sourceId'])) {
throw new CzgException("异常请求");
}
$draws = self::draws($count + 1, $orders['pay_money'], $params['sourceId'], $userId, $params['source']);
$resp = $draws;
// $this->receive($draws);
});
});
pushQueue(DiscReceiveQueue::class, [
'draws' => $resp
]);
$resp = convertToCamelCase($resp);
$resp['img'] = $resp['imgUrl'];
$this->successWithData($resp);
}
public static function draws($drawCount, $orderAmount, $sourceId, $userId, $source)
{
$result = [
'name' => '谢谢惠顾',
'source_id' => $sourceId,
'user_id' => $userId,
'img_url' => '',
'type' => 1,
'number' => 1,
'draw_day' => date('Y-m-d'),
'create_time' => date('Y-m-d H:i:s'),
'source' => $source == 1 ? 'order' : 'task'
];
// 查询奖项
$prizes = Db::name('disc_spinning')->where([
'disc_type' => $source
])->order('number', 'asc')->select()->toArray();
if (empty($prizes)) {
DatabaseRoute::getDb('disc_spinning_record', $userId, true, true)->insert($result);
return $result;
}
// 获取最大概率
$maxNumber = array_reduce($prizes, function ($carry, $prize) {
return bccomp($prize['number'], $carry) > 0 ? $prize['number'] : $carry;
}, '0');
// 最大值为 0直接谢谢惠顾
if (bccomp($maxNumber, '0') === 0) {
$record = $result;
DatabaseRoute::getDb('disc_spinning_record', $userId, true, true)->insert($record);
return $record;
}
// 获取随机数(整数)
if ($maxNumber > 1) {
$randomNum = rand(0, (int)$maxNumber - 1);
} else {
$randomNum = rand(0, (int)$maxNumber); // 或者其它默认值
}
// 查询奖励金额列表(模拟 redis 逻辑)
$amounts = Db::name('disc_spinning_amount')->where([
'status' => 1,
'type' => $source
])->order('max_amount', 'asc')->select()->toArray();
// 按 num 分组
$amountMaps = [];
foreach ($amounts as $item) {
$num = isset($item['num']) ? intval($item['num']) : 0;
$amountMaps[$num][] = $item;
}
// 按照 drawCount 向下查找匹配组
$filteredAmounts = [];
if (!empty($amountMaps)) {
for ($i = $drawCount; $i >= 0; $i--) {
if (isset($amountMaps["{$i}"])) {
$filteredAmounts = $amountMaps["{$i}"];
break;
}
}
}
// 抽奖逻辑
$finalPrize = null;
foreach ($prizes as $prize) {
if (bccomp((string)$randomNum, $prize['number']) < 0) {
if ($prize['type'] == 2) {
// 金额类奖品
$maxAmount = (new CommonInfo())->getByCodeToInt(900); // 最大金额限制
$baseRandom = mt_rand() / mt_getrandmax();
$baseRandom = bccomp($baseRandom, "1", 2) ? 0.99 : $baseRandom;
$baseAmount = 0;
$resultAmount = 0;
foreach ($filteredAmounts as $amount) {
if ($baseRandom < $amount['random']) {
$resultAmount = $baseAmount + (mt_rand() / mt_getrandmax()) * $amount['max_amount'];
break;
}
$baseAmount = $amount['max_amount'];
}
if ($resultAmount < 0.01) {
$resultAmount = 0.01;
}
$randomFactor = mt_rand(50, 90) / 100; // 生成 0.5 到 0.9 的随机数
$resultAmount = $resultAmount * $randomFactor;
$resultAmount += $orderAmount;
if ($resultAmount > $maxAmount) {
$resultAmount = $maxAmount;
}
$finalPrize = [
'name' => $prize['name'],
'type' => 2,
'number' => round($resultAmount, 2),
'id' => $prize['id'],
'url' => $prize['url'] ?? ''
];
break;
} else {
// 非金额奖品
if ($source != 1) {
$finalPrize = [
'name' => $prize['name'],
'type' => $prize['type'],
'number' => 1,
'id' => $prize['id'],
'url' => $prize['url'] ?? ''
];
break;
}
}
}
}
if (!$finalPrize) {
// 没抽中任何奖品,默认“谢谢惠顾”
$finalPrize = [
'name' => '谢谢惠顾',
'type' => 1,
'number' => 1,
'id' => null,
'url' => ''
];
}
// 构建记录
$record = [
'id' => Random::generateRandomPrefixedId(19),
'name' => $finalPrize['name'],
'source_id' => $sourceId,
'user_id' => $userId,
'img_url' => $finalPrize['url'] ?? '',
'type' => $finalPrize['type'],
'number' => $finalPrize['number'],
'draw_day' => date('Y-m-d'),
'create_time' => date('Y-m-d H:i:s'),
'source' => $source == 1 ? 'order' : 'task'
];
// 保存
DatabaseRoute::getDb('disc_spinning_record', $userId, true)->insert($record);
$record['discSpinningId'] = $finalPrize['id'];
return $record;
}
/**
* 获取大转盘抽奖次数
*/
public function drawCount()
{
$get = $this->request->get();
if(empty($get['source'])) {
$soure = 1;
}else {
$soure = $get['source'];
}
$user = $this->auth->getUser();
$drawCount = (int)CommonInfo::where(['type' => 901])->find()->value;
$data['sum'] = $drawCount;
if(!empty($soure) && $soure != 1) {
if($soure == 2) {
$sourceType = 'taskW';
}else {
$sourceType = 'taskM';
}
$spinningCount = DatabaseRoute::getDb('disc_spinning_record', $user['user_id'])->where(['source' => $sourceType])->count();
if($spinningCount != null && $spinningCount > 0) {
$data['count'] = 0;
}else {
$i = DiscSpinningRecord::countTaskDisc($user['user_id'], $soure);
$data['count'] = $i>0?1:0;
}
}else {
$i = DatabaseRoute::getDb('disc_spinning_record', $user['user_id'])->where(['source' => 'order'])->where([
'draw_day' => ['between', date('Y-m-d 00:00:00'), date('Y-m-d 11:59:59')]
])->count();
if($drawCount - $i > 0) {
$data['count'] = DiscSpinningRecord::selectOrdersCountStatisticsByDay($user['user_id'], $drawCount - $i);
}else {
$data['count'] = 0;
}
}
$this->success('ok', $data);
}
// 查询大转盘
public function selectDiscSpinning()
{
$get = $this->request->get();
if(empty($get['source'])) {
$this->error('参数不完整');
}
$page = 1;
$limit = 20;
$db = Db::connect(config('database.search_library'));
$list = $db->name('disc_spinning')
->where(['disc_type' => $get['source']]);
$count = $list->count();
$list = $list->order('disc_type', 'asc')
->order('odds', 'asc')
->limit(page($page, $limit), $limit)
->select()->toArray();
foreach ($list as $k => &$v) {
$v['odds'] = null;
$v['number'] = null;
$v['discType'] = null;
$v['img'] = $v['url'];
}
$this->success('ok', [
'currPage' => $page,
'pageSize' => $limit,
'records' => convertToCamelCase($list),
'totalCount' => $count,
'totalPage' => ceil($count / $limit),
]);
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\Orders;
use app\api\model\TbUser;
use app\common\controller\Frontend;
use app\common\library\DatabaseRoute;
use app\exception\CzgException;
use app\queue\DiscReceiveQueue;
use ba\Random;
use think\facade\Db;
class DiscSpinningRecordController extends Frontend
{
// 查询大转盘抽奖记录
public function selectDiscSpinningRecord()
{
$get = $this->request->get();
if(empty($get['source']) || empty($get['page']) || empty($get['limit'])) {
$this->error('参数不完整');
}
$user = $this->auth->getUser();
$db = Db::connect(DatabaseRoute::getConnection('disc_spinning_record', ['user_id' => $user['user_id']]));
$list = $db->name('disc_spinning_record')
->where(['user_id' => $user['user_id']]);
$count = $list->count();
$list = $list->order('create_time', 'asc')
->limit(page($get['page'], $get['limit']), $get['limit'])
->select()->toArray();
$this->success('ok', [
'currPage' => $get['page'],
'pageSize' => $get['limit'],
'records' => convertToCamelCase($list),
'totalCount' => $count,
'totalPage' => ceil($count / $get['limit']),
]);
}
}

View File

@@ -0,0 +1,108 @@
<?php
namespace app\czg\app\controller;
use Throwable;
use ba\Captcha;
use ba\ClickCaptcha;
use think\facade\Validate;
use app\common\model\User;
use app\common\library\Email;
use app\common\controller\Frontend;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
class EmsController extends Frontend
{
protected array $noNeedLogin = ['send'];
public function initialize(): void
{
parent::initialize();
}
/**
* 发送邮件
* event 事件:user_register=用户注册,user_change_email=用户修改邮箱,user_retrieve_pwd=用户找回密码,user_email_verify=验证账户
* 不同的事件,会自动做各种必要检查,其中 验证账户 要求用户输入当前密码才能发送验证码邮件
* @throws Throwable
*/
public function send(): void
{
$params = $this->request->post(['email', 'event', 'captchaId', 'captchaInfo']);
$mail = new Email();
if (!$mail->configured) {
$this->error(__('Mail sending service unavailable'));
}
$validate = Validate::rule([
'email' => 'require|email',
'event' => 'require',
'captchaId' => 'require',
'captchaInfo' => 'require'
])->message([
'email' => 'email format error',
'event' => 'Parameter error',
'captchaId' => 'Captcha error',
'captchaInfo' => 'Captcha error'
]);
if (!$validate->check($params)) {
$this->error(__($validate->getError()));
}
// 检查验证码
$captchaObj = new Captcha();
$clickCaptcha = new ClickCaptcha();
if (!$clickCaptcha->check($params['captchaId'], $params['captchaInfo'])) {
$this->error(__('Captcha error'));
}
// 检查频繁发送
$captcha = $captchaObj->getCaptchaData($params['email'] . $params['event']);
if ($captcha && time() - $captcha['create_time'] < 60) {
$this->error(__('Frequent email sending'));
}
// 检查邮箱
$userInfo = User::where('email', $params['email'])->find();
if ($params['event'] == 'user_register' && $userInfo) {
$this->error(__('Email has been registered, please log in directly'));
} elseif ($params['event'] == 'user_change_email' && $userInfo) {
$this->error(__('The email has been occupied'));
} elseif (in_array($params['event'], ['user_retrieve_pwd', 'user_email_verify']) && !$userInfo) {
$this->error(__('Email not registered'));
}
// 通过邮箱验证账户
if ($params['event'] == 'user_email_verify') {
if (!$this->auth->isLogin()) {
$this->error(__('Please login first'));
}
if ($this->auth->email != $params['email']) {
$this->error(__('Please use the account registration email to send the verification code'));
}
// 验证账户密码
$password = $this->request->post('password');
if (!verify_password($password, $this->auth->password, ['salt' => $this->auth->salt])) {
$this->error(__('Password error'));
}
}
// 生成一个验证码
$code = $captchaObj->create($params['email'] . $params['event']);
$subject = __($params['event']) . '-' . get_sys_config('site_name');
$body = __('Your verification code is: %s', [$code]);
try {
$mail->isSMTP();
$mail->addAddress($params['email']);
$mail->isHTML();
$mail->setSubject($subject);
$mail->Body = $body;
$mail->send();
} catch (PHPMailerException) {
$this->error($mail->ErrorInfo);
}
$this->success(__('Mail sent successfully~'));
}
}

View File

@@ -0,0 +1,34 @@
<?php
namespace app\czg\app\controller;
use app\api\model\HelpClassify;
use app\api\model\UserMoney;
use app\common\controller\Frontend;
use think\facade\Db;
class HelpWordController extends Frontend
{
// 帮助中心
public function selectHelpList()
{
$get = $this->request->get();
if(empty($get['types'])) {
$this->error('参数不完整');
}
$word = new HelpClassify;
$word->setConnection(Config('think-orm.search_library'));
$result = $word
->with('helpword')
->where('types', $get['types'])->select()->toArray();
$result = convertToCamelCase($result);
foreach ($result as $k => $v) {
$result[$k]['helpWordList'] = convertToCamelCase($v['helpword']);
unset($result[$k]['helpword']);
}
$this->success('ok', $result);
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace app\czg\app\controller;
use ba\Tree;
use Throwable;
use think\facade\Db;
use think\facade\Config;
use app\common\controller\Frontend;
use app\common\library\token\TokenExpirationException;
class IndexController extends Frontend
{
protected array $noNeedLogin = ['index'];
public function initialize(): void
{
parent::initialize();
}
/**
* 前台和会员中心的初始化请求
* @throws Throwable
*/
public function index(): void
{
// $menus = [];
// if ($this->auth->isLogin()) {
// $rules = [];
// $userMenus = $this->auth->getMenus();
//
// // 首页加载的规则,验权,但过滤掉会员中心菜单
// foreach ($userMenus as $item) {
// if ($item['type'] == 'menu_dir') {
// $menus[] = $item;
// } elseif ($item['type'] != 'menu') {
// $rules[] = $item;
// }
// }
// $rules = array_values($rules);
// } else {
// // 若是从前台会员中心内发出的请求,要求必须登录,否则会员中心异常
// $requiredLogin = $this->request->get('requiredLogin/b', false);
// if ($requiredLogin) {
//
// // 触发可能的 token 过期异常
// try {
// $token = get_auth_token(['ba', 'user', 'token']);
// $this->auth->init($token);
// } catch (TokenExpirationException) {
// $this->error(__('Token expiration'), [], 409);
// }
//
// $this->error(__('Please login first'), [
// 'type' => $this->auth::NEED_LOGIN
// ], $this->auth::LOGIN_RESPONSE_CODE);
// }
//
// $rules = Db::name('user_rule')
// ->where('status', 1)
// ->where('no_login_valid', 1)
// ->where('type', 'in', ['route', 'nav', 'button'])
// ->order('weigh', 'desc')
// ->select()
// ->toArray();
// $rules = Tree::instance()->assembleChild($rules);
// }
//
// $this->success('', [
// 'site' => [
// 'siteName' => get_sys_config('site_name'),
// 'version' => get_sys_config('version'),
// 'cdnUrl' => full_url(),
// 'upload' => keys_to_camel_case(get_upload_config(), ['max_size', 'save_name', 'allowed_suffixes', 'allowed_mime_types']),
// 'recordNumber' => get_sys_config('record_number'),
// 'cdnUrlParams' => Config::get('buildadmin.cdn_url_params'),
// ],
// 'openMemberCenter' => Config::get('buildadmin.open_member_center'),
// 'userInfo' => $this->auth->getUserInfo(),
// 'rules' => $rules,
// 'menus' => $menus,
// ]);
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace app\czg\app\controller;
use app\common\controller\Frontend;
class InviteController extends Frontend
{
// 我的收益
public function selectInviteMoney()
{
$res = \app\api\model\Invite::selectInviteMoney($this->auth->getUser());
return $this->ApiDataReturn($res);
}
// 查看我邀请的人员列表(查看所有邀请列表)
public function selectInviteByUserIdLists()
{
$get = $this->request->get();
$res = \app\api\model\Invite::selectInviteByUserIdLists($this->auth->getUser(), $get, 'api');
return $this->ApiDataReturn($res);
}
}

View File

@@ -16,7 +16,7 @@ use app\common\facade\Token;
use app\common\controller\Frontend;
use app\api\validate\User as UserValidate;
class LoginController extends BaseController
class LoginControllerController extends BaseController
{
protected array $noNeedLogin = ['*'];
@@ -50,7 +50,7 @@ class LoginController extends BaseController
// 发送验证码
public function sendMsg()
{
$get = $this->request->route();
$get = $this->request->route->param();
return $this->ApiDataReturn(Msg::sendMsg($get['phone'], $get['event']));
}

View File

@@ -0,0 +1,30 @@
<?php
namespace app\czg\app\controller;
use app\api\model\MessageInfo as MessageModel;
use app\common\controller\Frontend;
class MessageController extends Frontend
{
protected array $noNeedLogin = ['selectMessage', 'sendMessage'];
public function selectMessage()
{
return $this->ApiDataReturn(MessageModel::getList($this->request->get()));
}
public function sendMessage()
{
$post = $this->request->post();
return $this->ApiDataReturn(MessageModel::sendMessage($post, $this->auth->user_id));
}
public function selectMessageByUserId()
{
$get = $this->request->get();
$get['user_id'] = $this->getUserId();
return $this->ApiDataReturn(MessageModel::getList($get));
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace app\czg\app\controller;
use app\api\model\UserMoney;
use app\common\controller\Frontend;
class MoneyDetailsController extends Frontend
{
public function selectUserMoney()
{
return $this->ApiDataReturn(UserMoney::selectUserMoney($this->auth->user_id));
}
public function queryUserMoneyDetails()
{
$get = $this->request->get();
return $this->ApiDataReturn(UserMoney::queryUserMoneyDetails($this->auth->user_id, $get));
}
}

View File

@@ -6,8 +6,8 @@ use app\api\model\Orders;
use app\api\model\UserMoney;
use app\common\controller\BaseController;
use app\common\library\DatabaseRoute;
use app\czg\app\model\CommonInfo;
use app\czg\app\model\TbUser;
use app\api\model\CommonInfo;
use app\api\model\TbUser;
use app\enums\ErrEnums;
use app\exception\SysException;
use app\utils\RedisUtils;

View File

@@ -0,0 +1,38 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\TaskCenterRecord;
use app\api\model\UserInfo;
use app\api\model\UserSignRecord;
use app\common\controller\Frontend;
use app\common\library\DatabaseRoute;
use think\facade\Cache;
use think\facade\Db;
class TaskCenterController extends Frontend
{
public function selectTaskCenter()
{
$user_id = $this->auth->getUser()['user_id'];
return $this->ApiDataReturn(TaskCenterRecord::selectTaskCenter($user_id, $this->auth->getUser()['inviter_user_id']));
}
public function taskReceive()
{
$get = $this->request->get();
if(empty($get['id'])) {
$this->error('参数错误');
}
$id = $get['id'];
$userId = $this->auth->getUser()['user_id'];
if($id !== null && $id == 19) {
TaskCenterRecord::addBlackUser($userId, '任务中心领取');
}
return $this->ApiDataReturn(TaskCenterRecord::taskReceive($userId, $id, $this->auth->getUser()['inviter_user_id']));
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\UniAdCallbackRecord;
use app\api\model\WithDraw;
use app\common\controller\Frontend;
use app\exception\SysException;
use app\utils\RedisUtils;
use think\cache\driver\Redis;
use think\facade\Db;
use think\facade\Cache;
use app\api\model\Cash as CashModel;
use support\Log;
class UniCallBackController extends Frontend
{
public function adCallBack()
{
$params = [
'adpid' => $this->request->param('adpid'),
'provider' => $this->request->param('provider'),
'platform' => $this->request->param('platform'),
'sign' => $this->request->param('sign'),
'trans_id' => $this->request->param('trans_id'),
'user_id' => $this->request->param('user_id'),
'extra' => $this->request->param('extra', '') // 可选参数,默认空字符串
];
// 记录日志
Log::write("接收到uni-ad广告完播回调回调信息: " . json_encode($params));
// 调用服务处理回调
$result = UniAdCallbackRecord::adCallBack($params);
// 返回成功响应
$this->successWithData($result);
}
}

View File

@@ -0,0 +1,389 @@
<?php
namespace app\czg\app\controller;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\AddShortUrlResponseBody\data;
use app\api\model\Msg;
use app\api\model\TbUser;
use app\api\model\UserInfo;
use app\common\library\DatabaseRoute;
use app\common\model\BaseModel;
use app\common\model\SysUser;
use app\exception\SysException;
use app\utils\AliUtils;
use app\utils\RedisUtils;
use think\facade\Db;
use Throwable;
use ba\Captcha;
use ba\ClickCaptcha;
use think\facade\Config;
use app\common\facade\Token;
use app\common\controller\Frontend;
use app\api\validate\User as UserValidate;
class UserController extends Frontend
{
protected array $noNeedLogin = ['checkIn', 'logout', 'realNameAuth', 'selectNewApp'];
public function initialize(): void
{
parent::initialize();
}
public function test()
{
p($this->auth->user_id);
// Db::connect(DatabaseRoute::getConnection('course_collect', ['user_id' => 10]))
// ->name('course_collect')
// ->where('user_id', 10)
// ->find();
// 查询
// $user = new SysUser();
// // 查询或者删除前设置分库连接
// $user->setConnection($user::findbefore($user, ['user_id' => 1072634324253292306]));
// $user = $user->where(['user_id' => 1072634324253292306]);
//// $res = $user->delete();
// $data = $user->find();
// p($data);
// SysUser::update(['username' => 99999], ['user_id' => 130677]);
// SysUser::create([
// 'user_id' => rand(000000, 999999),
// 'username' => '哎呀' . rand(000000, 999999),
// ]);
}
public function bindAlipay()
{
$get = $this->request->param();
$user = $this->auth->getUser();
// 获取请求参数
$userId = $user['user_id'];
$zhiFuBao = $get['zhiFuBao'] ?? null;
$certName = $get['certName'] ?? null;
// 验证参数不能为空
if (empty($zhiFuBao) || empty($certName)) {
$this->error("支付宝账号或姓名不能为空");
}
// 包含*号直接返回成功(业务特殊处理)
if (str_contains($zhiFuBao, '*') || str_contains($certName, '*')) {
$this->success();
}
$slave_db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId]));
// 查询用户信息
$userEntity = $slave_db->name('tb_user')
->where('user_id', $userId)
->find();
// 检查是否与原有信息一致
if ($zhiFuBao == $userEntity['zhi_fu_bao'] && $certName == $userEntity['zhi_fu_bao_name']) {
$this->success();
}
// 检查支付宝账号是否已被其他用户绑定
$count = $slave_db->name('tb_user')
->where('user_id', '<>', $userId)
->where('zhi_fu_bao_name', $certName)
->where('zhi_fu_bao', $zhiFuBao)
->count();
if ($count > 0) {
$this->error("支付宝信息修改失败: 此支付宝账号已被绑定");
}
// 检查实名认证信息是否匹配
$userInfo = $slave_db->name('user_info')
->where('user_id', $userId)
->find();
if ($userInfo) {
if (!empty($userInfo['cert_name']) && $certName != $userInfo['cert_name']) {
$this->error("支付宝信息修改失败: 姓名与实名认证信息不相符");
}
}
// 获取配置的限制次数
$limitConfig = Db::name('common_info')
->where('type', 924)
->value('value');
// 获取当前时间戳(秒)
$currentTime = time();
// 获取本月最后一天的日期2024-08-31
$lastDayOfMonth = date('Y-m-t');
// 拼接本月最后一刻的时间23:59:59
$endOfMonth = $lastDayOfMonth . ' 23:59:59';
// 转换为时间戳
$endTime = strtotime($endOfMonth);
// 计算剩余秒数若当前时间已过本月最后一刻返回0
$remainingSeconds = max(0, $endTime - $currentTime);
// 检查支付宝账号每月绑定次数限制
if (!\app\common\model\Common::isAccessAllowed($zhiFuBao, $certName, (int)$limitConfig, $remainingSeconds, true)) {
$this->error("支付宝信息修改失败: 相同支付宝账号每月可绑定次数已用完");
}
// 检查用户每月修改次数限制
$updateLimitConfig = Db::name('common_info')
->where('id', 925)
->value('value');
if (!\app\common\model\Common::isAccessAllowed((string)$userId, "updateZFB", (int)$updateLimitConfig, $remainingSeconds)) {
$this->error("支付宝信息修改失败: 每月可修改次数已用完,请联系管理员");
}
// 更新用户支付宝信息
$master_db = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $userId], true));
$master_db->name('tb_user')
->where('user_id', $userId)
->update([
'zhi_fu_bao' => $zhiFuBao,
'zhi_fu_bao_name' => $certName,
// 可添加更新时间字段
'update_time' => date('Y-m-d H:i:s')
]);
$this->success('ok', 1);
}
public function updatePhone()
{
$user_id = $this->auth->user_id;
$post = $this->request->post();
if(empty($post['phone']) || empty($post['msg'])) {
$this->error('参数不正常');
}
// 验证码
if(Msg::checkCode($post['phone'], $post['msg'])) {
$user = TbUser::GetByusername($post['phone']);
if($user) {
$this->error('手机号已经存在');
}
$db = DatabaseRoute::getDb('tb_user', $user_id, true)->where(['user_id' => $user_id])->update(['phone' => $post['phone']]);
if($db) {
$this->success('操作成功');
}else {
$this->error('操作失败');
}
}else {
$this->error('验证码错误');
}
}
/**
* 会员签入(登录和注册)
* @throws Throwable
*/
public function checkIn(): void
{
$openMemberCenter = Config::get('buildadmin.open_member_center');
if (!$openMemberCenter) {
$this->error(__('Member center disabled'));
}
// 检查登录态
if ($this->auth->isLogin()) {
$this->success(__('You have already logged in. There is no need to log in again~'), [
'type' => $this->auth::LOGGED_IN
], $this->auth::LOGIN_RESPONSE_CODE);
}
$userLoginCaptchaSwitch = Config::get('buildadmin.user_login_captcha');
if ($this->request->isPost()) {
$params = $this->request->post(['tab', 'email', 'mobile', 'username', 'password', 'keep', 'captcha', 'captchaId', 'captchaInfo', 'registerType']);
// 提前检查 tab ,然后将以 tab 值作为数据验证场景
if (!in_array($params['tab'] ?? '', ['login', 'register'])) {
$this->error(__('Unknown operation'));
}
$validate = new UserValidate();
try {
$validate->scene($params['tab'])->check($params);
} catch (Throwable $e) {
$this->error($e->getMessage());
}
if ($params['tab'] == 'login') {
if ($userLoginCaptchaSwitch) {
$captchaObj = new ClickCaptcha();
if (!$captchaObj->check($params['captchaId'], $params['captchaInfo'])) {
$this->error(__('Captcha error'));
}
}
$res = $this->auth->login($params['username'], $params['password'], !empty($params['keep']));
} elseif ($params['tab'] == 'register') {
$captchaObj = new Captcha();
if (!$captchaObj->check($params['captcha'], $params[$params['registerType']] . 'user_register')) {
$this->error(__('Please enter the correct verification code'));
}
$res = $this->auth->register($params['username'], $params['password'], $params['mobile'], $params['email']);
}
if (isset($res) && $res === true) {
$this->success(__('Login succeeded!'), [
'userInfo' => $this->auth->getUserInfo(),
'routePath' => '/user'
]);
} else {
$msg = $this->auth->getError();
$msg = $msg ?: __('Check in failed, please try again or contact the website administrator~');
$this->error($msg);
}
}
$this->success('', [
'userLoginCaptchaSwitch' => $userLoginCaptchaSwitch,
'accountVerificationType' => get_account_verification_type()
]);
}
public function logout(): void
{
if ($this->request->isPost()) {
$refreshToken = $this->request->post('refreshToken', '');
if ($refreshToken) Token::delete((string)$refreshToken);
$this->auth->logout();
$this->success();
}
}
public function selectNewApp()
{
$this->n_success(['data' => apiconvertToCamelCase(Db::connect(get_slave_connect_name())->name('app')->order('version', 'desc')->select()->toArray())]);
}
/**
* 实名接口
*/
public function realNameAuth()
{
$params = $this->request->post();
// (new UserValidate())->scene('realName')->check($params);
$params['certNum'] = trim($params['certNum']);
$params['certName'] = trim($params['certName']);
$userId = $this->getUserId();
$regex = '/^[0-9Xx*]+$/';
if (!preg_match($regex, $params['certNum'])) {
$this->success();
}
$count = DatabaseRoute::getDb('user_info', $userId)->where([
'cert_name' => $params['certName'],
'cert_no' => $params['certNum'],
])->count();
if ($count) {
$this->error('已完成实名认证,无需重复操作');
}
$count = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($params) {
return $query->where([
'cert_name' => $params['certName'],
'cert_no' => $params['certNum'],
]);
})->count();
if ($count >= 3) {
$this->error('实名认证失败: 1个身份证号码最多绑定3个账号');
}
RedisUtils::checkRealCount($userId);
$resp = AliUtils::verify($params['certName'], $params['certNum'], $params['accountNo'], $params['mobile']);
$userInfo = UserInfo::getByUserIdOrSave($userId);
$userInfo['cert_name'] = $params['certName'];
$userInfo['cert_no'] = $params['certNum'];
$userInfo['account_no'] = $params['accountNo'];
$userInfo['mobile'] = $params['mobile'];
$userInfo['bank_name'] = $resp['bankName'];
$userInfo['province'] = $params['province'] ?? '';
$userInfo['city'] = $params['city'] ?? '';
$userInfo['bank_branch'] = $params['bankBranch'];
$userInfo['resp_json'] = $resp['respJson'];
$userInfo['update_time'] = getNormalDate();
DatabaseRoute::getDb('user_info', $userId, true, true)->update($userInfo);
RedisUtils::setRealCount($userId);
// 校验实名黑名单
$count = Db::name('tb_user_blacklist')->where([
'id_card_no' => $params['certNum']
])->count();
if ($count) {
DatabaseRoute::getDb('tb_user', $userId, true, true)->update([
'status' => 0,
'plat_form' => '异常行为用户:实名信息异常 在黑名单'
]);
throw new SysException("异常行为: 您的实名信息存在异常行为");
}
$this->successWithData(1);
}
public function selectUserById()
{
$user = $this->auth->getUser();
// 获取用户详情
$userInfo = DatabaseRoute::getDb('user_info', $user['user_id'])->find();
$userInfo['resp_json'] = null; // 移除敏感字段
// 对用户详情中的敏感信息进行脱敏
if (!empty($userInfo['account_no'])) {
$userInfo['account_no'] = bankCard($userInfo['account_no']);
}
if (!empty($userInfo['mobile'])) {
$userInfo['mobile'] = maskPhoneNumber($userInfo['mobile']);
}
if (!empty($userInfo['cert_no'])) {
$userInfo['cert_no'] = idCardNum($userInfo['cert_no'], 3, 2);
}
// 对支付宝信息进行脱敏
if (!empty($user['zhi_fu_bao'])) {
if (filter_var($user['zhi_fu_bao'], FILTER_VALIDATE_EMAIL)) {
$user['zhi_fu_bao'] = email($user['zhi_fu_bao']);
} else {
$user['zhi_fu_bao'] = maskPhoneNumber($user['zhi_fu_bao']);
}
}
// 合并用户信息和用户详情
$map = array_merge($user, $userInfo);
$map['user_id'] = (string)$map['user_id']; // 确保用户ID为字符串类型
// 如果支付宝姓名为空,使用实名认证姓名
if (empty($user['zhi_fu_bao_name']) && !empty($userInfo['cert_name'])) {
$map['zhi_fu_bao_name'] = $userInfo['cert_name'];
}
$this->success('ok', convertToCamelCase($map));
}
public function updateUsers()
{
$post = $this->request->post();
$user = $this->auth->getUser();
$db_name = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $user['user_id']], true));
$db_name->name('tb_user')->where(['user_id' => $user['user_id']])->update(['user_name' => $post['userName'], 'avatar' => $post['avatar']]);
$this->success('ok');
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace app\czg\app\controller;
use app\api\model\CommonInfo;
use app\api\model\Orders;
use app\api\model\TbUser;
use app\common\controller\Frontend;
use app\common\library\DatabaseRoute;
use app\exception\CzgException;
use app\queue\DiscReceiveQueue;
use ba\Random;
use think\facade\Db;
class UserPrizeExchangeController extends Frontend
{
// 查询大转盘抽奖记录
public function page()
{
$get = $this->request->get();
return $this->ApiDataReturn(\app\api\model\UserPrizeExchange::pages($get, $this->auth->user_id));
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace app\czg\app\controller;
use app\common\library\DatabaseRoute;
use app\common\model\BaseModel;
use app\common\model\SysUser;
use think\facade\Db;
use Throwable;
use ba\Captcha;
use ba\ClickCaptcha;
use app\common\controller\Frontend;
use app\api\validate\User as UserValidate;
class UserSignRecordController extends Frontend
{
// 获取用户连续签到数据
public function getUserSignData()
{
$user_id = $this->auth->user_id;
$res = \app\api\model\UserSignRecord::getUserSignData($user_id, $this->auth->getUser());
return $this->ApiDataReturn($res);
}
}

View File

@@ -7,14 +7,15 @@ use app\common\controller\BaseController;
use app\common\library\DatabaseRoute;
use app\exception\SysException;
use app\utils\RedisUtils;
use app\api\validate\WuyouValidate;
use app\utils\WuYouPayUtils;
use ba\Random;
use Orders;
use app\api\model\Orders;
use support\Log;
use think\facade\Db;
use Throwable;
class Wuyou extends BaseController
class WuyouController extends BaseController
{
protected array $noNeedLogin = ['payOrder', 'index', 'test', 'notify', 'queryOrder'];

View File

@@ -0,0 +1,292 @@
<?php
namespace app\api\controller\user;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\AddShortUrlResponseBody\data;
use app\api\model\Msg;
use app\api\model\TbUser;
use app\api\model\UserInfo;
use app\common\library\DatabaseRoute;
use app\common\model\BaseModel;
use app\common\model\SysUser;
use app\exception\SysException;
use app\utils\AliUtils;
use app\utils\RedisUtils;
use think\facade\Db;
use Throwable;
use ba\Captcha;
use ba\ClickCaptcha;
use think\facade\Config;
use app\common\facade\Token;
use app\common\controller\Frontend;
use app\api\validate\User as UserValidate;
class User extends Frontend
{
protected array $noNeedLogin = ['checkIn', 'logout', 'realNameAuth'];
public function initialize(): void
{
parent::initialize();
}
public function test()
{
p($this->auth->user_id);
// Db::connect(DatabaseRoute::getConnection('course_collect', ['user_id' => 10]))
// ->name('course_collect')
// ->where('user_id', 10)
// ->find();
// 查询
// $user = new SysUser();
// // 查询或者删除前设置分库连接
// $user->setConnection($user::findbefore($user, ['user_id' => 1072634324253292306]));
// $user = $user->where(['user_id' => 1072634324253292306]);
//// $res = $user->delete();
// $data = $user->find();
// p($data);
// SysUser::update(['username' => 99999], ['user_id' => 130677]);
// SysUser::create([
// 'user_id' => rand(000000, 999999),
// 'username' => '哎呀' . rand(000000, 999999),
// ]);
}
public function updatePhone()
{
$user_id = $this->auth->user_id;
$post = $this->request->post();
if(empty($post['phone']) || empty($post['msg'])) {
$this->error('参数不正常');
}
// 验证码
if(Msg::checkCode($post['phone'], $post['msg'])) {
$user = TbUser::GetByusername($post['phone']);
if($user) {
$this->error('手机号已经存在');
}
$db = DatabaseRoute::getDb('tb_user', $user_id, true)->where(['user_id' => $user_id])->update(['phone' => $post['phone']]);
if($db) {
$this->success('操作成功');
}else {
$this->error('操作失败');
}
}else {
$this->error('验证码错误');
}
}
/**
* 会员签入(登录和注册)
* @throws Throwable
*/
public function checkIn(): void
{
$openMemberCenter = Config::get('buildadmin.open_member_center');
if (!$openMemberCenter) {
$this->error(__('Member center disabled'));
}
// 检查登录态
if ($this->auth->isLogin()) {
$this->success(__('You have already logged in. There is no need to log in again~'), [
'type' => $this->auth::LOGGED_IN
], $this->auth::LOGIN_RESPONSE_CODE);
}
$userLoginCaptchaSwitch = Config::get('buildadmin.user_login_captcha');
if ($this->request->isPost()) {
$params = $this->request->post(['tab', 'email', 'mobile', 'username', 'password', 'keep', 'captcha', 'captchaId', 'captchaInfo', 'registerType']);
// 提前检查 tab ,然后将以 tab 值作为数据验证场景
if (!in_array($params['tab'] ?? '', ['login', 'register'])) {
$this->error(__('Unknown operation'));
}
$validate = new UserValidate();
try {
$validate->scene($params['tab'])->check($params);
} catch (Throwable $e) {
$this->error($e->getMessage());
}
if ($params['tab'] == 'login') {
if ($userLoginCaptchaSwitch) {
$captchaObj = new ClickCaptcha();
if (!$captchaObj->check($params['captchaId'], $params['captchaInfo'])) {
$this->error(__('Captcha error'));
}
}
$res = $this->auth->login($params['username'], $params['password'], !empty($params['keep']));
} elseif ($params['tab'] == 'register') {
$captchaObj = new Captcha();
if (!$captchaObj->check($params['captcha'], $params[$params['registerType']] . 'user_register')) {
$this->error(__('Please enter the correct verification code'));
}
$res = $this->auth->register($params['username'], $params['password'], $params['mobile'], $params['email']);
}
if (isset($res) && $res === true) {
$this->success(__('Login succeeded!'), [
'userInfo' => $this->auth->getUserInfo(),
'routePath' => '/user'
]);
} else {
$msg = $this->auth->getError();
$msg = $msg ?: __('Check in failed, please try again or contact the website administrator~');
$this->error($msg);
}
}
$this->success('', [
'userLoginCaptchaSwitch' => $userLoginCaptchaSwitch,
'accountVerificationType' => get_account_verification_type()
]);
}
public function logout(): void
{
if ($this->request->isPost()) {
$refreshToken = $this->request->post('refreshToken', '');
if ($refreshToken) Token::delete((string)$refreshToken);
$this->auth->logout();
$this->success();
}
}
public static function selectInviteCount()
{
}
/**
* 实名接口
*/
public function realNameAuth()
{
$params = $this->request->post();
// (new UserValidate())->scene('realName')->check($params);
$params['certNum'] = trim($params['certNum']);
$params['certName'] = trim($params['certName']);
$userId = $this->getUserId();
$regex = '/^[0-9Xx*]+$/';
if (!preg_match($regex, $params['certNum'])) {
$this->success();
}
$count = DatabaseRoute::getDb('user_info', $userId)->where([
'cert_name' => $params['certName'],
'cert_no' => $params['certNum'],
])->count();
if ($count) {
$this->error('已完成实名认证,无需重复操作');
}
$count = DatabaseRoute::getAllDbData('tb_user', function ($query) use ($params) {
return $query->where([
'cert_name' => $params['certName'],
'cert_no' => $params['certNum'],
]);
})->count();
if ($count >= 3) {
$this->error('实名认证失败: 1个身份证号码最多绑定3个账号');
}
RedisUtils::checkRealCount($userId);
$resp = AliUtils::verify($params['certName'], $params['certNum'], $params['accountNo'], $params['mobile']);
$userInfo = UserInfo::getByUserIdOrSave($userId);
$userInfo['cert_name'] = $params['certName'];
$userInfo['cert_no'] = $params['certNum'];
$userInfo['account_no'] = $params['accountNo'];
$userInfo['mobile'] = $params['mobile'];
$userInfo['bank_name'] = $resp['bankName'];
$userInfo['province'] = $params['province'] ?? '';
$userInfo['city'] = $params['city'] ?? '';
$userInfo['bank_branch'] = $params['bankBranch'];
$userInfo['resp_json'] = $resp['respJson'];
$userInfo['update_time'] = getNormalDate();
DatabaseRoute::getDb('user_info', $userId, true, true)->update($userInfo);
RedisUtils::setRealCount($userId);
// 校验实名黑名单
$count = Db::name('tb_user_blacklist')->where([
'id_card_no' => $params['certNum']
])->count();
if ($count) {
DatabaseRoute::getDb('tb_user', $userId, true, true)->update([
'status' => 0,
'plat_form' => '异常行为用户:实名信息异常 在黑名单'
]);
throw new SysException("异常行为: 您的实名信息存在异常行为");
}
$this->successWithData(1);
}
public function selectUserById()
{
$user = $this->auth->getUser();
// 获取用户详情
$userInfo = DatabaseRoute::getDb('user_info', $user['user_id'])->find();
$userInfo['resp_json'] = null; // 移除敏感字段
// 对用户详情中的敏感信息进行脱敏
if (!empty($userInfo['account_no'])) {
$userInfo['account_no'] = bankCard($userInfo['account_no']);
}
if (!empty($userInfo['mobile'])) {
$userInfo['mobile'] = maskPhoneNumber($userInfo['mobile']);
}
if (!empty($userInfo['cert_no'])) {
$userInfo['cert_no'] = idCardNum($userInfo['cert_no'], 3, 2);
}
// 对支付宝信息进行脱敏
if (!empty($user['zhi_fu_bao'])) {
if (filter_var($user['zhi_fu_bao'], FILTER_VALIDATE_EMAIL)) {
$user['zhi_fu_bao'] = email($user['zhi_fu_bao']);
} else {
$user['zhi_fu_bao'] = maskPhoneNumber($user['zhi_fu_bao']);
}
}
// 合并用户信息和用户详情
$map = array_merge($user, $userInfo);
$map['user_id'] = (string)$map['user_id']; // 确保用户ID为字符串类型
// 如果支付宝姓名为空,使用实名认证姓名
if (empty($user['zhi_fu_bao_name']) && !empty($userInfo['cert_name'])) {
$map['zhi_fu_bao_name'] = $userInfo['cert_name'];
}
$this->success('ok', convertToCamelCase($map));
}
public function updateUsers()
{
$post = $this->request->post();
$user = $this->auth->getUser();
$db_name = Db::connect(DatabaseRoute::getConnection('tb_user', ['user_id' => $user['user_id']]));
$db_name->name('tb_user')->where(['user_id' => $user['user_id']])->update(['user_name' => $post['userName'], 'avatar' => $post['avatar']]);
$this->success('ok');
}
}