Ver código fonte

feat: add verificao de limite de antecipacao para recipient

Gustavo Mantovani 10 horas atrás
pai
commit
a3f7867725

+ 7 - 1
.env.example

@@ -39,6 +39,8 @@ BROADCAST_DRIVER=log
 
 SANCTUM_STATEFUL_DOMAINS=localhost
 
+#
+
 PAGARME_BASE_URL=https://api.pagar.me/core/v5
 
 PAGARME_SECRET_KEY=
@@ -49,8 +51,12 @@ PAGARME_WEBHOOK_PASSWORD=
 
 PAGARME_PLATFORM_RECIPIENT_ID=
 
+#
+
 PAGARME_PIX_DISABLE_SPLIT=false
 
-PAGARME_PLATFORM_FEE_RATE=0.11
+PAGARME_PLATFORM_PIX_FEE_RATE=0.11
+
+PAGARME_PLATFORM_CREDIT_CARD_FEE_RATE=0.1457
 
 PAGARME_TRANSFER_FEE_AMOUNT=3.67

+ 35 - 0
app/Data/Pagarme/Anticipation/AnticipationLimitData.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Data\Pagarme\Anticipation;
+
+use App\Data\Pagarme\PagarmeResponseData;
+
+final readonly class AnticipationLimitData extends PagarmeResponseData
+{
+    public function __construct(
+        public int $amount,
+        public int $anticipationFee,
+        public int $fee,
+        public int $fraudCoverageFee,
+    ) {}
+
+    public static function fromArray(array $payload): static
+    {
+        return new self(
+            amount:           static::arrInt($payload, 'amount')             ?? 0,
+            anticipationFee:  static::arrInt($payload, 'anticipation_fee')   ?? 0,
+            fee:              static::arrInt($payload, 'fee')                ?? 0,
+            fraudCoverageFee: static::arrInt($payload, 'fraud_coverage_fee') ?? 0,
+        );
+    }
+
+    public function toArray(): array
+    {
+        return [
+            'amount'              => $this->amount,
+            'anticipation_fee'    => $this->anticipationFee,
+            'fee'                 => $this->fee,
+            'fraud_coverage_fee'  => $this->fraudCoverageFee,
+        ];
+    }
+}

+ 29 - 0
app/Data/Pagarme/Anticipation/BulkAnticipationLimitsResponseData.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Data\Pagarme\Anticipation;
+
+use App\Data\Pagarme\PagarmeResponseData;
+
+final readonly class BulkAnticipationLimitsResponseData extends PagarmeResponseData
+{
+    public function __construct(
+        public AnticipationLimitData $maximum,
+        public AnticipationLimitData $minimum,
+    ) {}
+
+    public static function fromArray(array $payload): static
+    {
+        return new self(
+            maximum: AnticipationLimitData::fromArray(static::arrArray($payload, 'maximum')),
+            minimum: AnticipationLimitData::fromArray(static::arrArray($payload, 'minimum')),
+        );
+    }
+
+    public function toArray(): array
+    {
+        return [
+            'maximum' => $this->maximum->toArray(),
+            'minimum' => $this->minimum->toArray(),
+        ];
+    }
+}

+ 59 - 1
app/Services/Pagarme/PagarmeAnticipationService.php

@@ -2,11 +2,14 @@
 
 namespace App\Services\Pagarme;
 
+use App\Data\Pagarme\Anticipation\AnticipationLimitData;
+use App\Data\Pagarme\Anticipation\BulkAnticipationLimitsResponseData;
 use App\Data\Pagarme\Anticipation\BulkAnticipationRequestData;
 use App\Data\Pagarme\Anticipation\BulkAnticipationResponseData;
 use App\Data\Pagarme\Order\OrderRequestData;
 use App\Models\Payment;
 use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
+use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Log;
 use Throwable;
 
@@ -42,13 +45,30 @@ class PagarmeAnticipationService
             return null;
         }
 
+        $paymentDate = $this->getAnticipationPaymentDate();
+
+        $limits = $this->fetchAnticipationLimits($recipientId, $paymentDate);
+
+        if ($limits && $limits->minimum->amount > 0 && $requestedAmount < $limits->minimum->amount) {
+            Log::channel('pagarme')->warning('Antecipacao ignorada: valor abaixo do minimo do recebedor.', [
+                'payment_id'       => $payment->id,
+                'provider_id'      => $payment->provider_id,
+                'recipient_id'     => $recipientId,
+                'requested_amount' => $requestedAmount,
+                'minimum_amount'   => $limits->minimum->amount,
+                'maximum_amount'   => $limits->maximum->amount,
+            ]);
+
+            return null;
+        }
+
         try {
             $response = BulkAnticipationResponseData::fromArray($this->pagarmeRequest(
                 method: 'POST',
                 path:   "/recipients/{$recipientId}/bulk_anticipations",
 
                 payload: new BulkAnticipationRequestData(
-                    paymentDate:       $this->getAnticipationPaymentDate(),
+                    paymentDate:       $paymentDate,
                     timeframe:         'start',
                     requestedAmount:   $requestedAmount,
                     automaticTransfer: false,
@@ -67,6 +87,8 @@ class PagarmeAnticipationService
                 'provider_id'      => $payment->provider_id,
                 'recipient_id'     => $recipientId,
                 'requested_amount' => $requestedAmount,
+                'minimum_amount'   => $limits?->minimum->amount,
+                'maximum_amount'   => $limits?->maximum->amount,
                 'error'            => $e->getMessage(),
             ]);
 
@@ -74,6 +96,42 @@ class PagarmeAnticipationService
         }
     }
 
+    private function fetchAnticipationLimits(string $recipientId, string $paymentDate): ?BulkAnticipationLimitsResponseData
+    {
+        try {
+            $secretKey = config('services.pagarme.secret_key');
+
+            if (empty($secretKey)) {
+                return null;
+            }
+
+            $endpoint = $this->pagarmeUrl("/recipients/{$recipientId}/bulk_anticipations/limits");
+
+            $response = Http::withBasicAuth($secretKey, '')
+                ->withHeaders([
+                    'Content-Type' => 'application/json',
+                    'Accept'       => 'application/json',
+                ])
+                ->get($endpoint, [
+                    'payment_date' => $paymentDate,
+                    'timeframe'    => 'start',
+                ])
+                ->throw();
+
+            $body = $response->json() ?? [];
+
+            return BulkAnticipationLimitsResponseData::fromArray($body);
+        } catch (Throwable $e) {
+            Log::channel('pagarme')->warning('Falha ao consultar limites de antecipacao.', [
+                'recipient_id' => $recipientId,
+                'payment_date' => $paymentDate,
+                'error'        => $e->getMessage(),
+            ]);
+
+            return null;
+        }
+    }
+
     private function getAnticipationPaymentDate(): string
     {
         $now = now()->timezone('America/Sao_Paulo');