From dbe885986aedc86cb6a896c500ce1b4d22b406dd Mon Sep 17 00:00:00 2001 From: Lucas Macedo Date: Tue, 14 May 2019 14:24:47 -0300 Subject: [PATCH] first commit --- .gitignore | 11 +++ CONTRIBUTING.md | 10 +++ LICENSE | 21 ++++++ README.md | 46 +++++++++++++ composer.json | 32 +++++++++ phpunit.xml.dist | 25 +++++++ src/Gateway.php | 86 ++++++++++++++++++++++++ src/Item.php | 27 ++++++++ src/Message/AbstractRequest.php | 66 ++++++++++++++++++ src/Message/CompletePurchaseRequest.php | 41 +++++++++++ src/Message/CompletePurchaseResponse.php | 40 +++++++++++ src/Message/PurchaseRequest.php | 72 ++++++++++++++++++++ src/Message/PurchaseResponse.php | 44 ++++++++++++ src/Message/TokenRequest.php | 72 ++++++++++++++++++++ src/Message/TokenResponse.php | 15 +++++ tests/GatewayTest.php | 39 +++++++++++ tests/Mock/PurchaseSuccess.txt | 0 17 files changed, 647 insertions(+) create mode 100644 .gitignore create mode 100755 CONTRIBUTING.md create mode 100644 LICENSE create mode 100755 README.md create mode 100644 composer.json create mode 100644 phpunit.xml.dist create mode 100644 src/Gateway.php create mode 100644 src/Item.php create mode 100644 src/Message/AbstractRequest.php create mode 100644 src/Message/CompletePurchaseRequest.php create mode 100644 src/Message/CompletePurchaseResponse.php create mode 100644 src/Message/PurchaseRequest.php create mode 100644 src/Message/PurchaseResponse.php create mode 100644 src/Message/TokenRequest.php create mode 100644 src/Message/TokenResponse.php create mode 100644 tests/GatewayTest.php create mode 100644 tests/Mock/PurchaseSuccess.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..331cce1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/vendor +composer.lock +composer.phar +phpunit.xml +.idea/ + +.directory +dirlist.app +dirlist.vendor +dirlist.cache +documents/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100755 index 0000000..d67ed30 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,10 @@ +# Contributing Guidelines + +* Fork the project. +* Make your feature addition or bug fix. +* Add tests for it. This is important so I don't break it in a future version unintentionally. +* Commit just the modifications, do not mess with the composer.json or CHANGELOG.md files. +* Ensure your code is nicely formatted in the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) + style and that all tests pass. +* Send the pull request. +* Check that the Travis CI build passed. If not, rinse and repeat. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c58fb0e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Victor Ximenis + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..e320ad6 --- /dev/null +++ b/README.md @@ -0,0 +1,46 @@ +# Omnipay: MercadoPago + +**MercadoPago driver for the Omnipay PHP payment processing library** + +[Omnipay](https://github.com/thephpleague/omnipay) is a framework agnostic, multi-gateway payment +processing library for PHP 5.3+. This package implements MercadoPago support for Omnipay. + +## Installation + +Omnipay is installed via [Composer](http://getcomposer.org/). To install, simply add it +to your `composer.json` file: + +```json +{ + "require": { + "victorximenis/omnipay-mercadopago": "~1.0" + } +} +``` + +And run composer to update your dependencies: + + $ curl -s http://getcomposer.org/installer | php + $ php composer.phar update + +## Basic Usage + +The following gateways are provided by this package: + +* MercadoPago + +For general usage instructions, please see the main [Omnipay](https://github.com/thephpleague/omnipay) +repository. + +## Support + +If you are having general issues with Omnipay, we suggest posting on +[Stack Overflow](http://stackoverflow.com/). Be sure to add the +[omnipay tag](http://stackoverflow.com/questions/tagged/omnipay) so it can be easily found. + +If you want to keep up to date with release anouncements, discuss ideas for the project, +or ask more detailed questions, there is also a [mailing list](https://groups.google.com/forum/#!forum/omnipay) which +you can subscribe to. + +If you believe you have found a bug, please report it using the [GitHub issue tracker](https://github.com/victorximenis/omnipay-mercadopago/issues), +or better yet, fork the library and submit a pull request. diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..58d262d --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "lucassmacedo/omnipay-mercadopago", + "type": "library", + "description": "MercadoPago gateway for OmniPay", + "keywords": [ + "mercadopago", + "mp", + "gateway", + "merchant", + "omnipay", + "pay", + "payment", + "PHPeste" + ], + "homepage": "https://github.com/lucassmacedo/omnipay-mercadopago", + "license": "MIT", + "authors": [ + { + "name": "Lucas Macedo", + "email": "luuckymacedo@gmail.com" + } + ], + "autoload": { + "psr-4": { "Omnipay\\MercadoPago\\" : "src/" } + }, + "require": { + "omnipay/common": "^3.0" + }, + "require-dev": { + "omnipay/tests": "^3.0" + } +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..a35b736 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,25 @@ + + + + + ./tests/ + + + + + + + + ./src + + + diff --git a/src/Gateway.php b/src/Gateway.php new file mode 100644 index 0000000..9281d97 --- /dev/null +++ b/src/Gateway.php @@ -0,0 +1,86 @@ +getParameter('client_id'); + } + + public function setClientId($value) + { + return $this->setParameter('client_id', $value); + } + + public function getClientSecret() + { + return $this->getParameter('client_secret'); + } + + public function setClientSecret($value) + { + return $this->setParameter('client_secret', $value); + } + + public function getGrantType() + { + return $this->getParameter('grant_type'); + } + + public function setGrantType($value) + { + return $this->setParameter('grant_type', $value); + } + + public function setAccessToken($value) + { + return $this->setParameter('access_token', $value); + } + + public function getAccessToken() + { + return $this->getParameter('access_token'); + } + + public function setExternalReference($value) + { + return $this->setParameter('external_reference', $value); + } + + public function getExternalReference() + { + return $this->getParameter('external_reference'); + } + + public function purchase(array $parameters = array()) + { + return $this->createRequest('\Omnipay\MercadoPago\Message\PurchaseRequest', $parameters); + } + + public function requestToken(array $parameters = array()) + { + return $this->createRequest('\Omnipay\MercadoPago\Message\TokenRequest', $parameters); + } + + /** + * @param array $parameters + * @return \Omnipay\MercadoPago\Message\CompletePurchaseRequest + */ + public function completePurchase(array $parameters = array()) + { + return $this->createRequest('\Omnipay\MercadoPago\Message\CompletePurchaseRequest', $parameters); + } + +} + +?> diff --git a/src/Item.php b/src/Item.php new file mode 100644 index 0000000..708a28a --- /dev/null +++ b/src/Item.php @@ -0,0 +1,27 @@ +getParameter('category_id'); + } + public function setCategoryId($value) + { + return $this->setParameter('category_id', $value); + } + public function getCurrencyId() + { + return $this->getParameter('currency_id'); + } + public function setCurrencyId($value) + { + return $this->setParameter('currency_id', $value); + } +} + +?> diff --git a/src/Message/AbstractRequest.php b/src/Message/AbstractRequest.php new file mode 100644 index 0000000..f0baa8e --- /dev/null +++ b/src/Message/AbstractRequest.php @@ -0,0 +1,66 @@ +getExternalReference(); + return $data; + } + + public function sendData($data) + { + $url = $this->getEndpoint() . '?access_token=' . $this->getAccessToken(); + $httpRequest = $this->httpClient->createRequest( + 'POST', + $url, + array( + 'Content-type' => 'application/json', + ), + $this->toJSON($data) + ); + $httpResponse = $httpRequest->send(); + return $this->createResponse($httpResponse->json()); + } + + public function setExternalReference($value) + { + return $this->setParameter('external_reference', $value); + } + + public function getExternalReference() + { + return $this->getParameter('external_reference'); + } + + public function setAccessToken($value) + { + return $this->setParameter('access_token', $value); + } + + public function getAccessToken() + { + return $this->getParameter('access_token'); + } + + protected function getEndpoint() + { + return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint; + } + + public function toJSON($data, $options = 0) + { + if (version_compare(phpversion(), '5.4.0', '>=') === true) { + return json_encode($data, $options | 64); + } + return str_replace('\\/', '/', json_encode($data, $options)); + } + +} + +?> diff --git a/src/Message/CompletePurchaseRequest.php b/src/Message/CompletePurchaseRequest.php new file mode 100644 index 0000000..ec4c3c1 --- /dev/null +++ b/src/Message/CompletePurchaseRequest.php @@ -0,0 +1,41 @@ +httpRequest->query->get('collection_id'); + $url = $this->getEndpoint() . "$id?access_token=" . $this->getAccessToken(); + $httpRequest = $this->httpClient->createRequest( + 'GET', + $url, + array( + 'Content-type' => 'application/json', + ) + ); + $httpResponse = $httpRequest->send(); + $response = $httpResponse->json(); + return isset($response['collection']) ? $response['collection'] : null; + } + + public function sendData($data) + { + return $this->createResponse($data); + } + + protected function createResponse($data) + { + return $this->response = new CompletePurchaseResponse($this, $data); + } + +} + +?> diff --git a/src/Message/CompletePurchaseResponse.php b/src/Message/CompletePurchaseResponse.php new file mode 100644 index 0000000..854f192 --- /dev/null +++ b/src/Message/CompletePurchaseResponse.php @@ -0,0 +1,40 @@ +data['status']) && $this->data['status'] == 'approved'; + } + + /** + * This response never redirects + * + * @return bool + */ + public function isRedirect() + { + return false; + } + + /** + * The transaction reference obtained from the purchase() + * + * @return string + */ + public function getTransactionReference() + { + return $this->data['order_id']; + } +} diff --git a/src/Message/PurchaseRequest.php b/src/Message/PurchaseRequest.php new file mode 100644 index 0000000..eecf9a6 --- /dev/null +++ b/src/Message/PurchaseRequest.php @@ -0,0 +1,72 @@ +getItems(); + if ($items) { + foreach ($items as $n => $item) { + $item_array = []; + $item_array['title'] = $item->getName(); + $item_array['category_id'] = $item->getCategoryId(); + $item_array['quantity'] = $item->getQuantity(); + $item_array['currency_id'] = $item->getCurrencyId(); + $item_array['unit_price'] = (double)($this->formatCurrency($item->getPrice())); + array_push($data, $item_array); + } + } + return $data; + } + + public function getData() + { + + $data = array( + "items" => array( + array( + 'title' => 'PurchaseTest', + 'quantity' => 1, + 'category_id' => 'tickets', + 'currency_id' => 'BRL', + 'unit_price' => 10.0 + ) + )); + + $items = $this->getItemData(); + $external_reference = parent::getData(); + $purchaseObject = [ + 'items' => $items, + 'external_reference' => $external_reference, + 'auto_return' => 'approved', + 'back_urls' => [ + 'success' => $this->getReturnUrl() + ], + + //TODO add option for that + 'payment_methods' => [ + 'excluded_payment_types' => [ + ["id" => "ticket"], + ["id" => "atm"] + ] + ] + ]; + return $purchaseObject; + } + + protected function createResponse($data) + { + return $this->response = new PurchaseResponse($this, $data); + } + + protected function getEndpoint() + { + return $this->getTestMode() ? ($this->testEndpoint . '/checkout/preferences') : ($this->liveEndpoint . '/checkout/preferences'); + } + +} + +?> diff --git a/src/Message/PurchaseResponse.php b/src/Message/PurchaseResponse.php new file mode 100644 index 0000000..c2c14b5 --- /dev/null +++ b/src/Message/PurchaseResponse.php @@ -0,0 +1,44 @@ +data['init_point']) && $this->data['init_point']; + } + + + public function getRedirectMethod() + { + return 'GET'; + } + + public function getRedirectData() + { + return null; + } + + public function getRedirectUrl() + { + if ($this->isRedirect()) { + return $this->data['init_point']; + } + } +} + +?> diff --git a/src/Message/TokenRequest.php b/src/Message/TokenRequest.php new file mode 100644 index 0000000..d98f4b6 --- /dev/null +++ b/src/Message/TokenRequest.php @@ -0,0 +1,72 @@ +setGrantType("client_credentials"); + return [ + 'grant_type' => $this->getGrantType(), + 'client_id' => $this->getClientId(), + 'client_secret' => $this->getClientSecret() + ]; + } + + public function sendData($data) + { + $url = $this->getEndpoint(); + $headers = [ + 'headers' => ['Content-Type' => 'x-www-form-urlencoded; charset=UTF-8', 'Accept' => 'application/json'] + ]; + $httpResponse = $this->httpClient->post($url, $headers, $data)->send(); + return $this->createResponse($httpResponse->json()); + } + + protected function getEndpoint() + { + return $this->getTestMode() ? $this->testEndpoint : $this->liveEndpoint; + } + + public function getClientId() + { + return $this->getParameter('client_id'); + } + + public function setClientId($value) + { + return $this->setParameter('client_id', $value); + } + + public function getClientSecret() + { + return $this->getParameter('client_secret'); + } + + public function setClientSecret($value) + { + return $this->setParameter('client_secret', $value); + } + + public function getGrantType() + { + return $this->getParameter('grant_type'); + } + + public function setGrantType($value) + { + return $this->setParameter('grant_type', $value); + } + + protected function createResponse($data) + { + return $this->response = new TokenResponse($this, $data); + } + +} + +?> diff --git a/src/Message/TokenResponse.php b/src/Message/TokenResponse.php new file mode 100644 index 0000000..8558467 --- /dev/null +++ b/src/Message/TokenResponse.php @@ -0,0 +1,15 @@ +data['status']) && in_array($this->data['status'], array('Success', 'SuccessWithWarning')); + } +} + +?> diff --git a/tests/GatewayTest.php b/tests/GatewayTest.php new file mode 100644 index 0000000..f6236bc --- /dev/null +++ b/tests/GatewayTest.php @@ -0,0 +1,39 @@ +gateway = new Gateway($this->getHttpClient(), $this->getHttpRequest()); + $this->gateway->setClientId("1409715019698491"); + $this->gateway->setClientSecret("PNGxKb6I7mqs1npFwCf4nDqRfSMqAOpE"); + $this->gateway->setExternalReference(178); + $item = new Item(); + $item->setName("PurchaseTest"); + $item->setCategoryId("tickets"); + $item->setQuantity(1); + $item->setCurrencyId("BRL"); + $item->setPrice(10.0); + $this->items = array("items" => [$item]); + } + + public function testPurchase() + { + $responseToken = $this->gateway->requestToken($this->items)->send(); + $dataToken = $responseToken->getData(); + $this->gateway->setAccessToken($dataToken['access_token']); + $this->assertInstanceOf('\Omnipay\MercadoPago\Message\TokenResponse', $responseToken); + $this->assertTrue($this->gateway->getAccessToken() != null); + + $response = $this->gateway->purchase($this->items)->send(); + $data = $response->getData(); + $this->assertInstanceOf('\Omnipay\MercadoPago\Message\PurchaseResponse', $response); + $this->assertTrue($data['init_point'] != null); + } +} + +?> diff --git a/tests/Mock/PurchaseSuccess.txt b/tests/Mock/PurchaseSuccess.txt new file mode 100644 index 0000000..e69de29