From 4c18d9c575bc17b30e616b130474747116746c9b Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Wed, 26 Mar 2014 16:19:28 +0300 Subject: [PATCH 1/8] add validation options and documentation for this options --- DependencyInjection/Configuration.php | 9 +++++++ DependencyInjection/LexikPayboxExtension.php | 6 +++++ README.md | 26 ++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 98f9ffa..2d51f10 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -85,6 +85,15 @@ public function getConfigTreeBuilder() ->scalarNode('key')->isRequired()->end() ->end() ->end() + ->enumNode('validation_by') + ->values(array('url_ipn', 'pbx_retour')) + ->cannotBeEmpty() + ->defaultValue('url_ipn') + ->info("Define the method for IPN validation. Select 'pbx_retour' only if you use 'PBX_REPONSE_A' option.") + ->end() + ->scalarNode('pbx_retour') + ->info("PBX_RETOUR option for validation by 'pbx_retour'") + ->end() ->end() ->end() diff --git a/DependencyInjection/LexikPayboxExtension.php b/DependencyInjection/LexikPayboxExtension.php index 2fdc7da..8caa01c 100644 --- a/DependencyInjection/LexikPayboxExtension.php +++ b/DependencyInjection/LexikPayboxExtension.php @@ -33,6 +33,12 @@ public function load(array $configs, ContainerBuilder $container) $config['parameters']['public_key'] = __DIR__ . '/../Resources/config/paybox_public_key.pem'; } + if('pbx_retour' == $config['parameters']['validation_by'] && (!isset($config['parameters']['pbx_retour']) || !$config['parameters']['pbx_retour'])){ + throw new \InvalidArgumentException( + 'The "pbx_retour" option must be set for validation_by "pbx_retour"' + ); + } + $container->setParameter('lexik_paybox.public_key', $config['parameters']['public_key']); } } diff --git a/README.md b/README.md index 5ab7a9e..d7a314a 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ lexik_paybox: - '826' # GBP - '840' # USD - '978' # EUR + validation_by: url_ipn ``` The routing collection must be set in your routing.yml @@ -218,4 +219,29 @@ To toggle in production, you just need to specify 'prod' in parameter of the get Resources --------- +Validation respons IPN +---------------------- + +For security, the status returned by PBX_EFFECTUE, PBX_REFUSE, PBX_ANNULE and PBX_ATTENTE, should +not be trusted as it can by altered by malicous user. You must instead use IPN notification. +IPN notification is send directly from Paybox server to the URL you specified either in PBX_REPONDRE_A +option or in Paybox interface. + +If you use PBX_REPONDRE_A option you must specify in your config.yml the following parameters : + +```yml +lexik_paybox: + parameters: + validation_by: pbx_retour + pbx_retour: Mt:M;Ref:R;Auto:A;Erreur:E # report the PBX_RETOUR option you defined +``` + +If you don't use PBX_REPONDRE_A you can the defaults parameters : + +```yml +lexik_paybox: + parameters: + validation_by: url_ipn +``` + All transactions parameters are available in the [official documentation](http://www1.paybox.com/telechargement_focus.aspx?cat=3). From 9cec22ae477bea22034fa5f29da0236ed13418de Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Wed, 26 Mar 2014 16:43:56 +0300 Subject: [PATCH 2/8] fix error on extension --- DependencyInjection/LexikPayboxExtension.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/DependencyInjection/LexikPayboxExtension.php b/DependencyInjection/LexikPayboxExtension.php index 8caa01c..e4d3758 100644 --- a/DependencyInjection/LexikPayboxExtension.php +++ b/DependencyInjection/LexikPayboxExtension.php @@ -33,12 +33,21 @@ public function load(array $configs, ContainerBuilder $container) $config['parameters']['public_key'] = __DIR__ . '/../Resources/config/paybox_public_key.pem'; } - if('pbx_retour' == $config['parameters']['validation_by'] && (!isset($config['parameters']['pbx_retour']) || !$config['parameters']['pbx_retour'])){ - throw new \InvalidArgumentException( - 'The "pbx_retour" option must be set for validation_by "pbx_retour"' - ); + if('pbx_retour' == $config['parameters']['validation_by']){ + if(!isset($config['parameters']['pbx_retour']) || !$config['parameters']['pbx_retour']){ + throw new \InvalidArgumentException( + 'The "pbx_retour" option must be set for validation_by "pbx_retour"' + ); + }else{ + $container->setParameter('lexik_paybox.pbx_retour', $config['parameters']['pbx_retour']); + } + }else{ + $container->setParameter('lexik_paybox.pbx_retour', null); } $container->setParameter('lexik_paybox.public_key', $config['parameters']['public_key']); + $container->setParameter('lexik_paybox.validation_by', $config['parameters']['validation_by']); + + } } From 3a0ccf9967bbf8ce5859ac4d8d7f954ce4229b3d Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Wed, 26 Mar 2014 16:44:47 +0300 Subject: [PATCH 3/8] modify validation method --- Paybox/System/Base/Response.php | 21 +++++++++++++++++++-- Resources/config/services.yml | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/Paybox/System/Base/Response.php b/Paybox/System/Base/Response.php index 847a66b..be27b51 100644 --- a/Paybox/System/Base/Response.php +++ b/Paybox/System/Base/Response.php @@ -47,6 +47,16 @@ class Response */ private $publicKey; + /** + * @var string + */ + private $validationBy; + + /** + * @var string + */ + private $pbxRetour; + /** * Contructor. * @@ -55,12 +65,14 @@ class Response * @param EventDispatcherInterface $dispatcher * @param string $publicKey */ - public function __construct(HttpRequest $request, LoggerInterface $logger, EventDispatcherInterface $dispatcher, $publicKey) + public function __construct(HttpRequest $request, LoggerInterface $logger, EventDispatcherInterface $dispatcher, $publicKey, $validationBy, $pbxRetour) { $this->request = $request; $this->logger = $logger; $this->dispatcher = $dispatcher; $this->publicKey = $publicKey; + $this->validationBy = $validationBy; + $this->pbxRetour = $pbxRetour; } /** @@ -137,8 +149,12 @@ public function verifySignature() $publicKey = openssl_get_publickey($cert); + $data = 'url_ipn' == $this->validationBy ? + Paybox::stringify($this->data) : + $this->pbxRetour; + $result = openssl_verify( - Paybox::stringify($this->data), + $data, $this->signature, $publicKey ); @@ -163,4 +179,5 @@ public function verifySignature() return $result; } + } diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 5732986..7570246 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -14,7 +14,7 @@ services: lexik_paybox.response_handler: class: '%lexik_paybox.response_handler.class%' - arguments: ['@request=', '@logger', '@event_dispatcher', %lexik_paybox.public_key%] + arguments: ['@request=', '@logger', '@event_dispatcher', %lexik_paybox.public_key%, %lexik_paybox.validation_by%, %lexik_paybox.pbx_retour%] tags: - { name: monolog.logger, channel: payment } From 12098e5a400f346228373a3c10a4c212c760b6d8 Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Wed, 26 Mar 2014 16:48:49 +0300 Subject: [PATCH 4/8] fix error on readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d7a314a..b0f5e83 100644 --- a/README.md +++ b/README.md @@ -216,9 +216,6 @@ Production By default, getUrl() returns the preproduction url. To toggle in production, you just need to specify 'prod' in parameter of the getUrl('prod') method. -Resources ---------- - Validation respons IPN ---------------------- @@ -244,4 +241,7 @@ lexik_paybox: validation_by: url_ipn ``` +Resources +--------- + All transactions parameters are available in the [official documentation](http://www1.paybox.com/telechargement_focus.aspx?cat=3). From 21732fe8bc0f1c8e7631957411fcac202089d792 Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Thu, 27 Mar 2014 08:06:38 +0300 Subject: [PATCH 5/8] fix validation process --- DependencyInjection/LexikPayboxExtension.php | 9 ++++++++- Paybox/System/Base/Response.php | 19 +++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/DependencyInjection/LexikPayboxExtension.php b/DependencyInjection/LexikPayboxExtension.php index e4d3758..461df5d 100644 --- a/DependencyInjection/LexikPayboxExtension.php +++ b/DependencyInjection/LexikPayboxExtension.php @@ -39,7 +39,14 @@ public function load(array $configs, ContainerBuilder $container) 'The "pbx_retour" option must be set for validation_by "pbx_retour"' ); }else{ - $container->setParameter('lexik_paybox.pbx_retour', $config['parameters']['pbx_retour']); + // if PXB_REPONDRE_A is used the signature only sign parameter from PBX_RETOUR without 'Sign' parameter + $param_signed = explode(';', $config['parameters']['pbx_retour']); + $param_signed = array_map(function($param){ + return substr($param, 0, strpos($param, ':')); + }, $param_signed); + $param_signed = array_diff($param_signed, array(Paybox::SIGNATURE_PARAMETER)); + + $container->setParameter('lexik_paybox.pbx_retour', $param_signed); } }else{ $container->setParameter('lexik_paybox.pbx_retour', null); diff --git a/Paybox/System/Base/Response.php b/Paybox/System/Base/Response.php index be27b51..8a12f23 100644 --- a/Paybox/System/Base/Response.php +++ b/Paybox/System/Base/Response.php @@ -53,7 +53,7 @@ class Response private $validationBy; /** - * @var string + * @var array */ private $pbxRetour; @@ -64,8 +64,10 @@ class Response * @param LoggerInterface $logger * @param EventDispatcherInterface $dispatcher * @param string $publicKey + * @param string $validationBy + * @param array $pbxRetour */ - public function __construct(HttpRequest $request, LoggerInterface $logger, EventDispatcherInterface $dispatcher, $publicKey, $validationBy, $pbxRetour) + public function __construct(HttpRequest $request, LoggerInterface $logger, EventDispatcherInterface $dispatcher, $publicKey, $validationBy, array $pbxRetour) { $this->request = $request; $this->logger = $logger; @@ -125,7 +127,7 @@ protected function initData() foreach ($this->getRequestParameters() as $key => $value) { $this->logger->info(sprintf('%s=%s', $key, $value)); - if (Paybox::SIGNATURE_PARAMETER !== $key) { + if (in_array($key, $this->pbxRetour)) { $this->data[$key] = urlencode($value); } } @@ -143,18 +145,11 @@ public function verifySignature() $this->initData(); $this->initSignature(); - $file = fopen($this->publicKey, 'r'); - $cert = fread($file, 8192); - fclose($file); - + $cert = file_get_contents($this->publicKey); $publicKey = openssl_get_publickey($cert); - $data = 'url_ipn' == $this->validationBy ? - Paybox::stringify($this->data) : - $this->pbxRetour; - $result = openssl_verify( - $data, + Paybox::stringify($this->data), $this->signature, $publicKey ); From fc9b8f3df13c0ff0079bf3b0f7bed03ad5194dda Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Thu, 27 Mar 2014 09:50:33 +0300 Subject: [PATCH 6/8] fix missing namespace --- DependencyInjection/LexikPayboxExtension.php | 1 + README.md | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/DependencyInjection/LexikPayboxExtension.php b/DependencyInjection/LexikPayboxExtension.php index 461df5d..d9cda45 100644 --- a/DependencyInjection/LexikPayboxExtension.php +++ b/DependencyInjection/LexikPayboxExtension.php @@ -6,6 +6,7 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; +use Lexik\Bundle\PayboxBundle\Paybox\Paybox; /** * This is the class that loads and manages your bundle configuration diff --git a/README.md b/README.md index b0f5e83..901f0d6 100644 --- a/README.md +++ b/README.md @@ -216,24 +216,24 @@ Production By default, getUrl() returns the preproduction url. To toggle in production, you just need to specify 'prod' in parameter of the getUrl('prod') method. -Validation respons IPN ----------------------- +Validation IPN response +----------------------- For security, the status returned by PBX_EFFECTUE, PBX_REFUSE, PBX_ANNULE and PBX_ATTENTE, should not be trusted as it can by altered by malicous user. You must instead use IPN notification. IPN notification is send directly from Paybox server to the URL you specified either in PBX_REPONDRE_A option or in Paybox interface. -If you use PBX_REPONDRE_A option you must specify in your config.yml the following parameters : +If you use PBX_REPONDRE_A option you must specify in your `config.yml` file the following parameters : ```yml lexik_paybox: parameters: validation_by: pbx_retour - pbx_retour: Mt:M;Ref:R;Auto:A;Erreur:E # report the PBX_RETOUR option you defined + pbx_retour: Mt:M;Ref:R;Auto:A;Erreur:E # report the PBX_RETOUR option you defined in your code ``` -If you don't use PBX_REPONDRE_A you can the defaults parameters : +If you use the Paybox interface, you can let the default parameters : ```yml lexik_paybox: From 636ae0aee187d7da8f6ac39a8c99b4b5d887080d Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Thu, 27 Mar 2014 20:08:14 +0300 Subject: [PATCH 7/8] update tests --- Tests/Paybox/System/ResponseTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tests/Paybox/System/ResponseTest.php b/Tests/Paybox/System/ResponseTest.php index 7507aa9..3e1c26d 100644 --- a/Tests/Paybox/System/ResponseTest.php +++ b/Tests/Paybox/System/ResponseTest.php @@ -47,8 +47,10 @@ protected function initMock(array $parameters, array $messages) ; $publicKey = __DIR__ . '/../../../Resources/config/paybox_public_key.pem'; + $validationBy = 'url_ipn'; + $pbxRetour = array_diff(array_keys($parameters), array('Sign')); - $this->_response = new Response($request, $logger, $dispatcher, $publicKey); + $this->_response = new Response($request, $logger, $dispatcher, $publicKey, $validationBy, $pbxRetour); } protected function tearDown() From f7677a28a4608359b9ab0964be1dabb9c08fdd17 Mon Sep 17 00:00:00 2001 From: Johan Desmyter Date: Thu, 3 Apr 2014 08:10:53 +0300 Subject: [PATCH 8/8] Fix forgotten data validation for url_ipn --- Paybox/System/Base/Response.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Paybox/System/Base/Response.php b/Paybox/System/Base/Response.php index 8a12f23..16a6677 100644 --- a/Paybox/System/Base/Response.php +++ b/Paybox/System/Base/Response.php @@ -127,7 +127,13 @@ protected function initData() foreach ($this->getRequestParameters() as $key => $value) { $this->logger->info(sprintf('%s=%s', $key, $value)); - if (in_array($key, $this->pbxRetour)) { + if(Paybox::SIGNATURE_PARAMETER == $key){ + continue; + } + + if ('url_ipn' == $this->validationBy) { + $this->data[$key] = urlencode($value); + } elseif (in_array($key, $this->pbxRetour)) { $this->data[$key] = urlencode($value); } }