245 lines
8.2 KiB
PHP
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,
|
|
]);
|
|
}
|
|
|
|
}
|