支持 余额扣费

This commit is contained in:
iVampireSP.com 2022-10-07 13:15:08 +08:00
parent 3555d0ba2d
commit 7b874970c6
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
7 changed files with 110 additions and 55 deletions

View File

@ -7,6 +7,7 @@
use App\Models\User\Balance;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use App\Exceptions\ChargeException;
class UserAddBalance extends Command
{
@ -53,8 +54,9 @@ public function handle()
$balance = new Balance();
$this->info($user->name . ', 当前余额: ' . $user->balance);
$this->info($user->name . ', 当前余额: ' . $user->balance . ' 元');
$this->info('充值后余额: ' . ($user->balance + $amount) . ' 元');
if (!$this->confirm('确认充值 ' . $amount . ' 元?')) {
$this->info('已取消。');
return;
@ -70,30 +72,18 @@ public function handle()
$transaction = new Transaction();
DB::beginTransaction();
$description = '控制台充值 ' . $amount . ' 元';
try {
$balance->user->increment('balance', $amount);
$description = '控制台充值 ' . $amount . ' 元';
$transaction->addIncomeBalance($balance->user_id, 'console', $amount, $description);
$balance->update([
'paid_at' => now(),
]);
DB::commit();
$transaction->addAmount($user->id, 'console', $amount, $description);
$this->info('充值成功。');
$user->refresh();
$this->info($user->name . ', 当前余额: ' . $user->balance);
} catch (ChargeException $e) {
} catch (\Exception $e) {
DB::rollBack();
$this->error('充值失败。' . $e->getMessage());
return;
return $this->error($e->getMessage());
}
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ChargeException extends Exception
{
//
}

View File

@ -2,7 +2,6 @@
namespace App\Http\Controllers\Remote\Host;
use Cache;
use App\Models\Host;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
@ -52,7 +51,6 @@ public function store(Request $request)
$host['host_id'] = $host->id;
return $this->created($host);
}
/**
@ -86,15 +84,24 @@ public function update(Request $request, Host $host)
// 如果是立即扣费
'cost_once' => 'sometimes|numeric|nullable',
'cost_balance' => 'sometimes|numeric|nullable',
]);
// if has cost_once
if ($request->has('cost_once')) {
$host->cost($request->cost_once, false);
$host->cost($request->cost_once ?? 0, false);
return $this->updated($request->cost_once);
return $this->updated();
}
if ($request->has('cost_balance')) {
$host->costBalance($request->cost_balance ?? 0);
return $this->updated();
}
$update = $request->all();
// module_id 不能被更新
unset($update['module_id']);

View File

@ -3,15 +3,16 @@
namespace App\Http\Controllers\User;
use Exception;
use App\Models\Transaction;
use App\Models\User\Balance;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Exceptions\ChargeException;
use Illuminate\Support\Facades\Log;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Alipay\EasySDK\Kernel\Util\ResponseChecker;
use Alipay\EasySDK\Kernel\Factory as AlipayFactory;
use App\Models\Transaction;
class BalanceController extends Controller
{
@ -161,16 +162,9 @@ public function checkAndCharge(Balance $balance)
$transaction = new Transaction();
DB::beginTransaction();
try {
$balance->user->increment('balance', $trade->totalAmount);
$description = '充值 ' . $trade->totalAmount . ' 元';
$transaction->addIncomeBalance($balance->user_id, 'alipay', $trade->totalAmount, $description);
DB::commit();
} catch (\Exception $e) {
DB::rollBack();
$transaction->addAmount($balance->user_id, 'alipay', $trade->totalAmount);
} catch (ChargeException $e) {
AlipayFactory::payment()->common()->refund($balance->order_id, $trade->totalAmount);
return $this->error($e->getMessage());
}

View File

@ -152,6 +152,24 @@ public function cost($price = null, $auto = true)
return true;
}
public function costBalance($amount = 1)
{
$transaction = new Transaction();
$left = $transaction->reduceAmount($this->user_id, $amount);
broadcast(new UserEvent($this->user_id, 'balances.amount.reduced', $this->user));
if ($left < 0) {
$this->update([
'status' => 'suspended',
]);
}
return true;
}
protected static function boot()
{
parent::boot();

View File

@ -2,9 +2,11 @@
namespace App\Models;
use Jenssegers\Mongodb\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use App\Exceptions\ChargeException;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
use Jenssegers\Mongodb\Eloquent\Model;
use Illuminate\Contracts\Cache\LockTimeoutException;
class Transaction extends Model
{
@ -203,27 +205,61 @@ public function addPayoutBalance($user_id, $amount, $description)
return $this->addLog($user_id, $data);
}
public function reduceAmount($user_id, $amount = 0, $description = '扣除费用请求。')
{
$user = User::findOrFail($user_id);
if ($user) {
$lock = Cache::lock("user_balance_lock_" . $user_id, 10);
try {
$lock->block(5);
$user = User::findOrFail($user_id);
$user->balance -= $amount;
$user->save();
$this->addPayoutBalance($user_id, $amount, $description);
return $user->balance;
} finally {
optional($lock)->release();
}
$data = [
'type' => 'payout',
'payment' => 'balance',
'description' => $description,
'income' => 0,
'income_drops' => 0,
'outcome' => $amount,
'outcome_drops' => 0
];
return false;
}
return $this->addLog($user_id, $data);
public function addAmount($user_id, $payment = 'console', $amount = 0, $description = null)
{
$lock = Cache::lock("user_balance_lock_" . $user_id, 10);
try {
$lock->block(5);
$user = User::findOrFail($user_id);
$left_balance = $user->balance + $amount;
$user->increment('balance', $amount);
if (!$description) {
$description = '充值金额。';
} else {
$description = '充值 ' . $amount . ' 元';
}
$this->addIncomeBalance($user_id, $payment, $amount, $description);
return $left_balance;
} catch (LockTimeoutException $e) {
Log::error($e);
throw new ChargeException('充值失败,请稍后再试。');
} finally {
optional($lock)->release();
}
return false;
}

View File

@ -96,14 +96,14 @@ public function toDrops($amount = 1)
return $this;
}
// when update
// protected static function boot()
// {
// parent::boot();
protected static function boot()
{
parent::boot();
// // when update
// static::updating(function ($model) {
static::updating(function ($model) {
// });
// }
// balance 四舍五入
$model->balance = round($model->balance, 2);
});
}
}