This commit is contained in:
2025-11-21 01:42:54 +08:00
parent ff026c6f32
commit f89196c73c
1953 changed files with 9 additions and 15246 deletions
+124
View File
@@ -0,0 +1,124 @@
<?php
namespace app\api\controller;
use support\Request;
use taoser\facade\Validate;
use app\model\Address as AddressModel;
use hg\apidoc\annotation as Apidoc;
/**
* 提现地址
*/
class AddressController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* 列表
* @Apidoc\Method("POST")
* @Apidoc\Query("network", type="string", require=true, desc="网络")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list()
{
$limit = (int)input('limit',10);
$page = (int)input('page',1);
$status = (int)input('status',-1);
$network = input('network');
$type = input('type');
$model = AddressModel::where('user_id',\support\Jwt\JwtToken::getCurrentId());
//->where('network','BEP-20');
if($type){
$model = $model->where('status',1);
}
if($network){
$model = $model->where('network',$network);
}
$list = $model->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 创建
* @Apidoc\Method("POST")
* @Apidoc\Param("network", type="string", require=true, desc="网络,BEP-20,TRC-20,ALIPAY,WECHAT",default="BEP-20")
* @Apidoc\Param("address", type="string", require=true, desc="地址")
* @Apidoc\Param("title", type="string", require=true, desc="名称")
* @Apidoc\Param("status", type="string", require=true, desc="状态,可选,1,0,默认1")
*/
public function create()
{
//captcha_verfiy('image','create_address');
//* @Apidoc\Param("code", type="string", require=true, desc="图形验证码 event=create_address")
//$trade_password = input('trade_password');
//\support\Jwt::verify_trade_password($trade_password);
//* @Apidoc\Param("trade_password", type="string", require=true, desc="交易密码")
$data = [
'network' => input('network','BEP-20'),
'title' => input('title'),
'address' => input('address'),
'img' => input('img'),
'is_default' => input('is_default'),
'status' => input('status',0),
'user_id' => \support\Jwt\JwtToken::getCurrentId()
];
if(!$data['title']){
return $this->error(__('Invalid title'));
}
if(!$data['address']){
return $this->error(__('Invalid address'));
}
AddressModel::create($data);
return $this->success(__('successful'));
}
/**
* 编辑
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="string", require=true, desc="id")
* @Apidoc\Param("title", type="string", require=true, desc="名称")
* @Apidoc\Param("status", type="string", require=true, desc="状态,可选,1,0,默认1")
*/
public function update()
{
//captcha_verfiy('image','update_address');
//$trade_password = input('trade_password');
//\support\Jwt::verify_trade_password($trade_password);
$data = [
'id' => input('id',''),
'title' => input('title',''),
//'is_default' => input('is_default'),
'status' => input('status',1),
];
if(!$data['id']){
return $this->error(__('Invalid parameters'));
}
if(!$data['title']){
return $this->error(__('Invalid title'));
}
AddressModel::where('id',$data['id'])->save($data);
return $this->success(__('successful'));
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="id")
*/
public function detail(){
$appid = input('id');
$vo = AddressModel::where('id',$appid)->find();
if($vo) {
return $this->success(__('successful'),$vo->toArray());
}else{
return $this->error(__("Address is not exist"));
}
}
}
+144
View File
@@ -0,0 +1,144 @@
<?php
namespace app\api\controller;
use app\model\Archives as ArchivesModel;
use support\Request;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 文章模块
*/
class ArticleController extends BaseController{
public $noNeedLogin = ['*'];
/**
* 列表
* @Apidoc\Query("category_id", type="int", require=true, desc="分类ID",default=10)
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$category_id = (int)input('category_id',0);
$model = ArchivesModel::where('status','1')->where('type','article');
if($category_id){
$model = $model->where('category_id',$category_id);
}
$list = $model->order('id','desc')->paginate($limit);
$user_id=0;
try {
$user_id = \support\Jwt\JwtToken::getCurrentId();
} catch (\Throwable $th) {
}
$list->each(function($item)use($user_id){
if(!$user_id){
$item->is_read = 0;
}
$item->is_read = cache('article_read_'.$item->id.'_'.$user_id)?:0;
return $item;
});
return $this->success(__('successful'),$list->toArray());
}
/**
* faq
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function faq(){
$limit = (int)input('limit',10);
$model = ArchivesModel::alias('a')
->join('content c', 'a.id = c.id')
->where('a.status','1')
->where('a.type','article')
->where('a.category_id',9);
$list = $model->Field('a.title,a.id,c.content')->order('a.id','desc')->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function detail(){
$appid = input('id');
/** @var ArchivesModel $vo */
$vo = ArchivesModel::where('id',$appid)->find();
if($vo) {
$addon = \app\model\Content::where('id', $vo->id)->find()->toArray();
if ($addon) {
$vo->setAddonData($addon);
}
$user_id=0;
try {
$user_id = \support\Jwt\JwtToken::getCurrentId();
} catch (\Throwable $th) {
}
if($user_id){
cache('article_read_'.$vo->id.'_'.$user_id,1);
}
return $this->success(__('successful'),$vo->toArray());
}else{
return $this->error(__("Article does not exist"));
}
}
/**
* 单页详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
* @Apidoc\Query("name", type="string", require=true, desc="二选1")
*/
public function singpage(){
$appid = input('id');
$name = input('name');
/** @var ArchivesModel $vo */
if($name){
$vo = ArchivesModel::where('name',$name)->find();
}else{
if($appid){
$vo = ArchivesModel::where('id',$appid)->find();
}
}
if($vo) {
$addon = \app\model\Content::where('id', $vo->id)->find()->toArray();
if ($addon) {
$vo->setAddonData($addon);
}
return $this->success(__('successful'),$vo->toArray());
}else{
return $this->error(__("Article does not exist"));
}
}
/**
* 幻灯片
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function slide(){
$list = [
['image'=>domain().'/storage/slide/1.jpg','title'=>''],
['image'=>domain().'/storage/slide/2.webp','title'=>''],
['image'=>domain().'/storage/slide/3.webp','title'=>''],
['image'=>domain().'/storage/slide/4.jpg','title'=>''],
];
return $this->success(__('successful'),$list);
}
/**
* 设为已读
* @Apidoc\Query("id", type="int", require=true, desc="ID,多个逗号隔开")
*/
function mask_as_read(){
$ids = input('id');
$user_id = \support\Jwt\JwtToken::getCurrentId();
if(!$user_id){
return $this->success(__('successful'));
}
$ids = explode(',',$ids);
foreach ($ids as $id) {
$key = 'article_read_'.$id.'_'.$user_id;
cache($key,1);
}
return $this->success(__('successful'));
}
}
@@ -0,0 +1,49 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use support\Request;
use hg\apidoc\annotation as Apidoc;
/**
* 余额日志
*/
class BalanceLogController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* 余额日志
* @Apidoc\Query("currency", type="string", require=true, desc="货币",default="money")
* @Apidoc\Query("type", type="string", require=true, desc="类型")
* @Apidoc\Query("startTime", type="string", require=true, desc="开始时间")
* @Apidoc\Query("endTime", type="string", require=true, desc="结束时间")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
function list(Request $request){
$user_id = \support\Jwt\JwtToken::getCurrentId();
$type = Input('type',0);
$currency = Input('currency','money');
$startTime = Input('startTime');
$endTime = Input('endTime');
$list = \app\model\BalanceLog::queryLogs($user_id,$currency,$type,$startTime,$endTime);
$BalanceTypeList= \app\enum\BalanceType::toArray();
$list->each(function($item)use($BalanceTypeList){
if($item->type == \app\enum\BalanceType::TRANSFER->value && $item->memo){
$item['target'] = UserModel::where('id',$item->memo)->value('username');
$item->memo = idEncode($item->memo);
}
$item->_type= $item->type;
$item->type= $BalanceTypeList[$item->type];
});
return $this->success(__('successful'),$list);
}
}
+80
View File
@@ -0,0 +1,80 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
/**
* 基础控制器
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class BaseController
{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = [];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
function __construct()
{
$this->_init();
}
protected function _init(){
}
/**
* 返回格式化json数据
*
* @param int $code
* @param string $msg
* @param array $data
* @return Response
*/
protected function json(int $code, string $msg = 'ok', array|object|null $data = []): Response
{
return json(['code' => $code, 'data' => $data, 'msg' => $msg]);
}
protected function success(string $msg = '成功', array|object|null $data = []): Response
{
return $this->json(0, $msg, $data);
}
protected function fail(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
protected function error(string $msg = '失败', array|object|null $data = []): Response
{
return $this->json(1,$msg, $data);
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
*/
function upload(Request $request)
{
//多文件上传
$files = $request->file();
try {
$result = Storage::adapter('public')
->path('upload/files')
->size(1024*1024*10)
->extYes(['image/jpeg','image/png'])
->uploads($files,0,1024*1024*100,false);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
+123
View File
@@ -0,0 +1,123 @@
<?php
namespace app\api\controller;
use app\model\Card as CardModel;
use app\model\Cdkey as CdkeyModel;
use app\model\User as UserModel;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 卡密模块
*/
class CardController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = ['detail','list'];
/**
* 列表
* @Apidoc\Query("kw", type="string", require=false, desc="搜索关键字")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$kw = (string)input('kw');
$model = CardModel::where('status',1);
if($kw){
$model = $model->whereLike('title',$kw);
}
$list = $model->order('id desc')->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
* @Apidoc\Query("status", type="string", require=true, desc="状态")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function detail(){
$limit = (int)input('limit',10);
$id = (int)input('id',0);
$status = (string)input('status','all');
$model = CdkeyModel::where('category_id',$id);
if($status!='all'){
$model = $model->where('status',$status);
}
$list = $model->order('id desc')->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function download(){
$id = (int)input('id',0);
$model = CdkeyModel::where('category_id',$id);
$list = $model->order('id desc')->select();
return $this->success(__('successful'),$list->toArray());
}
/**
* 购买产品
* @Apidoc\Method("POST")
* @Apidoc\Param("title", type="string", require=true, desc="标题")
* @Apidoc\Param("total", type="int", require=true, desc="数量")
* @Apidoc\Param("days", type="int", require=true, desc="金额")
* @Apidoc\Param("trade_password", type="string", require=true, desc="交易密码")
*/
public function create()
{
$user = \support\Jwt::getUser();
$data = [
'user_id' => $user->id,
'title'=> input('title'),
'total' => (int)input('total'),
'days' => input('days'),
'status' => 0
];
if(!$data['title']){
return $this->error(__('Incorrect title'));
}
/** @var CardModel $gift */
if(!in_array($data['days'],[100,200,300,500])){
return $this->error(__('Incorrect amount'));
}
if($data['total'] < 1){
return $this->error(__('Incorrect quantity'));
}
$amount = $data['days'] * $data['total'];
$data['user_id'] = $user->id;
$data['amount'] = $amount;
$data['type'] = 'active';
$data['expires'] = strtotime('2030-12-31');
//验证交易密码
$trade_password = input('trade_password');
\support\Jwt::verify_trade_password($trade_password);
//var_dump($user);
//验证余额
if($data['amount'] < 1){
return $this->error(__('Incorrect amount'));
}
if($data['amount'] > $user->score){
return $this->error(__('Insufficient balance'));
}
Db::startTrans();
try{
$data = CardModel::create($data);
UserModel::score($data['user_id'],-$data['amount'],\app\enum\BalanceType::CDKEY,$data['id']);
Hook('card.create',$data);
Db::commit();
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('successful'));
}
}
+448
View File
@@ -0,0 +1,448 @@
<?php
namespace app\api\controller;
use taoser\facade\Validate;
use app\model\User as UserModel;
use support\Request;
use support\Response;
use Webman\Captcha\CaptchaBuilder;
use Webman\Captcha\PhraseBuilder;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
/**
* 公共接口
*/
class CommonController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = [];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = ['*'];
/**
* 加载初始化
*
* @Apidoc\Query("version", type="string", require=true, desc="版本号")
*/
public function init()
{
$lang = input('lang','en-US');
locale( $lang);
$config = Config('site');
$disallowFields = [
'api_token','reward_time_limit',
'mail_type','mail_smtp_host','mail_smtp_port','mail_smtp_user','mail_smtp_pass','mail_verify_type','mail_from',
'attachmentcategory','categorytype','cdkey_category','configgroup','flagtype',
'languages','forbiddenip','fixedpage','admin_login_captcha',
'mimetype','multipart','multiple','chunksize','classname','thumbstyle','previewtpl','timeout','maxsize','container',
'yeji_jicha_reward','suanli_rate','agent_expirs_retention','allow_currencys','allow_balance_log',
'agent_commission_total_rate','agent_commission_layer_rate','differential_commission_total_rate'
];
$config = array_diff_key($config, array_flip($disallowFields));
if(Request()->client != "web"){
$config["steps"] = Config('step');
}
$config['balance_type_list'] = \app\enum\BalanceType::toArray();
$config['recharge_status_list'] = \app\enum\RechargeStatus::toArray();
$config['withdrawl_status_list'] = \app\enum\WithdrawlStatus::toArray();
$config['server_status_list'] = \app\enum\ServerStatus::toArray();
return $this->success(__('successful'), $config);
}
/**
* test
* @Apidoc\Query("lang", type="string",require=true, desc="邮箱")
* @Apidoc\Method ("GET")
*/
function test(){
return $this->error(__('Invalid parameters'));
}
/**
* 注册会员
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("password", type="string",require=true, desc="密码")
* @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码")
* @Apidoc\Param("invite_code", type="string",require=true, desc="推荐码")
* @Apidoc\Param("code", type="string",require=true, desc="邮箱验证码,event=register")
*/
public function register()
{
$email = input('email');
$password = input('password');
$trade_password= input( 'trade_password');
$username = input('username');
$mobile = input('mobile');
$invite_code = input('invite_code');
if ($email && !Validate::is($email, "email")) {
return $this->error(__('Email is incorrect'));
}
if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) {
return $this->error(__('Mobile is incorrect'));
}
if(Config('site.user_register_way') == 'mobile'){
if (!$mobile) {
return $this->error(__('Invalid parameters'));
}
$username = $mobile;
captcha_verfiy('mobile','register',$mobile);
}else if(Config('site.user_register_way') == 'email'){
if (!$email) {
return $this->error(__('Invalid parameters'));
}
if ($email && !Validate::is($email, "email")) {
return $this->error(__('Email is incorrect'));
}
$username = $email;
captcha_verfiy('email','register',$email);
}else{
if (!$username) {
return $this->error(__('Invalid parameters'));
}
}
if (!$password) {
return $this->error(__('Invalid parameters'));
}
$extends = [
'role_id' => 0,
'group' => 0,
'avatar' => '/static/img/avatar.png',
];
// if (!$trade_password) {
// return $this->error(__('Invalid trade password'));
// }else{
// $extends['trade_password'] = \plugin\admin\app\common\Util::passwordHash($trade_password);
// }
//邀请码
if(!$invite_code){
return $this->error(__('Invalid invite code'));
}
if(strlen($invite_code) == 12){
//系统生产的一次性推荐吗
$inviteModel = \app\model\Invitecode::where('code',$invite_code)->find();
if(!$inviteModel){
return $this->error(__('错误的邀请码'));
}
$extends['group'] = 2;
$extends['role_id'] = 1;
$extends['parent_id'] = 0;
}else{
$inviter_user = UserModel::where('invite_code',$invite_code)->field('group,id')->find();
if(!$inviter_user){
return $this->error(__('Invalid invite code'));
}
$extends['parent_id'] = $inviter_user['id'];
}
try {
$user = \support\Jwt::register($username, $password, $email, $mobile, $extends);
if($inviteModel){
$inviteModel->status = 1;
$inviteModel->save();
}
$data = ['userinfo' => $user];
return $this->success(__('Sign up successful'), $data);
} catch (\Throwable $e) {
return $this->error($e->getMessage());
}
}
/**
* 登录
* @Apidoc\Method("POST")
* @Apidoc\Param("username", type="string",require=true, desc="用户名")
* @Apidoc\Param("password", type="string",require=true, desc="密码")
*/
public function login(Request $request){
$username = input('username');
$password = input('password');
if (!$username || !$password) {
return $this->fail(__('Invalid username or password'));
}
try{
$user = \support\Jwt::login($username, $password,'username');
if($user === false){
return $this->fail(\support\Jwt::getError());
}
$user= Hook('user.profile',$user);
return $this->success(__('successful'), $user[0]);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
}
/**
* 退出登录
* @Apidoc\Method("GET")
*/
public function logout(){
\support\Jwt::logout();
return $this->success(__('successful'));
}
/**
* 重置密码
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("newpassword", type="string",require=true, desc="新密码")
* @Apidoc\Param("code", type="string",require=true, desc="邮箱验证码,event=resetpwd")
*/
public function resetpwd()
{
$email = input("email");
$mobile = input("mobile");
$newpassword = input("newpassword");
if (!$newpassword) {
return $this->error(__('Invalid parameters'));
}
//验证Token
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,30}'])) {
return $this->error(__('Password must be 6 to 30 characters'));
}
if (!$mobile && !$email){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
log_alert($e->getMessage());
$user = false;
}
if($user){
captcha_verfiy('mobile','reset_trade_pwd',$user->mobile);
}
}else{
if ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_trade_pwd',$email);
$user = UserModel::getByEmail($email);
}
if ($mobile && Validate::regex($mobile, "^1\d{10}$")) {
captcha_verfiy('mobile','reset_trade_pwd',$mobile);
$user = UserModel::getByMobile($mobile);
}
}
if (!$user) {
return $this->error(__('Invalid parameters'));
}
//模拟一次登录,需不需要充值登录信息?????
//\support\Jwt::direct($user->id);
try{
UserModel::where('id',$user->id)->save([
'loginfailure' => 0,
'password' => \plugin\admin\app\common\Util::passwordHash($newpassword)
]);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
return $this->success(__('Reset password successful'));
}
/**
* 重置交易密码
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("newpassword", type="string",require=true, desc="新密码")
* @Apidoc\Param("code", type="string",require=true, desc="邮箱验证码,event=reset_trade_pwd")
*/
public function reset_trade_pwd()
{
$email = input("email");
$mobile = input("mobile");
$newpassword = input("newpassword");
if (!$newpassword) {
return $this->error(__('Invalid parameters'));
}
//验证Token
if (!Validate::check(['newpassword' => $newpassword], ['newpassword' => 'require|regex:\S{6,6}'])) {
return $this->error(__('Trade password must be 6 characters'));
}
if (!$mobile && !$email){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
log_alert($e->getMessage());
$user = false;
}
if($user){
captcha_verfiy('mobile','reset_trade_pwd',$user->mobile);
}
}else{
if ($email && Validate::is($email, "email")) {
captcha_verfiy('email','reset_trade_pwd',$email);
$user = UserModel::getByEmail($email);
}
if ($mobile && Validate::regex($mobile, "^1\d{10}$")) {
captcha_verfiy('mobile','reset_trade_pwd',$mobile);
$user = UserModel::getByMobile($mobile);
}
}
if (!$user) {
return $this->error(__('Invalid parameters'));
}
//模拟一次登录,需不需要充值登录信息?????
//\support\Jwt::direct($user->id);
try{
log_alert($user->id.' 重置交易密码'.$newpassword);
UserModel::where('id',$user->id)->save([
'trade_password' => \plugin\admin\app\common\Util::passwordHash($newpassword)
]);
} catch (\Exception $e) {
return $this->error($e->getMessage());
}
return $this->success(__('Reset Trade password successful'));
}
/**
* 验证码
* @Apidoc\Method ("POST")
* @Apidoc\Param("type", type="string",require=true, desc="GET参数,类型,email:邮箱验证码,image:图片验证码")
* @Apidoc\Param("event", type="string",require=true, desc="事件,regiser:注册,resetpwd:重置密码,withdrawl:提现")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱,可选")
*/
public function captcha(Request $request){
$request->input('type');
$type = $request->input('type');
$event = $request->input('event');
if($type == 'email'){
$email = $request->input('email');
if(!$email){
try {
$user = \support\Jwt::getUser();
$email = $user->email;
} catch (\Exception $th) {
return $this->error(__('Incoret param'));
}
}
$key = 'captcha_'.$event.'_'.$email;
$list = cache($key);
$list = $list ?:[];
$expris = 60;
if(cache('?exp_'.$key)){
if(cache('exp_'.$key)+$expris > time()){
return $this->fail(__('Only one verification code can be sent within %second% seconds',['%second%'=>$expris]));
}
}
$code =\support\Random::numeric(4);
$list[$code] = time();
cache($key,$list);
cache('exp_'.$key,time());
addJob([
'email' => $email,
'title' => __("Mt email code"),
'event' => $event,
'code' => $code
],'Email');
return $this->success(__('Email sent successfully'));
}elseif($type == 'mobile'){
$mobile = $request->input('mobile');
if(!$mobile){
try {
$user = \support\Jwt::getUser();
$mobile = $user->mobile;
} catch (\Exception $th) {
return $this->error(__('Incoret param'));
}
}
if (!Validate::regex($mobile, "^1\d{10}$")) {
return $this->error(__('Mobile is incorrect'));
}
$key = 'captcha_'.$event.'_'.$mobile;
$list = cache($key);
$list = $list ?:[];
$expris = 60;
if(cache('?exp_'.$key)){
if(cache('exp_'.$key)+$expris > time()){
return $this->fail(__('Only one verification code can be sent within %second% seconds',['%second%'=>$expris]));
}
}
$code =\support\Random::numeric(4);
$list[$code] = time();
cache($key,$list);
cache('exp_'.$key,time());
addJob([
'mobile' => $mobile,
'event' => $event,
'code' => $code
],'Sms');
return $this->success(__('SMS sent successfully'));
}else{
//TODO 图像验证码没有唯一的KEY
$key = 'captcha_'.$event.'_';
//abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ
$builder = new PhraseBuilder(4, '0123456789');
$captcha = new CaptchaBuilder(null, $builder);
$captcha->build(120);
$code = strtolower($captcha->getPhrase());
$list[$code] = time();
cache($key,$list);
if($request->method() =='GET'){
$img_content = $captcha->get();
return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
}else{
$img_content = $captcha->inline();
return json([
'code' => 0,
'msg' => __('successful'),
'data' => $img_content
]);
}
}
}
/**
* 校验验证码
* @Apidoc\Param("type", type="string",require=true, desc="GET参数,类型,email:邮箱验证码,image:图片验证码")
* @Apidoc\Param("event", type="string",require=true, desc="事件,register:注册,resetpwd:重置密码,withdrawl:提现")
* @Apidoc\Param("email", type="string",require=false, desc="邮箱,可选,仅type==email时必填")
* @Apidoc\Param("code", type="string",require=true, desc="验证码")
*/
public function verify_captcha(Request $request): Response
{
$email = $request->post('email');
$mobile = $request->input('mobile');
$event = $request->post('event');
try {
if($email){
$result = captcha_verfiy('email', $event , $email,false);
}elseif($mobile){
$result = captcha_verfiy('mobile', $event , $mobile,false);
}else{
$result = captcha_verfiy('image', $event , '',false);
}
if(!$result){
return $this->fail(__('Captcha is incorrect'));
}
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
return $this->success(__('successful'));
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
*/
function upload(Request $request)
{
//多文件上传
$files = $request->file();
try {
$result = Storage::adapter('public')
->path('upload/files')
->size(1024*1024*10)
->extYes(['image/jpeg','image/png'])
->uploads($files,0,1024*1024*100,false);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
+159
View File
@@ -0,0 +1,159 @@
<?php
namespace app\api\controller;
use app\model\Gift as GiftModel;
use app\model\GiftOrder as GiftOrderModel;
use app\model\User as UserModel;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 礼品模块
*/
class GiftController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = ['detail','list'];
/**
* 列表
* @Apidoc\Query("kw", type="string", require=false, desc="搜索关键字")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$model = GiftModel::where('status',1);
$list = $model->order('weight desc,id asc')->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function detail(){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
$user = ['id'=>0,'role_id'=>0];
}
$appid = input('id');
if(!$appid){
return $this->error(__("Product does not exist"));
}
/** @var GiftModel $gift */
$gift = GiftModel::where('id',$appid)->find();
//->cache(true,86400,'product_detail')
if(!$gift) {
return $this->error(__("Product does not exist"));
}
if($user['id']){
/** @var GiftOrderModel $total_quantity_user */
$total_quantity_user = GiftOrderModel::where('gift_id',$gift->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $gift->user_quantity ?: 99999999;
$max_quantity = $total_quantity_system-$total_quantity_user;
$max_quantity= $max_quantity < 0 ? 0: $max_quantity;
$gift->max_quantity = $max_quantity;
$gift->total_quantity_user = $total_quantity_user;
}else{
$gift->total_quantity_user = 0;
$gift->max_quantity = 0;
}
return $this->success(__('successful'),$gift->toArray());
}
/**
* 列表
* @Apidoc\Query("status", type="int", require=false, desc="状态")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function record(){
$limit = (int)input('limit',10);
$page = (int)input('page',1);
$status = input('status','all');
$user_id = \support\Jwt\JwtToken::getCurrentId();
$model = GiftOrderModel::with(['gift'])->where('user_id',$user_id);
if($status!='all'){
$model = $model->where('status',$status);
}
$list = $model->order('created_at desc')
->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 购买产品
* @Apidoc\Method("POST")
* @Apidoc\Param("gift_id", type="string", require=true, desc="产品ID")
* @Apidoc\Param("quantity", type="int", require=true, desc="数量")
* @Apidoc\Param("trade_password", type="string", require=true, desc="交易密码")
*/
public function create()
{
$user = \support\Jwt::getUser();
$data = [
'user_id' => $user->id,
'gift_id'=> input('gift_id'),
'quantity' => (int)input('quantity'),
'denomination' => input('denomination',0),
'status' => 0
];
if(!$data['gift_id']){
return $this->error(__('Gift is incorrect'));
}
/** @var GiftModel $gift */
$gift = GiftModel::where('id',$data['gift_id'])->find();
if(!$gift){
return $this->error(__('Gift is incorrect'));
}
// if(!in_array($data['denomination'],$gift->amounts)){
// return $this->error(__('Denomination is incorrect'));
// }
if($data['quantity'] < 1){
return $this->error(__('Quantity is incorrect'));
}
if($gift->stock < $data['quantity']){
return $this->error(__('Gift stock is insufficient'));
}
//$data['amount'] = $data['denomination'] * $data['quantity'];
$data['denomination'] = $gift->price;
$data['amount'] = $gift->price * $data['quantity'];
$total_quantity_user = GiftOrderModel::where('gift_id',$gift->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $gift->user_quantity ?: 99999999;
$can_purchase = $total_quantity_system-$total_quantity_user;
$can_purchase= $can_purchase < 0 ? 0: $can_purchase;
if($can_purchase < $data['quantity']){
return $this->error(__('You can only purchase %max_quantity% copies',[
'%max_quantity%' => $can_purchase
]));
}
//验证交易密码
$trade_password = input('trade_password');
\support\Jwt::verify_trade_password($trade_password);
//var_dump($user);
//验证余额
if($data['amount'] > $user->score){
return $this->error(__('Insufficient balance'));
}
Db::startTrans();
try{
$data = GiftOrderModel::create($data);
$gift->stock = $gift->stock - $data['quantity'];
$gift->sales = $gift->sales + $data['quantity'];
$gift->save();
UserModel::score($data['user_id'],-$data['amount'],\app\enum\BalanceType::GIFT_BUY,$data['id']);
Hook('gift.buy',$data);
Db::commit();
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('successful'));
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace app\api\controller;
use Response;
use support\Request;
use hg\apidoc\annotation as Apidoc;
/**
* 主控制器
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
class IndexController extends BaseController{
public $noNeedLogin=['index','chart'];
public function index(){
return $this->success(__("Unverified address"));
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace app\api\controller;
use app\model\Product as ProductModel;
use app\model\ProductOrder as ProductOrderModel;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 产品模块
*/
class ProductController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = ['detail','list'];
/**
* 列表
* @Apidoc\Query("kw", type="string", require=false, desc="搜索关键字")
* @Apidoc\Query("step", type="string", require=false, desc="类型,progress,done")
* @Apidoc\Query("billing_cycle", type="int", require=true, desc="周期",default=1)
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$model = ProductModel::where('status',1);
$list = $model->order('weight desc,id asc')->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function detail(){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
$user = ['id'=>0,'role_id'=>0];
}
$appid = input('id');
if(!$appid){
return $this->error(__("Product does not exist"));
}
/** @var ProductModel $product */
$product = ProductModel::where('id',$appid)->find();
//->cache(true,86400,'product_detail')
if(!$product) {
return $this->error(__("Product does not exist"));
}
if($user['id']){
$total_quantity_user = ProductOrderModel::where('product_id',$product->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $product->user_quantity ?: 99999999;
$max_quantity = $total_quantity_system-$total_quantity_user;
$max_quantity= $max_quantity < 0 ? 0: $max_quantity;
$product->max_quantity = $max_quantity;
$product->total_quantity_user = $total_quantity_user;
}else{
$product->total_quantity_user = 0;
$product->max_quantity = 0;
}
return $this->success(__('successful'),$product->toArray());
}
}
@@ -0,0 +1,145 @@
<?php
namespace app\api\controller;
use app\model\ProductOrder as ProductOrderModel;
use app\model\Product as ProductModel;
use app\model\User as UserModel;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 我的产品
*/
class ProductOrderController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = [];
/**
* 列表
* @Apidoc\Query("step", type="int", require=false, desc="工作状态")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$page = (int)input('page',1);
$step = (int)input('step',0);
$user_id = \support\Jwt\JwtToken::getCurrentId();
$model = ProductOrderModel::with(['product'])->where('user_id',$user_id);
if($step){
$ids = \app\model\WorkRecord::where('user_id',$user_id)
->distinct(true)
->where('status',$step)
->column('order_id');
$model = $model->whereIn('id',$ids);
}
$list = $model->where('status',1)
->order('created_at desc')
->paginate($limit);
$list->each(function($item)use($step){
//$_step=1;
if($step){
$_step = $step;
}else{
$_step = \app\model\WorkRecord::where('order_id',$item->id)
->order('status','asc')
->limit(0,1)
->value('status');
}
$item->step = $_step;
return $item;
});
return $this->success(__('successful'),$list->toArray());
}
/**
* 购买产品
* @Apidoc\Method("POST")
* @Apidoc\Param("product_id", type="string", require=true, desc="产品ID")
* @Apidoc\Param("quantity", type="int", require=true, desc="数量")
* @Apidoc\Param("trade_password", type="string", require=true, desc="交易密码")
*/
public function create()
{
$user = \support\Jwt::getUser();
//验证交易密码
$trade_password = input('trade_password');
\support\Jwt::verify_trade_password($trade_password);
$data = [
'user_id' => $user->id,
'product_id'=> input('product_id'),
'quantity' => (int)input('quantity'),
'accelerate' => input('accelerate'),
'status' => 1
];
if(!$data['product_id']){
return $this->error(__('Product is incorrect'));
}
if($data['quantity'] < 1){
return $this->error(__('Quantity is incorrect'));
}
if($data['product_id'] == 12){
$exsit = ProductOrderModel::where('product_id',$data['product_id'])->where('user_id',$data['user_id'])->count('id');
if($exsit != 0){
return $this->error(__('微量包每个用户只能购买一个'));
}
if($data['quantity'] != 1){
return $this->error(__('微量包每个用户只能购买一个'));
}
}
/** @var ProductModel $product */
$product = ProductModel::where('id',$data['product_id'])->find();
if(!$product){
return $this->error(__('Product is incorrect'));
}
/*
if ($product->start_time > time() || $product->end_time < time()) {
return $this->error(__('Can\'t buy now'));
}
*/
//return $this->success(__('successful'),[$product->start_time]);
$data['price'] = $product['price'];
if($data['accelerate']){
$data['price'] += $product['accelerate_price'];
$data['accelerate_times'] = $product['accelerate_assign_times'];
$data['accelerate_used'] = 0;
}
$data['amount'] = $data['price'] * $data['quantity'];
$data['total'] = $product['total'] * $data['quantity'];
$data['assigned'] = 0;
/*
$total_quantity_user = ProductOrderModel::where('product_id',$product->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $product->user_quantity ?: 99999999;
$can_purchase = $total_quantity_system-$total_quantity_user;
$can_purchase= $can_purchase < 0 ? 0: $can_purchase;
if($can_purchase < $data['quantity']){
return $this->error(__('You can only purchase %max_quantity% copies',[
'%max_quantity%' => $can_purchase
]));
}
*/
//var_dump($user);
//验证余额
if($data['amount'] > $user->money){
return $this->error(__('Insufficient balance'));
}
Db::startTrans();
try{
$data = ProductOrderModel::create($data);
$product->sales = $product->sales + $data['quantity'];
$product->save();
UserModel::money($data['user_id'],-$data['amount'],\app\enum\BalanceType::PRODUCT_BUY,$data['id']);
Hook('product.buy',$data);
Db::commit();
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('successful'));
}
}
@@ -0,0 +1,251 @@
<?php
namespace app\api\controller;
use app\model\WorkRecord as WorkRecordModel;
use app\model\Questionnaire as QuestionnaireModel;
use app\model\Product as ProductModel;
use app\model\ProductOrder as ProductOrderModel;
use app\model\BalanceLog;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 问卷
*/
class QuestionnaireController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
public $noNeedLogin = [];
/**
* 简介
* @Apidoc\Method("GET")
*/
public function info(){
$user = \support\Jwt::getUser();
return $this->success(__('successful'),[
'success_count' => WorkRecordModel::where('status',\app\enum\ServerStatus::COMPLETE->value)
->where('user_id',$user->id)
->count('id'),
'audit_count' => WorkRecordModel::where('status',\app\enum\ServerStatus::AUDITING->value)
->where('user_id',$user->id)
->count('id'),
]);
}
/**
* 列表
* @Apidoc\Query("kw", type="string", require=false, desc="搜索关键字")
* @Apidoc\Query("country", type="string", require=false, desc="国家,i18n编码")
* @Apidoc\Query("category_id", type="int", require=false, desc="分类")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$model = QuestionnaireModel::with(['category'])->where('status',1);
if($category_id = input('category_id')){
$model = $model->where('category_id', $category_id);
}
if($country = input('country')){
$model = $model->where('country', $country);
}
$list = $model->order('id desc')->paginate($limit);
$list = $list->toArray();
foreach($list['data'] as $k=>$item){
$list['data'][$k]['id'] = idEncode($item['id']);
}
return $this->success(__('successful'),$list);
}
/**
* 问卷详情
* @Apidoc\Query("id", type="int", require=true, desc="ID")
*/
public function detail(){
try{
$user = \support\Jwt::getUser();
}catch(\Exception $e){
$user = ['id'=>0,'role_id'=>0];
}
$appid = input('id');
if(!$appid){
return $this->error(__("Product does not exist"));
}
/** @var ProductModel $product */
$product = ProductModel::where('id',$appid)->find();
//->cache(true,86400,'product_detail')
if(!$product) {
return $this->error(__("Product does not exist"));
}
if($user['id']){
$total_quantity_user = ProductOrderModel::where('product_id',$product->id)->where('user_id',$user['id'])->sum('quantity');
$total_quantity_system = $product->user_quantity ?: 99999999;
$max_quantity = $total_quantity_system-$total_quantity_user;
$max_quantity= $max_quantity < 0 ? 0: $max_quantity;
$product->max_quantity = $max_quantity;
$product->total_quantity_user = $total_quantity_user;
}else{
$product->total_quantity_user = 0;
$product->max_quantity = 0;
}
return $this->success(__('successful'),$product->toArray());
}
/**
* 领取问卷
* @Apidoc\Method("GET")
*/
function claim(){
$user = \support\Jwt::getUser();
//判断是否有问卷可领取
if($user->currency6<=0){
return $this->success(__('successful'));
}
//产生工作记录
$datas = [];
$questionnaire_ids = QuestionnaireModel::where('status',1)
->whereTime('start_time','<',time())
->whereTime('end_time','>',time())
->column('id');
$time = time();
for ($i=0; $i < $user->currency6; $i++) {
//随机选取一份问卷
$questionnaire_id = $questionnaire_ids[array_rand($questionnaire_ids)];
/** @var QuestionnaireModel $questionnaire */
$questionnaire = QuestionnaireModel::field('id,score')->find($questionnaire_id);
array_push($datas,[
"user_id" => $user->id,
"product_id" => null,
"questionnaire_id" => $questionnaire->id,
"order_id" => null,
"income" => $questionnaire->score,
"start_time" => 0,
"end_time" => 0,
"status" => 0, //自动开始
"created_at" => $time,
]);
}
Db::startTrans();
try {
(new WorkRecordModel)->saveAll($datas);
//领取完成,待领取清0;
$logData = [
'user_id' => $user->id.'',
'currency' => 'currency6',
'amount' => (0-$user->currency6).'',
'before' => $user->currency6.'',
'after' => '0',
'type' => \app\enum\BalanceType::CLAIM->value,
'created_at' => $time.'',
'memo' => ''
];
// 写入日志
BalanceLog::create($logData);
$user->currency6 = 0;
$user->save();
Db::commit();
} catch (\Exception $e) {
Db::rollback();
return $this->error($e->getMessage());
}
return $this->success(__('successful'));
}
/**
* 用户参与的问卷列表
* @Apidoc\Query("order_id", type="string", require=false, desc="订单号")
* @Apidoc\Query("step", type="string", require=false, desc="类型,progress,done")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function record(){
$limit = (int)input('limit',10);
$type = input('type','all');
$user_id = \support\Jwt\JwtToken::getCurrentId();
$step = input('step');
$order_id = input('order_id');
$model = WorkRecordModel::withJoin([
'questionnaire' => function($query) {
$query->field('title,category_id,country');
},
// 'product' => function($query) {
// $query->field('title');
// }
])->where('work_record.user_id',$user_id);
if($type && $type !='all'){
$model = $model->where('work_record.status', $type);
}
if($order_id){
$model = $model->where('work_record.order_id',$order_id);
}
if($step){
if($step=='done'){
$model = $model->where('work_record.status',\app\enum\ServerStatus::COMPLETE->value);
}
if($step=='progress'){
$model = $model->whereBetween('work_record.status',[1,\app\enum\ServerStatus::AUDITING->value,\app\enum\ServerStatus::SETTLEMENT->value]);
}
}
$list = $model->order('work_record.id desc')
->paginate($limit);
$list->each(function($item){
$item->questionnaire->country = Config('site.questionnaire_country')[$item->questionnaire->country];
$item->category = Db::name('category')->where('id',$item->questionnaire->category_id)->value('name');
return $item;
});
return $this->success(__('successful'),$list->toArray());
}
/**
* 开始任务
* @Apidoc\Method("POST")
* @Apidoc\Param("server_id", type="string", require=true, desc="产品ID")
*/
public function start()
{
$server_id = input('server_id');
$user = \support\Jwt::getUser();
if(!$server_id){
return $this->error(__('Incorrect parameter'));
}
if($server_id === 'all'){
$work_records = WorkRecordModel::where('user_id',$user->id)
->where('status',\app\enum\ServerStatus::WAITING->value)
->select();
}else{
$work_records = WorkRecordModel::where('user_id',$user->id)
->where('status',\app\enum\ServerStatus::WAITING->value)
->where('id',$server_id)->select();
if(count($work_records) === 0){
return $this->error(__('Server is not exist'));
}
}
/** @var WorkRecordModel $server */
foreach($work_records as $server){
$server->start();
}
return $this->success(__('successful'));
}
/**
* 用户参与的问卷详情
* @Apidoc\Method("POST")
* @Apidoc\Param("server_id", type="string", require=true, desc="产品ID")
*/
function progress(){
$server_id = (int)input('server_id',1);
$user = \support\Jwt::getUser();
/** @var WorkRecordModel $work_record */
$work_record = WorkRecordModel::with(['questionnaire'])->where('id',$server_id)->find();
if(!$work_record){
return $this->error(__('Server is not exist %sadds_f%',["%sadds_f%"=>'']));
}
$work_record->step_text = $work_record->getStep();
return $this->success(__('successful'),$work_record->toArray());
}
}
+481
View File
@@ -0,0 +1,481 @@
<?php
namespace app\api\controller;
use support\Request;
use support\think\Db;
use taoser\facade\Validate;
use app\model\Recharge as RechargeModel;
use app\model\User as UserModel;
use hg\apidoc\annotation as Apidoc;
/**
* 充值模块
*/
class RechargeController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = ['notify','watch_list','updateUserBalance'];
/**
* 列表
* @Apidoc\Method("POST")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list()
{
$limit = (int)input('limit',10);
$status = Input('status',null);
if(!is_null($status)){
$list = RechargeModel::where('user_id',\support\Jwt\JwtToken::getCurrentId())->where('status',$status)->order('id desc')->paginate($limit);
}else{
$list = RechargeModel::where('user_id',\support\Jwt\JwtToken::getCurrentId())->order('id desc')->paginate($limit);
}
return $this->success(__('successful'),$list->toArray());
}
/**
* 创建
* @Apidoc\Method("POST")
* @Apidoc\Param("amount", type="string", require=true, desc="金额")
* @Apidoc\Param("network", type="string", require=true, desc="网络")
*/
function create(){
return $this->create1();
}
public function create2()
{
$user = \support\Jwt::getUser();
$data = [
'user_id' => $user->id,
'amount' => input('amount',0),
'network' => input('network',''),
'status' => \app\enum\WithdrawlStatus::CREATED->value
];
//验证最小金额
if($data['amount'] < Config('site.recharge_minimum')){
return $this->error(__('Minimum recharge of %num%',[
'%num%' => Config('site.recharge_minimum')
]));
}
if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20','wxpay','alipay','qqpay'])) {
return $this->error(__('Network is incorrect'));
}
if(in_array($data['network'],['BEP-20','TRC-20'])){
$ing_count = RechargeModel::where('user_id',$data['user_id'])->where('status',\app\enum\RechargeStatus::CREATED->value)->count('id');
if($ing_count >= 2){
return $this->error(__('You have reached the limit of uncompleted orders ( %max% ). Please complete the existing orders before trying to create another one.',[
'%max%' => 2
]));
}
Db::startTrans();
try {
/** @var RechargeModel $order */
$order = RechargeModel::create($data);
//$order->notify_url = Request()->domain().'/api/recharge/notify';
$order->notify_url = config('pay.notify_server').'/api/recharge/notify';
$order->out_trade_no = $order->id;
$order->env = 'product';
$order->appid = Config('pay.appid');
$order->created_at = time();
$postdata = $order->toArray();
unset($postdata['id']);
//转换成USDT
$postdata['amount'] = bcdiv($order->amount,Config('site.money_to_usdt_rate'),4);
//折扣
$postdata['amount'] = bcdiv($postdata['amount'],Config('site.usdt_recharge_discount'),4);
$res = post(Config('pay.server').'/recharge/create',$postdata);
\support\Log::alert("create res:".$res);
//cp($res);
$res = json_decode($res,true);
if($res['code'] === 0){
$order->address = $res['data']['address'];
}else{
Db::rollback();
return $this->error(__('Failed to create recharge order, please try again later'));
}
$order->allowField(['address'])->save();
Db::commit();
return $this->success(__('successful'),[
'order' => $order
]);
} catch (\Exception $e) {
Db::rollback();
\support\Log::alert("create error".$e->getMessage());
return $this->error(__('Failed to create recharge order, please try again later'));
}
}else{
$sign = aesencode(json_encode($data));
return $this->success(__('successful'),[
'order' => [
'id' => 0,
'network' => $data['network'],
'amount' => $data['amount'],
"url" => 'http://43.240.74.89:9595/pay/index?sign='.$sign
]
]);
}
}
public function create1()
{
$user = \support\Jwt::getUser();
$data = [
'user_id' => $user->id,
'amount' => input('amount',0),
'network' => input('network',''),
'status' => \app\enum\WithdrawlStatus::CREATED->value
];
//验证最小金额
if($data['amount'] < Config('site.recharge_minimum')){
return $this->error(__('Minimum recharge of %num%',[
'%num%' => Config('site.recharge_minimum')
]));
}
if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20','wxpay','alipay','qqpay'])) {
return $this->error(__('Network is incorrect'));
}
if(in_array($data['network'],['BEP-20','TRC-20'])){
$ing_count = RechargeModel::where('user_id',$data['user_id'])->where('status',\app\enum\RechargeStatus::CREATED->value)->count('id');
if($ing_count >= 2){
return $this->error(__('You have reached the limit of uncompleted orders ( %max% ). Please complete the existing orders before trying to create another one.',[
'%max%' => 2
]));
}
}
Db::startTrans();
try {
/** @var RechargeModel $order */
$order = RechargeModel::create($data);
if(in_array($data['network'],['BEP-20','TRC-20'])){
//$order->notify_url = Request()->domain().'/api/recharge/notify';
$order->notify_url = config('pay.notify_server').'/api/recharge/notify';
$order->out_trade_no = $order->id;
$order->env = 'product';
$order->appid = Config('pay.appid');
$order->created_at = time();
$postdata = $order->toArray();
unset($postdata['id']);
//转换成USDT
$postdata['amount'] = bcdiv($order->amount,Config('site.money_to_usdt_rate'),4);
//折扣
$postdata['amount'] = bcmul($postdata['amount'],Config('site.usdt_recharge_discount'),4);
$res = post(Config('pay.server').'/recharge/create',$postdata);
\support\Log::alert("create res:".$res);
//cp($res);
$res = json_decode($res,true);
if($res['code'] === 0){
$order->address = $res['data']['address'];
}else{
Db::rollback();
return $this->error(__('Failed to create recharge order, please try again later'));
}
$order->allowField(['address'])->save();
}else{
$postdata = [
"pid" => '144604',
"type" => $order->network,
"out_trade_no" => $order->id,
"notify_url" => Config('pay.notify_server').'/api/recharge/notify_ok',
"return_url" => Config('pay.notify_server').'/api/recharge/notify_ok',
"name" => 'VIP会员',
"money" => $order->amount,
"device" => "mobile",
"clientip" => request()->getRealIp()
];
$postdata['money'] = bcdiv($postdata['money'] ,Config('site.rmb_recharge_discount'),2);
//\support\Log::alert("create postdata:".json_encode($postdata));
$this->getsign($postdata);
$res = post('https://pay.yf2.cn/mapi.php',$postdata);
\support\Log::alert("create res:".$res);
$res = json_decode($res,true);
if($res['code'] === 1){
if(isset($res['payurl'])){
$order->address = $res['qrcode'];
}elseif(isset($res['qrcode'])){
$order->address = $res['qrcode'];
}elseif(isset($res['urlscheme'])){
$order->address = $res['urlscheme'];
}
}else{
Db::rollback();
\support\Log::error(json_encode($res));
throw new \Exception($res['msg']);
}
$order->allowField(['address'])->save();
}
Db::commit();
return $this->success(__('successful'),[
'order' => $order
]);
} catch (\Exception $e) {
Db::rollback();
\support\Log::alert("create error".$e->getMessage());
return $this->error(__('Failed to create recharge order, please try again later'));
}
}
/**
* 更新
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="int", require=true, desc="ID")
* @Apidoc\Param("amount", type="string", require=true, desc="金额")
* @Apidoc\Param("network", type="string", require=true, desc="网络")
*/
function update(){
$id = input('id');
$amount = input('amount');
$network = input('network');
$data = [];
if(!$id){
return $this->error(__('Invalid parameters'));
}
/** @var RechargeModel $order */
$order = RechargeModel::where('id',$id)->find();
if(!$order){
return $this->error(__('Order not exsit'));
}
if($amount && $amount != $order->amount){
$data['amount'] = $amount;
//验证最小金额
if($data['amount'] < Config('site.recharge_minimum')){
return $this->error(__('Minimum recharge of %num%',[
'%num%' => Config('site.recharge_minimum')
]));
}
$data['amount'] = bcdiv($data['amount'],Config('site.money_to_usdt_rate'),4);
}
if($network && $network != $order->network){
$data['network'] = $network;
if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20'])) {
return $this->error(__('Network is incorrect'));
}
}
if(empty($data)){
return $this->error(__('Invalid parameters'));
}
foreach($data as $field=>$value){
$order->$field = $value;
}
$data['out_trade_no'] = $order->id;
$data['action'] = 'update';
$data['appid'] = Config('pay.appid');
$res = post(Config('pay.server').'/recharge/create',$data);
//\support\Log::alert("update res:".$res);
$res = json_decode($res,true);
//cp($res);
if($res['code'] === 0){
if($order->address != $res['data']['address']){
$order->address = $res['data']['address'];
}
}else{
return $this->error(__('Failed to create recharge order, please try again later'));
}
$order->save();
return $this->success(__('successful'),[
'order' => $order
]);
}
/**
* 详情
* @Apidoc\Query("id", type="string", require=true, desc="ID")
*/
public function detail(){
$appid = input('id');
$vo = RechargeModel::where('id',$appid)->find();
if($vo) {
return $this->success(__('successful'),[
'order' => $vo
]);
}
return $this->error(__("Record does not exist"));
}
/**
* 转账成功异步通知
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
public function notify(){
$data = aesdecode(input('data'));
$data = json_decode($data,true);
/** @var RechargeModel $vo */
$vo = RechargeModel::where('id',$data['out_trade_no'])->find();
if($vo){
if($data['result'] == 'SUCCESS'){
if($vo->status != \app\enum\RechargeStatus::COMPLETE->value){
try{
$vo->status = \app\enum\RechargeStatus::COMPLETE->value;
$vo->txid = $data['txid'];
$vo->real_amount = isset($data['real_amount']) ? $data['real_amount'] : 0;
$vo->transfer_at = $data['transfer_at'] ?: time();
$vo->save();
//消除USDT和人民币的误差,因为USDT支付可能不是一模一样的金额
$money = bcmul($vo->amount ,Config('site.rmb_to_money_rate'));
UserModel::money($vo->user_id,$money,\app\enum\BalanceType::RECHARGE,$vo->id);
Hook('recharge.success',$vo);
}catch(\Exception $e){
log_write('充值回调失败:'.$e->getMessage());
log_write($data);
}
}
}else{
$vo->status = \app\enum\RechargeStatus::FAIL->value;
$vo->txid = $data['txid'];
$vo->reason = $data['reason'];
$vo->save();
}
}
return response("SUCCESS");
}
/**
* 人民币转账成功异步通知
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
public function notify_ok(){
$data = Input('post.');
$sign = get_pay_sign($data);
if($sign != $data['sign']){
return response("FAIL");
}
/** @var RechargeModel $vo */
$vo = RechargeModel::where('id',$data['out_trade_no'])->find();
if($vo && isset($data['trade_status'])){
if($data['trade_status'] === 'TRADE_SUCCESS'){
if($vo->status != \app\enum\RechargeStatus::COMPLETE->value){
try{
$vo->status = \app\enum\RechargeStatus::COMPLETE->value;
$vo->txid = isset($data['trade_no']) ? $data['trade_no'] : '';
$vo->from='pay.yf2.cn';
$vo->real_amount = isset($data['money']) ? $data['money'] : 0;
$vo->save();
$money = bcmul($vo->real_amount ,Config('site.rmb_to_money_rate'));
UserModel::money($vo->user_id,$money,\app\enum\BalanceType::RECHARGE,$vo->id);
Hook('recharge.success',$vo);
}catch(\Exception $e){
log_write('充值回调失败:'.$e->getMessage());
log_write($data);
return response("FAIL");
}
}
}
}
return response("SUCCESS");
}
/**
* 根据TXID更新用户余额,补单的功能
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
* @return \support\Response
*/
function update_balance_by_txid(){
$user_id = \support\Jwt\JwtToken::getCurrentId();
$data = [
'txid' => input('txid'),
'id' => input('id'),
'status' => \app\enum\WithdrawlStatus::CREATED->value
];
/** @var RechargeModel $vo */
$vo = RechargeModel::where('id',$data['id'])->find();
if($vo->user_id !=$user_id){
return $this->error(__('permission denied'));
}
//验证最小金额
if(!$data['txid']){
return $this->error(__('Invalid parameters'));
}
$res = get(Config('pay.server').'/Util/txid?txid='.$data['txid']);
$res = json_decode($res,true);
if($res['code'] !== 0){
return $this->error($res['msg']);
}
$vo->txid = $data['txid'];
$vo->result = $res['result'];
if($res['result'] == 'SUCCESS'){
$vo->from = $res['from'];
$vo->real_amount = $res['real_amount'];
$vo->pay_time = $res['timestamp'];
$vo->status = \app\enum\RechargeStatus::COMPLETE->value;
}else{
$vo->result = $res['from'];
$vo->reason = $res['real_amount'];
$vo->status = \app\enum\RechargeStatus::FAIL->value;
}
$vo->save();
return $this->success(__('successful'));
}
/**
* 根据监视上报数据更新用户余额
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
function updateUserBalance(Request $request){
$decimal_part = $request->post('decimal_part');
$data = [
'user_id' => 0 ,
'amount' => $request->post('amount'),
'network' => $request->post('chain'),
'address' => $request->post('to'),
'from' => $request->post('from'),
'txid' => $request->post('txid'),
'pay_time' => $request->post('pay_time'),
'created_at' => $request->post('pay_time'),
];
if($data['network'] == 'TRC-20'){
$data['user_id'] = UserModel::where('trc_recharge_address',$data['address'])->where('decimal_part',$decimal_part)->value('id');
}else{
$data['user_id'] = UserModel::where('bep_recharge_address',$data['address'])->where('decimal_part',$decimal_part)->value('id');
}
if(!$data['user_id']){
return $this->success(__('user not exist'));
}
$data['real_amount'] = $data['amount'];
//$data['pay_time'] = time();
$data['status'] = 2;
$vo = RechargeModel::where('txid',$data['txid'])->find();
if($vo){
return $this->success(__('exist'));
}
Db::startTrans();
try{
$idata = RechargeModel::create($data);
UserModel::score($data['user_id'],$data['amount'],\app\enum\BalanceType::RECHARGE,$idata['id'].'');
Db::commit();
Hook('recharge.success',$idata);
return $this->success(__('successful'));
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
}
/**
* 监视列表
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
function watch_list(){
//$bep = UserModel::distinct(true)->column('LOWER(bep_recharge_address)');
//$trc = UserModel::distinct(true)->column('LOWER(trc_recharge_address)');
$bep = UserModel::distinct(true)->column('bep_recharge_address');
$trc = UserModel::distinct(true)->column('trc_recharge_address');
return $this->success(__('successful'),[
'BEP-20'=>$bep,
'TRC-20'=>$trc,
]);
}
protected function getsign(&$data, $key = "3E7551E3707DFB6B6E8A6E83B01FF437") {
return get_pay_sign($data,$key);
}
}
+122
View File
@@ -0,0 +1,122 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 用户角色
*/
class RoleController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = ['recent'];
/**
* @Apidoc\Title("当前角色信息")
* @Apidoc\Method("GET")
*/
function detail(){
$user = \support\Jwt::getUser();
$data = \app\model\UserRole::where('id',$user->role_id)->field('name,id,price')->find();
return $this->success(__('successful'),$data);
}
/**
* @Apidoc\Title("列表")
* @Apidoc\Method("GET")
* @Apidoc\Param("page", type="int",require=false, desc="页码")
* @Apidoc\Param("limit", type="int",require=false, desc="分页大小")
*/
public function list(Request $request){
$user = \support\Jwt::getUser();
$limit = $request->get('limit',10);
$page = $request->get('page',1);
$kw = $request->get('kw');
$model = \app\model\UserRole::where('id','>',0)->field('id,name,price')
->order('id asc');
if($limit == 'all' || $limit >= 999999){
$result = $model->select();
$result= \think\Paginator::make($result, 99999999999, 1, count($result));
}else{
$result = $model->paginate($limit);
}
return $this->success(__('successful'),$result);
}
/**
* @Apidoc\Title("最近购买列表")
* @Apidoc\Method("GET")
*/
public function recent(Request $request){
$list = (new \app\model\BalanceLog)->setSuffix('_money')->where('type',\app\enum\BalanceType::PURCHASE_ROLE->value)
->order('created_at','desc')->limit(0,10)->field('user_id,created_at,memo')->select();
$list = $list->toArray();
$data = [];
$role_list = \app\model\UserRole::where('id', '>',1)
->column('name','id');
foreach($list as $v){
$data[] = [
'username' => \app\model\User::where('id',$v['user_id'])->value('username'),
'created_at' => $v['created_at'],
'v' => $v,
//'role' => $role_list[str_replace('购买用户组:','',$v['memo'])]
'role' => 'K'.str_replace('购买用户组:','',$v['memo'])
];
}
return $this->success(__('successful'),$data);
}
/**
* @Apidoc\Title("购买")
* @Apidoc\Method("POST")
* @Apidoc\Param("role_id", type="string",require=true, desc="要购买的角色ID")
* @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码")
*/
function buy(Request $request): Response{
$user = \support\Jwt::getUser();
$role_id = (int)$request->post('role_id');
if($user->role_id > $role_id){
return $this->fail(__('Your level is too high to purchase this character'));
}
if(abs($role_id - $user->role_id) !== 1 && $role_id !==6){
return $this->fail(__('Your level is too high to purchase this character'));
}
$role = \app\model\UserRole::where('id',$role_id)->find();
if(!$role){
return $this->fail(__('Role does not exist'));
}
if($role->price <=0){
return $this->fail(__('This character group is not allowed to be sold'));
}
if($user->money < $role->price){
return $this->fail(__('Insufficient balance'));
}
\support\Jwt::verify_trade_password($request->post('trade_password'));
$amount = $role->price;
$power = bcmul($amount,config('site.suanli_rate'),4);
\app\model\User::where('id',$user->id)->save(['role_id'=>$role_id]);
\app\model\User::money($user->id,-$amount,\app\enum\BalanceType::PURCHASE_ROLE,'购买用户组:'.$role_id);
\app\model\User::score($user->id,$power,\app\enum\BalanceType::POWER_ADD,'购买用户组:'.$role_id);
cache_add('user_power_total_'.$user->id,$power);
Hook('user.roleup', $user);
$data = [
'role_id' => $role_id,
'user_id' => $user->id,
'parent_id' => $user->parent_id,
'amount' => $amount,
];
Hook('role.buy', $data);
return $this->success(__('successful'));
}
}
+293
View File
@@ -0,0 +1,293 @@
<?php
namespace app\api\controller;
use support\Request;
use support\Response;
use app\model\UserSignin as UserSigninModel;
use app\model\UserXuanchuan as UserXuanchuanModel;
use support\Jwt\JwtToken;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use hg\apidoc\annotation as Apidoc;
/**
* 签到模块
*/
class SigninController extends BaseController
{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* 列表
* @Apidoc\Query("status", type="int", require=true, desc="状态")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list(){
$limit = (int)input('limit',10);
$status = (int)input('status');
$model = UserXuanchuanModel::where('id','>',0);
if($status && $status!='all'){
$model = $model->where('status',$status);
}
$list = $model->order('id','desc')->paginate($limit);
return $this->success(__('successful'),$list);
}
/**
* @Apidoc\Title("用户签到")
* @Apidoc\Method("GET")
*/
public function info(Request $request)
{
$user_id = JwtToken::getCurrentId();
if (!$user_id) {
return $this->error(__('Please login first'));
}
/** @var UserSigninModel $last */
$last = UserSigninModel::where('user_id', $user_id)->order('id','desc')->find();
return $this->success(__('successful'),[
'continuous_days' => $last->continuous_days,
'last_day' => $last->sign_date,
'signed' => $last->sign_date == date('Y-m-d'),
'invite_complete' => cache('invite_'.$user_id.'_'.date('Ymd')),
'pyq_complete' => UserXuanchuanModel::where('user_id',$user_id)->where('type','pyq')->whereTime('created_at','today')->count() > 0,
'group_complete' => UserXuanchuanModel::where('user_id',$user_id)->where('type','group_complete')->whereTime('created_at','today')->count() > 0,
'signinList' => [20,20,20,20,20,20,100]
]);
}
/**
* @Apidoc\Title("用户签到")
* @Apidoc\Method("GET")
*/
public function sign(Request $request)
{
$user = JwtToken::getUser();
if (!$user->realname_verify) {
return $this->error(__('Please complete real-name verification first'));
}
$user_id = $user->id;
$today = date('Y-m-d');
// 检查今天是否已签到
if (UserSigninModel::where('user_id', $user_id)->where('sign_date', $today)->find()) {
return $this->error(__('今日已签到'));
}
// 检查昨天是否签到
$continuous_days = UserSigninModel::where('user_id', $user_id)->count('id');
$continuous_days = $continuous_days ? ($continuous_days + 1) : 1;
// 奖励规则(可自定义/读取配置/数据库)
$reward = $this->getReward($continuous_days);
// 写入签到记录
UserSigninModel::create([
'user_id' => $user_id,
'sign_date' => $today,
'reward' => $reward,
'continuous_days' => $continuous_days,
]);
// 发放奖励(如积分、余额等)
\app\model\User::currency1($user_id, $reward, \app\enum\BalanceType::SIGNIN);
return $this->success(__('successful'),[
'reward' => $reward,
'continuous_days' => $continuous_days
]);
}
/**
* @Apidoc\Title("查询签到状态")
* @Apidoc\Method("GET")
*/
public function status(Request $request)
{
$user_id = JwtToken::getCurrentId();
if (!$user_id) {
return $this->error(__('Please login first'));
}
$today = date('Y-m-d');
$record = UserSigninModel::where('user_id', $user_id)->where('sign_date', $today)->find();
$continuous_days = UserSigninModel::where('user_id', $user_id)->order('id','desc')->value('continuous_days');
return $this->success(__('successful'),[
'signed' => !!$record,
'continuous_days' => $continuous_days ?: 0,
]);
}
/**
* @Apidoc\Title("查询签到记录")
* @Apidoc\Method("GET")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function records(Request $request)
{
$user_id = JwtToken::getCurrentId();
if (!$user_id) {
return $this->error(__('Please login first'));
}
$limit = (int)$request->get('limit', 30);
$list = UserSigninModel::where('user_id', $user_id)
->order('id','desc')
->limit($limit)
->select();
return $this->success(__('successful'),$list);
}
/**
* @Apidoc\Title("发布朋友圈")
* @Apidoc\Method("POST")
* @Apidoc\Param("files", type="string",require=true, desc="文件列表")
*/
public function pyq(Request $request)
{
$user = JwtToken::getUser();
if (!$user->realname_verify) {
return $this->error(__('Please complete real-name verification first'));
}
$user_id = $user->id;
$files = Input('files');
if(count($files) != 2) {
return $this->error(__('请上传2张图片'));
}
if(UserXuanchuanModel::where('user_id',$user_id)->where('type','pyq')->whereTime('created_at','today')->count() > 0) {
return $this->error(__('请明日再来'));
}
UserXuanchuanModel::create([
'user_id' => $user_id,
'files' => implode(',',$files),
'type' => 'pyq'
]);
return $this->success(__('successful'));
}
/**
* @Apidoc\Title("发布微信群")
* @Apidoc\Method("POST")
* @Apidoc\Param("files", type="string",require=true, desc="文件")
*/
public function wx(Request $request)
{
$user = JwtToken::getUser();
if (!$user->realname_verify) {
return $this->error(__('Please complete real-name verification first'));
}
$user_id = $user->id;
$files = Input('files');
if(count($files) != 1) {
return $this->error(__('请上传1张图片'));
}
if(UserXuanchuanModel::where('user_id',$user_id)->where('type','group')->whereTime('created_at','today')->count() > 0) {
return $this->error(__('请每日再来'));
}
UserXuanchuanModel::create([
'user_id' => $user_id,
'files' => implode(',',$files),
'type' => 'group'
]);
return $this->success(__('successful'));
}
/**
* @Apidoc\Title("补签")
* @Apidoc\Method("POST")
* @Apidoc\Param("date", type="string",require=true, desc="补签日期")
*/
public function makeUp(Request $request)
{
$user_id = JwtToken::getCurrentId();
if (!$user_id) {
return $this->error(__('Please login first'));
}
$date = $request->post('date');
$today = date('Y-m-d');
if (!$date || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
return $this->error(__('日期格式错误'));
}
// 补签日期不能大于今天
if ($date > $today) {
return $this->error(__('补签日期不能大于今天'));
}
// 检查是否已签到
if (UserSigninModel::where('user_id', $user_id)->where('sign_date', $date)->find()) {
return $this->error(__('该日已签到'));
}
// 补签消耗积分或奖励减半(此处以奖励减半为例)
$yesterday = date('Y-m-d', strtotime($date . ' -1 day'));
/** @var UserSigninModel $last */
$last = UserSigninModel::where('user_id', $user_id)->where('sign_date', $yesterday)->find();
$continuous_days = $last ? ($last->continuous_days + 1) : 1;
$reward = floor($this->getReward($continuous_days) / 2); // 奖励减半
UserSigninModel::create([
'user_id' => $user_id,
'sign_date' => $date,
'reward' => $reward,
'continuous_days' => $continuous_days,
]);
\app\model\User::currency1($user_id, $reward, \app\enum\BalanceType::SIGNIN);
return $this->success(__('successful'),['reward' => $reward, 'continuous_days' => $continuous_days]);
}
/**
* @Apidoc\Title("签到统计报表")
* @Apidoc\Method("GET")
*/
public function report(Request $request)
{
$user_id = JwtToken::getCurrentId();
if (!$user_id) {
return $this->error(__('Please login first'));
}
$total = UserSigninModel::where('user_id', $user_id)->count();
$max_continuous = UserSigninModel::where('user_id', $user_id)->max('continuous_days');
$month = date('Y-m');
$month_count = UserSigninModel::where('user_id', $user_id)
->whereLike('sign_date', "$month%")
->count();
return $this->success(__('successful'),[
'total' => $total,
'max_continuous' => $max_continuous,
'month_count' => $month_count,
]);
}
// 奖励规则,可自定义
protected function getReward($continuous_days)
{
$rewards = [20,20,20,20,20,20,100];
$continuous_days = $continuous_days - 1;
$continuous_days = $continuous_days % 7;
return $rewards[$continuous_days];
}
/**
* @Apidoc\Title("上传")
* @Apidoc\Method("POST")
* @Apidoc\Param("file", type="string",require=true, desc="文件")
*/
function upload(Request $request)
{
//多文件上传
$files = $request->file();
try {
$result = Storage::adapter('public')
->path('upload/files')
->size(1024*1024*50)
->extYes(['image/jpeg','image/png'])
->uploads($files,0,1024*1024*20,false);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
}
+207
View File
@@ -0,0 +1,207 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use app\model\UserTeam as UserTeamModel;
use app\model\WorkRecord as WorkRecordModel;
use support\Request;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 用户团队
*/
class TeamController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* @Apidoc\Title("团队概览")
* @Apidoc\Method("GET")
* @Apidoc\Param("username", type="string",require=true, desc="用户名")
* @Apidoc\Param("nickname", type="string",require=true, desc="密码")
*/
public function index(Request $request){
$user = \support\Jwt::getUserinfo();
$user_id = $user['id'];
$user= Hook('user.profile',$user);
$team_ids = UserTeamModel::where('ancestor_id',$user_id)->where('depth','>',0)->column('descendant_id');
$result=[
'total_count' => count($team_ids),//团队总人数
'direct_total' => cache('team_direct_total_'.$user_id)??0,//直属团队人数
'recharge_total' => cache('team_recharge_total_'.$user_id)??0,
'withdrawl_total' => cache('team_withdrawl_total_'.$user_id)??0,
'income_total' => cache('team_income_total_'.$user_id)??0,
'today_income_total' => cache('user_today_income_total_'.$user_id)??0,
'promotion_income_total' => cache('user_promotion_income_total_'.$user_id)??0,
'consume_total' => Db::name('user_extend')->where('user_id',$user_id)->value('sales'),//cache('team_consume_total_'.$user_id)??0,//团队总业绩
'user_sales_reward' => cache('user_sales_reward_'.$user_id)??0,//销售奖
'user_output_reward' => cache('user_output_reward_'.$user_id)??0,//产值奖
'user_withdrawl_reward' => cache('user_withdrawl_reward'.$user_id)??0,//提现奖
'user' => $user[0],
];
return $this->success(__('successful'),$result);
}
/**
* @Apidoc\Title("团队列表")
* @Apidoc\Method("GET")
* @Apidoc\Param("page", type="int",require=false, desc="页码")
* @Apidoc\Param("limit", type="int",require=false, desc="分页大小")
*/
public function list(Request $request){
$user = \support\Jwt::getUser();
$limit = $request->get('limit',10);
$page = $request->get('page',1);
$kw = $request->get('kw');
// 假设 $user_id 是要查询的用户 ID
// $user = User::find($user['id']); // 查询用户对象
// // 获取该用户的下属团队
// $teamMembers = $user->team()
// ->where('status', 1) // 只查询有效的下属
// ->with('user') // 联合查询 User 模型,获取下属的详细信息
// ->order('depth') // 按照层级深度排序
// ->select();
// foreach ($teamMembers as $member) {
// echo '下属用户ID: ' . $member->descendant_id . ',层级深度: ' . $member->depth . ',状态: ' . $member->status . ',用户名: ' . $member->user->name . ',邮箱: ' . $member->user->email . "\n";
// }
// return $this->success(__('successful'),$result);
// $model = Db::name('user_team')
// ->alias('ut')
// ->join('user wu', 'ut.descendant_id = wu.id')
// ->where('ut.ancestor_id', $user['id'])
// ->where('ut.depth', '<=', 3) // 限制三级内
// ->field('wu.id, wu.username, wu.group, ut.depth')
// ->order('ut.depth ASC, wu.username ASC');
// if($limit == 'all' || $limit >= 999999){
// $result = $model->select();
// }else{
// // 分页处理
// $result = $model->page($page, $limit)->select();
// $total = $model->count(); // 获取总记录数
// $result->each(function ($item) {
// //cache_add('user_recharge_total_'.$item['id'],1);
// //cache_add('user_withdrawl_total_'.$item['id'],1);
// //cache_add('user_income_total_'.$item['id'],1);
// $item['avatar'] = cdnurl($item['avatar'] ?: '/storage/avatar/default.png');
// $item['recharge_total'] = cache('user_recharge_total_'.$item['id']);
// $item['withdrawl_total'] = cache('user_withdrawl_total_'.$item['id']);
// $item['income_total'] = cache('user_income_total_'.$item['id']);
// $item['created_at'] = date('Y-m-d H:i:s', $item['created_at']);
// return $item;
// });
// $result = [
// 'data' => $result,
// 'total' => $total,
// 'current_page' => $page,
// 'last_page' => ceil($total / $limit),
// 'per_page' => $limit,
// ];
// }
$user_id = \support\Jwt\JwtToken::getCurrentId();
$model = UserModel::alias('u')
->where('parent_id',$user_id)
->join('user_extend ue', 'u.id = ue.user_id')
->where('u.parent_id', $user['id'])
//->where('ue.active', 1)
->field('u.id, u.username,u.money,u.score,u.role_id, u.group,u.avatar, u.created_at')
->order('u.created_at desc');
if($kw){
$model = $model->whereLike("u.username",'%'.$kw.'%');
}
if($limit == 'all' || $limit >= 999999){
$result = $model->select();
// $result = [
// 'data' => $result,
// 'total' => count($result),
// 'current_page' => 1,
// 'last_page' => 1,
// 'per_page' => count($result),
// ];
$result= \think\Paginator::make($result, 99999999999, 1, count($result));
}else{
$result = $model->paginate($limit);
}
$role_arr = [
'0' => __('普通用户'),
'1' => __('V1'),
'2' => __('V2'),
'3' => __('V3'),
'4' => __('V4'),
'5' => __('V5'),
];
$result = $result->toArray();
foreach($result['data'] as $k=>$item){
$result['data'][$k]['avatar'] = cdnurl($item['avatar'] ?: '/storage/avatar/default.png');
$result['data'][$k]['recharge_total'] = cache('user_recharge_total_'.$item['id'])??0;
$result['data'][$k]['withdrawl_total'] = cache('user_withdrawl_total_'.$item['id'])??0;
$result['data'][$k]['withdrawl_reward'] = cache('user_withdrawl_reward_'.$item['id'])??0;
$result['data'][$k]['income_total'] = cache('user_income_total_'.$item['id'])??0;
$result['data'][$k]['consume_total'] = cache('user_consume_total_'.$item['id'])??0;
$result['data'][$k]['play_count'] = cache('user_play_count_'.$item['id'])??0;
//$result['data'][$k]['created_at'] = date('Y-m-d H:i:s', $item['created_at']);
$result['data'][$k]['total_count'] = UserTeamModel::where('ancestor_id',$item['id'])->where('status',1)->where('depth','>',0)->count('descendant_id');
$result['data'][$k]['direct_total'] = cache('team_direct_total_'.$item['id'])??0;
$performance = get_performance($item['id']);
$result['data'][$k]['performance_large'] = $performance[0];
$result['data'][$k]['performance_small'] = $performance[1];
$result['data'][$k]['role'] = isset($role_arr[$item['role_id']]) ? $role_arr[$item['role_id']] : __('普通用户');
$result['data'][$k]['level'] = get_user_level($item['id'],$item['performance_small']);
$result['data'][$k]['questionnaire_count'] = WorkRecordModel::where('user_id',$item['id'])->count('id');
$result['data'][$k]['id'] = idEncode($item['id']);
//return $item;
}
return $this->success(__('successful'),$result);
}
/**
* @Apidoc\Title("改变用户等级")
* @Apidoc\Method("POST")
* @Apidoc\Param("id", type="string",require=false, desc="ID")
* @Apidoc\Param("level", type="int",require=false, desc="等级")
*/
function changelevel(Request $request){
$user = \support\Jwt::getUser();
$id = $request->post('id');
$level = $request->post('level');
$id = idDecode($id);
if(!$id || !$level){
return $this->error(__('Invalid parameters'));
}
$child_user = UserModel::find($id);
if(!$child_user){
return $this->error(__('Invalid user'));
}
if($child_user->parent_id!=$user->id){
return $this->error(__('Access denied'));
}
if($user->role_id <= $level){
return $this->error(__('It cannot be lower than the user\'s current level'));
}
if($child_user->role_id >= $level){
return $this->error(__('It cannot be lower than the user\'s current level'));
}
$child_user->role_id = $level;
$child_user->save();
return $this->success(__('successful'));
}
}
+181
View File
@@ -0,0 +1,181 @@
<?php
namespace app\api\controller;
use Shopwwi\WebmanFilesystem\FilesystemFactory;
use Shopwwi\WebmanFilesystem\Facade\Storage;
use app\model\User as UserModel;
use app\model\Realname as RealnameModel;
use support\Request;
use taoser\facade\Validate;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 用户相关
*/
class UserController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* @Apidoc\Title("个人资料")
* @Apidoc\Method("GET")
* @Apidoc\Desc("GET为获取用户信息,POST为修改数据")
* @Apidoc\Param("nickname", type="string",require=true, desc="昵称")
*/
public function profile(){
$data = \support\Jwt::getUser();
if(Request()->method() == 'POST'){
$nickname = input('nickname');
//$username = input('username');
//$password = input('password');
if(!$nickname){
return $this->error('Invalid nickname');
}
\support\Jwt::getUser()->save([
'nickname' => $nickname,
]);
return $this->success(__('successful'));
}
$data= Hook('user.profile',$data);
return $this->success(__('successful'),$data[0]);
}
/**
* @Apidoc\Title("修改密码")
* @Apidoc\Method("POST")
* @Apidoc\Param("password", type="string",require=true, desc="旧密码")
* @Apidoc\Param("newpassword", type="string",require=true, desc="新密码")
* @Apidoc\Param("renewpassword", type="string",require=true, desc="新密码")
*/
public function change_password(){
$password = input('password');
$newpassword = input('newpassword');
$renewpassword = input('renewpassword');
if (!$password || !$newpassword || !$renewpassword) {
return $this->error(__('Invalid parameters'));
}
if ($newpassword !== $renewpassword) {
return $this->error(__('Invalid parameters'));
}
try{
\support\Jwt::changepwd($newpassword,$password);
return $this->success(__('Reset password successful'));
} catch (\Throwable $e) {
return $this->error($e->getMessage());
}
}
/**
* 修改交易密码
* @Apidoc\Method("POST")
* @Apidoc\Param("password", type="string",require=true, desc="旧密码(新设时可用为空)")
* @Apidoc\Param("newpassword", type="string",require=true, desc="新密码")
* @Apidoc\Param("renewpassword", type="string",require=true, desc="新密码")
*/
public function change_trade_password(){
$password = input('password');
$newpassword = input('newpassword');
$renewpassword = input('renewpassword');
if (!$newpassword || !$renewpassword || $newpassword !== $renewpassword) {
return $this->error(__('Invalid parameters'));
}
try{
\support\Jwt::change_trade_pwd($newpassword,$password);
return $this->success(__('Reset trade password successful'));
} catch (\Throwable $e) {
return $this->error($e->getMessage());
}
}
/**
* 根据关键字查询用户列表
* @Apidoc\Method("POST")
* @Apidoc\Param("kw", type="string",require=true, desc="关键字")
*/
function getuserlist(){
$kw = Input('kw');
$user_id = \support\Jwt\JwtToken::getCurrentId();
$list = [];
if($kw){
//$list = User::where('id','<>',\support\Jwt\JwtToken::getCurrentId())->whereLike('nickname|username|email','%'.$kw.'%')->limit(0,10)->order('id asc')->field('id,username')->select();
//$list = User::where('id','<>',\support\Jwt\JwtToken::getCurrentId())->whereLike('username','%'.$kw.'%')->limit(0,10)->order('id asc')->field('id,username,username as name')->select();
$list = UserModel::whereLike('username','%'.$kw.'%')->where('id','<>',$user_id)->limit(0,10)->order('id asc')->field('id,username,username as name')->select();
// foreach($list as $k=>$v){
// }
}
return $this->success(__('successful'),$list);
}
/**
* 头像上传
* @Apidoc\Method("POST")
* @Apidoc\Param("file", type="File", require=true, desc="文件")
*/
public function avatar(Request $request)
{
//单文件上传
$file = $request->file('file0');
try {
$result = Storage::adapter('public')->path('upload/avatar')->size(1024*1024*5)->extYes(['image/jpeg','image/png'])->processUpload($file,function ($image){
$image->resize(200,200);
return $image;
},true);
\support\Jwt::getUser()->save([
'avatar' => '/'.$result->file_name,
]);
//$result->ss = cdnurl($result->url);
//P($result);
return $this->success(__('successful'),$result);
}catch (\Exception $e){
return $this->error($e->getMessage());
}
}
function realname(Request $request){
/**
* @var UserModel $user
*/
$user = \support\Jwt::getUser();
if($request->method() == 'POST'){
$data = [
'realname' => Input('realname'),
'idcard' => Input('idcard'),
'user_id' => $user->id,
];
log_alert($data);
if(!$data['realname'] || !$data['idcard']){
return $this->error(__('Incoret param'));
}
if($user->realname_verify == 1){
return $this->error(__('You have verified'));
}
if(RealnameModel::where('idcard',$data['idcard'])->where('user_id','<>',$user->id)->count()){
return $this->error(__('ID card already exists'));
}
Db::startTrans();
try {
RealnameModel::create($data);
$user->realname_verify = 1;
$user->save();
if($user->parent_id && cache('invite_'.$user->parent_id.'_'.date('Ymd')) < 1){
\app\model\User::currency1($user->parent_id,40,\app\enum\BalanceType::INVITE_NEW_USER);
cache('invite_'.$user->parent_id.'_'.date('Ymd'),1);
}
Db::commit();
return $this->success('ok',$user);
} catch (\Exception $e) {
Db::rollback();
return $this->error(__($e->getMessage()));
}
}else{
$user->realname = RealnameModel::where('user_id',$user->id)->find();
return $this->success('ok',$user);
}
}
}
+163
View File
@@ -0,0 +1,163 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use hg\apidoc\annotation as Apidoc;
/**
* 验证接口
*/
class ValidateController extends BaseController
{
public $noNeedLogin = '*';
/**
* 检测邮箱是否可用
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("id", type="string",require=true, desc="排除会员ID")
*/
public function check_email_available()
{
$email = input('email');
$id = (int)input('id');
$count = UserModel::where('email', '=', $email)->where('id', '<>', $id)->count();
if ($count > 0) {
return $this->error(__('The mailbox is already occupied'));
}
return $this->success(__('successful'));
}
/**
* 检测用户名
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("username", type="string",require=true, desc="用户名")
* @Apidoc\Param("id", type="string",require=true, desc="排除会员ID")
*/
public function check_username_available()
{
$username = input('username');
$id = (int)input('id');
$count = UserModel::where('username', '=', $username)->where('id', '<>', $id)->count();
if ($count > 0) {
return $this->error(__('Username is already taken'));
}
return $this->success(__('successful'));
}
/**
* 检测昵称
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("nickname", type="string",require=true, desc="昵称")
* @Apidoc\Param("id", type="string",require=true, desc="排除会员ID")
*/
public function check_nickname_available()
{
$nickname = input('nickname');
$id = (int)input('id');
$count = UserModel::where('nickname', '=', $nickname)->where('id', '<>', $id)->count();
if ($count > 0) {
return $this->error(__('Nickname is already taken'));
}
return $this->success(__('successful'));
}
/**
* 检测手机
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("mobile", type="string",require=true, desc="手机号")
* @Apidoc\Param("id", type="string",require=true, desc="排除会员ID")
*/
public function check_mobile_available()
{
$mobile = input('mobile');
$id = (int)input('id');
$count = UserModel::where('mobile', '=', $mobile)->where('id', '<>', $id)->count();
if ($count > 0) {
return $this->error(__('Phone Number is already taken'));
}
return $this->success(__('successful'));
}
/**
* 检测手机是否存在
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("mobile", type="string",require=true, desc="手机号")
*/
public function check_mobile_exist()
{
$mobile = input('mobile');
$count = UserModel::where('mobile', '=', $mobile)->count();
if (!$count) {
return $this->error(__('Mobile number does not exist'));
}
return $this->success(__('successful'));
}
/**
* 检测邮箱是否存在
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
*/
public function check_email_exist()
{
$email = input('email');
$count = UserModel::where('email', '=', $email)->count();
if (!$count) {
return $this->error(__('Email does not exist'));
}
return $this->success(__('successful'));
}
/**
* 检测手机验证码(弃用)
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("mobile", type="string",require=true, desc="手机号")
* @Apidoc\Param("code", type="string",require=true, desc="验证码")
* @Apidoc\Param("event", type="string",require=true, desc="事件")
*/
protected function check_sms_correct()
{
$mobile = input('mobile');
$captcha = input('captcha');
$event = input('event');
// if (!\app\common\library\Sms::check($mobile, $captcha, $event)) {
// $this->error(__('Incorrect verification code'));
// }
return $this->success(__('successful'));
}
/**
* 检测邮箱验证码
*
* @Apidoc\Method ("POST")
* @Apidoc\Param("email", type="string",require=true, desc="邮箱")
* @Apidoc\Param("code", type="string",require=true, desc="验证码")
* @Apidoc\Param("event", type="string",require=true, desc="事件")
*/
public function check_ems_correct()
{
$email = input('email');
$captcha = input('code');
$event = input('event');
$cache_key = 'captcha_'.$event.'_'.$email;
$list = cache($cache_key);
$list = $list?:[];
if(!isset($list[$captcha])){
return $this->error(__('Incorrect verification code'));
}
if($list[$captcha]+5*60 >= time()){
unset($list[$captcha]);
cache($cache_key,$list);
return $this->error(__('Verification code has expired'));
}
return $this->success(__('successful'));
}
}
+227
View File
@@ -0,0 +1,227 @@
<?php
namespace app\api\controller;
use app\model\User as UserModel;
use support\Request;
use app\model\Cdkey as CdkeyModel;
use taoser\facade\Validate;
use support\think\Db;
use hg\apidoc\annotation as Apidoc;
/**
* 钱包接口
*/
class WalletController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = [];
/**
* 用户调研币兑换问卷指标
* @Apidoc\Method("POST")
* @Apidoc\Param("currency", type="string",require=true, desc="货币money_to_score")
* @Apidoc\Param("sendAmount", type="string",require=true, desc="调研币兑换数量")
* @Apidoc\Param("receiveAmount", type="string",require=true, desc="问卷指标兑换数量")
* @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码")
* @Apidoc\Param("code", type="string",require=true, desc="图形验证码(event=exchange)")
*/
public function exchange(){
//return $this->error(__('The system is under maintenance, please wait...'));
$user = \support\Jwt\JwtToken::getUser();
// if(Config('site.trade_password_type') == 'email'){
// captcha_verfiy('email','exchange',$user['username']);
// }else{
// $trade_password = input('trade_password');
// \support\Jwt::verify_trade_password($trade_password);
// }
$currency_pair = input('currency');
$currencys = explode('_to_', $currency_pair);
$from_currency = $currencys[0];
$to_currency = $currencys[1];
if(!$from_currency || !$to_currency){
return $this->error(__('Invalid parameters'));
}
$sendAmount = (float)input('sendAmount');
$receiveAmount = (float)input('receiveAmount');
$rate = Config('site.'.$currency_pair.'_rate');
if(!$sendAmount || !$receiveAmount || !$rate){
return $this->error(__('Invalid parameters'));
}
$_receiveAmount = intval($sendAmount / $rate);
$_sendAmount = $_receiveAmount * $rate;
if($sendAmount > $user->$from_currency || $receiveAmount <= 0){
return $this->error(__('Invalid parameters').$sendAmount .'<' .$user->$from_currency .'||'. $receiveAmount);
}
Db::startTrans();
try{
UserModel::$from_currency($user->id,-$_sendAmount,\app\enum\BalanceType::EXCHANGE);
UserModel::$to_currency($user->id,$_receiveAmount,\app\enum\BalanceType::EXCHANGE);
Db::commit();
return $this->success(__('Exchange successful'));
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
}
/**
* 用户间score转账
* @Apidoc\Method("POST")
* @Apidoc\Param("username", type="string",require=true, desc="收款用户/用户ID")
* @Apidoc\Param("amount", type="string",require=true, desc="金额")
* @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码")
* @Apidoc\Param("code", type="string",require=true, desc="图形验证码(event=transfer)")
*/
public function transfer(){
//return $this->error(__('The system is under maintenance, please wait...'));
$user = \support\Jwt::getUser();
$username = input('username');
if(!$username){
return $this->error(__('User is incorrect'));
}
/** @var UserModel $to_user */
if(str_contains($username,'@')){
$to_user = UserModel::where('username',$username)->find();
}else{
$to_user_id = idDecode($username);
$to_user = UserModel::where('id',$to_user_id)->find();
}
if(!$to_user){
return $this->error(__('User is incorrect'));
}
if(Config('site.trade_password_type') == 'email'){
//captcha_verfiy('email','transfer',$to_user['username']);
}else{
$trade_password = input('trade_password');
\support\Jwt::verify_trade_password($trade_password);
}
$amount = (float)input('amount');
if($amount <= 0){
return $this->error(__('Invalid parameters'));
}
if($user->score < $amount){
return $this->error(__('Insufficient balance'));
}
Db::startTrans();
try{
UserModel::score($user->id,-$amount,\app\enum\BalanceType::TRANSFER,$to_user->id);
UserModel::score($to_user->id,$amount,\app\enum\BalanceType::TRANSFER,$user->id);
Db::commit();
return $this->success(__('Transfer successful'));
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
}
/**
* 根据关键字查询用户列表
* @Apidoc\Method("POST")
* @Apidoc\Param("kw", type="string",require=true, desc="关键字")
*/
function getuserlist(){
$kw = Input('kw');
$user_id = \support\Jwt\JwtToken::getCurrentId();
$list = [];
if($kw){
//$list = User::where('id','<>',\support\Jwt\JwtToken::getCurrentId())->whereLike('nickname|username|email','%'.$kw.'%')->limit(0,10)->order('id asc')->field('id,username')->select();
//$list = User::where('id','<>',\support\Jwt\JwtToken::getCurrentId())->whereLike('username','%'.$kw.'%')->limit(0,10)->order('id asc')->field('id,username,username as name')->select();
$list = UserModel::whereLike('username','%'.$kw.'%')->where('id','<>',$user_id)->limit(0,10)->order('id asc')->field('id,username,username as name')->select();
// foreach($list as $k=>$v){
// }
}
return $this->success(__('successful'),$list);
}
/**
* 本地cdkey兑换
* @Apidoc\Method("POST")
* @Apidoc\Param("cdkey", type="string",require=true, desc="cdkey")
* @Apidoc\Param("trade_password", type="string",require=true, desc="交易密码")
* @Apidoc\Param("code", type="string",require=true, desc="图形验证码(event=cdkeyExchange)")
*/
public function cdkeyExchange_local_cdkey(){
//return $this->error(__('The system is under maintenance, please wait...'));
$user = \support\Jwt\JwtToken::getUser();
// if(Config('site.trade_password_type') == 'email'){
// captcha_verfiy('email','exchange',$user['username']);
// }else{
// $trade_password = input('trade_password');
// \support\Jwt::verify_trade_password($trade_password);
// }
$cdkey = input('cdkey');
/** @var CdkeyModel $Cdkey */
$Cdkey = CdkeyModel::where('account',$cdkey)->lock(true)->where('is_used',0)->find();
if(!$Cdkey){
return $this->error(__('卡密不存在'));
}
if($Cdkey['type'] == 3){
//不能使用续费激活码
return $this->error(__('卡密不存在'));
}
Db::startTrans();
try{
CdkeyModel::where('id',$Cdkey->id)->save([
'record_id' => $user->id,
'is_used' => 1,
'use_time' => time(),
]);
UserModel::score($user->id,$Cdkey->days,\app\enum\BalanceType::RECHARGE_CARD);
Db::commit();
return $this->success(__('Exchange successful'));
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
}
/**
* cdkey兑换
* @Apidoc\Method("POST")
* @Apidoc\Param("card_number", type="string",require=true, desc="卡号")
* @Apidoc\Param("password", type="string",require=true, desc="密码")
*/
function cdkey_exchange(){
$user = \support\Jwt\JwtToken::getUser();
$domain = 'http://127.0.0.1:8383';
$data=[
'user_id' => \support\Jwt\JwtToken::getCurrentId(),
'card_number'=> input('card_number'),
'password'=> input('password'),
];
$activeData = [
'app_id' => 8,
'card_number' => $data['card_number'],
'password' => $data['password'],
'type' => 'recharge',
'record_id' => $user->id
];
$remoteResponse = post($domain.'/api/cdkey/redeem',$activeData);
\support\Log::info($remoteResponse);
try{
$remoteResponse = json_decode($remoteResponse,true);
}catch(\Exception $e){
return $this->error($e->getMessage());
}
if($remoteResponse['code'] !== 0){
\support\Log::info(json_encode($remoteResponse));
return $this->error($remoteResponse['msg']);
}
if($remoteResponse['data']['days']){
UserModel::money($user->id,$remoteResponse['data']['days'],\app\enum\BalanceType::RECHARGE_CARD);
return $this->success(__('Exchange successful'));
}
return $this->error($remoteResponse['msg'],$remoteResponse);
}
}
+186
View File
@@ -0,0 +1,186 @@
<?php
namespace app\api\controller;
use app\model\Address as AddressModel;
use app\model\User as UserModel;
use app\model\Withdrawl as WithdrawlModel;
use support\Request;
use support\think\Db;
use taoser\facade\Validate;
use hg\apidoc\annotation as Apidoc;
/**
* 提现模块
*/
class WithdrawlController extends BaseController{
/**
* 不需要鉴权的方法
* @var array
*/
public $noNeedAuth = ['*'];
/**
* 无需登录及鉴权的方法
* @var array
*/
public $noNeedLogin = ['notify','notify1','recent'];
/**
* 列表
* @Apidoc\Method("GET")
* @Apidoc\Query("status", type="int", require=false, desc="状态")
* @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
* @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
*/
public function list()
{
$limit = (int)input('limit',10);
$status = input('status','all');
$model = WithdrawlModel::where('user_id',\support\Jwt\JwtToken::getCurrentId())
->order('id desc');
if($status!='all'){
$model = $model->where('status',$status);
}
$list = $model->paginate($limit);
return $this->success(__('successful'),$list->toArray());
}
/**
* 最近提现
* @Apidoc\Method("GET")
*/
public function recent()
{
$list = WithdrawlModel::with(['user'])->
where('status',\app\enum\WithdrawlStatus::COMPLETE->value)->
order('id desc')->
limit(10)->select();
$list->each(function($item){
$item->user = UserModel::field('username,email')->where('id',$item->user_id)->find();
});
return $this->success(__('successful'),$list->toArray());
}
/**
* 创建
* @Apidoc\Method("POST")
* @Apidoc\Param("amount", type="string", require=true, desc="金额")
* @Apidoc\Param("address_id", type="string", require=true, desc="地址ID,列表选择")
* @Apidoc\Param("trade_password", type="string", require=true, desc="交易密码")
*/
public function create()
{
//return $this->error(__('The system is under maintenance, please wait...'));
//* @Apidoc\Param("code", type="string", require=true, desc="图形验证码(type=withdrawl)")
//captcha_verfiy('image','withdrawl');
$address_id = input('address_id');
if(!$address_id){
return $this->error(__('Address is incorrect'));
}
/** @var AddressModel $address */
$address = AddressModel::where('id',$address_id)->find();
if(!$address){
return $this->error(__('Address is incorrect'));
}
// if(!$address->status){
// return $this->error(__('Unverified address'));
// }
$user = \support\Jwt::getUser();
if(Config('site.trade_password_type') == 'email'){
captcha_verfiy('email','withdrawl',$user['username']);
}else{
//验证交易密码
$trade_password = input('trade_password');
\support\Jwt::verify_trade_password($trade_password);
}
$deduction_amount = input('amount',0);
$fee = config('site.withdrawl_fee')[$address['network']];
if($fee < 0.5){
$fee = bcmul( $fee , $deduction_amount,2);
}
$data = [
'user_id' => \support\Jwt\JwtToken::getCurrentId(),
'deduction_amount' => $deduction_amount,
'title' => $address['title'],
'network' => $address['network'],
'address' => $address['address'],
'fee' => $fee,
'type' => 0,
'status' => \app\enum\WithdrawlStatus::CREATED->value
];
//验证最小提现金额
$data['recive_amount'] = $data['deduction_amount'] - $data['fee'];
$withdrawl_minimum = Config('site.withdrawl_minimum')[$data['network']];
if($data['deduction_amount'] < $withdrawl_minimum){
return $this->error(__('Minimum withdrawal of %num%',[
'%num%' => $withdrawl_minimum
]));
}
//var_dump($user);
//验证余额
if($data['deduction_amount'] > $user->money){
return $this->error(__('The amount exceeds the available balance'));
}
//if(WithdrawlModel::whereTime('created_at','-24 hours')->count('id')){
if(WithdrawlModel::whereTime('created_at','today')->where('user_id',$data['user_id'])->count('id')){
return $this->error(__('You can only withdraw once a day.'));
}
if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20','ALIPAY','WECHAT'])) {
return $this->error(__('Network is incorrect'));
}
if (!$data['address']) {
return $this->error(__('Address is incorrect'));
}
Db::startTrans();
try{
/** @var WithdrawlModel $data */
$data = WithdrawlModel::create($data);
UserModel::money($data->user_id,-$data->deduction_amount,\app\enum\BalanceType::WITHDRAWAL,$data->id);
Db::commit();
return $this->success(__('successful'),$data);
}catch(\Exception $e){
Db::rollback();
return $this->error($e->getMessage());
}
}
/**
* 详情
* @Apidoc\Query("id", type="string", require=true, desc="ID")
*/
public function detail(){
$appid = input('id');
$vo = WithdrawlModel::where('id',$appid)->find();
if($vo) {
return $this->success(__('successful'),$vo->toArray());
}else{
return $this->error(__("Record does not exist"));
}
}
/**
* 转账成功异步通知
* @Apidoc\NotParse()
* @Apidoc\NotDebug()
*/
public function notify(){
$data = aesdecode(input('data',''));
$data = json_decode($data,true);
/** @var WithdrawlModel $vo */
$vo = WithdrawlModel::where('id',$data['out_trade_no'])->find();
if($vo){
if($data['result'] == 'SUCCESS'){
if($vo->status != \app\enum\WithdrawlStatus::COMPLETE->value){
$vo->status = \app\enum\WithdrawlStatus::COMPLETE->value;
$vo->txid = $data['txid'];
$vo->transfer_at = $data['transfer_at'] ?: time();
$vo->save();
Hook('withdrawl.success',$vo);
}
}else{
$vo->status = \app\enum\WithdrawlStatus::FAIL->value;
$vo->txid = $data['txid'];
$vo->memo = $data['reason'];
$vo->save();
}
}
return response("SUCCESS");
}
}
+150
View File
@@ -0,0 +1,150 @@
<?php
namespace app\api\middleware;
use ReflectionException;
use support\exception\BusinessException;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;
use support\Container;
class Auth implements MiddlewareInterface
{
/**
* @param Request $request
* @param callable $handler
* @return Response
* @throws ReflectionException|BusinessException
*/
public function process(Request $request, callable $next): Response
{
if($request->method() == 'OPTIONS'){
$headers = [
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => $request->header('origin', '*'),
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
];
$response = response('200',200,$headers);
return $response;
}
$lang = $request->input('lang','zh-Hans');
locale($lang);
if ($request->controller) {
$request->client = $request->header('client',"web");
// if($request->client=='win' && $request->header('version') < 2.06){
// abort('旧版本不能再使用,请更新到最新版本', 603);
// }
//跨域请求检测
//check_cors_request();
// 检测IP是否允许
//check_ip_allowed();
$request->start_time = microtime();
$controller = Container::get($request->controller);
// 检测是否需要验证登录
if (!\support\Jwt::match($controller->noNeedLogin)) {
//检测是否登录
try {
if (!\support\Jwt::isLogin()) {
return json([
"code"=>401,
"data"=>[],
"msg"=>__('Please login first')
]);
}
} catch (\Exception $e) {
return json([
"code"=>401,
"data"=>[],
"msg"=>__('Please login first')
]);
}
$user = \support\Jwt\JwtToken::getUser();
if(!$user['status']){
return json([
"code"=>403,
"data"=>[],
"msg"=>__('Account is locked')
]);
}
// $key = "debounce_" . $request->path() . "_" . ($user->id ?? 'guest');
// $ttl = 1; // 防抖时间(秒)
// $redishandler = new \Redis;
// $redishandler->connect(
// \support\Env::get('host'),
// (int) \support\Env::get('port'),
// (int) \support\Env::get('timeout'));
// $redishandler->select(12);
// if ($redishandler->setnx($key, 1)) {
// $redishandler->expire($key, $ttl);
// }else{
// return new Response(429,[],__('Too frequent operation'));
// }
// 判断是否需要验证权限
if (!\support\Jwt::match($controller->noNeedAuth)) {
// 判断控制器和方法判断是否有对应权限
$controllername = get_controller_name();
$actionname = strtolower(get_action_name());
$path = str_replace('.', '/', $controllername) . '/' . $actionname;
if (!\support\Jwt::check($path)) {
return json([
"code"=>405,
"data"=>[],
"msg"=>__('You have no permission')
]);
}
}
}
if($request->client!='web'){
$data = $request->post('data');
if($data){
$data = str_replace('%3D','=',$data);
$data = str_replace(' ','+',$data);
//var_dump($data);
$data = aesdecode($data);
$data = json_decode($data,true);
//var_dump($data);
$request->withBody($data);
}
}
$config = Config('site');
$config['debug'] = config('app.debug');
$config['controller'] = $request->controller_name;
$config['action'] = $request->action_name;
$request->_view_vars = array_merge((array) $request->_view_vars,[
'user' => session('admin'),
'config' => $config
]);
$response = $next($request);
$headers = [
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => $request->header('origin', '*'),
'Access-Control-Allow-Methods' => $request->header('access-control-request-method', '*'),
'Access-Control-Allow-Headers' => $request->header('access-control-request-headers', '*'),
];
$response->withHeaders($headers);
//cp('auth');
//\support\Log::alert('auth');
$body = str_replace([
'__SELF__'
],[
request()->path()
],$response->rawBody());
if($request->app=="api" && $request->client!='web'){
$body = aesencode($body);
}
$response->withBody($body)->getStatusCode();
$time = microtime() - $request->start_time;
//echo("响应时间:".$request->uri().':'.$time.PHP_EOL);
//$response = $next($request);
//\support\Log::error($response->rawBody());
return $response;
}
return $next($request);
}
}