增加 API 充值

优化 Balance 代码
This commit is contained in:
iVampireSP.com 2023-01-03 15:24:29 +08:00
parent 796fd6fce2
commit 15ecf5516a
No known key found for this signature in database
GPG Key ID: 2F7B001CA27A8132
5 changed files with 126 additions and 44 deletions

View File

@ -0,0 +1,69 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Balance;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class BalanceController extends Controller
{
/**
* Display a listing of the resource.
*
* @return JsonResponse
*/
public function index()
{
$balances = Balance::thisUser()->paginate(100);
return $this->success($balances);
}
/**
* Store a newly created resource in storage.
*
* @param Request $request
*
* @return JsonResponse
*/
public function store(Request $request)
{
$this->validate($request, [
'amount' => 'required|integer|min:0.1|max:10000',
'payment' => 'required|in:wechat,alipay',
]);
$balance = Balance::create([
'user_id' => auth('sanctum')->id(),
'amount' => $request->input('amount'),
'payment' => $request->input('payment'),
]);
$url = route('balances.show', compact('balance'));
$balance->url = $url;
return $this->success($balance);
}
/**
* Display the specified resource.
*
* @param Balance $balance
*
* @return JsonResponse
*/
public function show(Balance $balance)
{
if ($balance->canPay()) {
$url = route('balances.show', compact('balance'));
$balance->url = $url;
return $this->success($balance);
} else {
return $this->badRequest('无法支付。');
}
}
}

View File

@ -18,8 +18,6 @@
class BalanceController extends Controller
{
//
public function index(Request $request): View
{
$balance = $request->user()->balance;
@ -31,29 +29,16 @@ public function index(Request $request): View
public function store(Request $request)
{
// 充值
$this->validate($request, [
'amount' => 'required|integer|min:0.1|max:10000',
'payment' => 'required|in:wechat,alipay',
]);
$user = $request->user();
$balance = new Balance();
$data = [
'user_id' => $user->id,
$balance = Balance::create([
'user_id' => auth('web')->id(),
'amount' => $request->input('amount'),
'payment' => $request->input('payment'),
];
$balance = $balance->create($data);
// 生成 18 位订单号
$order_id = date('YmdHis') . $balance->id . rand(1000, 9999);
$balance->order_id = $order_id;
$balance->save();
]);
return redirect()->route('balances.show', compact('balance'));
}
@ -64,7 +49,7 @@ public function store(Request $request)
public function show(Request $request, Balance $balance)
{
if ($balance->paid_at !== null) {
if ($balance->isPaid()) {
if ($request->ajax()) {
return $this->success($balance);
}
@ -76,13 +61,14 @@ public function show(Request $request, Balance $balance)
}
}
if ($balance->isOverdue()) {
if (now()->diffInDays($balance->created_at) > 1) {
if ($request->ajax()) {
return $this->forbidden($balance);
}
if (now()->diffInDays($balance->created_at) > 1) {
if ($request->ajax()) {
return $this->forbidden($balance);
return redirect()->route('index')->with('error', '订单已逾期。');
}
return redirect()->route('index')->with('error', '订单已逾期。');
}
$balance->load('user');
@ -109,14 +95,16 @@ public function show(Request $request, Balance $balance)
}
if (!isset($qr_code)) {
abort(500, '支付方式错误');
return redirect()->route('index')->with('error', '支付方式错误。');
}
return view('balances.pay', compact('balance', 'qr_code'));
}
private function xunhu_wechat(Balance $balance, $subject = '支付')
{
private
function xunhu_wechat(
Balance $balance, $subject = '支付'
) {
$data = [
'version' => '1.1',
'lang' => 'zh-cn',
@ -142,7 +130,7 @@ private function xunhu_wechat(Balance $balance, $subject = '支付')
$response = Http::post(config('pay.xunhu.gateway'), $data);
if (!$response->successful()) {
abort(500, '支付网关错误');
return redirect()->route('index')->with('error', '支付网关错误。');
}
$response = $response->json();
@ -150,14 +138,16 @@ private function xunhu_wechat(Balance $balance, $subject = '支付')
$hash = $this->xunhu_hash($response);
if (!isset($response['hash']) || $response['hash'] !== $hash) {
abort(500, '无法校验支付网关返回数据');
return redirect()->route('index')->with('error', '无法校验支付网关返回数据');
}
return $response;
}
private function xunhu_hash(array $arr)
{
private
function xunhu_hash(
array $arr
) {
ksort($arr);
$pre = [];
@ -188,10 +178,11 @@ private function xunhu_hash(array $arr)
/**
* @throws ValidationException
*/
public function notify(Request $request, $payment): View|JsonResponse
{
public
function notify(
Request $request, $payment
): View|JsonResponse {
$is_paid = false;
// $pay_amount = 0;
if ($payment === 'alipay') {
$out_trade_no = $request->input('out_trade_no');
@ -216,7 +207,6 @@ public function notify(Request $request, $payment): View|JsonResponse
return view('balances.process', compact('balance'));
}
// 处理验证
if ($payment === 'wechat') {
if (!($request->filled('hash') || $request->filled('trade_order_id'))) {

View File

@ -77,12 +77,6 @@ class Balance extends Model
'amount' => 'decimal:2',
];
// route key
public function getRouteKeyName(): string
{
return 'order_id';
}
public function user(): BelongsToAlias
{
return $this->belongsTo(User::class);
@ -92,4 +86,31 @@ public function scopeThisUser($query)
{
return $query->where('user_id', auth()->id());
}
public function isPaid(): bool
{
return $this->paid_at !== null;
}
public function isOverdue(): bool
{
return $this->created_at->diffInDays(now()) > 1 && !$this->isPaid();
}
public function canPay(): bool
{
return !$this->isPaid() && !$this->isOverdue();
}
protected static function boot()
{
parent::boot();
static::creating(function ($balance) {
// $balance->remaining_amount = $balance->amount;
$balance->remaining_amount = 0;
$balance->order_id = date('YmdHis') . $balance->id . rand(1000, 9999);
});
}
}

View File

@ -1,5 +1,6 @@
<?php
use App\Http\Controllers\Api\BalanceController;
use App\Http\Controllers\Api\ForumController;
use App\Http\Controllers\Api\HostController;
use App\Http\Controllers\Api\IndexController;
@ -17,6 +18,8 @@
Route::get('user', [UserController::class, 'index']);
Route::get('users', [UserController::class, 'index']);
Route::resource('balances', BalanceController::class);
Route::get('servers', ServerController::class);
Route::get('modules', [ModuleController::class, 'index']);

View File

@ -23,11 +23,10 @@
Route::post('newToken', [AuthController::class, 'newToken'])->name('newToken');
Route::delete('deleteAll', [AuthController::class, 'deleteAll'])->name('deleteAll');
Route::get('transactions', [BalanceController::class, 'transactions'])->name('transactions');
Route::resource('balances', BalanceController::class)->except('show');
Route::get('/balances/{balance}', [BalanceController::class, 'show'])->name('balances.show')->withoutMiddleware('auth');
Route::get('/balances/{balance:order_id}', [BalanceController::class, 'show'])->name('balances.show')->withoutMiddleware('auth');
Route::get('transfer', [TransferController::class, 'index'])->name('transfer');
Route::post('transfer', [TransferController::class, 'transfer']);
@ -37,6 +36,6 @@
Route::view('contact', 'contact')->name('contact');
Route::view('not_verified', 'not_verified')->name('not_verified');
Route::any('/balances/notify/{payment}', [BalanceController::class, 'notify'])->name('balances.notify');
Route::match(['get', 'post'], '/balances/notify/{payment}', [BalanceController::class, 'notify'])->name('balances.notify');