|
@@ -61,7 +61,11 @@ class PagarmePaymentService
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function createOrder(
|
|
public function createOrder(
|
|
|
- Payment $payment, array $items, array $customer, array $paymentMethod, array $options = []
|
|
|
|
|
|
|
+ Payment $payment,
|
|
|
|
|
+ array $items,
|
|
|
|
|
+ array $customer,
|
|
|
|
|
+ array $paymentMethod,
|
|
|
|
|
+ array $options = []
|
|
|
): array {
|
|
): array {
|
|
|
if (empty($items)) {
|
|
if (empty($items)) {
|
|
|
throw new \InvalidArgumentException('items nao pode estar vazio.');
|
|
throw new \InvalidArgumentException('items nao pode estar vazio.');
|
|
@@ -71,11 +75,24 @@ class PagarmePaymentService
|
|
|
throw new \InvalidArgumentException('payment_method e obrigatorio.');
|
|
throw new \InvalidArgumentException('payment_method e obrigatorio.');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (! in_array($paymentMethod['payment_method'], ['credit_card', 'pix'], true)) {
|
|
|
|
|
+ throw new \InvalidArgumentException('payment_method deve ser credit_card ou pix.');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $customerPayload = $options['customer_id'] ?? null;
|
|
|
|
|
+
|
|
|
|
|
+ if (! $this->filled($customerPayload)) {
|
|
|
|
|
+ $customerPayload = $this->filterFilledRecursive($customer);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (empty($customerPayload)) {
|
|
|
|
|
+ throw new \InvalidArgumentException('customer ou customer_id e obrigatorio.');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
$payload = [
|
|
$payload = [
|
|
|
'code' => $options['order_code'] ?? "payment-{$payment->id}",
|
|
'code' => $options['order_code'] ?? "payment-{$payment->id}",
|
|
|
- 'items' => $items,
|
|
|
|
|
- 'customer' => $customer,
|
|
|
|
|
- 'payments' => [$paymentMethod],
|
|
|
|
|
|
|
+ 'items' => $this->validateItems($items),
|
|
|
|
|
+ 'payments' => [$this->filterFilledRecursive($paymentMethod)],
|
|
|
'closed' => $options['closed'] ?? true,
|
|
'closed' => $options['closed'] ?? true,
|
|
|
|
|
|
|
|
'metadata' => array_merge([
|
|
'metadata' => array_merge([
|
|
@@ -86,6 +103,12 @@ class PagarmePaymentService
|
|
|
], $options['metadata'] ?? []),
|
|
], $options['metadata'] ?? []),
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
|
|
+ if (is_string($customerPayload)) {
|
|
|
|
|
+ $payload['customer_id'] = $customerPayload;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $payload['customer'] = $customerPayload;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (! empty($options['channel'])) {
|
|
if (! empty($options['channel'])) {
|
|
|
$payload['channel'] = $options['channel'];
|
|
$payload['channel'] = $options['channel'];
|
|
|
}
|
|
}
|
|
@@ -119,9 +142,11 @@ class PagarmePaymentService
|
|
|
|
|
|
|
|
public function applyGatewayResponseToPayment(Payment $payment, array $orderResponse): Payment
|
|
public function applyGatewayResponseToPayment(Payment $payment, array $orderResponse): Payment
|
|
|
{
|
|
{
|
|
|
- $charge = $orderResponse['charges'][0] ?? [];
|
|
|
|
|
- $transaction = $charge['last_transaction'] ?? [];
|
|
|
|
|
- $chargeStatus = $charge['status'] ?? null;
|
|
|
|
|
|
|
+ $charge = $orderResponse['charges'][0] ?? [];
|
|
|
|
|
+
|
|
|
|
|
+ $transaction = $charge['last_transaction'] ?? [];
|
|
|
|
|
+ $chargeStatus = $charge['status'] ?? null;
|
|
|
|
|
+
|
|
|
$transactionStatus = $transaction['status'] ?? null;
|
|
$transactionStatus = $transaction['status'] ?? null;
|
|
|
|
|
|
|
|
$payment->forceFill([
|
|
$payment->forceFill([
|
|
@@ -131,7 +156,7 @@ class PagarmePaymentService
|
|
|
'gateway_operation_reference' => $transaction['id'] ?? $charge['id'] ?? $orderResponse['id'] ?? null,
|
|
'gateway_operation_reference' => $transaction['id'] ?? $charge['id'] ?? $orderResponse['id'] ?? null,
|
|
|
'gateway_operation_label' => isset($transaction['id']) ? 'transaction' : (isset($charge['id']) ? 'charge' : 'order'),
|
|
'gateway_operation_label' => isset($transaction['id']) ? 'transaction' : (isset($charge['id']) ? 'charge' : 'order'),
|
|
|
'status' => $this->mapPaymentStatus($chargeStatus, $transactionStatus),
|
|
'status' => $this->mapPaymentStatus($chargeStatus, $transactionStatus),
|
|
|
- 'paid_at' => $charge['paid_at'] ?? null,
|
|
|
|
|
|
|
+ 'paid_at' => $this->filledArrayValue($charge, 'paid_at'),
|
|
|
'authorized_at' => $this->resolveAuthorizedAt($transactionStatus, $transaction),
|
|
'authorized_at' => $this->resolveAuthorizedAt($transactionStatus, $transaction),
|
|
|
'gateway_payload' => $orderResponse,
|
|
'gateway_payload' => $orderResponse,
|
|
|
'failure_code' => $this->extractFailureCode($transaction),
|
|
'failure_code' => $this->extractFailureCode($transaction),
|
|
@@ -151,11 +176,16 @@ class PagarmePaymentService
|
|
|
->filter(fn (PaymentTransfer $transfer) => ! empty($transfer->gateway_transfer_target_reference))
|
|
->filter(fn (PaymentTransfer $transfer) => ! empty($transfer->gateway_transfer_target_reference))
|
|
|
->map(function (PaymentTransfer $transfer) {
|
|
->map(function (PaymentTransfer $transfer) {
|
|
|
return [
|
|
return [
|
|
|
- 'amount' => $this->toGatewayAmountInCents((float) $transfer->gross_amount),
|
|
|
|
|
- 'recipient_id' => $transfer->gateway_transfer_target_reference,
|
|
|
|
|
- 'type' => 'flat',
|
|
|
|
|
- ];
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ 'amount' => $this->toGatewayAmountInCents((float) $transfer->gross_amount),
|
|
|
|
|
+ 'recipient_id' => $transfer->gateway_transfer_target_reference,
|
|
|
|
|
+ 'type' => 'flat',
|
|
|
|
|
+ 'options' => [
|
|
|
|
|
+ 'charge_processing_fee' => false,
|
|
|
|
|
+ 'charge_remainder_fee' => false,
|
|
|
|
|
+ 'liable' => false,
|
|
|
|
|
+ ],
|
|
|
|
|
+ ];
|
|
|
|
|
+ })
|
|
|
->values()
|
|
->values()
|
|
|
->all();
|
|
->all();
|
|
|
}
|
|
}
|
|
@@ -202,7 +232,7 @@ class PagarmePaymentService
|
|
|
'channel',
|
|
'channel',
|
|
|
'payment_origin',
|
|
'payment_origin',
|
|
|
] as $field) {
|
|
] as $field) {
|
|
|
- if (array_key_exists($field, $creditCard)) {
|
|
|
|
|
|
|
+ if (array_key_exists($field, $creditCard) && $this->filled($creditCard[$field])) {
|
|
|
$payload[$field] = $creditCard[$field];
|
|
$payload[$field] = $creditCard[$field];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -227,14 +257,14 @@ class PagarmePaymentService
|
|
|
|
|
|
|
|
private function buildPixPayload(array $pix): array
|
|
private function buildPixPayload(array $pix): array
|
|
|
{
|
|
{
|
|
|
- if (empty($pix['expires_in']) && empty($pix['expires_at'])) {
|
|
|
|
|
|
|
+ if (! $this->filled($pix['expires_in'] ?? null) && ! $this->filled($pix['expires_at'] ?? null)) {
|
|
|
throw new \InvalidArgumentException('pix.expires_in ou pix.expires_at e obrigatorio.');
|
|
throw new \InvalidArgumentException('pix.expires_in ou pix.expires_at e obrigatorio.');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
$payload = [];
|
|
$payload = [];
|
|
|
|
|
|
|
|
foreach (['expires_in', 'expires_at', 'additional_information'] as $field) {
|
|
foreach (['expires_in', 'expires_at', 'additional_information'] as $field) {
|
|
|
- if (array_key_exists($field, $pix)) {
|
|
|
|
|
|
|
+ if (array_key_exists($field, $pix) && $this->filled($pix[$field])) {
|
|
|
$payload[$field] = $pix[$field];
|
|
$payload[$field] = $pix[$field];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -247,7 +277,7 @@ class PagarmePaymentService
|
|
|
private function resolveAuthorizedAt(?string $transactionStatus, array $transaction): ?string
|
|
private function resolveAuthorizedAt(?string $transactionStatus, array $transaction): ?string
|
|
|
{
|
|
{
|
|
|
if (in_array($transactionStatus, ['authorized_pending_capture', 'captured', 'partial_capture'], true)) {
|
|
if (in_array($transactionStatus, ['authorized_pending_capture', 'captured', 'partial_capture'], true)) {
|
|
|
- return $transaction['created_at'] ?? now()->toISOString();
|
|
|
|
|
|
|
+ return $this->filledArrayValue($transaction, 'created_at');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
return null;
|
|
@@ -257,12 +287,71 @@ class PagarmePaymentService
|
|
|
|
|
|
|
|
private function extractFailureCode(array $transaction): ?string
|
|
private function extractFailureCode(array $transaction): ?string
|
|
|
{
|
|
{
|
|
|
- return $transaction['gateway_response']['code'] ?? null;
|
|
|
|
|
|
|
+ return $this->filledArrayValue($transaction['gateway_response'] ?? [], 'code');
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private function extractFailureMessage(array $transaction): ?string
|
|
private function extractFailureMessage(array $transaction): ?string
|
|
|
{
|
|
{
|
|
|
- return $transaction['acquirer_message'] ?? null;
|
|
|
|
|
|
|
+ return $this->filledArrayValue($transaction, 'acquirer_message');
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param array<int, array<string, mixed>> $items
|
|
|
|
|
+ * @return array<int, array<string, mixed>>
|
|
|
|
|
+ */
|
|
|
|
|
+ private function validateItems(array $items): array
|
|
|
|
|
+ {
|
|
|
|
|
+ return collect($items)
|
|
|
|
|
+ ->map(function (array $item, int $index) {
|
|
|
|
|
+ foreach (['code', 'amount', 'quantity'] as $field) {
|
|
|
|
|
+ if (! array_key_exists($field, $item) || ! $this->filled($item[$field])) {
|
|
|
|
|
+ throw new \InvalidArgumentException("items.{$index}.{$field} e obrigatorio.");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ((int) $item['amount'] <= 0 || (int) $item['quantity'] <= 0) {
|
|
|
|
|
+ throw new \InvalidArgumentException("items.{$index}.amount e quantity devem ser maiores que zero.");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $this->filterFilledRecursive($item);
|
|
|
|
|
+ })
|
|
|
|
|
+ ->values()
|
|
|
|
|
+ ->all();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function filledArrayValue(array $data, string $field): ?string
|
|
|
|
|
+ {
|
|
|
|
|
+ if (! array_key_exists($field, $data) || ! $this->filled($data[$field])) {
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return (string) $data[$field];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param array<string, mixed> $data
|
|
|
|
|
+ * @return array<string, mixed>
|
|
|
|
|
+ */
|
|
|
|
|
+ private function filterFilledRecursive(array $data): array
|
|
|
|
|
+ {
|
|
|
|
|
+ $filtered = [];
|
|
|
|
|
+
|
|
|
|
|
+ foreach ($data as $key => $value) {
|
|
|
|
|
+ if (is_array($value)) {
|
|
|
|
|
+ $value = $this->filterFilledRecursive($value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ($this->filled($value)) {
|
|
|
|
|
+ $filtered[$key] = $value;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return $filtered;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function filled(mixed $value): bool
|
|
|
|
|
+ {
|
|
|
|
|
+ return $value !== null && $value !== '' && $value !== [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|