Skip to content

Commit 8a25512

Browse files
committed
🎯َAdd transaction gateway
1 parent 0f3a311 commit 8a25512

File tree

6 files changed

+242
-0
lines changed

6 files changed

+242
-0
lines changed

app/Enum/TransactionStatus.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace App\Enum;
4+
5+
enum TransactionStatus: string
6+
{
7+
case Pending = 'pending';
8+
case Verified = 'verified';
9+
case Failed = 'failed';
10+
11+
12+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Api\v1\Transaction;
4+
5+
use App\Enum\TransactionStatus;
6+
use App\Http\Controllers\Controller;
7+
use App\Models\Transaction;
8+
use Illuminate\Http\JsonResponse;
9+
use Illuminate\Http\Request;
10+
use OpenApi\Annotations as OA;
11+
12+
class TransactionController extends Controller
13+
{
14+
15+
/**
16+
* @OA\Post(
17+
* path="/api/v1/payment/request",
18+
* tags={"Transaction"},
19+
* summary="Create a new transaction",
20+
* @OA\RequestBody(
21+
* required=true,
22+
* @OA\JsonContent(
23+
* required={"amount"},
24+
* @OA\Property(property="amount", type="number", format="float", example=100000)
25+
* )
26+
* ),
27+
* @OA\Response(
28+
* response=201,
29+
* description="Transaction created successfully"
30+
* ),
31+
* @OA\Response(
32+
* response=401,
33+
* description="Unauthenticated"
34+
* )
35+
* )
36+
*/
37+
public function create(Request $request): JsonResponse
38+
{
39+
$transaction = Transaction::create([
40+
'transaction_id' => uniqid('', true),
41+
'user_id' => $request->user()->id,
42+
'amount' => $request->amount,
43+
'status' => TransactionStatus::Pending,
44+
]);
45+
46+
return response()->json([
47+
'code' => 100,
48+
'message' => 'Transaction created successfully',
49+
'authority' => $transaction->transaction_id,
50+
], 201);
51+
}
52+
53+
/**
54+
* @OA\Post(
55+
* path="/api/v1/payment/verify",
56+
* tags={"Transaction"},
57+
* summary="Verify a transaction",
58+
* @OA\RequestBody(
59+
* required=true,
60+
* @OA\JsonContent(
61+
* required={"authority"},
62+
* @OA\Property(property="authority", type="string", example="5f8f8c44d6e36")
63+
* )
64+
* ),
65+
* @OA\Response(
66+
* response=200,
67+
* description="Transaction verified successfully"
68+
* ),
69+
* @OA\Response(
70+
* response=400,
71+
* description="Transaction already verified or failed"
72+
* )
73+
* )
74+
*/
75+
public function verify(Request $request): JsonResponse
76+
{
77+
$transaction = Transaction::where('transaction_id', $request->authority)->firstOrFail();
78+
79+
if ($transaction->status === TransactionStatus::Pending) {
80+
$transaction->update(['status' => TransactionStatus::Verified]);
81+
return response()->json([
82+
'code' => 100,
83+
'message' => 'Transaction verified successfully',
84+
]);
85+
}
86+
87+
return response()->json([
88+
'code' => 101,
89+
'message' => 'Transaction already verified or failed',
90+
]);
91+
}
92+
}

app/Models/Transaction.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use App\Enum\TransactionStatus;
6+
use Illuminate\Database\Eloquent\Factories\HasFactory;
7+
use Illuminate\Database\Eloquent\Model;
8+
9+
class Transaction extends Model
10+
{
11+
use HasFactory;
12+
13+
protected $fillable = [
14+
'transaction_id',
15+
'user_id',
16+
'amount',
17+
'status',
18+
];
19+
20+
protected function casts(): array
21+
{
22+
return [
23+
'status' => TransactionStatus::class
24+
];
25+
}
26+
27+
28+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::create('transactions', function (Blueprint $table) {
15+
$table->id();
16+
$table->string('transaction_id')->unique();
17+
$table->unsignedBigInteger('user_id');
18+
$table->decimal('amount', 15, 2);
19+
$table->string('status')->default('pending');
20+
$table->timestamps();
21+
});
22+
}
23+
24+
/**
25+
* Reverse the migrations.
26+
*/
27+
public function down(): void
28+
{
29+
Schema::dropIfExists('transactions');
30+
}
31+
};

routes/Api/v1/V1.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use App\Http\Controllers\Api\v1\Product\ProductCategoryController;
1111
use App\Http\Controllers\Api\v1\Product\ProductController;
1212
use App\Http\Controllers\Api\v1\Product\ProductSubCategoryController;
13+
use App\Http\Controllers\Api\v1\Transaction\TransactionController;
1314
use App\Http\Controllers\Api\v1\UserController;
1415
use Illuminate\Support\Facades\Route;
1516

@@ -32,6 +33,11 @@
3233

3334
Route::resource('/brands' , BrandController::class);
3435
Route::resource('/features' , FeatureController::class);
36+
37+
Route::middleware('auth:sanctum')->group(function () {
38+
Route::post('/payment/request', [TransactionController::class, 'create']);
39+
Route::post('/payment/verify', [TransactionController::class, 'verify']);
40+
});
3541
});
3642

3743
require __DIR__.'/auth.php';

storage/api-docs/api-docs.json

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,79 @@
17431743
}
17441744
}
17451745
},
1746+
"/api/v1/payment/request": {
1747+
"post": {
1748+
"tags": [
1749+
"Transaction"
1750+
],
1751+
"summary": "Create a new transaction",
1752+
"operationId": "989c5a63d30874283a2699953f898ebc",
1753+
"requestBody": {
1754+
"required": true,
1755+
"content": {
1756+
"application/json": {
1757+
"schema": {
1758+
"required": [
1759+
"amount"
1760+
],
1761+
"properties": {
1762+
"amount": {
1763+
"type": "number",
1764+
"format": "float",
1765+
"example": 100000
1766+
}
1767+
},
1768+
"type": "object"
1769+
}
1770+
}
1771+
}
1772+
},
1773+
"responses": {
1774+
"201": {
1775+
"description": "Transaction created successfully"
1776+
},
1777+
"401": {
1778+
"description": "Unauthenticated"
1779+
}
1780+
}
1781+
}
1782+
},
1783+
"/api/v1/payment/verify": {
1784+
"post": {
1785+
"tags": [
1786+
"Transaction"
1787+
],
1788+
"summary": "Verify a transaction",
1789+
"operationId": "c3f5d6ba42e4de06ec3e656a4d48e28b",
1790+
"requestBody": {
1791+
"required": true,
1792+
"content": {
1793+
"application/json": {
1794+
"schema": {
1795+
"required": [
1796+
"authority"
1797+
],
1798+
"properties": {
1799+
"authority": {
1800+
"type": "string",
1801+
"example": "5f8f8c44d6e36"
1802+
}
1803+
},
1804+
"type": "object"
1805+
}
1806+
}
1807+
}
1808+
},
1809+
"responses": {
1810+
"200": {
1811+
"description": "Transaction verified successfully"
1812+
},
1813+
"400": {
1814+
"description": "Transaction already verified or failed"
1815+
}
1816+
}
1817+
}
1818+
},
17461819
"/api/v1/users": {
17471820
"get": {
17481821
"tags": [

0 commit comments

Comments
 (0)