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"}
-
-
-
-
-
-
-{/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"}
+
+
+
+
+
+
+{/elseloop}