PagarmeCustomerService.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. <?php
  2. namespace App\Services\Pagarme;
  3. use App\Data\Pagarme\Customer\CustomerRequestData;
  4. use App\Data\Pagarme\Customer\CustomerResponseData;
  5. use App\Data\Pagarme\Customer\Parts\Request\AddressData;
  6. use App\Data\Pagarme\Customer\Parts\Request\PhoneData;
  7. use App\Data\Pagarme\Customer\Parts\Request\PhonesData;
  8. use App\Models\Client;
  9. use App\Services\Pagarme\Concerns\FormatsPagarmeData;
  10. use App\Services\Pagarme\Concerns\MocksPagarmeRequests;
  11. use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
  12. class PagarmeCustomerService
  13. {
  14. use FormatsPagarmeData;
  15. use MocksPagarmeRequests;
  16. use SendsPagarmeRequests;
  17. public function createCustomerForClient(Client $client, array $data): ?string
  18. {
  19. if (! empty($client->gateway_customer_id)) {
  20. return $client->gateway_customer_id;
  21. }
  22. $client->loadMissing('user');
  23. $name = $client->user?->name ?? data_get($data, 'name', 'Cliente');
  24. $email = $client->user?->email ?? data_get($data, 'email');
  25. $code = $client->ensureGatewayCode();
  26. $document = $this->customerDocument($client->document ?? data_get($data, 'document'));
  27. $documentType = $this->customerDocumentType($document);
  28. $address = $this->buildAddressData($data);
  29. $phones = $this->buildPhones($client->user?->phone ?? data_get($data, 'phone'));
  30. if ($this->shouldMockPagarmeRequest()) {
  31. $customerId = $this->mockPagarmeId('cus', $client->id);
  32. $client->forceFill([
  33. 'gateway_customer_id' => $customerId,
  34. 'gateway_customer_code' => $code,
  35. ])->save();
  36. return $customerId;
  37. }
  38. $customerRequest = new CustomerRequestData(
  39. name: $name,
  40. email: (string) $email,
  41. document: $document,
  42. type: $documentType === 'CNPJ' ? 'company' : 'individual',
  43. documentType: $documentType,
  44. code: $code,
  45. address: $address,
  46. phones: $phones,
  47. );
  48. $customerData = CustomerResponseData::fromArray($this->pagarmeRequest(
  49. method: 'POST',
  50. path: '/customers',
  51. payload: $customerRequest,
  52. idempotencyKey: $this->idempotencyKey($client),
  53. errorMessage: 'Erro ao criar cliente no Pagar.me.',
  54. ));
  55. $customerId = $customerData->requireId();
  56. $client->forceFill([
  57. 'gateway_customer_id' => $customerId,
  58. 'gateway_customer_code' => $code,
  59. ])->save();
  60. return $customerId;
  61. }
  62. //
  63. private function buildAddressData(array $data): AddressData
  64. {
  65. $line1Parts = array_filter([
  66. (string) data_get($data, 'number', '0'),
  67. (string) data_get($data, 'address', ''),
  68. (string) data_get($data, 'district', ''),
  69. ], static fn ($value) => $value !== '');
  70. return new AddressData(
  71. line1: implode(', ', $line1Parts),
  72. line2: (string) data_get($data, 'complement', data_get($data, 'instructions', '')),
  73. zipCode: $this->digits(data_get($data, 'zip_code')),
  74. city: (string) data_get($data, 'city', ''),
  75. state: (string) data_get($data, 'state', ''),
  76. country: (string) data_get($data, 'country', 'BR'),
  77. );
  78. }
  79. private function buildPhones(?string $phone): PhonesData
  80. {
  81. $digits = $this->digits($phone);
  82. if ($digits === '') {
  83. return new PhonesData;
  84. }
  85. $areaCode = substr($digits, 0, 2);
  86. $number = substr($digits, 2);
  87. if (strlen($digits) <= 2) {
  88. $areaCode = '';
  89. $number = $digits;
  90. }
  91. return new PhonesData(
  92. mobilePhone: new PhoneData(
  93. countryCode: '55',
  94. areaCode: $areaCode,
  95. number: $number,
  96. ),
  97. );
  98. }
  99. // evita criacao duplicada de customer
  100. // formato: customer-{email}-{documento}
  101. private function idempotencyKey(Client $client): string
  102. {
  103. if (! empty($client->idempotency_key)) {
  104. return $client->idempotency_key;
  105. }
  106. $client->loadMissing('user');
  107. $key = $this->pagarmeIdempotencyKey('customer', [
  108. $client->user?->email ?: "client-{$client->id}",
  109. $this->customerDocument($client->document) ?: "document-client-{$client->id}",
  110. ]);
  111. $client->forceFill(['idempotency_key' => $key])->save();
  112. return $key;
  113. }
  114. }