shopit-back/app/Domains/Integration/Services/TelepagosWebhookService.php

99 lines
4.0 KiB
PHP

<?php
namespace App\Domains\Integration\Services;
use App\Domains\Purchase\Services\CheckoutService;
use App\Domains\Purchase\Models\TelepagosPayment;
use App\Domains\Purchase\Models\TelepagosQr;
use App\Domains\Tenant\Models\Tenant;
use Exception;
use Illuminate\Support\Facades\Log;
class TelepagosWebhookService
{
public function __construct(
private readonly CheckoutService $checkoutService,
) {}
/**
* Handle the Telepagos webhook notification.
*
* @param string $tenantCodigo
* @param string $cashinId
* @return void
* @throws Exception
*/
public function handleWebhook(string $tenantCodigo, string $cashinId): void
{
$tenant = Tenant::where('codigo', $tenantCodigo)->firstOrFail();
$telepagosService = new TelepagosIntegrationService();
$telepagosService->forTenant($tenant);
try {
$details = $telepagosService->getCashinDetails($cashinId);
// Extract the qr_order_id from the response
// The exact path depends on Telepagos response structure, assuming it's inside 'data'
// Need to handle potential nested structures based on actual API
$qrOrderId = $details['data']['qr_order_id'] ?? $details['qr_order_id'] ?? null;
$amount = $details['data']['amount'] ?? $details['amount'] ?? 0;
if (!$qrOrderId) {
Log::warning("Telepagos webhook: qr_order_id not found for cashin {$cashinId}");
return;
}
$telepagosQr = TelepagosQr::where('qr_order_id', $qrOrderId)->first();
if (!$telepagosQr) {
Log::warning("Telepagos webhook: QR {$qrOrderId} not found in database for cashin {$cashinId}");
return;
}
$compra = $telepagosQr->compra;
if (!$compra) {
Log::warning("Telepagos webhook: Purchase not found for QR {$qrOrderId}");
return;
}
$totalAmount = $compra->getTotalAmount();
// Depending on precision, we might need a looser comparison, but == should work for floats here
if ($amount != $totalAmount) {
Log::warning("Telepagos webhook: Amount mismatch. Cashin amount: {$amount}, Purchase amount: {$totalAmount}");
// In a real scenario, you might want to record a partial payment or flag it,
// but the instructions say to finalize ONLY if the amount is correct.
return;
}
// Create the TelepagosPayment and finalize the purchase in a transaction
$paymentData = [
'compra_id' => $compra->id,
'cuit_buyer' => $details['data']['cuit_buyer'] ?? $details['cuit_buyer'] ?? null,
'cvu_buyer' => $details['data']['cvu_buyer'] ?? $details['cvu_buyer'] ?? null,
'amount' => $amount,
'concept' => $details['data']['concept'] ?? $details['concept'] ?? null,
'operation' => $details['data']['operation'] ?? $details['operation'] ?? null,
'operation_id' => $details['data']['operation_id'] ?? $details['operation_id'] ?? null,
'transaction_id' => $details['data']['transaction_id'] ?? $details['transaction_id'] ?? null,
'qr_order_id' => $qrOrderId,
'link_id' => $details['data']['link_id'] ?? $details['link_id'] ?? null,
];
\Illuminate\Support\Facades\DB::transaction(function () use ($compra, $paymentData) {
TelepagosPayment::create($paymentData);
$this->checkoutService->confirmPurchase($compra);
$compra->finalize();
});
Log::info("Telepagos webhook: Successfully processed cashin {$cashinId} for purchase {$compra->id}");
} catch (Exception $e) {
Log::error("Telepagos webhook error: " . $e->getMessage());
throw $e;
}
}
}