recordWebhook($payload, $event, $data); Log::channel('pagarme')->info('Webhook do Pagar.me recebido', [ 'hook_id' => data_get($payload, 'id'), 'event' => $event, ]); if (! in_array($event, self::PAYMENT_EVENTS, true)) { if (str_starts_with((string) $event, 'transfer.')) { $this->providerWithdrawalService->handleTransferWebhook($data); $webhook->update([ 'status' => 'processed', 'processed_at' => now(), ]); return null; } $webhook->update([ 'status' => 'ignored', 'processed_at' => now(), ]); return null; } $orderResponse = $this->normalizeOrderResponse($event, $data); $payment = $this->findPayment($orderResponse); if (! $payment) { $webhook->update([ 'status' => 'payment_not_found', 'processed_at' => now(), ]); Log::channel('pagarme')->warning('Pagamento não encontrado para o webhook do Pagar.me', [ 'hook_id' => data_get($payload, 'id'), 'event' => $event, 'order_id' => data_get($orderResponse, 'id'), 'charge_id' => data_get($orderResponse, 'charges.0.id'), 'transaction_id' => data_get($orderResponse, 'charges.0.last_transaction.id'), 'metadata' => data_get($orderResponse, 'metadata', []), ]); return null; } try { $payment = $this->pagarmePaymentService->applyGatewayResponseToPayment($payment, $orderResponse); $this->paymentService->syncPaymentTargets($payment); $webhook->update([ 'payment_id' => $payment->id, 'status' => 'processed', 'processed_at' => now(), ]); return $payment; } catch (\Throwable $e) { $webhook->update([ 'payment_id' => $payment->id, 'status' => 'failed', 'processed_at' => now(), 'error_message' => $e->getMessage(), ]); throw $e; } } // private function recordWebhook(array $payload, ?string $event, array $data): Webhook { $references = $this->extractReferences($event, $data); $hookId = data_get($payload, 'id'); $attributes = [ 'hook_id' => $hookId, 'provider' => 'pagarme', 'event' => $event, 'account_id' => data_get($payload, 'account.id'), 'order_id' => data_get($references, 'order_id'), 'charge_id' => data_get($references, 'charge_id'), 'transaction_id' => data_get($references, 'transaction_id'), 'status' => 'received', 'payload' => $payload, 'received_at' => now(), 'processed_at' => null, 'error_message' => null, ]; if (empty($hookId)) { return Webhook::create($attributes); } $webhook = Webhook::firstOrNew([ 'provider' => 'pagarme', 'hook_id' => $hookId, ]); $webhook->fill([ ...$attributes, 'attempts_count' => $webhook->exists ? $webhook->attempts_count + 1 : 1, ])->save(); return $webhook; } // private function extractReferences(?string $event, array $data): array { if (str_starts_with((string) $event, 'order.')) { $charge = data_get($data, 'charges.0', []); return [ 'order_id' => data_get($data, 'id'), 'charge_id' => data_get($charge, 'id'), 'transaction_id' => data_get($charge, 'last_transaction.id'), ]; } if (str_starts_with((string) $event, 'charge.')) { return [ 'order_id' => data_get($data, 'order.id', data_get($data, 'order_id')), 'charge_id' => data_get($data, 'id'), 'transaction_id' => data_get($data, 'last_transaction.id'), ]; } return [ 'order_id' => null, 'charge_id' => null, 'transaction_id' => null, ]; } private function findPayment(array $orderResponse): ?Payment { $charge = data_get($orderResponse, 'charges.0', []); $transaction = data_get($charge, 'last_transaction', []); $metadata = data_get($orderResponse, 'metadata', data_get($charge, 'metadata', [])); $metadataId = filter_var(data_get($metadata, 'payment_id'), FILTER_VALIDATE_INT) ?: null; $chargeId = data_get($charge, 'id'); $transactionId = data_get($transaction, 'id'); $orderId = data_get($orderResponse, 'id'); $references = array_filter([$metadataId, $chargeId, $transactionId, $orderId]); if (empty($references)) { return null; } return Payment::query() ->where('gateway_provider', 'pagarme') ->where(function ($query) use ($metadataId, $chargeId, $transactionId, $orderId) { $query ->when($metadataId, fn ($query) => $query->orWhere('id', $metadataId)) ->when($chargeId, fn ($query) => $query->orWhere('gateway_entity_reference', $chargeId)) ->when($transactionId, fn ($query) => $query->orWhere('gateway_operation_reference', $transactionId)) ->when($orderId, fn ($query) => $query->orWhere(function ($query) use ($orderId) { $query->where('gateway_entity_label', 'order') ->where('gateway_entity_reference', $orderId); })); }) ->latest('id') ->first(); } private function normalizeOrderResponse(?string $event, array $data): array { if (str_starts_with((string) $event, 'order.')) { return $data; } return [ 'id' => data_get($data, 'order.id', data_get($data, 'order_id')), 'metadata' => data_get($data, 'metadata', data_get($data, 'order.metadata', [])), 'charges' => [$data], ]; } }