Files

364 lines
13 KiB
PHP

<?php
/*************************************************************************************/
/* This file is part of the Thelia package. */
/* */
/* Copyright (c) OpenStudio */
/* email : dev@thelia.net */
/* web : http://www.thelia.net */
/* */
/* For the full copyright and license information, please view the LICENSE.txt */
/* file that was distributed with this source code. */
/*************************************************************************************/
namespace Atos;
use Atos\Model\AtosCurrencyQuery;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\Connection\ConnectionInterface;
use Symfony\Component\Routing\Router;
use Thelia\Core\HttpFoundation\Response;
use Thelia\Core\Template\ParserInterface;
use Thelia\Core\Translation\Translator;
use Thelia\Install\Database;
use Thelia\Log\Tlog;
use Thelia\Model\Config;
use Thelia\Model\ConfigQuery;
use Thelia\Model\Message;
use Thelia\Model\MessageQuery;
use Thelia\Model\Order;
use Thelia\Module\AbstractPaymentModule;
use Thelia\Tools\URL;
class Atos extends AbstractPaymentModule
{
const MODULE_DOMAIN = 'atos';
/**
* The confirmation message identifier
*/
const CONFIRMATION_MESSAGE_NAME = 'atos_payment_confirmation';
private $parameters;
public function postActivation(ConnectionInterface $con = null)
{
// Setup some default values
if (null === Atos::getConfigValue('atos_merchantId', null)) {
Atos::setConfigValue('atos_transactionId', 1);
Atos::setConfigValue('minimum_amount', 0);
Atos::setConfigValue('maximum_amount', 0);
Atos::setConfigValue('send_payment_confirmation_message', 1);
}
// Try to chmod binaries if they're not executables
$binFile = Atos::getBinDirectory() . 'request';
if (! is_executable($binFile)) {
@chmod($binFile, 0755);
}
$binFile = Atos::getBinDirectory() . 'response';
if (! is_executable($binFile)) {
@chmod($binFile, 0755);
}
$database = new Database($con);
$database->insertSql(null, array(
__DIR__ . DS . 'Config'.DS.'thelia.sql'
));
// Create payment confirmation message from templates, if not already defined
$email_templates_dir = __DIR__.DS.'I18n'.DS.'email-templates'.DS;
if (null === MessageQuery::create()->findOneByName(Atos::CONFIRMATION_MESSAGE_NAME)) {
$message = new Message();
$message
->setName(Atos::CONFIRMATION_MESSAGE_NAME)
->setHtmlTemplateFileName('atos-payment-confirmation.html')
->setTextTemplateFileName('atos-payment-confirmation.txt')
->setLocale('en_US')
->setTitle('Atos payment confirmation')
->setSubject('Payment of order {$order_ref}')
->setLocale('fr_FR')
->setTitle('Confirmation de paiement par Atos')
->setSubject('Confirmation du paiement de votre commande {$order_ref}')
->save()
;
}
$this->replacePath();
}
public function update($currentVersion, $newVersion, ConnectionInterface $con = null)
{
// Migrate old configuration
if (null === Atos::getConfigValue('atos_merchantId', null)) {
if (null !== $atosConfigs = ConfigQuery::create()->filterByName('atos_%', Criteria::LIKE)->find()) {
/** @var Config $atosConfig */
foreach ($atosConfigs as $atosConfig) {
Atos::setConfigValue($atosConfig->getName(), $atosConfig->getValue());
$atosConfig->delete($con);
}
}
}
parent::update($currentVersion, $newVersion, $con);
}
public function destroy(ConnectionInterface $con = null, $deleteModuleData = false)
{
if ($deleteModuleData) {
$database = new Database($con);
$database->execute('drop table `atos_currency`');
MessageQuery::create()->findOneByName(Atos::CONFIRMATION_MESSAGE_NAME)->delete();
}
}
protected function replacePath()
{
$pathfile = $this->getPathfilePath();
$pathfileContent = @file_get_contents($pathfile . '.dist');
if ($pathfileContent) {
$pathfileContent = str_replace('__PATH__', __DIR__, $pathfileContent);
if (! file_put_contents($this->getConfigDirectory() . 'pathfile', $pathfileContent)) {
throw new \RuntimeException(
Translator::getInstance()->trans(
'File %file must be writable, please check Atos/Config directory permissions.',
[ '%file' => 'pathfile' ],
Atos::MODULE_DOMAIN
)
);
}
} else {
throw new \RuntimeException(
Translator::getInstance()->trans(
'Failed to read the %file file. Please check file and directory permissions.',
[ '%file' => $pathfile . '.dist' ],
Atos::MODULE_DOMAIN
)
);
}
}
/**
* @param string $key atos key parameter
* @param string $value parameter value
* @return $this
*/
protected function addParam($key, $value)
{
$this->parameters = sprintf("%s %s=%s", $this->parameters, $key, $value);
return $this;
}
protected function getParameters()
{
return trim($this->parameters);
}
/**
*
* generate a transaction id for atos solution
*
* @return int|mixed
*/
private function generateTransactionID()
{
$transId = Atos::getConfigValue('atos_transactionId', 1);
$transId = 1 + intval($transId);
if (strlen($transId) > 6) {
$transId = 1;
}
Atos::setConfigValue('atos_transactionId', $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 \Thelia\Model\Order $order processed order
* @return null|\Thelia\Core\HttpFoundation\Response
*/
public function pay(Order $order)
{
$pathBin = Atos::getBinDirectory() .'request';
$atosCurrency = AtosCurrencyQuery::create()->findPk(
$order->getCurrency()->getCode()
);
if (null == $atosCurrency) {
throw new \InvalidArgumentException(
sprintf(
"Atos does not supprot this currency : %s",
$order->getCurrency()->getCode()
)
);
}
$amount = $order->getTotalAmount();
$amount = number_format($amount, $atosCurrency->getDecimals(), '', '');
$transactionId = $this->generateTransactionID();
$order->setTransactionRef($transactionId)->save();
/** @var Router $router */
$router = $this->getContainer()->get('router.atos');
$this
->addParam('pathfile', Atos::getPathfilePath())
->addParam('merchant_id', Atos::getConfigValue('atos_merchantId'))
->addParam('customer_email', $order->getCustomer()->getEmail())
->addParam('currency_code', $atosCurrency->getAtosCode())
->addParam('amount', $amount)
->addParam('language', $order->getLang()->getCode())
->addParam('transaction_id', $transactionId)
->addParam('order_id', $order->getId())
->addParam('automatic_response_url', URL::getInstance()->absoluteUrl($router->generate('atos.payment.confirmation')))
->addParam('cancel_return_url', URL::getInstance()->absoluteUrl($router->generate('atos.payment.cancel', [ 'orderId' => $order->getId() ])))
->addParam('normal_return_url', $this->getPaymentSuccessPageUrl($order->getId()))
;
$encrypt = exec(sprintf("%s %s", $pathBin, $this->getParameters()));
if (! empty($encrypt)) {
$datas = explode('!', $encrypt);
if ($datas[1] == '' && $datas[2] == '') {
throw new \RuntimeException(
Translator::getInstance()->trans('Request binary not found in "%path"', ['%path' => $pathBin])
);
} elseif ($datas[1] != 0) {
throw new \RuntimeException($datas[2]);
} else {
/** @var ParserInterface $parser */
$parser = $this->getContainer()->get('thelia.parser');
$parser->setTemplateDefinition(
$parser->getTemplateHelper()->getActiveFrontTemplate(),
true
);
$content = $parser->render('atos/payment.html', [
'site_name' => self::getConfigValue('store_name'),
'form' => $datas[3],
'order_id' => $order->getId()
]);
return Response::create($content);
}
} else {
throw new \RuntimeException(
Translator::getInstance()->trans(
'Empty response recevied from Atos binary "%path". Please check path and permissions.',
['%path' => $pathBin],
Atos::MODULE_DOMAIN
)
);
// FIXME : show something to the customer
}
}
/**
* @return boolean true to allow usage of this payment module, false otherwise.
*/
public function isValidPayment()
{
$valid = false;
// Check config files
$parmcomFile = Atos::getConfigDirectory() . 'parmcom.' . Atos::getConfigValue('atos_merchantId', '0');
$certifFile = Atos::getConfigDirectory() . 'certif.fr.' . Atos::getConfigValue('atos_merchantId', '0');
if (is_readable($parmcomFile) && is_readable($certifFile)) {
$mode = Atos::getConfigValue('atos_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", Atos::getConfigValue('atos_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);
} elseif ('PRODUCTION' == $mode) {
$valid = true;
}
if ($valid) {
// Check if total order amount is in the module's limits
$valid = $this->checkMinMaxAmount();
}
} else {
Tlog::getInstance()->addWarning(
Translator::getInstance()->trans(
"Atos payment module is nort properly configured. Please check module configuration in your back-office.",
[],
Atos::MODULE_DOMAIN
)
);
}
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 = Atos::getConfigValue('atos_minimum_amount', 0);
$max_amount = Atos::getConfigValue('atos_maximum_amount', 0);
return
$order_total > 0
&&
($min_amount <= 0 || $order_total >= $min_amount) && ($max_amount <= 0 || $order_total <= $max_amount);
}
public static function getBinDirectory()
{
return __DIR__ . DS . 'bin' . DS;
}
public static function getConfigDirectory()
{
return __DIR__ . DS . 'Config' . DS;
}
public static function getPathfilePath()
{
return Atos::getConfigDirectory() . 'pathfile';
}
}