|
|
@@ -2,14 +2,26 @@
|
|
|
|
|
|
namespace App\Services\Pagarme;
|
|
|
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientAddressData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientAutomaticAnticipationSettingsData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientBankAccountData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientPhoneData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientPhoneNumbersData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientRegisterInformationData;
|
|
|
+use App\Data\Pagarme\Request\Objects\PagarmeRecipientTransferSettingsData;
|
|
|
+use App\Data\Pagarme\Request\PagarmeBankAccountUpdateRequestData;
|
|
|
+use App\Data\Pagarme\Request\PagarmeRecipientRequestData;
|
|
|
+use App\Data\Pagarme\Response\PagarmeRecipientResponseData;
|
|
|
use App\Models\Provider;
|
|
|
+use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
|
|
|
use Carbon\Carbon;
|
|
|
-use Illuminate\Support\Facades\Http;
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
use Illuminate\Support\Str;
|
|
|
|
|
|
class PagarmeRecipientService
|
|
|
{
|
|
|
+ use SendsPagarmeRequests;
|
|
|
+
|
|
|
public function createRecipientForProvider(Provider $provider, array $data): string
|
|
|
{
|
|
|
if (! empty($provider->recipient_id)) {
|
|
|
@@ -26,78 +38,56 @@ class PagarmeRecipientService
|
|
|
$monthlyIncome = isset($data['monthly_income']) ? (int) $data['monthly_income'] : 1000;
|
|
|
$occupation = $data['professional_occupation'] ?? 'autonomo';
|
|
|
|
|
|
- $payload = $this->filterFilledRecursive([
|
|
|
- 'code' => $this->buildRecipientCode($provider, $data),
|
|
|
-
|
|
|
- 'register_information' => [
|
|
|
- 'name' => $data['recipient_name'],
|
|
|
- 'email' => $data['recipient_email'],
|
|
|
- 'document' => preg_replace('/\D+/', '', $data['recipient_document']),
|
|
|
- 'type' => $recipientType,
|
|
|
- 'birthdate' => $this->formatBirthdate($data['birth_date'] ?? null),
|
|
|
- 'monthly_income' => $monthlyIncome,
|
|
|
- 'professional_occupation' => $occupation,
|
|
|
- 'phone_numbers' => $this->buildPhoneNumbers($data['phone'] ?? null),
|
|
|
-
|
|
|
- 'address' => [
|
|
|
- 'street' => $data['address'],
|
|
|
- 'complementary' => $addressParts['complementary'],
|
|
|
- 'street_number' => $addressParts['street_number'],
|
|
|
- 'neighborhood' => $addressParts['neighborhood'],
|
|
|
- 'city' => $data['city'] ?? null,
|
|
|
- 'state' => $data['state'] ?? null,
|
|
|
- 'zip_code' => preg_replace('/\D+/', '', $data['zip_code']),
|
|
|
- 'reference_point' => $addressParts['reference_point'],
|
|
|
- ],
|
|
|
- ],
|
|
|
-
|
|
|
- 'default_bank_account' => [
|
|
|
- 'holder_name' => $bankAccountData['holder_name'],
|
|
|
- 'holder_type' => $bankAccountData['holder_type'],
|
|
|
- 'holder_document' => preg_replace('/\D+/', '', $bankAccountData['holder_document']),
|
|
|
- 'bank' => $bankAccountData['bank'],
|
|
|
- 'branch_number' => $bankAccountData['branch_number'],
|
|
|
- 'branch_check_digit' => $bankAccountData['branch_check_digit'] ?? null,
|
|
|
- 'account_number' => $bankAccountData['account_number'],
|
|
|
- 'account_check_digit' => $bankAccountData['account_check_digit'],
|
|
|
- 'type' => $bankAccountData['type'],
|
|
|
- ],
|
|
|
-
|
|
|
- 'transfer_settings' => [
|
|
|
- 'transfer_enabled' => false,
|
|
|
- 'transfer_interval' => 'Daily',
|
|
|
- 'transfer_day' => 0,
|
|
|
- ],
|
|
|
-
|
|
|
- 'automatic_anticipation_settings' => [
|
|
|
- 'enabled' => false,
|
|
|
- ],
|
|
|
- ]);
|
|
|
-
|
|
|
- $endpoint = $this->pagarmeUrl('/recipients');
|
|
|
-
|
|
|
- PagarmeHttpLogger::logRequest('POST', $endpoint, $payload);
|
|
|
-
|
|
|
- $response = $this->pagarmeRequest($provider->id)
|
|
|
- ->post($endpoint, $payload);
|
|
|
-
|
|
|
- if ($response->failed()) {
|
|
|
- Log::channel('pagarme')->error('Pagar.me recipient creation failed', [
|
|
|
- 'status' => $response->status(),
|
|
|
- 'body' => $response->json() ?? $response->body(),
|
|
|
- 'payload' => $payload,
|
|
|
- ]);
|
|
|
-
|
|
|
- throw new \RuntimeException('Erro ao criar recebedor no Pagar.me.');
|
|
|
- }
|
|
|
-
|
|
|
- $recipientData = $response->json();
|
|
|
-
|
|
|
- $recipientId = $recipientData['id'] ?? null;
|
|
|
+ $recipientCode = $this->ensureRecipientCode($provider);
|
|
|
+
|
|
|
+ $defaultBankAccount = PagarmeRecipientBankAccountData::fromArray($bankAccountData);
|
|
|
+
|
|
|
+ $payload = new PagarmeRecipientRequestData(
|
|
|
+ code: $recipientCode,
|
|
|
+ registerInformation: new PagarmeRecipientRegisterInformationData(
|
|
|
+ name: $data['recipient_name'],
|
|
|
+ email: $data['recipient_email'],
|
|
|
+ document: preg_replace('/\D+/', '', $data['recipient_document']),
|
|
|
+ type: $recipientType,
|
|
|
+ birthdate: $this->formatBirthdate($data['birth_date'] ?? null),
|
|
|
+ monthlyIncome: $monthlyIncome,
|
|
|
+ professionalOccupation: $occupation,
|
|
|
+ phoneNumbers: new PagarmeRecipientPhoneNumbersData($this->buildPhoneNumber($data['phone'] ?? null)),
|
|
|
+ address: new PagarmeRecipientAddressData(
|
|
|
+ street: $data['address'],
|
|
|
+ complementary: $addressParts['complementary'],
|
|
|
+ streetNumber: $addressParts['street_number'],
|
|
|
+ neighborhood: $addressParts['neighborhood'],
|
|
|
+ city: $data['city'] ?? null,
|
|
|
+ state: $data['state'] ?? null,
|
|
|
+ zipCode: preg_replace('/\D+/', '', $data['zip_code']),
|
|
|
+ referencePoint: $addressParts['reference_point'],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ defaultBankAccount: $defaultBankAccount,
|
|
|
+ transferSettings: new PagarmeRecipientTransferSettingsData(
|
|
|
+ transferEnabled: false,
|
|
|
+ transferInterval: 'Daily',
|
|
|
+ transferDay: 0,
|
|
|
+ ),
|
|
|
+ automaticAnticipationSettings: new PagarmeRecipientAutomaticAnticipationSettingsData(
|
|
|
+ enabled: false,
|
|
|
+ ),
|
|
|
+ );
|
|
|
+
|
|
|
+ $recipientData = PagarmeRecipientResponseData::fromArray($this->pagarmeRequest(
|
|
|
+ method: 'POST',
|
|
|
+ path: '/recipients',
|
|
|
+ payload: $payload,
|
|
|
+ idempotencyKey: $this->idempotencyKey($provider->id),
|
|
|
+ errorMessage: 'Erro ao criar recebedor no Pagar.me.',
|
|
|
+ ));
|
|
|
+
|
|
|
+ $recipientId = $recipientData->id();
|
|
|
|
|
|
if (! $recipientId) {
|
|
|
Log::channel('pagarme')->error('Pagar.me recipient creation returned empty id', [
|
|
|
- 'response' => $recipientData,
|
|
|
+ 'response' => $recipientData->toArray(),
|
|
|
]);
|
|
|
|
|
|
throw new \RuntimeException('Pagar.me recipient creation returned an empty id.');
|
|
|
@@ -110,7 +100,7 @@ class PagarmeRecipientService
|
|
|
'recipient_description' => $data['recipient_description'],
|
|
|
'recipient_document' => $data['recipient_document'],
|
|
|
'recipient_type' => $recipientType,
|
|
|
- 'recipient_code' => $data['recipient_code'],
|
|
|
+ 'recipient_code' => $recipientCode,
|
|
|
'recipient_payment_mode' => $paymentMode,
|
|
|
'recipient_default_bank_account' => $bankAccountData,
|
|
|
|
|
|
@@ -139,33 +129,18 @@ class PagarmeRecipientService
|
|
|
$bankAccountData = $this->normalizeBankAccountPayload($bankAccountData);
|
|
|
$bankAccountData['holder_name'] = $this->normalizeBankAccountHolderName($bankAccountData['holder_name']);
|
|
|
|
|
|
- $payload = [
|
|
|
- 'bank_account' => $this->filterFilledRecursive($bankAccountData),
|
|
|
- ];
|
|
|
-
|
|
|
- $endpoint = $this->pagarmeUrl("/recipients/{$provider->recipient_id}/default-bank-account");
|
|
|
-
|
|
|
- PagarmeHttpLogger::logRequest('PATCH', $endpoint, $payload);
|
|
|
-
|
|
|
- $response = $this->pagarmeRequest($provider->id, 'default-bank-account-'.sha1(json_encode($payload)))
|
|
|
- ->patch($endpoint, $payload);
|
|
|
+ $payload = PagarmeBankAccountUpdateRequestData::fromArray($bankAccountData);
|
|
|
|
|
|
- if ($response->failed()) {
|
|
|
- Log::channel('pagarme')->error('Pagar.me recipient bank account update failed', [
|
|
|
- 'provider_id' => $provider->id,
|
|
|
- 'recipient_id' => $provider->recipient_id,
|
|
|
- 'status' => $response->status(),
|
|
|
- 'body' => $response->json() ?? $response->body(),
|
|
|
- 'payload' => $payload,
|
|
|
- ]);
|
|
|
-
|
|
|
- throw new \RuntimeException('Erro ao atualizar conta bancaria do recebedor no Pagar.me.');
|
|
|
- }
|
|
|
-
|
|
|
- $recipientData = $response->json();
|
|
|
+ $recipientData = PagarmeRecipientResponseData::fromArray($this->pagarmeRequest(
|
|
|
+ method: 'PATCH',
|
|
|
+ path: "/recipients/{$provider->recipient_id}/default-bank-account",
|
|
|
+ payload: $payload,
|
|
|
+ idempotencyKey: $this->idempotencyKey($provider->id, 'default-bank-account-'.sha1(json_encode($payload->toArray()))),
|
|
|
+ errorMessage: 'Erro ao atualizar conta bancaria do recebedor no Pagar.me.',
|
|
|
+ ));
|
|
|
|
|
|
$provider->forceFill([
|
|
|
- 'recipient_default_bank_account' => $recipientData['default_bank_account'] ?? $bankAccountData,
|
|
|
+ 'recipient_default_bank_account' => $recipientData->defaultBankAccount()?->toArray() ?: $bankAccountData,
|
|
|
])->save();
|
|
|
|
|
|
return $provider->fresh();
|
|
|
@@ -178,41 +153,16 @@ class PagarmeRecipientService
|
|
|
return "provider-{$providerId}-{$suffix}";
|
|
|
}
|
|
|
|
|
|
- private function pagarmeRequest(int $providerId, string $suffix = 'recipient')
|
|
|
- {
|
|
|
- $secretKey = config('services.pagarme.secret_key');
|
|
|
-
|
|
|
- if (empty($secretKey)) {
|
|
|
- Log::channel('pagarme')->error('PAGARME_SECRET_KEY is not configured.');
|
|
|
-
|
|
|
- throw new \RuntimeException('PAGARME_SECRET_KEY is not configured.');
|
|
|
- }
|
|
|
-
|
|
|
- return Http::withBasicAuth($secretKey, '')
|
|
|
- ->withHeaders([
|
|
|
- 'Idempotency-Key' => $this->idempotencyKey($providerId, $suffix),
|
|
|
- 'Content-Type' => 'application/json',
|
|
|
- 'Accept' => 'application/json',
|
|
|
- ]);
|
|
|
- }
|
|
|
-
|
|
|
- private function pagarmeUrl(string $path): string
|
|
|
- {
|
|
|
- return rtrim(config('services.pagarme.base_url'), '/').'/'.ltrim($path, '/');
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
-
|
|
|
- private function buildPhoneNumbers(?string $phone): array
|
|
|
+ private function buildPhoneNumber(?string $phone): PagarmeRecipientPhoneData
|
|
|
{
|
|
|
$digits = preg_replace('/\D+/', '', (string) $phone) ?? '';
|
|
|
|
|
|
if (strlen($digits) < 10) {
|
|
|
- return [[
|
|
|
- 'ddd' => '11',
|
|
|
- 'number' => '999999999',
|
|
|
- 'type' => 'mobile',
|
|
|
- ]];
|
|
|
+ return new PagarmeRecipientPhoneData(
|
|
|
+ ddd: '11',
|
|
|
+ number: '999999999',
|
|
|
+ type: 'mobile',
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
if (str_starts_with($digits, '55')) {
|
|
|
@@ -223,19 +173,30 @@ class PagarmeRecipientService
|
|
|
|
|
|
$number = substr($digits, 2);
|
|
|
|
|
|
- return [[
|
|
|
- 'ddd' => $areaCode,
|
|
|
- 'number' => $number,
|
|
|
- 'type' => 'mobile',
|
|
|
- ]];
|
|
|
+ return new PagarmeRecipientPhoneData(
|
|
|
+ ddd: $areaCode,
|
|
|
+ number: $number,
|
|
|
+ type: 'mobile',
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
- private function buildRecipientCode(Provider $provider, array $data): string
|
|
|
+ private function ensureRecipientCode(Provider $provider): string
|
|
|
{
|
|
|
- $baseCode = preg_replace('/\D+/', '', (string) ($data['recipient_code'] ?? '')) ?: (string) $provider->id;
|
|
|
+ if ($this->hasUuidCode($provider->recipient_code, 'provider')) {
|
|
|
+ return $provider->recipient_code;
|
|
|
+ }
|
|
|
+
|
|
|
+ $recipientCode = 'provider-'.(string) Str::uuid();
|
|
|
+
|
|
|
+ $provider->forceFill(['recipient_code' => $recipientCode])->save();
|
|
|
|
|
|
- // Pagar.me exige external_id unico; usar code deterministico por provider evita colisao entre contas.
|
|
|
- return Str::limit("provider-{$provider->id}-{$baseCode}", 52, '');
|
|
|
+ return $recipientCode;
|
|
|
+ }
|
|
|
+
|
|
|
+ private function hasUuidCode(?string $code, string $prefix): bool
|
|
|
+ {
|
|
|
+ return is_string($code)
|
|
|
+ && preg_match("/^{$prefix}-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i", $code) === 1;
|
|
|
}
|
|
|
|
|
|
private function extractAddressParts(array $data): array
|