PagarmeCustomerService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. <?php
  2. namespace App\Services\Pagarme;
  3. use App\Models\Client;
  4. use Illuminate\Support\Facades\Log;
  5. use PagarmeApiSDKLib\Authentication\BasicAuthCredentialsBuilder;
  6. use PagarmeApiSDKLib\Models\CreateAddressRequest;
  7. use PagarmeApiSDKLib\Models\CreatePhonesRequest;
  8. use PagarmeApiSDKLib\Models\Builders\CreateAddressRequestBuilder;
  9. use PagarmeApiSDKLib\Models\Builders\CreateCustomerRequestBuilder;
  10. use PagarmeApiSDKLib\Models\Builders\CreatePhoneRequestBuilder;
  11. use PagarmeApiSDKLib\Models\Builders\CreatePhonesRequestBuilder;
  12. use PagarmeApiSDKLib\PagarmeApiSDKClient;
  13. use PagarmeApiSDKLib\PagarmeApiSDKClientBuilder;
  14. class PagarmeCustomerService
  15. {
  16. private ?PagarmeApiSDKClient $client = null;
  17. public function createCustomerForClient(Client $client, array $data): ?string
  18. {
  19. if (!empty($client->external_customer_id)) {
  20. return $client->external_customer_id;
  21. }
  22. $client->loadMissing('user');
  23. $name = $client->user?->name ?? $data['name'] ?? 'Cliente';
  24. $email = $client->user?->email ?? $data['email'] ?? null;
  25. $document = $this->sanitizeDigits($client->document ?? $data['document'] ?? null);
  26. if (empty($email) || empty($document)) {
  27. Log::warning('Skipping customer creation because the client is missing email or document.', [
  28. 'client_id' => $client->id,
  29. 'user_id' => $client->user_id,
  30. ]);
  31. return null;
  32. }
  33. $address = $this->buildAddress($data);
  34. $phones = $this->buildPhones($client->user?->phone ?? $data['phone'] ?? null);
  35. $code = $client->external_customer_code ?? "client-{$client->id}";
  36. $customerRequest = CreateCustomerRequestBuilder::init(
  37. $name,
  38. $email,
  39. $document,
  40. $this->personType($document),
  41. $address,
  42. [
  43. 'client_id' => (string) $client->id,
  44. 'user_id' => (string) ($client->user_id ?? ''),
  45. ],
  46. $phones,
  47. $code
  48. )
  49. ->documentType($this->documentType($document))
  50. ->build();
  51. $customer = $this->client()->getCustomersController()->createCustomer(
  52. $customerRequest,
  53. $this->idempotencyKey($client->id)
  54. );
  55. $customerId = $customer->getId();
  56. if (!$customerId) {
  57. throw new \RuntimeException('Customer creation returned an empty id.');
  58. }
  59. $client->forceFill([
  60. 'external_customer_id' => $customerId,
  61. 'external_customer_code' => $code,
  62. ])->save();
  63. return $customerId;
  64. }
  65. private function buildAddress(array $data): CreateAddressRequest
  66. {
  67. $zipCode = $this->sanitizeDigits($data['zip_code'] ?? null);
  68. $street = (string) ($data['address'] ?? '');
  69. $number = (string) ($data['number'] ?? '0');
  70. $neighborhood = (string) ($data['district'] ?? '');
  71. $city = (string) ($data['city'] ?? '');
  72. $state = (string) ($data['state'] ?? '');
  73. $country = (string) ($data['country'] ?? 'BR');
  74. $complement = (string) ($data['complement'] ?? '');
  75. $line1Parts = array_filter([$number, $street, $neighborhood], static fn ($value) => $value !== '');
  76. $line1 = implode(', ', $line1Parts);
  77. $line2 = $complement ?: (string) ($data['instructions'] ?? '');
  78. return CreateAddressRequestBuilder::init(
  79. $street,
  80. $number,
  81. $zipCode,
  82. $neighborhood,
  83. $city,
  84. $state,
  85. $country,
  86. $complement,
  87. $line1,
  88. $line2
  89. )
  90. ->metadata([
  91. 'source' => 'register-client',
  92. ])
  93. ->build();
  94. }
  95. private function buildPhones(?string $phone): CreatePhonesRequest
  96. {
  97. $digits = $this->sanitizeDigits($phone);
  98. $phonesBuilder = CreatePhonesRequestBuilder::init();
  99. if (empty($digits)) {
  100. return $phonesBuilder->build();
  101. }
  102. $countryCode = '55';
  103. $areaCode = substr($digits, 0, 2);
  104. $number = substr($digits, 2);
  105. if (strlen($digits) <= 2) {
  106. $areaCode = '';
  107. $number = $digits;
  108. }
  109. $mobilePhone = CreatePhoneRequestBuilder::init()
  110. ->countryCode($countryCode)
  111. ->areaCode($areaCode)
  112. ->number($number)
  113. ->type('mobile')
  114. ->build();
  115. return $phonesBuilder
  116. ->mobilePhone($mobilePhone)
  117. ->build();
  118. }
  119. private function documentType(string $document): string
  120. {
  121. return strlen($document) === 14 ? 'CNPJ' : 'CPF';
  122. }
  123. private function personType(string $document): string
  124. {
  125. return strlen($document) === 14 ? 'company' : 'individual';
  126. }
  127. private function sanitizeDigits(?string $value): string
  128. {
  129. return preg_replace('/\D+/', '', (string) $value) ?? '';
  130. }
  131. private function client(): PagarmeApiSDKClient
  132. {
  133. if ($this->client) {
  134. return $this->client;
  135. }
  136. $secretKey = config('services.pagarme.secret_key');
  137. if (empty($secretKey)) {
  138. throw new \RuntimeException('PAGARME_SECRET_KEY is not configured.');
  139. }
  140. $serviceRefererName = (string) config('services.pagarme.service_referer_name', config('app.name'));
  141. $this->client = PagarmeApiSDKClientBuilder::init()
  142. ->basicAuthCredentials(
  143. BasicAuthCredentialsBuilder::init($secretKey, '')
  144. )
  145. ->serviceRefererName($serviceRefererName)
  146. ->build();
  147. return $this->client;
  148. }
  149. private function idempotencyKey(int $clientId): string
  150. {
  151. return "client-{$clientId}-customer";
  152. }
  153. }