diff --git a/LICENSE b/LICENSE index 0734589..116bf0c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2013 by Forma-Pro +Copyright (C) 2013-2018 Maksim Kotlyar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -16,4 +16,4 @@ 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. \ No newline at end of file +THE SOFTWARE. diff --git a/README.md b/README.md index d7c712c..9ba973e 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,36 @@ +

Supporting Payum

+ +Payum is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and our customers. If you'd like to join them, please consider: + +- [Become a sponsor](https://www.patreon.com/makasim) +- [Become our client](http://forma-pro.com/) + +--- + # PayumModule +[![Join the chat at https://gitter.im/Payum/Payum](https://badges.gitter.im/Payum/Payum.svg)](https://gitter.im/Payum/Payum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + The modulee integrates [payum](https://github.com/Payum/Payum) into [zend2](http://framework.zend.com/) framework. -It already supports [+35 payments](https://github.com/Payum/Core/blob/master/Resources/docs/supported-payments.md). +It already supports [+35 gateways](https://github.com/Payum/Core/blob/master/Resources/docs/supported-gateways.md). Provide nice configuration layer, secured capture controller, storages integration and lots of more features. ## Resources -* [Documentation](http://payum.org/doc#PayumModule) +* [Site](https://payum.forma-pro.com/) +* [Documentation](https://github.com/Payum/PayumModule/blob/master/docs/index.md) * [Sandbox](https://github.com/makasim/PayumModuleSandbox) * [Questions](http://stackoverflow.com/questions/tagged/payum) * [Issue Tracker](https://github.com/Payum/PayumModule/issues) * [Twitter](https://twitter.com/payumphp) -## Contributing - -PayumModule is an open source, community-driven project. Pull requests are very welcome. +## Developed by Forma-Pro -## Like it? Spread the world! +Forma-Pro is a full stack development company which interests also spread to open source development. +Being a team of strong professionals we have an aim an ability to help community by developing cutting edge solutions in the areas of e-commerce, docker & microservice oriented architecture where we have accumulated a huge many-years experience. +Our main specialization is Symfony framework based solution, but we are always looking to the technologies that allow us to do our job the best way. We are committed to creating solutions that revolutionize the way how things are developed in aspects of architecture & scalability. -Star payum module on [github](https://github.com/Payum/PayumModule) or [packagist](https://packagist.org/packages/payum/payum-module). +If you have any questions and inquires about our open source development, this product particularly or any other matter feel free to contact at opensource@forma-pro.com ## License diff --git a/composer.json b/composer.json index d0e2cd7..8d29e29 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "require": { "php": ">=5.3.3", "zendframework/zendframework": "~2.2", - "payum/core": "0.11.*" + "payum/core": "^1.4" }, "suggest": { "payum/paypal-express-checkout-nvp": "If you want to use paypal express checkout nvp gateway", @@ -39,7 +39,7 @@ }, "extra": { "branch-alias": { - "dev-master": "0.11-dev" + "dev-master": "1.0-dev" } }, "config": { diff --git a/config/module.config.php b/config/module.config.php index 82729d3..59f4556 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -2,7 +2,7 @@ return array( 'payum' => array( 'token_storage' => null, - 'payments' => array(), + 'gateways' => array(), 'storages' => array(), ), ); diff --git a/config/module.config.routes.php b/config/module.config.routes.php index d3f42d0..f55aa2d 100644 --- a/config/module.config.routes.php +++ b/config/module.config.routes.php @@ -7,7 +7,7 @@ 'options' => array( 'route' => '/payment/capture[/:payum_token]', 'constraints' => array( - 'payum_token' => '[a-zA-Z0-9]+' + 'payum_token' => '[a-zA-Z0-9_-]+' ), 'defaults' => array( 'controller' => 'PayumCapture', @@ -20,7 +20,7 @@ 'options' => array( 'route' => '/payment/notify[/:payum_token]', 'constraints' => array( - 'payum_token' => '[a-zA-Z0-9]+' + 'payum_token' => '[a-zA-Z0-9_-]+' ), 'defaults' => array( 'controller' => 'PayumNotify', @@ -33,7 +33,7 @@ 'options' => array( 'route' => '/payment/authorize[/:payum_token]', 'constraints' => array( - 'payum_token' => '[a-zA-Z0-9]+' + 'payum_token' => '[a-zA-Z0-9_-]+' ), 'defaults' => array( 'controller' => 'PayumAuthorize', @@ -41,6 +41,19 @@ ), ), ), + 'payum_refund_do' => array( + 'type' => 'Segment', + 'options' => array( + 'route' => '/payment/refund[/:payum_token]', + 'constraints' => array( + 'payum_token' => '[a-zA-Z0-9_-]+' + ), + 'defaults' => array( + 'controller' => 'PayumRefund', + 'action' => 'do' + ), + ), + ), ), ), ); diff --git a/config/service/controller.config.php b/config/service/controller.config.php index 25d20e0..5c9b4ad 100644 --- a/config/service/controller.config.php +++ b/config/service/controller.config.php @@ -2,6 +2,8 @@ use Payum\PayumModule\Controller\AuthorizeController; use Payum\PayumModule\Controller\CaptureController; +use Payum\PayumModule\Controller\NotifyController; +use Payum\PayumModule\Controller\RefundController; return array( 'factories' => array( @@ -17,5 +19,17 @@ // Construct Authorize controller with required Payum Registry and HttpRequestVerifier dependencies. return new AuthorizeController($sm->get('payum'), $sm->get('payum.security.http_request_verifier')); }, + 'PayumNotify' => function ($cm) { + $sm = $cm->getServiceLocator(); + + // Construct Capture controller with required Payum Registry and HttpRequestVerifier dependencies. + return new NotifyController($sm->get('payum'), $sm->get('payum.security.http_request_verifier')); + }, + 'PayumRefund' => function ($cm) { + $sm = $cm->getServiceLocator(); + + // Construct Capture controller with required Payum Registry and HttpRequestVerifier dependencies. + return new RefundController($sm->get('payum'), $sm->get('payum.security.http_request_verifier')); + }, ), ); \ No newline at end of file diff --git a/docs/get-it-started.md b/docs/get-it-started.md index a85447f..2d68515 100644 --- a/docs/get-it-started.md +++ b/docs/get-it-started.md @@ -1,7 +1,7 @@ # Get it started. In this chapter we would show basic setup and usage of payum module for [zf2](http://framework.zend.com/). -We are using paypal here but it could be adopted for any other supported payments. +We are using paypal here but it could be adopted for any other supported gateways. ## Installation @@ -9,9 +9,9 @@ We are using paypal here but it could be adopted for any other supported payment php composer.phar require "payum/payum-module:*@stable" "payum/xxx:*@stable" ``` -_**Note**: Where payum/xxx is a payum package, for example it could be payum/paypal-express-checkout-nvp. Look at [supported payments](https://github.com/Payum/Core/blob/master/Resources/docs/supported-payments.md) to find out what you can use._ +_**Note**: Where payum/xxx is a payum package, for example it could be payum/paypal-express-checkout-nvp. Look at [supported gateways](https://github.com/Payum/Core/blob/master/Resources/docs/supported-gateways.md) to find out what you can use._ -_**Note**: Use payum/payum if you want to install all payments at once._ +_**Note**: Use payum/payum if you want to install all gateways at once._ Now you have all codes prepared and ready to be used. @@ -70,10 +70,12 @@ use Buzz\Client\Curl; use Payum\Core\Extension\StorageExtension; use Payum\Core\Storage\FilesystemStorage; use Payum\Paypal\ExpressCheckout\Nvp\Api; -use Payum\Paypal\ExpressCheckout\Nvp\PaymentFactory; +use Payum\Paypal\ExpressCheckout\Nvp\GatewayFactory; $detailsClass = 'Application\Model\PaymentDetails'; +$paypalFactory = new \Payum\Paypal\ExpressCheckout\Nvp\PaypalExpressCheckoutGatewayFactory(); + return array( 'payum' => array( 'token_storage' => new FilesystemStorage( @@ -81,13 +83,13 @@ return array( 'Application\Model\PaymentSecurityToken', 'hash' ), - 'payments' => array( - 'paypal_es' => PaymentFactory::create(new Api(new Curl(), array( - 'username' => 'REPLACE WITH YOURS', - 'password' => 'REPLACE WITH YOURS', - 'signature' => 'REPLACE WITH YOURS', + 'gateways' => array( + 'paypal_ec' => $paypalFactory->create(array( + 'username' => 'EDIT ME', + 'password' => 'EDIT ME', + 'signature' => 'EDIT ME', 'sandbox' => true - ))) + )), ), 'storages' => array( $detailsClass => new FilesystemStorage(__DIR__.'/../../data', $detailsClass, 'id'), @@ -112,16 +114,13 @@ class IndexController extends AbstractActionController { $storage = $this->getServiceLocator()->get('payum')->getStorage('Application\Model\PaymentDetails'); - $details = $storage->createModel(); + $details = $storage->create(); $details['PAYMENTREQUEST_0_CURRENCYCODE'] = 'EUR'; $details['PAYMENTREQUEST_0_AMT'] = 1.23; - $storage->updateModel($details); - - // FIXIT: I dont know how to inject controller plugin to the service. - $this->getServiceLocator()->get('payum.security.token_factory')->setUrlPlugin($this->url()); + $storage->update($details); $captureToken = $this->getServiceLocator()->get('payum.security.token_factory')->createCaptureToken( - 'paypal_es', $details, 'payment_done' + 'paypal_ec', $details, 'payment_done' ); $this->redirect()->toUrl($captureToken->getTargetUrl()); @@ -147,13 +146,13 @@ class IndexController extends AbstractActionController { public function doneAction() { - $token = $this->getServiceLocator()->get('payum.security.http_request_verifier')->verify($this->getRequest()); + $token = $this->getServiceLocator()->get('payum.security.http_request_verifier')->verify($this); - $payment = $this->getServiceLocator()->get('payum')->getPayment($token->getPaymentName()); + $gateway = $this->getServiceLocator()->get('payum')->getGateway($token->getGatewayName()); - $payment->execute($status = new GetHumanStatus($token)); + $gateway->execute($status = new GetHumanStatus($token)); - return new JsonModel(array('status' => $status->getStatus()) + iterator_to_array($status->getModel())); + return new JsonModel(array('status' => $status->getValue()) + iterator_to_array($status->getModel())); } } ``` diff --git a/src/Payum/PayumModule/Controller/AuthorizeController.php b/src/Payum/PayumModule/Controller/AuthorizeController.php index b223c52..ffb5279 100644 --- a/src/Payum/PayumModule/Controller/AuthorizeController.php +++ b/src/Payum/PayumModule/Controller/AuthorizeController.php @@ -4,23 +4,22 @@ use Payum\Core\Reply\HttpRedirect; use Payum\Core\Reply\HttpResponse; use Payum\Core\Reply\ReplyInterface; -use Payum\Core\Request\SecuredAuthorize; -use Payum\Core\Request\SecuredCapture; +use Payum\Core\Request\Authorize; use Zend\Http\Response; class AuthorizeController extends PayumController { public function doAction() { - $token = $this->getHttpRequestVerifier()->verify($this->getRequest()); + $token = $this->getHttpRequestVerifier()->verify($this); - $payment = $this->getPayum()->getPayment($token->getPaymentName()); + $gateway = $this->getPayum()->getGateway($token->getGatewayName()); try { - $payment->execute(new SecuredAuthorize($token)); + $gateway->execute(new Authorize($token)); } catch (ReplyInterface $reply) { if ($reply instanceof HttpRedirect) { - $this->redirect()->toUrl($reply->getUrl()); + return $this->redirect()->toUrl($reply->getUrl()); } if ($reply instanceof HttpResponse) { @@ -38,6 +37,6 @@ public function doAction() $this->getHttpRequestVerifier()->invalidate($token); - $this->redirect()->toUrl($token->getAfterUrl()); + return $this->redirect()->toUrl($token->getAfterUrl()); } -} \ No newline at end of file +} diff --git a/src/Payum/PayumModule/Controller/CaptureController.php b/src/Payum/PayumModule/Controller/CaptureController.php index 17b03d5..0b83c78 100644 --- a/src/Payum/PayumModule/Controller/CaptureController.php +++ b/src/Payum/PayumModule/Controller/CaptureController.php @@ -4,22 +4,22 @@ use Payum\Core\Reply\HttpRedirect; use Payum\Core\Reply\HttpResponse; use Payum\Core\Reply\ReplyInterface; -use Payum\Core\Request\SecuredCapture; +use Payum\Core\Request\Capture; use Zend\Http\Response; class CaptureController extends PayumController { public function doAction() { - $token = $this->getHttpRequestVerifier()->verify($this->getRequest()); + $token = $this->getHttpRequestVerifier()->verify($this); - $payment = $this->getPayum()->getPayment($token->getPaymentName()); + $gateway = $this->getPayum()->getGateway($token->getGatewayName()); try { - $payment->execute(new SecuredCapture($token)); + $gateway->execute(new Capture($token)); } catch (ReplyInterface $reply) { if ($reply instanceof HttpRedirect) { - $this->redirect()->toUrl($reply->getUrl()); + return $this->redirect()->toUrl($reply->getUrl()); } if ($reply instanceof HttpResponse) { @@ -37,6 +37,6 @@ public function doAction() $this->getHttpRequestVerifier()->invalidate($token); - $this->redirect()->toUrl($token->getAfterUrl()); + return $this->redirect()->toUrl($token->getAfterUrl()); } -} \ No newline at end of file +} diff --git a/src/Payum/PayumModule/Controller/NotifyController.php b/src/Payum/PayumModule/Controller/NotifyController.php index ce5283d..6cb491d 100644 --- a/src/Payum/PayumModule/Controller/NotifyController.php +++ b/src/Payum/PayumModule/Controller/NotifyController.php @@ -1,18 +1,18 @@ getHttpRequestVerifier()->verify($this->getRequest()); + $token = $this->getHttpRequestVerifier()->verify($this); - $payment = $this->getPayum()->getPayment($token->getPaymentName()); + $gateway = $this->getPayum()->getGateway($token->getGatewayName()); - $payment->execute(new SecuredNotify($_REQUEST, $token)); + $gateway->execute(new Notify($token)); $this->getResponse()->setStatusCode(204); } -} \ No newline at end of file +} diff --git a/src/Payum/PayumModule/Controller/RefundController.php b/src/Payum/PayumModule/Controller/RefundController.php new file mode 100644 index 0000000..da42785 --- /dev/null +++ b/src/Payum/PayumModule/Controller/RefundController.php @@ -0,0 +1,41 @@ +getHttpRequestVerifier()->verify($this); + $this->getHttpRequestVerifier()->invalidate($token); + + $gateway = $this->getPayum()->getGateway($token->getGatewayName()); + + try { + $gateway->execute(new Refund($token)); + } catch (ReplyInterface $reply) { + if ($reply instanceof HttpRedirect) { + return $this->redirect()->toUrl($reply->getUrl()); + } + + if ($reply instanceof HttpResponse) { + $this->getResponse()->setContent($reply->getContent()); + + $response = new Response(); + $response->setStatusCode(200); + $response->setContent($reply->getContent()); + + return $response; + } + + throw new \LogicException('Unsupported reply', null, $reply); + } + + return $this->redirect()->toUrl($token->getAfterUrl()); + } +} diff --git a/src/Payum/PayumModule/Options/PayumOptions.php b/src/Payum/PayumModule/Options/PayumOptions.php index 8962d18..616e209 100644 --- a/src/Payum/PayumModule/Options/PayumOptions.php +++ b/src/Payum/PayumModule/Options/PayumOptions.php @@ -7,7 +7,7 @@ class PayumOptions extends AbstractOptions { protected $tokenStorage; - protected $payments = array(); + protected $gateways = array(); protected $storages = array(); @@ -30,17 +30,17 @@ public function getTokenStorage() /** * @return array */ - public function getPayments() + public function getGateways() { - return $this->payments; + return $this->gateways; } /** - * @param array $payments + * @param array $gateways */ - public function setPayments(array $payments) + public function setGateways(array $gateways) { - $this->payments = $payments; + $this->gateways = $gateways; } /** diff --git a/src/Payum/PayumModule/Registry/RegistryFactory.php b/src/Payum/PayumModule/Registry/RegistryFactory.php index a74c05c..e6c99c1 100644 --- a/src/Payum/PayumModule/Registry/RegistryFactory.php +++ b/src/Payum/PayumModule/Registry/RegistryFactory.php @@ -17,19 +17,19 @@ public function createService(ServiceLocatorInterface $serviceLocator) $options = $serviceLocator->get('payum.options'); $registry = new ServiceLocatorAwareRegistry( - $options->getPayments(), + $options->getGateways(), $options->getStorages(), - null + array() ); - - $getHttpRequestAction = new GetHttpRequestAction($serviceLocator); - foreach ($registry->getPayments() as $payment) { - $payment->addAction($getHttpRequestAction); - } //TODO: quick fix. we should avoid early init of services. has to be reworked to be lazy $registry->setServiceLocator($serviceLocator); + $getHttpRequestAction = new GetHttpRequestAction($serviceLocator); + foreach ($registry->getGateways() as $gateway) { + $gateway->addAction($getHttpRequestAction); + } + return $registry; } } diff --git a/src/Payum/PayumModule/Security/HttpRequestVerifier.php b/src/Payum/PayumModule/Security/HttpRequestVerifier.php index ac92d12..5d82bde 100644 --- a/src/Payum/PayumModule/Security/HttpRequestVerifier.php +++ b/src/Payum/PayumModule/Security/HttpRequestVerifier.php @@ -26,8 +26,11 @@ public function __construct(StorageInterface $tokenStorage) /** * {@inheritDoc} */ - public function verify($httpRequest) + public function verify($controller) { + + $httpRequest = $controller->getRequest(); + if (false == $httpRequest instanceof Request) { throw new InvalidArgumentException(sprintf( 'Invalid request given. Expected %s but it is %s', @@ -36,8 +39,10 @@ public function verify($httpRequest) )); } + $hash = $controller->params()->fromRoute('payum_token') ?: $httpRequest->getQuery('payum_token'); + /** @var $httpRequest Request */ - if (false === $hash = $httpRequest->getQuery('payum_token')) { + if (!$hash) { //TODO we should set 404 to response but I do not know how. symfony just throws not found exception. throw new InvalidArgumentException('Token parameter not set in request'); } @@ -45,7 +50,7 @@ public function verify($httpRequest) if ($hash instanceof Token) { $token = $hash; } else { - if (false == $token = $this->tokenStorage->findModelById($hash)) { + if (false == $token = $this->tokenStorage->find($hash)) { //TODO here again should be 404 throw new InvalidArgumentException(sprintf('A token with hash `%s` could not be found.', $hash)); } @@ -68,6 +73,6 @@ public function verify($httpRequest) */ public function invalidate(TokenInterface $token) { - $this->tokenStorage->deleteModel($token); + $this->tokenStorage->delete($token); } -} \ No newline at end of file +} diff --git a/src/Payum/PayumModule/Security/TokenFactory.php b/src/Payum/PayumModule/Security/TokenFactory.php index 3810f04..138f9ce 100644 --- a/src/Payum/PayumModule/Security/TokenFactory.php +++ b/src/Payum/PayumModule/Security/TokenFactory.php @@ -1,10 +1,10 @@ urlPlugin->fromRoute($path, array(), array( - 'force_canonical' => true, - 'query' => $parameters - )); + return $this->urlPlugin->fromRoute($path, $parameters, array('force_canonical' => true)); } -} \ No newline at end of file +} diff --git a/src/Payum/PayumModule/Security/TokenFactoryFactory.php b/src/Payum/PayumModule/Security/TokenFactoryFactory.php index 0a86ba3..b57f9e0 100644 --- a/src/Payum/PayumModule/Security/TokenFactoryFactory.php +++ b/src/Payum/PayumModule/Security/TokenFactoryFactory.php @@ -1,6 +1,8 @@ get('ControllerPluginManager'); + + $tokenFactory = new TokenFactory( $serviceLocator->get('payum.security.token_storage'), - $serviceLocator->get('payum'), - 'payum_capture_do', - 'payum_notify_do', - 'payum_authorize_do' + $serviceLocator->get('payum') ); + $tokenFactory->setUrlPlugin($plugins->get('url')); + + return new GenericTokenFactory($tokenFactory, array( + 'capture' => 'payum_capture_do', + 'notify' => 'payum_notify_do', + 'authorize' => 'payum_authorize_do', + 'refund' => 'payum_refund_do' + )); } } \ No newline at end of file