PagarmePaymentService.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <?php
  2. namespace App\Services\Pagarme;
  3. use App\Data\Pagarme\Request\PagarmeCustomerRequestData\PagarmeCustomerRequestData;
  4. use App\Data\Pagarme\Request\PagarmeOrderRequestData\PagarmeOrderItemData;
  5. use App\Data\Pagarme\Request\PagarmeOrderRequestData\PagarmeOrderPaymentData\PagarmeOrderCreditCardData;
  6. use App\Data\Pagarme\Request\PagarmeOrderRequestData\PagarmeOrderPaymentData\PagarmeOrderPaymentData;
  7. use App\Data\Pagarme\Request\PagarmeOrderRequestData\PagarmeOrderPaymentData\PagarmeOrderPixData;
  8. use App\Data\Pagarme\Request\PagarmeOrderRequestData\PagarmeOrderRequestData;
  9. use App\Data\Pagarme\Response\PagarmeCustomerResponseData\PagarmeCustomerAddressResponseData;
  10. use App\Data\Pagarme\Response\PagarmeCustomerResponseData\PagarmeCustomerPhonesResponseData\PagarmeCustomerPhonesResponseData;
  11. use App\Data\Pagarme\Response\PagarmeCustomerResponseData\PagarmeCustomerPhonesResponseData\PagarmePhoneResponseData;
  12. use App\Data\Pagarme\Response\PagarmeCustomerResponseData\PagarmeCustomerResponseData;
  13. use App\Data\Pagarme\Response\PagarmeOrderResponseData\PagarmeOrderChargeResponseData\PagarmeOrderChargeResponseData;
  14. use App\Data\Pagarme\Response\PagarmeOrderResponseData\PagarmeOrderChargeResponseData\PagarmeOrderTransactionResponseData;
  15. use App\Data\Pagarme\Response\PagarmeOrderResponseData\PagarmeOrderCheckoutResponseData;
  16. use App\Data\Pagarme\Response\PagarmeOrderResponseData\PagarmeOrderItemResponseData;
  17. use App\Data\Pagarme\Response\PagarmeOrderResponseData\PagarmeOrderResponseData;
  18. use App\Enums\PaymentSplitStatusEnum;
  19. use App\Enums\PaymentStatusEnum;
  20. use App\Models\Payment;
  21. use App\Models\PaymentSplit;
  22. use App\Services\Pagarme\Concerns\SendsPagarmeRequests;
  23. use Illuminate\Support\Str;
  24. class PagarmePaymentService
  25. {
  26. use SendsPagarmeRequests;
  27. public function createOrderWithCreditCard(
  28. Payment $payment,
  29. array $items,
  30. PagarmeCustomerRequestData $customer,
  31. PagarmeOrderCreditCardData $creditCard,
  32. array $options = []
  33. ): array {
  34. return $this->createOrder(
  35. payment: $payment,
  36. items: $items,
  37. customer: $customer,
  38. paymentMethod: PagarmeOrderRequestData::creditCardPaymentMethod(
  39. creditCard: $creditCard,
  40. split: is_array($options['split'] ?? null) ? $options['split'] : null,
  41. ),
  42. options: $options,
  43. );
  44. }
  45. public function createOrderWithPix(
  46. Payment $payment,
  47. array $items,
  48. PagarmeCustomerRequestData $customer,
  49. PagarmeOrderPixData $pix,
  50. array $options = []
  51. ): array {
  52. return $this->createOrder(
  53. payment: $payment,
  54. items: $items,
  55. customer: $customer,
  56. paymentMethod: PagarmeOrderRequestData::pixPaymentMethod(
  57. pix: $pix,
  58. split: is_array($options['split'] ?? null) ? $options['split'] : null,
  59. ),
  60. options: $options,
  61. );
  62. }
  63. // criacao de pedidos por metodo de pagamento
  64. public function createOrder(
  65. Payment $payment,
  66. array $items,
  67. PagarmeCustomerRequestData $customer,
  68. PagarmeOrderPaymentData $paymentMethod,
  69. array $options = []
  70. ): array {
  71. $metadata = array_merge([
  72. 'payment_id' => (string) $payment->id,
  73. 'schedule_id' => (string) $payment->schedule_id,
  74. 'client_id' => (string) $payment->client_id,
  75. 'provider_id' => (string) $payment->provider_id,
  76. ], $options['metadata'] ?? []);
  77. $requestData = new PagarmeOrderRequestData(
  78. code: $this->ensurePaymentCode($payment),
  79. items: $items,
  80. payments: [$paymentMethod],
  81. metadata: $metadata,
  82. customer: $customer,
  83. customerId: $options['customer_id'] ?? null,
  84. closed: $options['closed'] ?? true,
  85. channel: $options['channel'] ?? null,
  86. );
  87. $raw = $this->pagarmeRequest(
  88. method: 'POST',
  89. path: '/orders',
  90. payload: $requestData,
  91. idempotencyKey: $this->idempotencyKey($payment),
  92. errorMessage: 'Erro ao criar pedido de pagamento no Pagar.me.',
  93. );
  94. $order = $this->buildOrderResponse($raw);
  95. $order->requireId();
  96. return $order->toArray();
  97. }
  98. // evita criacao duplicada de pedidos
  99. private function idempotencyKey(Payment $payment): string
  100. {
  101. return "payment-{$payment->id}-schedule-{$payment->schedule_id}";
  102. }
  103. private function ensurePaymentCode(Payment $payment): string
  104. {
  105. if (! empty($payment->gateway_code)) {
  106. return $payment->gateway_code;
  107. }
  108. $code = 'payment-'.(string) Str::uuid();
  109. $payment->forceFill(['gateway_code' => $code])->save();
  110. return $code;
  111. }
  112. //
  113. public function applyGatewayResponseToPayment(Payment $payment, array $orderResponse): Payment
  114. {
  115. $order = $this->buildOrderResponse($orderResponse);
  116. $newStatus = $order->paymentStatus();
  117. $failureCode = null;
  118. $failureMessage = null;
  119. if ($newStatus === PaymentStatusEnum::FAILED) {
  120. $failureCode = $order->failureCode();
  121. $failureMessage = $order->failureMessage();
  122. }
  123. $payment->forceFill([
  124. 'gateway_provider' => 'pagarme',
  125. 'gateway_entity_reference' => $order->gatewayEntityReference(),
  126. 'gateway_entity_label' => $order->gatewayEntityLabel(),
  127. 'gateway_operation_reference' => $order->gatewayOperationReference(),
  128. 'gateway_operation_label' => $order->gatewayOperationLabel(),
  129. 'status' => $newStatus,
  130. 'paid_at' => $order->paidAt(),
  131. 'authorized_at' => $order->authorizedAt(),
  132. 'gateway_payload' => $orderResponse,
  133. 'failure_code' => $failureCode,
  134. 'failure_message' => $failureMessage,
  135. ])->save();
  136. $splitStatus = match ($newStatus) {
  137. PaymentStatusEnum::PAID => PaymentSplitStatusEnum::TRANSFERRED,
  138. PaymentStatusEnum::FAILED => PaymentSplitStatusEnum::FAILED,
  139. PaymentStatusEnum::CANCELLED => PaymentSplitStatusEnum::CANCELLED,
  140. PaymentStatusEnum::AUTHORIZED => PaymentSplitStatusEnum::PROCESSING,
  141. default => PaymentSplitStatusEnum::PENDING,
  142. };
  143. PaymentSplit::query()
  144. ->where('payment_id', $payment->id)
  145. ->update(['status' => $splitStatus]);
  146. return $payment->fresh();
  147. }
  148. //
  149. private function buildOrderResponse(array $raw): PagarmeOrderResponseData
  150. {
  151. return new PagarmeOrderResponseData(
  152. id: $raw['id'] ?? null,
  153. code: $raw['code'] ?? null,
  154. amount: isset($raw['amount']) ? (int) $raw['amount'] : null,
  155. currency: $raw['currency'] ?? null,
  156. closed: $raw['closed'] ?? null,
  157. status: $raw['status'] ?? null,
  158. items: array_map(
  159. fn (array $item) => new PagarmeOrderItemResponseData(
  160. id: $item['id'] ?? null,
  161. code: $item['code'] ?? null,
  162. amount: isset($item['amount']) ? (int) $item['amount'] : null,
  163. quantity: isset($item['quantity']) ? (int) $item['quantity'] : null,
  164. description: $item['description'] ?? null,
  165. status: $item['status'] ?? null,
  166. ),
  167. $raw['items'] ?? [],
  168. ),
  169. customer: ! empty($raw['customer'])
  170. ? $this->buildCustomerResponse($raw['customer'])
  171. : null,
  172. charges: array_map(
  173. fn (array $charge) => $this->buildChargeResponse($charge),
  174. $raw['charges'] ?? [],
  175. ),
  176. checkouts: array_map(
  177. fn (array $checkout) => new PagarmeOrderCheckoutResponseData(
  178. id: $checkout['id'] ?? null,
  179. status: $checkout['status'] ?? null,
  180. url: $checkout['url'] ?? null,
  181. ),
  182. $raw['checkouts'] ?? [],
  183. ),
  184. metadata: $raw['metadata'] ?? [],
  185. createdAt: $raw['created_at'] ?? null,
  186. updatedAt: $raw['updated_at'] ?? null,
  187. closedAt: $raw['closed_at'] ?? null,
  188. );
  189. }
  190. private function buildChargeResponse(array $raw): PagarmeOrderChargeResponseData
  191. {
  192. return new PagarmeOrderChargeResponseData(
  193. id: $raw['id'] ?? null,
  194. status: $raw['status'] ?? null,
  195. amount: isset($raw['amount']) ? (int) $raw['amount'] : null,
  196. currency: $raw['currency'] ?? null,
  197. paidAt: $raw['paid_at'] ?? null,
  198. createdAt: $raw['created_at'] ?? null,
  199. lastTransaction: ! empty($raw['last_transaction'])
  200. ? new PagarmeOrderTransactionResponseData(
  201. id: $raw['last_transaction']['id'] ?? null,
  202. status: $raw['last_transaction']['status'] ?? null,
  203. amount: isset($raw['last_transaction']['amount']) ? (int) $raw['last_transaction']['amount'] : null,
  204. createdAt: $raw['last_transaction']['created_at'] ?? null,
  205. acquirerMessage: $raw['last_transaction']['acquirer_message'] ?? null,
  206. gatewayResponse: $raw['last_transaction']['gateway_response'] ?? [],
  207. )
  208. : null,
  209. );
  210. }
  211. private function buildCustomerResponse(array $raw): PagarmeCustomerResponseData
  212. {
  213. return new PagarmeCustomerResponseData(
  214. id: $raw['id'] ?? null,
  215. name: $raw['name'] ?? null,
  216. email: $raw['email'] ?? null,
  217. code: $raw['code'] ?? null,
  218. document: $raw['document'] ?? null,
  219. documentType: $raw['document_type'] ?? null,
  220. type: $raw['type'] ?? null,
  221. delinquent: $raw['delinquent'] ?? null,
  222. address: ! empty($raw['address'])
  223. ? new PagarmeCustomerAddressResponseData(
  224. id: $raw['address']['id'] ?? null,
  225. line1: $raw['address']['line_1'] ?? null,
  226. line2: $raw['address']['line_2'] ?? null,
  227. zipCode: $raw['address']['zip_code'] ?? null,
  228. city: $raw['address']['city'] ?? null,
  229. state: $raw['address']['state'] ?? null,
  230. country: $raw['address']['country'] ?? null,
  231. status: $raw['address']['status'] ?? null,
  232. createdAt: $raw['address']['created_at'] ?? null,
  233. updatedAt: $raw['address']['updated_at'] ?? null,
  234. )
  235. : null,
  236. phones: new PagarmeCustomerPhonesResponseData(
  237. homePhone: ! empty($raw['phones']['home_phone'])
  238. ? new PagarmePhoneResponseData(
  239. countryCode: $raw['phones']['home_phone']['country_code'] ?? null,
  240. areaCode: $raw['phones']['home_phone']['area_code'] ?? null,
  241. number: $raw['phones']['home_phone']['number'] ?? null,
  242. )
  243. : null,
  244. mobilePhone: ! empty($raw['phones']['mobile_phone'])
  245. ? new PagarmePhoneResponseData(
  246. countryCode: $raw['phones']['mobile_phone']['country_code'] ?? null,
  247. areaCode: $raw['phones']['mobile_phone']['area_code'] ?? null,
  248. number: $raw['phones']['mobile_phone']['number'] ?? null,
  249. )
  250. : null,
  251. ),
  252. createdAt: $raw['created_at'] ?? null,
  253. updatedAt: $raw['updated_at'] ?? null,
  254. );
  255. }
  256. }