改进 扣费
This commit is contained in:
parent
373ca437b9
commit
5a1356e26f
@ -22,7 +22,7 @@ protected function schedule(Schedule $schedule)
|
|||||||
|
|
||||||
// dispatch HostCost job
|
// dispatch HostCost job
|
||||||
$schedule->job(new HostCost())->everyFiveMinutes();
|
$schedule->job(new HostCost())->everyFiveMinutes();
|
||||||
$schedule->job(new UserSave())->everyTenMinutes();
|
// $schedule->job(new UserSave())->everyTenMinutes();
|
||||||
$schedule->job(new Remote\FetchModule())->everyMinute()->onOneServer();
|
$schedule->job(new Remote\FetchModule())->everyMinute()->onOneServer();
|
||||||
$schedule->job(new Remote\PushHost())->everyMinute()->onOneServer();
|
$schedule->job(new Remote\PushHost())->everyMinute()->onOneServer();
|
||||||
$schedule->job(new Remote\PushWorkOrder())->everyMinute()->onOneServer();
|
$schedule->job(new Remote\PushWorkOrder())->everyMinute()->onOneServer();
|
||||||
|
10
app/Exceptions/User/BalanceNotEnoughException.php
Normal file
10
app/Exceptions/User/BalanceNotEnoughException.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions\User;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class BalanceNotEnoughException extends Exception
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
54
app/Http/Controllers/User/BalanceController.php
Normal file
54
app/Http/Controllers/User/BalanceController.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\User;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class BalanceController extends Controller
|
||||||
|
{
|
||||||
|
//
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
$balance = $request->user();
|
||||||
|
return $this->success($balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
// 充值
|
||||||
|
$request->validate([
|
||||||
|
'amount' => 'required|numeric',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$balance = $request->user();
|
||||||
|
|
||||||
|
// 启用事物
|
||||||
|
\DB::beginTransaction();
|
||||||
|
try {
|
||||||
|
$balance->increment('amount', $request->amount);
|
||||||
|
\DB::commit();
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\DB::rollBack();
|
||||||
|
return $this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->success($balance);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// // 转换为 drops
|
||||||
|
// public function transfer($amount = 1)
|
||||||
|
// {
|
||||||
|
// $balance = auth('sanctum')->user();
|
||||||
|
// $balance->decrement('amount', $request->amount);
|
||||||
|
// return $this->success($balance);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
19
app/Http/Controllers/UserController.php
Normal file
19
app/Http/Controllers/UserController.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use Cache;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class UserController extends Controller
|
||||||
|
{
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$user = $request->user();
|
||||||
|
|
||||||
|
$user['drops'] = (float) Cache::get('user_drops_' . $user['id'], 0);
|
||||||
|
|
||||||
|
return $this->success($user);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@
|
|||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Log;
|
||||||
|
|
||||||
class UserSave implements ShouldQueue
|
class UserSave implements ShouldQueue
|
||||||
{
|
{
|
||||||
@ -34,7 +35,11 @@ public function __construct()
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
Host::active()->chunk(100, function ($hosts) {
|
|
||||||
|
// 弃用
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Host::all()->chunk(100, function ($hosts) {
|
||||||
foreach ($hosts as $host) {
|
foreach ($hosts as $host) {
|
||||||
$this->cache_key = 'user_' . $host->user_id;
|
$this->cache_key = 'user_' . $host->user_id;
|
||||||
|
|
||||||
@ -43,11 +48,18 @@ public function handle()
|
|||||||
if (Cache::has($this->cache_key)) {
|
if (Cache::has($this->cache_key)) {
|
||||||
// if user is not instances of Model
|
// if user is not instances of Model
|
||||||
$user = Cache::get($this->cache_key);
|
$user = Cache::get($this->cache_key);
|
||||||
|
|
||||||
|
Log::debug($user);
|
||||||
|
|
||||||
|
|
||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
$this->await($this->cache_key, function () use ($user, $host) {
|
$this->await($this->cache_key, function () use ($user) {
|
||||||
$user->save();
|
$user->save();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// save cache
|
||||||
|
$this->cache->put($this->cache_key, $host->user, now()->addDay());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Log;
|
||||||
use App\Models\Module\Module;
|
use App\Models\Module\Module;
|
||||||
use App\Exceptions\CommonException;
|
use App\Exceptions\CommonException;
|
||||||
use App\Models\WorkOrder\WorkOrder;
|
use App\Models\WorkOrder\WorkOrder;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
// use Illuminate\Database\Eloquent\SoftDeletes;
|
// use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Exceptions\User\BalanceNotEnoughException;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
class Host extends Model
|
class Host extends Model
|
||||||
@ -77,21 +79,26 @@ public function scopeThisUser($query, $module = null)
|
|||||||
public function cost($price = null)
|
public function cost($price = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
$cache_key = 'user_' . $this->user_id;
|
$this->load('user');
|
||||||
|
|
||||||
// if cache has user
|
|
||||||
|
|
||||||
if (Cache::has($cache_key)) {
|
if ($this->user->balance < 10) {
|
||||||
// if user is not instances of Model
|
$amount = 1;
|
||||||
$user = Cache::get($cache_key);
|
} else if ($this->user->balance < 100) {
|
||||||
|
$amount = 10;
|
||||||
if (!($user instanceof User)) {
|
} else if ($this->user->balance < 1000) {
|
||||||
$user = Cache::put($cache_key, $this->user, now()->addDay());
|
$amount = 100;
|
||||||
}
|
} else if ($this->user->balance < 10000) {
|
||||||
|
$amount = 1000;
|
||||||
} else {
|
} else {
|
||||||
$user = Cache::put($cache_key, $this->user, now()->addDay());
|
$amount = 10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$cache_key = 'user_drops_' . $this->user_id;
|
||||||
|
|
||||||
|
$drops = Cache::get($cache_key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Log::debug($user);
|
// Log::debug($user);
|
||||||
|
|
||||||
@ -103,24 +110,25 @@ public function cost($price = null)
|
|||||||
$this->price = $this->managed_price;
|
$this->price = $this->managed_price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if drops <= price
|
||||||
|
if ($drops < $this->price) {
|
||||||
|
try {
|
||||||
|
$this->user->toDrops($amount);
|
||||||
|
} catch (BalanceNotEnoughException) {
|
||||||
|
$this->update([
|
||||||
|
'status' => 'suspended',
|
||||||
|
]);
|
||||||
|
|
||||||
$user->drops -= (int) $this->price;
|
return false;
|
||||||
|
}
|
||||||
// update cache
|
|
||||||
Cache::put($cache_key, $user, now()->addDay());
|
|
||||||
|
|
||||||
|
|
||||||
// if $user->drops <= 0
|
|
||||||
if ($user->drops <= 0) {
|
|
||||||
$this->update([
|
|
||||||
'status' => 'suspended',
|
|
||||||
]);
|
|
||||||
} else if ($this->status == 'suspended') {
|
} else if ($this->status == 'suspended') {
|
||||||
$this->update([
|
$this->update([
|
||||||
'status' => 'running',
|
'status' => 'stopped',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cache::decrement($cache_key, $this->price);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,14 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
use App\Exceptions\CommonException;
|
||||||
|
use App\Exceptions\User\BalanceNotEnoughException;
|
||||||
|
use Illuminate\Support\Facades\Cache;
|
||||||
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Illuminate\Contracts\Cache\LockTimeoutException;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
@ -40,5 +44,38 @@ class User extends Authenticatable
|
|||||||
*/
|
*/
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
|
'balance' => 'float',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
public function toDrops($amount = 1)
|
||||||
|
{
|
||||||
|
$rate = Cache::get('drops_rate', 100);
|
||||||
|
$total = $amount * $rate;
|
||||||
|
|
||||||
|
$cache_key = 'user_drops_' . $this->id;
|
||||||
|
|
||||||
|
$lock = Cache::lock("lock_" . $cache_key, 5);
|
||||||
|
try {
|
||||||
|
$lock->block(5);
|
||||||
|
|
||||||
|
// if user balance <= 0
|
||||||
|
if ($this->balance < $amount) {
|
||||||
|
throw new BalanceNotEnoughException('余额不足');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->balance -= $amount;
|
||||||
|
$this->save();
|
||||||
|
|
||||||
|
// increment user drops
|
||||||
|
Cache::increment($cache_key, $total);
|
||||||
|
|
||||||
|
} catch (LockTimeoutException) {
|
||||||
|
throw new CommonException('暂时无法处理此请求,请稍后再试。');
|
||||||
|
} finally {
|
||||||
|
optional($lock)->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,23 @@ public static function boot()
|
|||||||
|
|
||||||
$rate = Cache::get('drops_rate', 100);
|
$rate = Cache::get('drops_rate', 100);
|
||||||
$drops->total = $drops->amount * $rate;
|
$drops->total = $drops->amount * $rate;
|
||||||
|
|
||||||
|
$this->cache_key = 'user_' . $drops->user_id;
|
||||||
|
|
||||||
|
// if cache has user
|
||||||
|
|
||||||
|
// if (Cache::has($this->cache_key)) {
|
||||||
|
// // if user is not instances of Model
|
||||||
|
// $user = Cache::get($this->cache_key);
|
||||||
|
// if ($user instanceof User) {
|
||||||
|
// $this->await($this->cache_key, function () use ($user) {
|
||||||
|
// $user->save();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // delete cache
|
||||||
|
// Cache::forget($this->cache_key);
|
||||||
|
// }
|
||||||
});
|
});
|
||||||
|
|
||||||
// created
|
// created
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
$table->decimal('balance', 10, 2)->default(0)->after('password');
|
||||||
|
|
||||||
|
// drop column if exists
|
||||||
|
if (Schema::hasColumn('users', 'drops')) {
|
||||||
|
$table->dropColumn('drops');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
$table->dropColumn('balance');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -4,7 +4,7 @@
|
|||||||
use App\Http\Controllers\User\DropController;
|
use App\Http\Controllers\User\DropController;
|
||||||
use App\Http\Controllers\User\TaskController;
|
use App\Http\Controllers\User\TaskController;
|
||||||
use App\Http\Controllers\Remote\ModuleController;
|
use App\Http\Controllers\Remote\ModuleController;
|
||||||
use App\Http\Controllers\Admin\User\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
use App\Http\Controllers\User\WorkOrder\ReplyController;
|
use App\Http\Controllers\User\WorkOrder\ReplyController;
|
||||||
use App\Http\Controllers\User\WorkOrder\WorkOrderController;
|
use App\Http\Controllers\User\WorkOrder\WorkOrderController;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user