From 2577e6037b73ec3a845bd575c27733c3a3946222 Mon Sep 17 00:00:00 2001 From: Franck Allimant Date: Fri, 13 Sep 2019 10:09:03 +0200 Subject: [PATCH] Using hook instead of AdminIncludes, code style fixes --- AdminIncludes/module_configuration.html | 75 ---------- CmCIC.php | 135 +++++++++++------- Config/config.json | 2 +- Config/config.xml | 6 + Config/module.xml | 2 +- Config/schema.xml | 7 - Controller/CmcicSaveConfig.php | 37 +++-- EventListeners/SendConfirmationEmail.php | 11 +- Hook/HookManager.php | 46 ++++++ .../default}/en_US.php | 0 .../default}/fr_FR.php | 0 .../default/cmcic/module-configuration.html | 75 ++++++++++ 12 files changed, 235 insertions(+), 161 deletions(-) delete mode 100755 AdminIncludes/module_configuration.html delete mode 100755 Config/schema.xml create mode 100644 Hook/HookManager.php rename I18n/{AdminIncludes => backOffice/default}/en_US.php (100%) rename I18n/{AdminIncludes => backOffice/default}/fr_FR.php (100%) create mode 100644 templates/backOffice/default/cmcic/module-configuration.html diff --git a/AdminIncludes/module_configuration.html b/AdminIncludes/module_configuration.html deleted file mode 100755 index 68b935a..0000000 --- a/AdminIncludes/module_configuration.html +++ /dev/null @@ -1,75 +0,0 @@ -
- - {loop name="checkrights" type="cmcic.check.rights"} -
-

{$ERRMES} {$ERRFILE} | {intl d='cmcic.ai' l="Please change the access rights"}.

-
- {/loop} -
-{elseloop rel="checkrights"} -
-
-
-
- {intl d='cmcic.ai' l="Configuration CmCIC"} -
-
- -
-
-
- {form name="cmcic.configure"}  -
- {form_hidden_fields form=$form} - - {include file = "includes/inner-form-toolbar.html" - hide_flags = true - page_url = "{url path='/admin/module/CmCIC'}" - close_url = "{url path='/admin/modules'}" - } - - {if $form_error} -
-
-
{$form_error_message}
-
-
- {/if} - -
-
- {render_form_field field="TPE"} - {render_form_field field="com_key"} - {render_form_field field="com_soc"} -
-

{intl d='cmcic.ai' l="URL de retour: %url" url={url path="/cmcic/validation"}}

-

{intl d='cmcic.ai' l="This is the value you should provide for the \"URL de Retour\" parameter in your bank back-office."}

-
- -
- -
- {render_form_field field="server"} - {render_form_field field="page"} - {render_form_field field="send_confirmation_message_only_if_paid"} - {render_form_field field="debug"} - {render_form_field field="allowed_ips"} - -
- -

- {intl d='cmcic.ai' l='Click here to download the communications log between the module and the bank server.' url={url path="/admin/module/cmcic/log"}} -

-
-
-
-
- {/form} -
-
-
-
-
-{/elseloop} diff --git a/CmCIC.php b/CmCIC.php index 7435d28..1b80f19 100755 --- a/CmCIC.php +++ b/CmCIC.php @@ -25,9 +25,10 @@ use CmCIC\Model\Config; use Propel\Runtime\Connection\ConnectionInterface; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Routing\Router; use Thelia\Core\HttpFoundation\Response; -use Thelia\Core\Template\TemplateDefinition; +use Thelia\Log\Tlog; use Thelia\Model\ModuleImageQuery; use Thelia\Model\Order; use Thelia\Model\OrderAddress; @@ -38,19 +39,15 @@ class CmCIC extends AbstractPaymentModule { const DOMAIN_NAME = "cmcic"; + const JSON_CONFIG_PATH = "/Config/config.json"; - - const CMCIC_CTLHMAC = "V1.04.sha1.php--[CtlHmac%s%s]-%s"; - const CMCIC_CTLHMACSTR = "CtlHmac%s%s"; + const CMCIC_CGI2_RECEIPT = "version=2\ncdr=%s"; const CMCIC_CGI2_MACOK = "0"; const CMCIC_CGI2_MACNOTOK = "1\n"; - - protected $sKey; - protected $sUsableKey; - + protected $config; - + /** * * This method is call on Payment loop. @@ -63,33 +60,33 @@ class CmCIC extends AbstractPaymentModule public function isValidPayment() { $debug = $this->getConfigValue('debug', false); - + if ($debug) { // Check allowed IPs when in test mode. $testAllowedIps = $this->getConfigValue('allowed_ips', ''); - + $raw_ips = explode("\n", $testAllowedIps); - + $allowed_client_ips = array(); - + foreach ($raw_ips as $ip) { $allowed_client_ips[] = trim($ip); } - + $client_ip = $this->getRequest()->getClientIp(); - + $valid = in_array($client_ip, $allowed_client_ips); } else { $valid = true; } - + if ($this->getCurrentOrderTotalAmount() <= 0) { $valid = false; } - + return $valid; } - + public function postActivation(ConnectionInterface $con = null) { /* insert the images from image folder if first module activation */ @@ -97,7 +94,7 @@ public function postActivation(ConnectionInterface $con = null) if (ModuleImageQuery::create()->filterByModule($module)->count() == 0) { $this->deployImageFolder($module, sprintf('%s/images', __DIR__), $con); } - + /* set module title */ $this->setTitle( $module, @@ -106,16 +103,34 @@ public function postActivation(ConnectionInterface $con = null) "fr_FR" => "Paiement par Carte Bancaire", ) ); - + } - + + public function update($currentVersion , $newVersion , ConnectionInterface $con = null) + { + // Delete obsolete admin includes + $fs = new Filesystem(); + + try { + $fs -> remove(__DIR__ . '/AdminIncludes'); + $fs -> remove(__DIR__ . 'I18n/AdminIncludes'); + } catch (\Exception $ex) { + Tlog::getInstance()->addWarning("Failed to delete CmCIC module AdminIncludes directory (".__DIR__ . '/AdminIncludes): ' . $ex->getMessage()); + } + } + + /** + * @param Order $order + * @return Response|null + * @throws \Exception + */ public function pay(Order $order) { $c = Config::read(CmCIC::JSON_CONFIG_PATH); $currency = $order->getCurrency()->getCode(); $cmCicRouter = $this->container->get('router.cmcic'); $mainRouter = $this->container->get('router.front'); - + $vars = array( "version" => $c["CMCIC_VERSION"], "TPE" => $c["CMCIC_TPE"], @@ -132,22 +147,22 @@ public function pay(Order $order) "3dsdebrayable" => "0", "ThreeDSecureChallenge" => "challenge_preferred", ); - - $hashable = self::getHashable($vars); - + + $hashable = self::getHashable($vars); + $mac = self::computeHmac( $hashable, self::getUsableKey($c["CMCIC_KEY"]) ); $vars["MAC"] = $mac; - + return $this->generateGatewayFormResponse( $order, $c["CMCIC_SERVER"] . $c["CMCIC_PAGE"], $vars ); } - + protected function harmonise($value, $type, $len) { switch ($type) { @@ -170,17 +185,17 @@ protected function harmonise($value, $type, $len) } break; } - + return $value; } - + public static function getUsableKey($key) { $hexStrKey = substr($key, 0, 38); $hexFinal = "" . substr($key, 38, 2) . "00"; - + $cca0 = ord($hexFinal); - + if ($cca0 > 70 && $cca0 < 97) { $hexStrKey .= chr($cca0 - 23) . substr($hexFinal, 1, 1); } else { @@ -190,36 +205,46 @@ public static function getUsableKey($key) $hexStrKey .= substr($hexFinal, 0, 2); } } - + return pack("H*", $hexStrKey); } - + public static function computeHmac($sData, $key) { return strtolower(hash_hmac("sha1", $sData, $key)); } - + + /** + * @param Order $order + * @return string + * @throws \Propel\Runtime\Exception\PropelException + */ public static function getCommandContext(Order $order) { - + $orderAddressId = $order->getInvoiceOrderAddressId(); $orderAddress = OrderAddressQuery::create()->findPk($orderAddressId); $billing = self::orderAddressForCbPayment($orderAddress); - - + + $deliveryAddressId = $order->getDeliveryOrderAddressId(); $deliveryAddress = OrderAddressQuery::create()->findPk($deliveryAddressId); $shipping = self::orderAddressForCbPayment($deliveryAddress); - + $commandContext = array("billing" => $billing, "shipping" => $shipping); - - $json = json_encode($commandContext); + + $json = json_encode($commandContext); $utf8 = utf8_encode( $json ); return base64_encode( $utf8 ); } - + + /** + * @param OrderAddress $orderAddress + * @return array + * @throws \Propel\Runtime\Exception\PropelException + */ public static function orderAddressForCbPayment(OrderAddress $orderAddress) { - + $address = array("name" => substr($orderAddress->getFirstname()." ".$orderAddress->getLastname()." ".$orderAddress->getCompany(), 0, 45), "firstName" => substr($orderAddress->getFirstname(), 0, 45), "lastName" => substr($orderAddress->getLastname(), 0, 45), @@ -230,30 +255,32 @@ public static function orderAddressForCbPayment(OrderAddress $orderAddress) { "city" => substr($orderAddress->getCity(), 0, 50), "postalCode" => $orderAddress->getZipcode(), ); - + if($orderAddress->getState() != null) { $address["stateOrProvince"] = $orderAddress->getState()->getIsocode(); } - + $address["country"] = $orderAddress->getCountry()->getIsoalpha2(); $address["phone"] = (substr($orderAddress->getPhone(),0,1) == "+")? $orderAddress->getPhone():""; $address["mobilePhone"] = (substr($orderAddress->getCellphone(),0,1) == "+")? $orderAddress->getPhone():""; - + return $address; } - - // Get the new format for seal content, for DSP-2 (cf https://www.monetico-paiement.fr/fr/info/documentations/Monetico_Paiement_documentation_migration_3DSv2_1.0.pdf#%5B%7B%22num%22%3A83%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C68%2C716%2C0%5D ) - public static function getHashable($vars) { + + /** + * Get the new format for seal content, for DSP-2 (cf https://www.monetico-paiement.fr/fr/info/documentations/Monetico_Paiement_documentation_migration_3DSv2_1.0.pdf#%5B%7B%22num%22%3A83%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C68%2C716%2C0%5D ) + * @param $vars + * @return string + */ + public static function getHashable($vars) { // Sort by keys according to ASCII order ksort($vars); - + // Formats the values in the following way : Nom_champ=Valeur_champ array_walk($vars, function (&$value, $key) {$value = "$key=$value";}); - - // Make it as a single string with * as separation character - $hashable = join("*", $vars); - return $hashable; - } + // Make it as a single string with * as separation character + return implode("*", $vars); + } } diff --git a/Config/config.json b/Config/config.json index 83d1339..d31242b 100755 --- a/Config/config.json +++ b/Config/config.json @@ -1 +1 @@ -{"CMCIC_TPE":"0000001","CMCIC_KEY":"12345678901234567890123456789012345678P0","CMCIC_CODESOCIETE":"4b18fba7070c8ae6bea8","CMCIC_VERSION":"3.0","CMCIC_SERVER":"https:\/\/p.monetico-services.com\/test\/","CMCIC_PAGE":"paiement.cgi"} +{"CMCIC_TPE":"0000001","CMCIC_KEY":"12345678901234567890123456789012345678P0","CMCIC_CODESOCIETE":"4b18fba7070c8ae6bea8","CMCIC_VERSION":"3.0","CMCIC_SERVER":"https:\/\/p.monetico-services.com\/","CMCIC_PAGE":"paiement.cgi"} \ No newline at end of file diff --git a/Config/config.xml b/Config/config.xml index 6425b9b..e5fe508 100755 --- a/Config/config.xml +++ b/Config/config.xml @@ -21,4 +21,10 @@ + + + + + + diff --git a/Config/module.xml b/Config/module.xml index b4eb561..dc84f05 100755 --- a/Config/module.xml +++ b/Config/module.xml @@ -14,7 +14,7 @@ fr_FR en_US - 1.3.2 + 1.4.0 Thelia diff --git a/Config/schema.xml b/Config/schema.xml deleted file mode 100755 index ace81b6..0000000 --- a/Config/schema.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Controller/CmcicSaveConfig.php b/Controller/CmcicSaveConfig.php index cede4e8..a783326 100755 --- a/Controller/CmcicSaveConfig.php +++ b/Controller/CmcicSaveConfig.php @@ -24,13 +24,12 @@ namespace CmCIC\Controller; use CmCIC\CmCIC; -use Thelia\Controller\Admin\BaseAdminController; -use CmCIC\Model\Config; use CmCIC\Form\ConfigureCmCIC; +use CmCIC\Model\Config; +use Thelia\Controller\Admin\BaseAdminController; use Thelia\Core\HttpFoundation\Response; -use Thelia\Core\Translation\Translator; -use Thelia\Core\Security\Resource\AdminResources; use Thelia\Core\Security\AccessManager; +use Thelia\Core\Security\Resource\AdminResources; use Thelia\Tools\URL; class CmcicSaveConfig extends BaseAdminController @@ -39,20 +38,20 @@ class CmcicSaveConfig extends BaseAdminController const CM_SERVER = "https://paiement.creditmutuel.fr/"; const OBC_SERVER = "https://ssl.paiement.banque-obc.fr/"; const MONETICO_SERVER = "https://p.monetico-services.com/"; - + const CMCIC_VERSION = "3.0"; const CMCIC_URLOK = "/order/placed/"; const CMCIC_URLKO = "/module/cmcic/payfail/"; const CMCIC_URLRECEIVE = "/module/cmcic/receive/"; - + public function downloadLog() { if (null !== $response = $this->checkAuth(AdminResources::MODULE, 'CmCIC', AccessManager::UPDATE)) { return $response; } - + $data = @file_get_contents(THELIA_LOG_DIR . "log-cmcic.txt"); - + if (empty($data)) { $data = $this->getTranslator()->trans("The CmCIC server log is currently empty.", [], CmCIC::DOMAIN_NAME); } @@ -75,14 +74,14 @@ public function save() $error_message=""; $conf = new Config(); $form = new ConfigureCmCIC($this->getRequest()); - + try { $vform = $this->validateForm($form); - + CmCIC::setConfigValue('debug', $vform->get('debug')->getData()); CmCIC::setConfigValue('allowed_ips', $vform->get('allowed_ips')->getData()); CmCIC::setConfigValue('send_confirmation_message_only_if_paid', $vform->get('send_confirmation_message_only_if_paid')->getData()); - + // After post checks (PREG_MATCH) & create json file if (preg_match("#^\d{7}$#", $vform->get('TPE')->getData()) && preg_match("#^[a-z\d]{40}$#i", $vform->get('com_key')->getData()) && @@ -90,28 +89,28 @@ public function save() preg_match("#^cic|cm|obc|mon$#", $vform->get('server')->getData()) ) { $serv = $vform->get('server')->getData(); - + switch($serv) { case 'mon': $serv = self::MONETICO_SERVER; break; - + case 'cic': $serv = self::CIC_SERVER; break; - + case 'cm': $serv = self::CM_SERVER; break; - + case 'obc': $serv = self::OBC_SERVER; break; - + default: throw new \InvalidArgumentException("Unknown server type '$serv'"); } - + if ($vform->get('debug')->getData() === true) { $serv .= 'test/'; } @@ -130,14 +129,14 @@ public function save() } } catch (\Exception $e) { $error_message = $e->getMessage(); - + $this->setupFormErrorContext( 'erreur sauvegarde configuration', $error_message, $form ); } - + return $this->generateRedirect(URL::getInstance()->absoluteUrl("/admin/module/CmCIC")); } } diff --git a/EventListeners/SendConfirmationEmail.php b/EventListeners/SendConfirmationEmail.php index 20eb90b..0480298 100644 --- a/EventListeners/SendConfirmationEmail.php +++ b/EventListeners/SendConfirmationEmail.php @@ -26,10 +26,10 @@ class SendConfirmationEmail implements EventSubscriberInterface * @var MailerFactory */ protected $mailer; - + /** @var EventDispatcherInterface */ protected $dispatcher; - + /** * SendConfirmationEmail constructor. * @param MailerFactory $mailer @@ -55,9 +55,12 @@ public function sendConfirmationEmail(OrderEvent $event) } } } - /* + + /** * @params OrderEvent $order * Checks if order payment module is paypal and if order new status is paid, send an email to the customer. + * @param OrderEvent $event + * @throws \Propel\Runtime\Exception\PropelException */ public function updateStatus(OrderEvent $event) { @@ -67,7 +70,7 @@ public function updateStatus(OrderEvent $event) if (CmCIC::getConfigValue('send_confirmation_message_only_if_paid')) { $this->dispatcher->dispatch(TheliaEvents::ORDER_SEND_CONFIRMATION_EMAIL, $event); } - + Tlog::getInstance()->debug("Confirmation email sent to customer " . $order->getCustomer()->getEmail()); } } diff --git a/Hook/HookManager.php b/Hook/HookManager.php new file mode 100644 index 0000000..6ca3444 --- /dev/null +++ b/Hook/HookManager.php @@ -0,0 +1,46 @@ +. */ +/* */ +/*************************************************************************************/ + +/** + * Created by Franck Allimant, CQFDev + * Date: 13/09/2019 09:41 + */ +namespace CmCIC\Hook; + +use Thelia\Core\Event\Hook\HookRenderEvent; +use Thelia\Core\Hook\BaseHook; + +class HookManager extends BaseHook +{ + /** + * Render configuration template + * + * @param HookRenderEvent $event + */ + public function onModuleConfigure(HookRenderEvent $event) + { + $event->add( + $this->render('cmcic/module-configuration.html') + ); + } +} diff --git a/I18n/AdminIncludes/en_US.php b/I18n/backOffice/default/en_US.php similarity index 100% rename from I18n/AdminIncludes/en_US.php rename to I18n/backOffice/default/en_US.php diff --git a/I18n/AdminIncludes/fr_FR.php b/I18n/backOffice/default/fr_FR.php similarity index 100% rename from I18n/AdminIncludes/fr_FR.php rename to I18n/backOffice/default/fr_FR.php diff --git a/templates/backOffice/default/cmcic/module-configuration.html b/templates/backOffice/default/cmcic/module-configuration.html new file mode 100644 index 0000000..8633b49 --- /dev/null +++ b/templates/backOffice/default/cmcic/module-configuration.html @@ -0,0 +1,75 @@ +
+ + {loop name="checkrights" type="cmcic.check.rights"} +
+

{$ERRMES} {$ERRFILE} | {intl d='cmcic.bo.default' l="Please change the access rights"}.

+
+ {/loop} +
+{elseloop rel="checkrights"} +
+
+
+
+ {intl d='cmcic.bo.default' l="Configuration CmCIC"} +
+
+ +
+
+
+ {form name="cmcic.configure"}  +
+ {form_hidden_fields form=$form} + + {include file = "includes/inner-form-toolbar.html" + hide_flags = true + page_url = "{url path='/admin/module/CmCIC'}" + close_url = "{url path='/admin/modules'}" + } + + {if $form_error} +
+
+
{$form_error_message}
+
+
+ {/if} + +
+
+ {render_form_field field="TPE"} + {render_form_field field="com_key"} + {render_form_field field="com_soc"} +
+

{intl d='cmcic.bo.default' l="URL de retour: %url" url={url path="/cmcic/validation"}}

+

{intl d='cmcic.bo.default' l="This is the value you should provide for the \"URL de Retour\" parameter in your bank back-office."}

+
+ +
+ +
+ {render_form_field field="server"} + {render_form_field field="page"} + {render_form_field field="send_confirmation_message_only_if_paid"} + {render_form_field field="debug"} + {render_form_field field="allowed_ips"} + +
+ +

+ {intl d='cmcic.bo.default' l='Click here to download the communications log between the module and the bank server.' url={url path="/admin/module/cmcic/log"}} +

+
+
+
+
+ {/form} +
+
+
+
+
+{/elseloop}