2025-12-18 15:24:46 +03:00

245 lines
8.2 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\Checkout\Session;
use Illuminate\Support\Str;
use App\Models\Payment;
use App\Repositories\CardRepositoryInterface;
class StripeController extends Controller
{
public function __construct(CardRepositoryInterface $cardRepository)
{
$this->cardRepository = $cardRepository;
}
public function createCheckoutSession(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
$count = $request->input('count');
$clientSessionId = Str::uuid();
$priceIds = [
6 => env('STRIPE_6_PRICE'),
18 => env('STRIPE_18_PRICE'),
];
if (!isset($priceIds[$count])) {
return response()->json(['error' => 'Invalid product selected.'], 400);
}
try {
$session = Session::create([
'line_items' => [[
'price' => $priceIds[$count],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => url(env('APP_URL') . '/success?client_session_id=' . $clientSessionId),
'cancel_url' => url(env('APP_URL') . '/cancel'),
'metadata' => [
'draw_count' => $request->input('count'),
'client_session_id' => $clientSessionId,
],
]);
Payment::create([
'amount' => $session->amount_total / 100,
'currency' => $session->currency,
'stripe_session_id' => $session->id,
'client_session_id' => $clientSessionId,
'draw_count' => $count,
'status' => 'pending',
]);
return response()->json(['sessionId' => $session->id]);
} catch (\Exception $e) {
\Log::error('Stripe session creation failed: ' . $e->getMessage());
return response()->json(['error' => 'Could not create checkout session.'], 500);
}
}
public function createRendezVousSession(Request $request)
{
Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
$userForm = $request->input('userForm');
$dateAppointment = $request->input('selectedDate');
$clientSessionId = Str::uuid();
$priceId = env('STRIPE_BOOKING');
try {
$session = Session::create([
'line_items' => [[
'price' => $priceId,
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => url(env('APP_URL') . '/rendez-vous/success?client_session_id=' . $clientSessionId),
'cancel_url' => url(env('APP_URL') . '/cancel'),
'metadata' => [
'client_session_id' => $clientSessionId,
'type_appointment' => true,
'appointment_date' => $dateAppointment
],
'customer_email' => $userForm["email"]
]);
Payment::create([
'amount' => $session->amount_total / 100,
'currency' => $session->currency,
'stripe_session_id' => $session->id,
'client_session_id' => $clientSessionId,
'draw_count' => 0,
'status' => 'pending',
]);
return response()->json(['sessionId' => $session->id]);
} catch (\Exception $e) {
\Log::error('Stripe session creation failed: ' . $e->getMessage());
return response()->json(['error' => 'Could not create checkout session.'], 500);
}
}
public function validatePayment(Request $request)
{
$clientSessionId = $request->query('client_session_id');
if (!$clientSessionId) {
return response()->json(['error' => 'Client session ID is required'], 400);
}
$payment = Payment::where('client_session_id', $clientSessionId)->first();
if (!$payment) {
return response()->json([
'success' => false,
'message' => 'Payment not found.',
], 404);
}
// If payment is already succeeded in our database
if ($payment->status === 'succeeded') {
return response()->json([
'success' => true,
'drawCount' => $payment->draw_count,
'cached' => true,
]);
}
// If payment is pending, check with Stripe directly to handle race condition
if ($payment->status === 'pending') {
try {
Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
$session = Session::retrieve($clientSessionId);
// Check if payment is completed on Stripe side
if ($session->payment_status === 'paid' && $session->status === 'complete') {
// Update our payment record and mark as succeeded
$payment->update(['status' => 'succeeded']);
return response()->json([
'success' => true,
'drawCount' => $payment->draw_count,
'updated' => true,
]);
}
// Payment not completed yet, return pending status
return response()->json([
'success' => false,
'message' => 'Payment is still being processed.',
'status' => 'pending',
], 202);
} catch (\Exception $e) {
\Log::error('Stripe validation failed: ' . $e->getMessage(), [
'client_session_id' => $clientSessionId,
'payment_id' => $payment->id
]);
return response()->json([
'success' => false,
'message' => 'Payment validation error.',
], 500);
}
}
// Payment failed or has other status
return response()->json([
'success' => false,
'message' => 'Payment failed or cancelled.',
'status' => $payment->status,
], 402);
}
public function getCards(Request $request)
{
$sessionId = $request->query('client_session_id');
if(!$sessionId)
{
$count = $request->query('count');
if($count == 1){
$freeCards = $this->cardRepository->draw(1);
return response()->json([
'success' => true,
'cards' => $freeCards
]);
}
}
// 1. Find the payment record
$payment = Payment::where('client_session_id', $sessionId)->first();
if (!$payment) {
return response()->json(['success' => false, 'message' => 'Payment not found.'], 404);
}
// 2. One-Time Use Check
if ($payment->status === 'processed') {
return response()->json([
'success' => true,
'cards' => $payment->cards,
'message' => 'Cards already drawn for this payment.',
]);
}
// 3. Verify payment status with Stripe
if ($payment->status !== 'succeeded') {
try {
$session = Session::retrieve($sessionId);
if ($session->payment_status !== 'paid' || $session->status !== 'complete') {
return response()->json(['success' => false, 'message' => 'Payment not complete.'], 402);
}
$payment->update(['status' => 'succeeded']);
} catch (\Exception $e) {
\Log::error('Stripe session retrieval failed: ' . $e->getMessage());
return response()->json(['success' => false, 'message' => 'Validation error.'], 500);
}
}
// 4. Securely draw the cards and store them
$drawnCards = $this->cardRepository->draw($payment->draw_count);
$payment->update([
'cards' => $drawnCards,
'status' => 'processed',
]);
return response()->json([
'success' => true,
'cards' => $drawnCards,
]);
}
}