From 258bd3caf7058dcbd6ad8c8c78d6c43daec3c53d Mon Sep 17 00:00:00 2001 From: Joe Cohen Date: Wed, 11 Oct 2017 13:38:20 -0500 Subject: [PATCH 1/3] Fix mercadopago statues and responses --- .../MercadoPago/MercadoPagoGateway.php | 9 ++- src/Gateways/MercadoPagoBasic/Charges.php | 23 +++++- .../MercadoPagoBasicGateway.php | 78 ++++++++++++++++++- src/Status.php | 2 + 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/src/Gateways/MercadoPago/MercadoPagoGateway.php b/src/Gateways/MercadoPago/MercadoPagoGateway.php index 3ac490f..0e4c933 100644 --- a/src/Gateways/MercadoPago/MercadoPagoGateway.php +++ b/src/Gateways/MercadoPago/MercadoPagoGateway.php @@ -178,7 +178,7 @@ public function mapResponse($success, $response) } /** - * Map OpenPay response to status object. + * Map MercadoPago response to status object. * * @param array $response * @@ -189,25 +189,26 @@ protected function getStatus(array $response) switch ($status = Arr::get($response, 'status', 'paid')) { case 'authorized': case 'refunded': + case 'partially_refunded': case 'charged_back': return new Status($status); case 'approved': - case 'closed': return new Status('paid'); case 'pending': case 'in_process': case 'in_mediation': - case 'open': return new Status('pending'); case 'cancelled': return new Status('canceled'); case 'rejected': return new Status('failed'); + default: + return new Status('pending'); } } /** - * Map OpenPay response to error code object. + * Map MercadoPago response to error code object. * * @param array $response * diff --git a/src/Gateways/MercadoPagoBasic/Charges.php b/src/Gateways/MercadoPagoBasic/Charges.php index f083176..0d192cb 100644 --- a/src/Gateways/MercadoPagoBasic/Charges.php +++ b/src/Gateways/MercadoPagoBasic/Charges.php @@ -89,9 +89,26 @@ public function refund($amount, $reference, array $options = []) */ protected function addPaymentMethod(array $params, $payment, array $options) { - $params['installments'] = isset($options['monthly_installments']) && in_array($options['monthly_installments'], [3, 6, 9, 12]) - ? (int) Arr::get($options, 'monthly_installments') - : 1; + $params['payment_methods'] = []; + + if (isset($options['monthly_installments'])) { + $params['payment_methods']['installments'] = in_array($options['monthly_installments'], [3, 6, 9, 12]) + ? (int) Arr::get($options, 'monthly_installments') + : 1; + } + + if (isset($options['enabled_brands'])) { + $paymentTypes = ['prepaid_card', 'digital_currency', 'credit_card', 'debit_card', 'ticket', 'atm', 'bank_transfer']; + $enabledTypes = Arr::get($options, 'enabled_brands', []); + + $excludedTypes = array_map(function($type) { + return ['id' => $type]; + }, array_values(array_filter($paymentTypes, function ($type) use ($enabledTypes) { + return !in_array($type, $enabledTypes); + }))); + + $params['payment_methods']['excluded_payment_types'] = $excludedTypes; + } return $params; } diff --git a/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php b/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php index e997635..e326424 100644 --- a/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php +++ b/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php @@ -154,28 +154,98 @@ public function mapResponse($success, $response) 'isRedirect' => $response['isRedirect'], 'success' => $response['isRedirect'] ? false : $success, 'reference' => $success ? Arr::get($response, 'id') : null, - 'message' => $success ? 'Transaction approved' : 'Redirect', + 'message' => 'Redirect', 'test' => $this->config['test'], 'authorization' => $success ? Arr::get($response, 'init_point') : null, 'status' => $success ? new Status('pending') : new Status('failed'), 'errorCode' => $success ? null : $this->getErrorCode($response), 'type' => null, ]); - } + } return (new Response())->setRaw($rawResponse)->map([ 'isRedirect' => false, 'success' => $success, - 'reference' => $success ? Arr::get($response, 'id') : null, + 'reference' => $success ? $this->getReference($response) : null, 'message' => $success ? 'Transaction approved' : null, 'test' => $this->config['test'], - 'authorization' => $success ? Arr::get($response, 'preference_id') : null, + 'authorization' => $success ?Arr::get($response, 'id') : null, 'status' => $success ? $this->getStatus($response) : new Status('failed'), 'errorCode' => $success ? null : $this->getErrorCode($response), 'type' => Arr::get($response, 'topic'), ]); } + /** + * Get MercadoPago authorization. + * + * @param array $response + * + * @return string|null + */ + protected function getReference(array $response) + { + $payments = Arr::get($response, 'payments'); + + if (!$payments) { + return Arr::get($response, 'preference_id'); + } + + $lastPayment = end($payments); + + return Arr::get($lastPayment, 'id'); + } + + /** + * Map MercadoPago response to status object. + * + * @param array $response + * + * @return \Shoperti\PayMe\Status|null + */ + protected function getStatus(array $response) + { + $payments = Arr::get($response, 'payments'); + + if (!$payments) { + return parent::getStatus($response); + } + + $newResponse = $response; + + if (count($payments) > 1) { + $totalPaid = 0; + $totalRefund = 0; + $total = $newResponse['shipping_cost'] + $newResponse['total_amount']; + + foreach ($payments as $payment) { + if ($payment['status'] === 'approved') { + // Get the total paid amount, considering only approved incomings. + $totalPaid += $payment['total_paid_amount'] - $payment['amount_refunded']; + } elseif ($payment['status'] === 'refunded') { + // Get the total refunded amount. + $totalRefund += $payment['amount_refunded']; + } + } + + if ($totalPaid >= $total) { + $newResponse['status'] = 'approved'; + } elseif ($totalRefund >= $total) { + $newResponse['status'] = 'refunded'; + } elseif ($totalRefund > 0) { + $newResponse['status'] = 'partially_refunded'; + } else { + $newResponse['status'] = 'pending'; + } + + return parent::getStatus($newResponse); + } + + $newResponse['status'] = $payments[0]['amount_refunded'] > 0 ? 'partially_refunded' : $payments[0]['status']; + + return parent::getStatus($newResponse); + } + /** * Get the request url. * diff --git a/src/Status.php b/src/Status.php index f36800d..e6868b8 100644 --- a/src/Status.php +++ b/src/Status.php @@ -37,6 +37,8 @@ class Status 'canceled', 'trial', 'charged_back', + 'expired', + 'declined', ]; /** From 21d5b5ce4e9081146d33e2778667048a9043bec0 Mon Sep 17 00:00:00 2001 From: Joe Cohen Date: Wed, 11 Oct 2017 16:22:42 -0500 Subject: [PATCH 2/3] Fix paypal status and type --- .../PaypalExpress/PaypalExpressGateway.php | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/Gateways/PaypalExpress/PaypalExpressGateway.php b/src/Gateways/PaypalExpress/PaypalExpressGateway.php index 0c6cda4..de16034 100644 --- a/src/Gateways/PaypalExpress/PaypalExpressGateway.php +++ b/src/Gateways/PaypalExpress/PaypalExpressGateway.php @@ -218,12 +218,12 @@ public function mapResponse($success, $response) 'isRedirect' => false, 'success' => $success ? true : false, 'reference' => $success ? Arr::get($response, 'invoice') : false, - 'message' => $success ? 'Transaction approved' : 'Transaction failed', + 'message' => $success ? 'VERIFIED' : 'INVALID', 'test' => $this->config['test'], 'authorization' => $success ? Arr::get($response, 'txn_id') : '', - 'status' => $success ? new Status('paid') : new Status('failed'), + 'status' => $success ? $this->getPaymentStatus($response) : new Status('failed'), 'errorCode' => null, - 'type' => $success ? Arr::get($response, 'payment_status') : null, + 'type' => $success ? Arr::get($response, 'txn_type') : null, ]); } @@ -231,7 +231,7 @@ public function mapResponse($success, $response) 'isRedirect' => $response['isRedirect'], 'success' => $response['isRedirect'] ? false : $success, 'reference' => $success ? $this->getReference($response, $response['isRedirect']) : false, - 'message' => $success ? 'Transaction approved' : $response['L_LONGMESSAGE0'], + 'message' => $success ? Arr::get($response, 'ACK', 'Transaction approved') : $response['L_LONGMESSAGE0'], 'test' => $this->config['test'], 'authorization' => $this->getAuthorization($response, $success, $response['isRedirect']), 'status' => $success ? $this->getStatus($response, $response['isRedirect']) : new Status('failed'), @@ -311,6 +311,40 @@ protected function getStatus($response, $isRedirect) return new Status('paid'); } + /** + * Map PayPal payment response to status object. + * + * @param array $response + * + * @return \Shoperti\PayMe\Status + */ + protected function getPaymentStatus($response) + { + switch ($status = Arr::get($response, 'payment_status', 'paid')) { + case 'Completed': + case 'Processed': + return new Status('paid'); + case 'Created': + case 'Pending': + return new Status('pending'); + case 'Canceled_Reversal': + return new Status('canceled'); + case 'Failed': + case 'Denied': + return new Status('failed'); + case 'Declined': + return new Status('declined'); + case 'Expired': + return new Status('expired'); + case 'Refunded': + return new Status('refunded'); + case 'Reversed': + return new Status('charged_back'); + case 'Voided': + return new Status('voided'); + } + } + /** * Map PayPalExpress response to error code object. * From 66d046e76a4ae7a8e03519b81136c22cc58d9cb6 Mon Sep 17 00:00:00 2001 From: Joe Cohen Date: Wed, 11 Oct 2017 21:23:05 +0000 Subject: [PATCH 3/3] Apply fixes from StyleCI --- src/Gateways/MercadoPagoBasic/Charges.php | 2 +- .../MercadoPagoBasicGateway.php | 38 +++++++++---------- .../PaypalExpress/PaypalExpressGateway.php | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Gateways/MercadoPagoBasic/Charges.php b/src/Gateways/MercadoPagoBasic/Charges.php index 0d192cb..b54dc10 100644 --- a/src/Gateways/MercadoPagoBasic/Charges.php +++ b/src/Gateways/MercadoPagoBasic/Charges.php @@ -101,7 +101,7 @@ protected function addPaymentMethod(array $params, $payment, array $options) $paymentTypes = ['prepaid_card', 'digital_currency', 'credit_card', 'debit_card', 'ticket', 'atm', 'bank_transfer']; $enabledTypes = Arr::get($options, 'enabled_brands', []); - $excludedTypes = array_map(function($type) { + $excludedTypes = array_map(function ($type) { return ['id' => $type]; }, array_values(array_filter($paymentTypes, function ($type) use ($enabledTypes) { return !in_array($type, $enabledTypes); diff --git a/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php b/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php index e326424..3855e3e 100644 --- a/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php +++ b/src/Gateways/MercadoPagoBasic/MercadoPagoBasicGateway.php @@ -161,7 +161,7 @@ public function mapResponse($success, $response) 'errorCode' => $success ? null : $this->getErrorCode($response), 'type' => null, ]); - } + } return (new Response())->setRaw($rawResponse)->map([ 'isRedirect' => false, @@ -169,7 +169,7 @@ public function mapResponse($success, $response) 'reference' => $success ? $this->getReference($response) : null, 'message' => $success ? 'Transaction approved' : null, 'test' => $this->config['test'], - 'authorization' => $success ?Arr::get($response, 'id') : null, + 'authorization' => $success ? Arr::get($response, 'id') : null, 'status' => $success ? $this->getStatus($response) : new Status('failed'), 'errorCode' => $success ? null : $this->getErrorCode($response), 'type' => Arr::get($response, 'topic'), @@ -180,7 +180,7 @@ public function mapResponse($success, $response) * Get MercadoPago authorization. * * @param array $response - * + * * @return string|null */ protected function getReference(array $response) @@ -190,7 +190,7 @@ protected function getReference(array $response) if (!$payments) { return Arr::get($response, 'preference_id'); } - + $lastPayment = end($payments); return Arr::get($lastPayment, 'id'); @@ -216,23 +216,23 @@ protected function getStatus(array $response) if (count($payments) > 1) { $totalPaid = 0; $totalRefund = 0; - $total = $newResponse['shipping_cost'] + $newResponse['total_amount']; + $total = $newResponse['shipping_cost'] + $newResponse['total_amount']; foreach ($payments as $payment) { - if ($payment['status'] === 'approved') { - // Get the total paid amount, considering only approved incomings. - $totalPaid += $payment['total_paid_amount'] - $payment['amount_refunded']; - } elseif ($payment['status'] === 'refunded') { - // Get the total refunded amount. - $totalRefund += $payment['amount_refunded']; - } + if ($payment['status'] === 'approved') { + // Get the total paid amount, considering only approved incomings. + $totalPaid += $payment['total_paid_amount'] - $payment['amount_refunded']; + } elseif ($payment['status'] === 'refunded') { + // Get the total refunded amount. + $totalRefund += $payment['amount_refunded']; + } } - - if ($totalPaid >= $total) { - $newResponse['status'] = 'approved'; - } elseif ($totalRefund >= $total) { - $newResponse['status'] = 'refunded'; - } elseif ($totalRefund > 0) { + + if ($totalPaid >= $total) { + $newResponse['status'] = 'approved'; + } elseif ($totalRefund >= $total) { + $newResponse['status'] = 'refunded'; + } elseif ($totalRefund > 0) { $newResponse['status'] = 'partially_refunded'; } else { $newResponse['status'] = 'pending'; @@ -242,7 +242,7 @@ protected function getStatus(array $response) } $newResponse['status'] = $payments[0]['amount_refunded'] > 0 ? 'partially_refunded' : $payments[0]['status']; - + return parent::getStatus($newResponse); } diff --git a/src/Gateways/PaypalExpress/PaypalExpressGateway.php b/src/Gateways/PaypalExpress/PaypalExpressGateway.php index de16034..1724656 100644 --- a/src/Gateways/PaypalExpress/PaypalExpressGateway.php +++ b/src/Gateways/PaypalExpress/PaypalExpressGateway.php @@ -325,7 +325,7 @@ protected function getPaymentStatus($response) case 'Processed': return new Status('paid'); case 'Created': - case 'Pending': + case 'Pending': return new Status('pending'); case 'Canceled_Reversal': return new Status('canceled');