diff --git a/app/Http/Controllers/Shop/PayboxController.php b/app/Http/Controllers/Shop/PayboxController.php index 8600446a..15d0c17f 100644 --- a/app/Http/Controllers/Shop/PayboxController.php +++ b/app/Http/Controllers/Shop/PayboxController.php @@ -3,13 +3,19 @@ namespace App\Http\Controllers\Shop; use App\Http\Controllers\Controller; +use App\Repositories\Core\User\ShopCart; +use App\Repositories\Shop\Paybox as PayboxGateway; use App\Repositories\Shop\Contents; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Log; + class PayboxController extends Controller { public function accepted() { + ShopCart::clear(); + return view('paybox.paybox', ['content' => Contents::getPayboxConfirmedContent()]); } @@ -30,8 +36,20 @@ class PayboxController extends Controller public function process(Request $request) { - $data = $request->all(); + $invoiceId = $request->input('order_number'); - return view('paybox.send', $data); + if (! $invoiceId) { + Log::warning('Paybox callback missing order_number', ['payload' => $request->all()]); + + return response('Missing order_number', 400); + } + + $success = PayboxGateway::verifyPayment($invoiceId); + + if (! $success) { + return response('KO', 400); + } + + return response('OK'); } } diff --git a/app/Repositories/Shop/Paybox.php b/app/Repositories/Shop/Paybox.php index 9dacff36..6ca3195f 100644 --- a/app/Repositories/Shop/Paybox.php +++ b/app/Repositories/Shop/Paybox.php @@ -2,12 +2,15 @@ namespace App\Repositories\Shop; +use App\Models\Shop\Invoice; use App\Models\Shop\InvoicePayment; +use App\Repositories\Core\DateTime; use Bnb\PayboxGateway\Requests\Paybox\AuthorizationWithCapture; use Bnb\PayboxGateway\Requests\PayboxDirect\Capture; use Bnb\PayboxGateway\Responses\Exceptions\InvalidSignature; use Bnb\PayboxGateway\Responses\Paybox\Verify; use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; class Paybox @@ -23,17 +26,141 @@ class Paybox public static function verifyPayment($invoiceId) { - $invoice = Invoices::get($invoiceId); - $payboxVerify = App::make(Verify::class); - try { - $success = $payboxVerify->isSuccess($invoice->total_shipped); - if ($success) { - // process order here after making sure it was real payment - } - echo 'OK'; - } catch (InvalidSignature $e) { - Log::alert('Invalid payment signature detected'); + $invoice = Invoices::get($invoiceId, ['order']); + + if (! $invoice) { + Log::warning('Paybox callback received for unknown invoice', [ + 'invoice_id' => $invoiceId, + 'payload' => request()->all(), + ]); + + return false; } + + $payboxVerify = App::make(Verify::class); + + try { + $isSuccessful = $payboxVerify->isSuccess($invoice->total_shipped); + } catch (InvalidSignature $e) { + Log::alert('Invalid payment signature detected', [ + 'invoice_id' => $invoiceId, + 'payload' => request()->except('signature'), + ]); + + return false; + } + + if (! $isSuccessful) { + Log::warning('Paybox payment verification failed', [ + 'invoice_id' => $invoiceId, + 'response_code' => $payboxVerify->getResponseCode(), + 'payload' => request()->except('signature'), + ]); + + return false; + } + + return self::finalizeInvoicePayment($invoice); + } + + protected static function finalizeInvoicePayment(Invoice $invoice) + { + $order = $invoice->order; + + if (! $order) { + Log::error('Paybox payment cannot be finalized: missing related order', [ + 'invoice_id' => $invoice->id, + ]); + + return false; + } + + $request = request(); + $referenceParts = array_filter([ + $request->input('call_number'), + $request->input('transaction_number'), + ]); + $reference = $referenceParts ? implode('-', $referenceParts) : $request->input('authorization_number'); + if (! $reference) { + $reference = 'paybox-'.$invoice->id; + } + + $payload = $request->except('signature'); + $existingPayment = InvoicePayment::where('invoice_id', $invoice->id) + ->where('reference', $reference) + ->first(); + $shouldNotify = false; + $validatedTotal = InvoicePayment::where('invoice_id', $invoice->id) + ->validated() + ->sum('amount'); + + if (! $existingPayment && (float) $validatedTotal >= (float) $invoice->total_shipped) { + Log::info('Paybox payment ignored: invoice already fully settled', [ + 'invoice_id' => $invoice->id, + 'order_id' => $order->id, + 'reference' => $reference, + ]); + + return true; + } + + DB::transaction(function () use ($invoice, $order, $reference, $payload, $existingPayment, &$shouldNotify) { + $attributes = [ + 'payment_type' => 1, + 'amount' => $invoice->total_shipped, + 'date' => DateTime::getDate(), + 'data' => json_encode($payload, JSON_UNESCAPED_UNICODE), + 'validated' => 1, + ]; + + if ($existingPayment) { + $previousValidationState = (int) ($existingPayment->validated ?? 0); + $existingPayment->fill($attributes); + + if ($existingPayment->isDirty()) { + $existingPayment->save(); + } + + if ($previousValidationState !== 1 && (int) $existingPayment->validated === 1) { + $shouldNotify = true; + } + } else { + InvoicePayment::create($attributes + [ + 'invoice_id' => $invoice->id, + 'reference' => $reference, + ]); + $shouldNotify = true; + } + + Invoices::checkPayments($invoice->id); + + $paidStatus = Orders::getStatusByName('Préparation'); + if ($paidStatus !== '' && (int) $order->status !== (int) $paidStatus) { + $order->status = $paidStatus; + $order->save(); + } + }); + + if ($shouldNotify) { + try { + OrderMails::sendOrderConfirmed($order->id); + } catch (\Throwable $exception) { + Log::error('Unable to send order confirmation email after Paybox payment', [ + 'order_id' => $order->id, + 'invoice_id' => $invoice->id, + 'exception' => $exception->getMessage(), + ]); + } + } + + Log::info('Paybox payment finalized successfully', [ + 'invoice_id' => $invoice->id, + 'order_id' => $order->id, + 'reference' => $reference, + 'notified' => $shouldNotify, + ]); + + return true; } public static function getPreviousAuthorizedRequest($request)