Files
opensem/app/Repositories/Shop/Paybox.php
Valentin Lab 61e34b4f4e fix: finalize payments and clear cart after Paybox success
This captures the Paybox verification flow, duplicate-payment guard, and cart cleanup.
2025-10-04 09:17:53 +02:00

181 lines
6.0 KiB
PHP

<?php
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
{
public static function makeAuthorizationRequest($order, $customer_email = 'test@example.com')
{
$authorizationRequest = App::make(AuthorizationWithCapture::class);
$invoiceId = $order->invoice->id;
return $authorizationRequest->setAmount($order->total_shipped)->setCustomerEmail($customer_email)
->setPaymentNumber($invoiceId)->send('paybox.send');
}
public static function verifyPayment($invoiceId)
{
$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)
{
$payment = InvoicePayment::where('number', $request->input('order_number'))->firstOrFail();
$captureRequest = App::make(Capture::class);
$response = $captureRequest->setAmount($payment->amount)
->setPayboxCallNumber($payment->call_number)
->setPayboxTransactionNumber($payment->transaction_number)
->setDayRequestNumber(2)
->send();
if ($response->isSuccess()) {
// process order here
}
}
}