firstOrFail(); $telepagosService = new TelepagosIntegrationService(); $telepagosService->forTenant($tenant->codigo); try { $details = $telepagosService->getCashinDetails($cashinId); $qrOrderId = $details['data']['qr_order_id'] ?? $details['qr_order_id'] ?? null; $amount = $this->normalizeAmount($details['data']['amount'] ?? $details['amount'] ?? 0); $operationId = $details['data']['operation_id'] ?? $details['operation_id'] ?? null; $transferenciaOperationIds = [1, 3, 11]; $qrOperationIds = [31, 37, 47]; $compra = null; if (in_array((int) $operationId, $transferenciaOperationIds, true)) { $cuit = $details['data']['buyer']['cuit'] ?? $details['buyer']['cuit'] ?? null; if (! $cuit) { Log::warning("Telepagos webhook: CUIT not found for Transferencia cashin {$cashinId}"); return; } $dni = substr($cuit, 2, -1); $compra = Purchase::where('tenant_codigo', $tenantCodigo) ->where('transfer_payer_dni', $dni) ->whereIn('status', [Purchase::STATUS_CREATED, Purchase::STATUS_PENDING_PAYMENT]) ->where('payment_method', 'transfer') ->where('total', $amount) ->latest() ->first(); if (! $compra) { Log::warning("Telepagos webhook: No matching purchase found for DNI {$dni} and amount {$amount} for cashin {$cashinId}"); return; } } elseif (in_array((int) $operationId, $qrOperationIds, true)) { if (! $qrOrderId) { Log::warning("Telepagos webhook: qr_order_id not found for QR 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; } if ($compra->status !== Purchase::STATUS_PENDING_PAYMENT) { Log::warning("Telepagos webhook: Purchase {$compra->id} is not awaiting payment confirmation"); return; } $totalAmount = $this->normalizeAmount($compra->getTotalAmount()); if ($amount !== $totalAmount) { Log::warning("Telepagos webhook: Amount mismatch. Cashin amount: {$amount}, Purchase amount: {$totalAmount}"); return; } } else { Log::warning("Telepagos webhook: Unknown operation_id {$operationId} for cashin {$cashinId}"); return; } $paymentData = [ 'compra_id' => $compra->id, 'cuit_buyer' => $details['data']['buyer']['cuit'] ?? $details['buyer']['cuit'] ?? null, 'cvu_buyer' => $details['data']['buyer']['cvu'] ?? $details['buyer']['cvu'] ?? 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->markAsPaid(); }); Log::info("Telepagos webhook: Successfully processed cashin {$cashinId} for purchase {$compra->id}"); } catch (Exception $e) { Log::error("Telepagos webhook error: " . $e->getMessage()); throw $e; } } protected function normalizeAmount(mixed $amount): string { return number_format((float) $amount, 2, '.', ''); } }