Files
sterivein/local/modules/Mercanet/Mercanet.php

271 lines
10 KiB
PHP

<?php
/*************************************************************************************/
/* Copyright (c) Franck Allimant, CQFDev */
/* email : thelia@cqfdev.fr */
/* web : http://www.cqfdev.fr */
/* */
/* For the full copyright and license information, please view the LICENSE */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Mercanet;
use Mercanet\Api\MercanetApi;
use Propel\Runtime\Connection\ConnectionInterface;
use Symfony\Component\Routing\Router;
use Thelia\Model\Message;
use Thelia\Model\MessageQuery;
use Thelia\Model\Order;
use Thelia\Module\AbstractPaymentModule;
use Thelia\Tools\URL;
/**
* Class Mercanet
* @package Mercanet
* @author Franck Allimant <franck@cqfdev.fr>
*/
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 "<html><body><form name=\"redirectForm\" method=\"POST\" action=\"" . $paymentRequest->getUrl() . "\">" .
"<input type=\"hidden\" name=\"Data\" value=\"". $paymentRequest->toParameterString() . "\">" .
"<input type=\"hidden\" name=\"InterfaceVersion\" value=\"". self::INTERFACE_VERSION . "\">" .
"<input type=\"hidden\" name=\"Seal\" value=\"" . $paymentRequest->getShaSign() . "\">" .
"<noscript><input type=\"submit\" name=\"Go\" value=\"Click to continue\"/></noscript> </form>" .
"<script type=\"text/javascript\"> document.redirectForm.submit(); </script>" .
"</body></html>";
*/
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);
}
}