PagarmeCardService.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <?php
  2. namespace App\Services\Pagarme;
  3. use App\Data\Pagarme\Card\CardRequestData;
  4. use App\Data\Pagarme\Card\CardResponseData;
  5. use App\Data\Pagarme\Card\Parts\Request\BillingAddressData;
  6. use App\Models\Address;
  7. use App\Models\ClientPaymentMethod;
  8. use App\Services\Pagarme\Concerns\FormatsPagarmeData;
  9. use App\Services\Pagarme\Concerns\MocksPagarmeRequests;
  10. use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
  11. class PagarmeCardService
  12. {
  13. use FormatsPagarmeData;
  14. use MocksPagarmeRequests;
  15. use SendsPagarmeRequests;
  16. public function __construct(
  17. private readonly PagarmeCustomerService $pagarmeCustomerService,
  18. ) {}
  19. public function createCardForPaymentMethod(ClientPaymentMethod $paymentMethod): ?string
  20. {
  21. if (! empty($paymentMethod->gateway_card_id)) {
  22. return $paymentMethod->gateway_card_id;
  23. }
  24. $paymentMethod->loadMissing('client.user');
  25. $customerId = $this->pagarmeCustomerService->createCustomerForClient(
  26. $paymentMethod->client,
  27. []
  28. );
  29. if ($this->shouldMockPagarmeRequest()) {
  30. $cardId = $this->mockPagarmeId('card', $paymentMethod->id);
  31. $paymentMethod->forceFill([
  32. 'gateway_card_id' => $cardId,
  33. 'brand' => $paymentMethod->brand ?: 'visa',
  34. 'last_four_digits' => $paymentMethod->last_four_digits ?: '1111',
  35. ])->save();
  36. return $cardId;
  37. }
  38. $cardData = CardResponseData::fromArray($this->pagarmeRequest(
  39. method: 'POST',
  40. path: "/customers/{$customerId}/cards",
  41. payload: new CardRequestData(
  42. token: $paymentMethod->token,
  43. label: $paymentMethod->card_name,
  44. billingAddress: BillingAddressData::fromAddress(
  45. Address::query()
  46. ->with(['city.state', 'state'])
  47. ->where('source', 'client')
  48. ->where('source_id', $paymentMethod->client_id)
  49. ->orderByDesc('is_primary')
  50. ->latest('id')
  51. ->first()
  52. ),
  53. ),
  54. idempotencyKey: $this->idempotencyKey($paymentMethod),
  55. errorMessage: 'Erro ao salvar cartao no Pagar.me.',
  56. ));
  57. $cardId = $cardData->requireId();
  58. $paymentMethod->forceFill([
  59. 'gateway_card_id' => $cardId,
  60. 'brand' => $paymentMethod->brand ?: $cardData->brand,
  61. 'last_four_digits' => $paymentMethod->last_four_digits ?: $cardData->lastFourDigits,
  62. ])->save();
  63. return $cardId;
  64. }
  65. // evita criacao duplicada de cartao
  66. // formato: card-{email}-{ultimos-4-digitos}-{bandeira}
  67. private function idempotencyKey(ClientPaymentMethod $paymentMethod): string
  68. {
  69. if (! empty($paymentMethod->idempotency_key)) {
  70. return $paymentMethod->idempotency_key;
  71. }
  72. $paymentMethod->loadMissing('client.user');
  73. $email = $paymentMethod->client?->user?->email
  74. ?: "client-{$paymentMethod->client_id}";
  75. $lastFourDigits = $paymentMethod->last_four_digits
  76. ?: substr($this->digits($paymentMethod->card_number), -4)
  77. ?: "card-{$paymentMethod->id}";
  78. $key = $this->pagarmeIdempotencyKey('card', [
  79. $email,
  80. $lastFourDigits,
  81. $paymentMethod->brand ?: 'unknown-brand',
  82. ]);
  83. $paymentMethod->forceFill(['idempotency_key' => $key])->save();
  84. return $key;
  85. }
  86. }