|
|
@@ -1,239 +0,0 @@
|
|
|
-<?php
|
|
|
-
|
|
|
-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\MocksPagarmeRequests;
|
|
|
-use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
|
|
|
-use Illuminate\Support\Facades\Http;
|
|
|
-use Illuminate\Support\Facades\Log;
|
|
|
-use Throwable;
|
|
|
-
|
|
|
-class PagarmeAnticipationService
|
|
|
-{
|
|
|
- use MocksPagarmeRequests;
|
|
|
- use SendsPagarmeRequests;
|
|
|
-
|
|
|
- public function createBulkAnticipation(
|
|
|
- Payment $payment,
|
|
|
- ?BulkAnticipationLimitsResponseData $limits = null,
|
|
|
- ): ?BulkAnticipationResponseData
|
|
|
- {
|
|
|
- $provider = $payment->provider()->first();
|
|
|
-
|
|
|
- if (! $provider) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- $recipientId = $provider->recipient_id;
|
|
|
-
|
|
|
- if (empty($recipientId)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- $providerSplit = $payment->splits()
|
|
|
- ->where('provider_id', $payment->provider_id)
|
|
|
- ->first();
|
|
|
-
|
|
|
- if (! $providerSplit) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- $requestedAmount = OrderRequestData::amountInCents((float) $providerSplit->gross_amount);
|
|
|
-
|
|
|
- if ($requestedAmount <= 0) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- $paymentDate = $this->getAnticipationPaymentDate();
|
|
|
-
|
|
|
- $limits ??= $this->fetchAnticipationLimits($recipientId, $paymentDate);
|
|
|
-
|
|
|
- if ($limits && $limits->maximum->amount <= 0) {
|
|
|
- Log::channel('pagarme')->warning('Antecipacao ignorada: recebedor sem valor disponivel para antecipar.', [
|
|
|
- '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;
|
|
|
- }
|
|
|
-
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- if ($limits && $limits->maximum->amount > 0 && $requestedAmount > $limits->maximum->amount) {
|
|
|
- Log::channel('pagarme')->warning('Antecipacao ignorada: valor acima do maximo disponivel 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 {
|
|
|
- if ($this->shouldMockPagarmeRequest()) {
|
|
|
- return new BulkAnticipationResponseData(
|
|
|
- id: $this->mockPagarmeId('ba', "{$payment->id}-{$payment->provider_id}"),
|
|
|
- status: 'pending',
|
|
|
- amount: $requestedAmount,
|
|
|
- fee: 0,
|
|
|
- fraudCoverageFee: 0,
|
|
|
- anticipationFee: 0,
|
|
|
- automaticTransfer: false,
|
|
|
- type: 'full',
|
|
|
- timeframe: 'start',
|
|
|
- paymentDate: $paymentDate,
|
|
|
- createdAt: now()->toISOString(),
|
|
|
- updatedAt: now()->toISOString(),
|
|
|
- anticipationTax: ['mocked' => true],
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- $response = BulkAnticipationResponseData::fromArray($this->pagarmeRequest(
|
|
|
- method: 'POST',
|
|
|
- path: "/recipients/{$recipientId}/bulk_anticipations",
|
|
|
-
|
|
|
- payload: new BulkAnticipationRequestData(
|
|
|
- paymentDate: $paymentDate,
|
|
|
- timeframe: 'start',
|
|
|
- requestedAmount: $requestedAmount,
|
|
|
- automaticTransfer: false,
|
|
|
- ),
|
|
|
-
|
|
|
- idempotencyKey: "bulk-ant-{$payment->id}-{$payment->provider_id}",
|
|
|
- errorMessage: 'Erro ao criar antecipacao no Pagar.me.',
|
|
|
- ));
|
|
|
-
|
|
|
- $response->requireId();
|
|
|
-
|
|
|
- return $response;
|
|
|
- } catch (Throwable $e) {
|
|
|
- Log::channel('pagarme')->warning('Falha ao criar antecipacao no Pagar.me.', [
|
|
|
- '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,
|
|
|
- 'error' => $e->getMessage(),
|
|
|
- ]);
|
|
|
-
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public function fetchAnticipationLimitsForPayment(Payment $payment): ?BulkAnticipationLimitsResponseData
|
|
|
- {
|
|
|
- $provider = $payment->provider()->first();
|
|
|
-
|
|
|
- if (! $provider || empty($provider->recipient_id)) {
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- return $this->fetchAnticipationLimits(
|
|
|
- recipientId: $provider->recipient_id,
|
|
|
- paymentDate: $this->getAnticipationPaymentDate(),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- private function fetchAnticipationLimits(string $recipientId, string $paymentDate): ?BulkAnticipationLimitsResponseData
|
|
|
- {
|
|
|
- try {
|
|
|
- if ($this->shouldMockPagarmeRequest()) {
|
|
|
- return new BulkAnticipationLimitsResponseData(
|
|
|
- maximum: new AnticipationLimitData(
|
|
|
- amount: 100000000,
|
|
|
- anticipationFee: 0,
|
|
|
- fee: 0,
|
|
|
- fraudCoverageFee: 0,
|
|
|
- ),
|
|
|
- minimum: new AnticipationLimitData(
|
|
|
- amount: 1,
|
|
|
- anticipationFee: 0,
|
|
|
- fee: 0,
|
|
|
- fraudCoverageFee: 0,
|
|
|
- ),
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- $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() ?? [];
|
|
|
- $limits = BulkAnticipationLimitsResponseData::fromArray($body);
|
|
|
-
|
|
|
- Log::channel('pagarme')->info('Limites de antecipacao consultados no Pagar.me.', [
|
|
|
- 'recipient_id' => $recipientId,
|
|
|
- 'payment_date' => $paymentDate,
|
|
|
- 'minimum_amount' => $limits->minimum->amount,
|
|
|
- 'maximum_amount' => $limits->maximum->amount,
|
|
|
- ]);
|
|
|
-
|
|
|
- return $limits;
|
|
|
- } 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');
|
|
|
-
|
|
|
- if ($now->hour < 11) {
|
|
|
- return $now->toISOString();
|
|
|
- }
|
|
|
-
|
|
|
- $nextBusinessDay = $now->copy()->addDay();
|
|
|
-
|
|
|
- while ($nextBusinessDay->isWeekend()) {
|
|
|
- $nextBusinessDay->addDay();
|
|
|
- }
|
|
|
-
|
|
|
- return $nextBusinessDay->startOfDay()->toISOString();
|
|
|
- }
|
|
|
-}
|