From 2a46679815aae9a727944796d9543f92f77ad3fc Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 16:27:27 -0300 Subject: [PATCH 01/11] Runtime enviroment New InvalidArgumentException, changes in MPDefaultHttpClient and MercadoPagoConfig --- .../Exceptions/InvalidArgumentException.php | 10 ++++++ src/MercadoPago/MercadoPagoConfig.php | 32 +++++++++++++++++++ src/MercadoPago/Net/MPDefaultHttpClient.php | 9 +++++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/MercadoPago/Exceptions/InvalidArgumentException.php diff --git a/src/MercadoPago/Exceptions/InvalidArgumentException.php b/src/MercadoPago/Exceptions/InvalidArgumentException.php new file mode 100644 index 00000000..f231fe46 --- /dev/null +++ b/src/MercadoPago/Exceptions/InvalidArgumentException.php @@ -0,0 +1,10 @@ + 'local', + self::SERVER => 'server' + ]; + + /** @var string Actual enviroment the user is running at. Default is SERVER */ + private static string $RUNTIME_ENVIROMENT = self::RUNTIME_ENVIROMENTS::LOCAL; + /** @var string access token */ private static string $access_token = ""; @@ -216,4 +226,26 @@ public static function setConnectionTimeout(int $connection_timeout): void { self::$connection_timeout = $connection_timeout; } + + /** + * Gets the enviroment the user is running at. + * @return string enviroment + */ + public static function getEnviroment(): string + { + return self::$RUNTIME_ENVIROMENT; + } + + /** + * Sets the enviroment the user is running at. + * @param string $enviroment one of the ENVIROMENT_TYPES + * @return void + */ + public static function setEnviroment(string $enviroment): void + { + if (!in_array($enviroment, self::RUNTIME_ENVIROMENTS)) { + throw new InvalidArgumentException("Enviroment must be equal to one of the options in MercadoPagoConfig::RUNTIME_ENVIROMENTS."); + } + self::$ENVIROMENT = $enviroment; + } } diff --git a/src/MercadoPago/Net/MPDefaultHttpClient.php b/src/MercadoPago/Net/MPDefaultHttpClient.php index affcc503..a89d4780 100644 --- a/src/MercadoPago/Net/MPDefaultHttpClient.php +++ b/src/MercadoPago/Net/MPDefaultHttpClient.php @@ -89,7 +89,7 @@ private function createHttpRequestOptions(MPRequest $request): array { $connection_timeout = $request->getConnectionTimeout() ?: MercadoPagoConfig::getConnectionTimeout(); - return array( + $options = array( CURLOPT_URL => MercadoPagoConfig::$BASE_URL . $request->getUri(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_HTTPHEADER => $request->getHeaders(), @@ -98,6 +98,13 @@ private function createHttpRequestOptions(MPRequest $request): array CURLOPT_MAXCONNECTS => MercadoPagoConfig::getMaxConnections(), CURLOPT_RETURNTRANSFER => true ); + + if (MercadoPagoConfig::getEnviroment() === MercadoPagoConfig::ENVIROMENT_TYPES::LOCAL) { + $options['CURLOPT_SSL_VERIFYHOST'] = false; + $options['CURLOPT_SSL_VERIFYPEER'] = false; + } + + return $options; } private function isServerError(int $status_code): bool From aa4f74e80439d97f1b987d7bffda21fcb3af1b13 Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 16:32:26 -0300 Subject: [PATCH 02/11] Naming and docs Renamed getter and setter to correspond naming of the runtime enviroment + docs --- README.md | 9 +++++++++ src/MercadoPago/MercadoPagoConfig.php | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7d92b90a..50a44631 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ Simple usage looks like: // Step 2: Set production or sandbox access token MercadoPagoConfig::setAccessToken(""); + // Step 2.2: Set your runtime enviroment from MercadoPagoConfig::RUNTIME_ENVIROMENTS (default is SERVER) + MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::RUNTIME_ENVIROMENTS::LOCAL); // Step 3: Initialize the API client $client = new PaymentClient(); @@ -77,6 +79,7 @@ Simple usage looks like: ``` ### Step 1: Require the library from your Composer vendor folder + ```php require_once 'vendor/autoload.php'; @@ -86,6 +89,7 @@ use MercadoPago\MercadoPagoConfig; ``` ### Step 2: Set production or sandbox access token + ```php MercadoPagoConfig::setAccessToken(""); ``` @@ -93,11 +97,13 @@ MercadoPagoConfig::setAccessToken(""); You can also set another properties as quantity of retries, tracking headers, timeouts and a custom http client. ### Step 3: Initialize the API client + ```php $client = new PaymentClient(); ``` ### Step 4: Create the request array + ```php $request = [ "transaction_amount" => 100, @@ -112,11 +118,13 @@ $request = [ ``` ### Step 5: Make the request + ```php $payment = $client->create($request); ``` ### Step 6: Handle exceptions + ```php ... // Handle API exceptions @@ -144,6 +152,7 @@ Please read and follow our [contribution guidelines](CONTRIBUTING.md). Contribut be disregarded. The guidelines are in place to make all of our lives easier and make contribution a consistent process for everyone. ### Patches to version 2.x.x + Since the release of version 3.0.0, version 2 is deprecated and will not be receiving new features, only bug fixes. If you need to submit PRs for that version, please do so by using [master-v2](https://github.com/mercadopago/sdk-php/tree/master-v2) as your base branch. ## ❤️ Support diff --git a/src/MercadoPago/MercadoPagoConfig.php b/src/MercadoPago/MercadoPagoConfig.php index 2dc07cda..5fbc5aad 100644 --- a/src/MercadoPago/MercadoPagoConfig.php +++ b/src/MercadoPago/MercadoPagoConfig.php @@ -231,7 +231,7 @@ public static function setConnectionTimeout(int $connection_timeout): void * Gets the enviroment the user is running at. * @return string enviroment */ - public static function getEnviroment(): string + public static function getRuntimeEnviroment(): string { return self::$RUNTIME_ENVIROMENT; } @@ -241,7 +241,7 @@ public static function getEnviroment(): string * @param string $enviroment one of the ENVIROMENT_TYPES * @return void */ - public static function setEnviroment(string $enviroment): void + public static function setRuntimeEnviroment(string $enviroment): void { if (!in_array($enviroment, self::RUNTIME_ENVIROMENTS)) { throw new InvalidArgumentException("Enviroment must be equal to one of the options in MercadoPagoConfig::RUNTIME_ENVIROMENTS."); From fefcb0fb6a62b1fe8ef95833abeb08590f3cce78 Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 17:05:43 -0300 Subject: [PATCH 03/11] MercadoPagoConfig constants Changed names and types for runtime enviroments in MercadoPagoConfig --- src/MercadoPago/MercadoPagoConfig.php | 21 +++++++++++---------- src/MercadoPago/Net/MPDefaultHttpClient.php | 2 +- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/MercadoPago/MercadoPagoConfig.php b/src/MercadoPago/MercadoPagoConfig.php index 5fbc5aad..6ed0e903 100644 --- a/src/MercadoPago/MercadoPagoConfig.php +++ b/src/MercadoPago/MercadoPagoConfig.php @@ -5,6 +5,7 @@ use MercadoPago\Exceptions\InvalidArgumentException; use MercadoPago\Net\MPDefaultHttpClient; use MercadoPago\Net\MPHttpClient; +use App\Enum; /** Mercado Pago configuration class. */ class MercadoPagoConfig @@ -18,14 +19,14 @@ class MercadoPagoConfig /** @var string Mercado Pago SDK PHP product version */ public static string $PRODUCT_ID = "BC32A7RU643001OI3940"; - /** @var array Types of enviroments the user can run at (local machine or server) */ - public const RUNTIME_ENVIROMENTS = [ - self::LOCAL => 'local', - self::SERVER => 'server' - ]; + /** @var string Class constant for local runtime enviroment */ + const LOCAL = 'local'; + + /** @var string Class constant for server runtime enviroment */ + const SERVER = 'server'; /** @var string Actual enviroment the user is running at. Default is SERVER */ - private static string $RUNTIME_ENVIROMENT = self::RUNTIME_ENVIROMENTS::LOCAL; + private static string $runtime_enviroment = self::LOCAL; /** @var string access token */ private static string $access_token = ""; @@ -233,7 +234,7 @@ public static function setConnectionTimeout(int $connection_timeout): void */ public static function getRuntimeEnviroment(): string { - return self::$RUNTIME_ENVIROMENT; + return self::$runtime_enviroment; } /** @@ -243,9 +244,9 @@ public static function getRuntimeEnviroment(): string */ public static function setRuntimeEnviroment(string $enviroment): void { - if (!in_array($enviroment, self::RUNTIME_ENVIROMENTS)) { - throw new InvalidArgumentException("Enviroment must be equal to one of the options in MercadoPagoConfig::RUNTIME_ENVIROMENTS."); + if ($enviroment != self::LOCAL && $enviroment != self::SERVER) { + throw new InvalidArgumentException("Enviroment must be equal to MercadoPagoConfig::LOCAL or MercadoPagoConfig::SERVER."); } - self::$ENVIROMENT = $enviroment; + self::$runtime_enviroment = $enviroment; } } diff --git a/src/MercadoPago/Net/MPDefaultHttpClient.php b/src/MercadoPago/Net/MPDefaultHttpClient.php index a89d4780..6a407053 100644 --- a/src/MercadoPago/Net/MPDefaultHttpClient.php +++ b/src/MercadoPago/Net/MPDefaultHttpClient.php @@ -99,7 +99,7 @@ private function createHttpRequestOptions(MPRequest $request): array CURLOPT_RETURNTRANSFER => true ); - if (MercadoPagoConfig::getEnviroment() === MercadoPagoConfig::ENVIROMENT_TYPES::LOCAL) { + if (MercadoPagoConfig::getRuntimeEnviroment() === MercadoPagoConfig::LOCAL) { $options['CURLOPT_SSL_VERIFYHOST'] = false; $options['CURLOPT_SSL_VERIFYPEER'] = false; } From dd49ab6aa8d999ef8b912db32680cb681f442c1a Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 17:06:22 -0300 Subject: [PATCH 04/11] Removed 'use App\Enum' from MercadoPagoConfig --- src/MercadoPago/MercadoPagoConfig.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/MercadoPago/MercadoPagoConfig.php b/src/MercadoPago/MercadoPagoConfig.php index 6ed0e903..77511d97 100644 --- a/src/MercadoPago/MercadoPagoConfig.php +++ b/src/MercadoPago/MercadoPagoConfig.php @@ -5,7 +5,6 @@ use MercadoPago\Exceptions\InvalidArgumentException; use MercadoPago\Net\MPDefaultHttpClient; use MercadoPago\Net\MPHttpClient; -use App\Enum; /** Mercado Pago configuration class. */ class MercadoPagoConfig From fb82df99734c5878b88dc003d468b74de1fa9126 Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 18:29:25 -0300 Subject: [PATCH 05/11] Testing MPDefaultHttpClient with error_log --- src/MercadoPago/Net/MPDefaultHttpClient.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/MercadoPago/Net/MPDefaultHttpClient.php b/src/MercadoPago/Net/MPDefaultHttpClient.php index 6a407053..a5dd8769 100644 --- a/src/MercadoPago/Net/MPDefaultHttpClient.php +++ b/src/MercadoPago/Net/MPDefaultHttpClient.php @@ -58,6 +58,8 @@ public function send(MPRequest $request): MPResponse private function makeRequest(MPRequest $request): MPResponse { $request_options = $this->createHttpRequestOptions($request); + error_log("request_options"); + error_log(json_encode($request_options)); $this->httpRequest->setOptionArray($request_options); $api_result = $this->httpRequest->execute(); $status_code = $this->httpRequest->getInfo(CURLINFO_HTTP_CODE); @@ -100,8 +102,8 @@ private function createHttpRequestOptions(MPRequest $request): array ); if (MercadoPagoConfig::getRuntimeEnviroment() === MercadoPagoConfig::LOCAL) { - $options['CURLOPT_SSL_VERIFYHOST'] = false; - $options['CURLOPT_SSL_VERIFYPEER'] = false; + $options += [CURLOPT_SSL_VERIFYHOST => false]; + $options += [CURLOPT_SSL_VERIFYPEER => false]; } return $options; From 5f971bc290f1355ab4ff4272b29e44d8e97943eb Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 18:37:09 -0300 Subject: [PATCH 06/11] Removing error_log from MPDefaultHttpClient --- src/MercadoPago/Net/MPDefaultHttpClient.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/MercadoPago/Net/MPDefaultHttpClient.php b/src/MercadoPago/Net/MPDefaultHttpClient.php index a5dd8769..0352db7a 100644 --- a/src/MercadoPago/Net/MPDefaultHttpClient.php +++ b/src/MercadoPago/Net/MPDefaultHttpClient.php @@ -58,8 +58,6 @@ public function send(MPRequest $request): MPResponse private function makeRequest(MPRequest $request): MPResponse { $request_options = $this->createHttpRequestOptions($request); - error_log("request_options"); - error_log(json_encode($request_options)); $this->httpRequest->setOptionArray($request_options); $api_result = $this->httpRequest->execute(); $status_code = $this->httpRequest->getInfo(CURLINFO_HTTP_CODE); From 8cff3a03ab58ed2ec444af564f05c0f336a8715a Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 19:42:12 -0300 Subject: [PATCH 07/11] Default runtime enviroment in MercadoPagoConfig is SERVER. Patch on README.md --- README.md | 2 +- src/MercadoPago/MercadoPagoConfig.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 50a44631..3699954b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Simple usage looks like: // Step 2: Set production or sandbox access token MercadoPagoConfig::setAccessToken(""); - // Step 2.2: Set your runtime enviroment from MercadoPagoConfig::RUNTIME_ENVIROMENTS (default is SERVER) + // Step 2.1 (optional - default is SERVER): Set your runtime enviroment from MercadoPagoConfig::RUNTIME_ENVIROMENTS MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::RUNTIME_ENVIROMENTS::LOCAL); // Step 3: Initialize the API client diff --git a/src/MercadoPago/MercadoPagoConfig.php b/src/MercadoPago/MercadoPagoConfig.php index 77511d97..031a6de4 100644 --- a/src/MercadoPago/MercadoPagoConfig.php +++ b/src/MercadoPago/MercadoPagoConfig.php @@ -25,7 +25,7 @@ class MercadoPagoConfig const SERVER = 'server'; /** @var string Actual enviroment the user is running at. Default is SERVER */ - private static string $runtime_enviroment = self::LOCAL; + private static string $runtime_enviroment = self::SERVER; /** @var string access token */ private static string $access_token = ""; From c89b50f18503e883af85fd7112322c4801d9ad5e Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 20:29:03 -0300 Subject: [PATCH 08/11] Patched README.md with checkout pro flow --- README.md | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3699954b..a23ae4d3 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,14 @@ composer require "mercadopago/dx-php:3.0.0" That's it! Mercado Pago SDK has been successfully installed. -## 🌟 Getting Started +## Useful links + +- [SDK Docs](https://www.mercadopago.com.br/developers/pt/docs/sdks-library/server-side) +- [REST API (consumed by the SDK)](https://www.mercadopago.com.br/developers/en/reference) + +Here you can check eg. data structures for each parameter used by the SDK for each class. + +## 🌟 Getting Started with payment data collected in your own website forms Simple usage looks like: @@ -46,7 +53,8 @@ Simple usage looks like: // Step 2: Set production or sandbox access token MercadoPagoConfig::setAccessToken(""); // Step 2.1 (optional - default is SERVER): Set your runtime enviroment from MercadoPagoConfig::RUNTIME_ENVIROMENTS - MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::RUNTIME_ENVIROMENTS::LOCAL); + // In case you want to test in your local machine first, set runtime enviroment to LOCAL + MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::LOCAL); // Step 3: Initialize the API client $client = new PaymentClient(); @@ -138,6 +146,129 @@ $payment = $client->create($request); } ``` +## 🌟 Getting started with payment data collected via Checkout Pro + +### Step 1: Require the libraries + +```php +use MercadoPago\MercadoPagoConfig; +use MercadoPago\Client\Preference\PreferenceClient; +use MercadoPago\Exceptions\MPApiException; +use Log; +``` + +### Step 2: Create an authentication function + +```php +protected function authenticate() +{ + // Getting the access token from .env file (create your own function) + $mpAccessToken = getVariableFromEnv('mercado_pago_access_token'); + // Set the token the SDK's config + MercadoPagoConfig::setAccessToken($mpAccessToken); + // (Optional) Set the runtime enviroment to LOCAL if you want to test on localhost + // Default value is set to SERVER + MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::LOCAL); +} +``` + +### Step 3: Create customer's preference before proceeding to Checkout Pro page + +```php +// Function that will return a request object to be sent to Mercado Pago API +function createPreferenceRequest($items, $payer): array +{ + $paymentMethods = [ + "excluded_payment_methods" => [], + "installments" => 12, + "default_installments" => 1 + ]; + + $backUrls = array( + 'success' => route('mercadopago.success'), + 'failure' => route('mercadopago.failed') + ); + + $request = [ + "items" => $items, + "payer" => $payer, + "payment_methods" => $paymentMethods, + "back_urls" => $backUrls, + "statement_descriptor" => "NAME_DISPLAYED_IN_USER_BILLING", + "external_reference" => "1234567890", + "expires" => false, + "auto_return" => 'approved', + ]; + + return $request; +} +``` + +### Step 4: Create the preference on Mercado Pago and retrieve it's ID [docs](https://www.mercadopago.com.br/developers/pt/docs/sdks-library/server-side/php/preferences) + +```php +public function createPaymentPreference(): ?Preference +{ + // Fill the data about the product(s) being pruchased + $product1 = array( + "id" => "1234567890", + "title" => "Product 1 Title", + "description" => "Product 1 Description", + "currency_id" => "BRL", + "quantity" => 12, + "unit_price" => 9.90 + ); + + $product2 = array( + "id" => "9012345678", + "title" => "Product 2 Title", + "description" => "Product 2 Description", + "currency_id" => "BRL", + "quantity" => 5, + "unit_price" => 19.90 + ); + + // Mount the array of products that will integrate the purchase amount + $items = array($product1, $product2); + + // Retrieve information about the user (use your own function) + $user = getSessionUser(); + + $payer = array( + "name" => $user->name, + "surname" => $user->surname, + "email" => $user->email, + ); + + // Create the request object to be sent to the API when the preference is created + $request = createPreferenceRequest($item, $payer); + + // Instantiate a new Preference Client + $client = new PreferenceClient(); + + try { + // Send the request that will create the new preference for user's checkout flow + $preference = $client->create($request); + + // Useful props you could use from this object is 'init_point' (URL to Checkout Pro) or the 'id' + return $preference; + } catch (MPApiException $error) { + Log::debug("Error creating Preference: " . $error->getApiResponse()); + + // Here you might return whatever your app needs. + // We are returning null here as an example. + return null; + } +} +``` + +In case you need to retrieve the preference by ID: + +```php + $client = new PreferenceClient(); + $client->get("123456789"); +``` + ## 📚 Documentation See our documentation for more details. From 7231abad18e663f751f9262eede19d3ddec68540 Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 20:31:41 -0300 Subject: [PATCH 09/11] Patch to README.md shrinking section texts --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index a23ae4d3..f069085a 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ That's it! Mercado Pago SDK has been successfully installed. Here you can check eg. data structures for each parameter used by the SDK for each class. -## 🌟 Getting Started with payment data collected in your own website forms +## 🌟 Getting Started with payment via your own website forms Simple usage looks like: @@ -134,19 +134,19 @@ $payment = $client->create($request); ### Step 6: Handle exceptions ```php -... -// Handle API exceptions +try{ + // Do your stuff here } catch (MPApiException $e) { + // Handle API exceptions echo "Status code: " . $e->getApiResponse()->getStatusCode() . "\n"; echo "Content: " . $e->getApiResponse()->getContent() . "\n"; - -// Handle all other exceptions } catch (\Exception $e) { + // Handle all other exceptions echo $e->getMessage(); } ``` -## 🌟 Getting started with payment data collected via Checkout Pro +## 🌟 Getting started with payment via Checkout Pro ### Step 1: Require the libraries From 70049c2aa36c3cba896d01ce798e8c4801c90269 Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 20:41:14 -0300 Subject: [PATCH 10/11] Removed Log::debug from README.md examples --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index f069085a..c52a6a05 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,6 @@ try{ use MercadoPago\MercadoPagoConfig; use MercadoPago\Client\Preference\PreferenceClient; use MercadoPago\Exceptions\MPApiException; -use Log; ``` ### Step 2: Create an authentication function @@ -253,8 +252,6 @@ public function createPaymentPreference(): ?Preference // Useful props you could use from this object is 'init_point' (URL to Checkout Pro) or the 'id' return $preference; } catch (MPApiException $error) { - Log::debug("Error creating Preference: " . $error->getApiResponse()); - // Here you might return whatever your app needs. // We are returning null here as an example. return null; From ebb747674da2a7370e167c6d47ace413d7b26b5a Mon Sep 17 00:00:00 2001 From: Marcelino Borges Date: Sun, 3 Dec 2023 20:43:39 -0300 Subject: [PATCH 11/11] Fix on Checkout Pro example Step 4 text on README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c52a6a05..5ad7394c 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ function createPreferenceRequest($items, $payer): array } ``` -### Step 4: Create the preference on Mercado Pago and retrieve it's ID [docs](https://www.mercadopago.com.br/developers/pt/docs/sdks-library/server-side/php/preferences) +### Step 4: Create the preference on Mercado Pago ([DOCS](https://www.mercadopago.com.br/developers/pt/docs/sdks-library/server-side/php/preferences)) ```php public function createPaymentPreference(): ?Preference