*/ class Mercanet extends AbstractPaymentModule { const MODULE_DOMAIN = 'mercanet'; /** * The confirmation message identifier */ const CONFIRMATION_MESSAGE_NAME = 'mercanet_payment_confirmation'; /** * @param ConnectionInterface|null $con * @throws \Propel\Runtime\Exception\PropelException */ public function postActivation(ConnectionInterface $con = null) { // Setup some default values if (null === self ::getConfigValue('merchantId', null)) { // Initialize with test data self::setConfigValue('merchantId', '211000021310001'); self::setConfigValue('secretKeyVersion', 1); self::setConfigValue('secretKey', 'S9i8qClCnb2CZU3y3Vn0toIOgz3z_aBi79akR30vM9o'); self::setConfigValue('mode', 'TEST'); self::setConfigValue('allowed_ip_list', $_SERVER['REMOTE_ADDR']); self::setConfigValue('minimum_amount', 0); self::setConfigValue('maximum_amount', 0); self::setConfigValue('send_payment_confirmation_message', 1); self::setConfigValue('transactionId', 1); self::setConfigValue('mode_v2_simplifie', 0); } if (null === MessageQuery::create()->findOneByName(self::CONFIRMATION_MESSAGE_NAME)) { $message = new Message(); $message ->setName(self::CONFIRMATION_MESSAGE_NAME) ->setHtmlTemplateFileName('mercanet-payment-confirmation.html') ->setTextTemplateFileName('mercanet-payment-confirmation.txt') ->setLocale('en_US') ->setTitle('Mercanet payment confirmation') ->setSubject('Payment of order {$order_ref}') ->setLocale('fr_FR') ->setTitle('Confirmation de paiement par Mercanet') ->setSubject('Confirmation du paiement de votre commande {$order_ref}') ->save() ; } } /** * @param ConnectionInterface|null $con * @param bool $deleteModuleData * @throws \Propel\Runtime\Exception\PropelException */ public function destroy(ConnectionInterface $con = null, $deleteModuleData = false) { if ($deleteModuleData) { MessageQuery::create()->findOneByName(self::CONFIRMATION_MESSAGE_NAME)->delete(); } } /** * * generate a transaction id * @return int|mixed */ private function generateTransactionID() { $transId = self::getConfigValue('transactionId', 1); $transId = 1 + (int)$transId; self::setConfigValue('transactionId', $transId); return sprintf('%s%d', uniqid('', false), $transId); } /** * * generate a V1 transaction id 'reset every 24 hour * @return int|mixed */ private function generateV1SimplifieTransactionID() { $transId = self::getConfigValue('v1TransactionId', 1); $transId = 1 + (int)$transId; // This ID is supposed unique for a single day. We wiil not rester it everyday, nut we will // set is to 1 when the limit size (6 digits) is reached. if ($transId > 999999) { $transId = 1; } self::setConfigValue('v1TransactionId', $transId); return sprintf("%06d", $transId); } /** * * Method used by payment gateway. * * If this method return a \Thelia\Core\HttpFoundation\Response instance, this response is send to the * browser. * * In many cases, it's necessary to send a form to the payment gateway. * On your response you can return this form already completed, ready to be sent * * @param Order $order processed order * @return null|\Thelia\Core\HttpFoundation\Response * @throws \Propel\Runtime\Exception\PropelException */ public function pay(Order $order) { $estModeV2Simplifile = (bool) self::getConfigValue('mode_v2_simplifie'); $amount = $order->getTotalAmount(); $customer = $order->getCustomer(); /** @var Router $router */ $router = $this->getContainer()->get('router.mercanet'); // Initialisation de la classe Mercanet avec passage en parametre de la cle secrete $paymentRequest = new MercanetApi(self::getConfigValue('secretKey')); if ($estModeV2Simplifile) { $transactionId = $this->generateV1SimplifieTransactionID(); $paymentRequest->sets10TransactionId($this->generateV1SimplifieTransactionID()); } else { $transactionId = $this->generateTransactionID(); $paymentRequest->setTransactionReference($transactionId); } // Indiquer quelle page de paiement appeler : TEST ou PRODUCTION if ('TEST' === self::getConfigValue('mode', 'TEST')) { $paymentRequest->setUrl(MercanetApi::TEST); } else { $paymentRequest->setUrl(MercanetApi::PRODUCTION); } // Renseigner les parametres obligatoires pour l'appel de la page de paiement $paymentRequest->setMerchantId(self::getConfigValue('merchantId')); $paymentRequest->setKeyVersion(self::getConfigValue('secretKeyVersion')); $paymentRequest->setAmount((int)round(100 * $amount)); $paymentRequest->setCurrency($order->getCurrency()->getCode()); $paymentRequest->setNormalReturnUrl(URL::getInstance()->absoluteUrl($router->generate('mercanet.payment.manual_response'))); $paymentRequest->setAutomaticResponseUrl(URL::getInstance()->absoluteUrl($router->generate('mercanet.payment.confirmation'))); // Renseigner les parametres facultatifs pour l'appel de la page de paiement try { $paymentRequest->setLanguage(substr($order->getLang()->getCode(), 0, 2)); } catch (\Exception $ex) { $paymentRequest->setLanguage('en'); } $paymentRequest->setCustomerContactEmail($customer->getEmail()); $paymentRequest->setOrderId($order->getId()); $order->setTransactionRef($transactionId)->save(); // Verification de la validite des parametres renseignes $paymentRequest->validate(); // Appel de la page de paiement Mercanet avec le connecteur POST en passant en parametres : Data, InterfaceVersion, Seal /* echo "
getUrl() . "\">" . "toParameterString() . "\">" . "" . "getShaSign() . "\">" . "
" . "" . ""; */ return $this->generateGatewayFormResponse( $order, $paymentRequest->getUrl(), [ 'Data' => $paymentRequest->toParameterString(), 'InterfaceVersion' => MercanetApi::INTERFACE_VERSION, 'Seal' => $paymentRequest->getShaSign(), ] ); } /** * @return boolean true to allow usage of this payment module, false otherwise. */ public function isValidPayment() { $valid = (null !== self::getConfigValue('secretKey')) && (null !== self::getConfigValue('merchantId')); if ($valid) { $mode = self::getConfigValue('mode', false); // If we're in test mode, do not display Payzen on the front office, except for allowed IP addresses. if ('TEST' === $mode) { $raw_ips = explode("\n", self::getConfigValue('allowed_ip_list', '')); $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 , true); } elseif ('PRODUCTION' === $mode) { $valid = true; } if ($valid) { // Check if total order amount is in the module's limits $valid = $this->checkMinMaxAmount(); } } return $valid; } /** * Check if total order amount is in the module's limits * * @return bool true if the current order total is within the min and max limits */ protected function checkMinMaxAmount() { // Check if total order amount is in the module's limits $order_total = $this->getCurrentOrderTotalAmount(); $min_amount = self::getConfigValue('minimum_amount', 0); $max_amount = self::getConfigValue('maximum_amount', 0); return $order_total > 0 && ($min_amount <= 0 || $order_total >= $min_amount) && ($max_amount <= 0 || $order_total <= $max_amount); } }