From 59752088773780456b7dff6e7cb80426498a5fe2 Mon Sep 17 00:00:00 2001 From: Tiago Ramos <2222055@my.ipleiria.pt> Date: Wed, 31 Dec 2025 01:13:27 +0000 Subject: [PATCH] Added endpoint to create tranasactions --- .../Controllers/CoinPurchaseController.php | 77 +++++++++++++++++++ api/app/Models/CoinPurchase.php | 34 ++++++++ api/routes/api.php | 2 + 3 files changed, 113 insertions(+) create mode 100644 api/app/Http/Controllers/CoinPurchaseController.php create mode 100644 api/app/Models/CoinPurchase.php diff --git a/api/app/Http/Controllers/CoinPurchaseController.php b/api/app/Http/Controllers/CoinPurchaseController.php new file mode 100644 index 0000000..5827e08 --- /dev/null +++ b/api/app/Http/Controllers/CoinPurchaseController.php @@ -0,0 +1,77 @@ +validate([ + 'euros' => 'required|numeric|min:1|max:100', + 'payment_type' => 'required|in:MBWAY,IBAN,MB,VISA,PAYPAL', + 'payment_reference' => [ + 'required', + function ($attribute, $value, $fail) use ($request) { + $type = $request->payment_type; + $regex = null; + + switch ($type) { + case 'MBWAY': $regex = '/^9[0-9]{8}$/'; break; + case 'IBAN': $regex = '/^[A-Z]{2}[0-9]{23}$/'; break; + case 'MB': $regex = '/^[0-9]{5}-[0-9]{9}$/'; break; + case 'VISA': $regex = '/^4[0-9]{15}$/'; break; + case 'PAYPAL': + if (!filter_var($value, FILTER_VALIDATE_EMAIL)) { + $fail("Invalid PayPal email."); + } + return; + } + + if ($regex && !preg_match($regex, $value)) { + $fail("Invalid format for $type."); + } + }, + ], + ]); + + $user = $request->user(); + $coinsAmount = $validated['euros'] * 10; + + return DB::transaction(function () use ($user, $validated, $coinsAmount) { + + $type = CoinTransactionType::firstOrCreate(['name' => 'Coin purchase'], ['type' => 'C']); + + $transaction = CoinTransaction::create([ + 'user_id' => $user->id, + 'coin_transaction_type_id' => $type->id, + 'transaction_datetime' => now(), + 'coins' => $coinsAmount, + ]); + + $purchase = CoinPurchase::create([ + 'purchase_datetime' => now(), + 'user_id' => $user->id, + 'coin_transaction_id' => $transaction->id, + 'euros' => $validated['euros'], + 'payment_type' => $validated['payment_type'], + 'payment_reference' => $validated['payment_reference'], + ]); + + $user->increment('coins_balance', $coinsAmount); + + return response()->json([ + 'message' => 'Purchase successful', + 'balance' => $user->coins_balance, + 'transaction_id' => $transaction->id, + 'purchase' => $purchase, + ], 201); + }); + } +} \ No newline at end of file diff --git a/api/app/Models/CoinPurchase.php b/api/app/Models/CoinPurchase.php new file mode 100644 index 0000000..1d10809 --- /dev/null +++ b/api/app/Models/CoinPurchase.php @@ -0,0 +1,34 @@ + 'datetime', + 'custom' => 'array', + ]; + + public function transaction() + { + return $this->belongsTo(CoinTransaction::class, 'coin_transaction_id'); + } +} \ No newline at end of file diff --git a/api/routes/api.php b/api/routes/api.php index e7c1d06..8e60833 100644 --- a/api/routes/api.php +++ b/api/routes/api.php @@ -6,6 +6,7 @@ use App\Http\Controllers\MatchController; use App\Http\Controllers\ProfileController; use App\Http\Controllers\StatisticsController; use App\Http\Controllers\UserController; +use App\Http\Controllers\CoinPurchaseController; use Illuminate\Support\Facades\Route; Route::prefix('v1')->group(function () { @@ -19,6 +20,7 @@ Route::prefix('v1')->group(function () { // Authenticated Routes Route::middleware(['auth:sanctum', 'throttle:60,1'])->group(function () { Route::post('/logout', [AuthController::class, 'logout']); + Route::post('/coin-purchases', [CoinPurchaseController::class, 'store']); Route::get('/statistics/me', [StatisticsController::class, 'getPersonalStats']); Route::prefix('users/me')->group(function () { Route::get('/', [ProfileController::class, 'show']);