349 lines
10 KiB
PHP
Executable File
349 lines
10 KiB
PHP
Executable File
<?php
|
|
if (!defined('_PS_VERSION_'))
|
|
exit;
|
|
|
|
include_once dirname(__FILE__).'/models/FraudCore.php';
|
|
|
|
class Fraud extends Module
|
|
{
|
|
public function __construct()
|
|
{
|
|
$this->name = 'fraud';
|
|
$this->tab = 'payments_gateways';
|
|
$this->version = 1.0;
|
|
$this->author = 'Antadis';
|
|
$this->need_instance = 0;
|
|
|
|
parent::__construct();
|
|
|
|
$this->displayName = $this->l('Fraud');
|
|
$this->description = $this->l('Check fraud orders.');
|
|
}
|
|
|
|
public function install()
|
|
{
|
|
if(!(parent::install()
|
|
&& $this->installDB()
|
|
&& $this->registerHook('adminOrder')
|
|
&& $this->registerHook('backBeforePayment')
|
|
&& $this->registerHook('afterChangeStatus'))) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function installDB()
|
|
{
|
|
return Db::getInstance()->Execute('
|
|
CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'reputation` (
|
|
`id_customer` INTEGER UNSIGNED NOT NULL,
|
|
`ip_address` VARCHAR(15) NOT NULL,
|
|
`score` INTEGER NOT NULL,
|
|
`date_upd` DATETIME NOT NULL,
|
|
PRIMARY KEY (`id_customer`),
|
|
INDEX (`ip_address`)
|
|
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;
|
|
') && Db::getInstance()->Execute('
|
|
CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'reputation_ip` (
|
|
`ip_address` VARCHAR(15) NOT NULL,
|
|
PRIMARY KEY (`ip_address`)
|
|
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;
|
|
') && Db::getInstance()->Execute('
|
|
CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'order_reputation` (
|
|
`id_cart` INTEGER NOT NULL,
|
|
`score` INTEGER NOT NULL,
|
|
`pass` BOOLEAN NOT NULL,
|
|
`report` TEXT,
|
|
PRIMARY KEY (`id_cart`)
|
|
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;
|
|
');
|
|
}
|
|
|
|
public function hookbackBeforePayment($params)
|
|
{
|
|
FraudCore::CartFraudConnexion($params['cart']);
|
|
}
|
|
|
|
public function hookAdminOrder($params)
|
|
{
|
|
global $currentIndex;
|
|
|
|
if (Tools::getIsset('validFraud')) {
|
|
$token = Tools::getValue('token');
|
|
$id_order = Tools::getValue('id_order');
|
|
if (!FraudCore::validOrder($id_order)) {
|
|
echo '<br /><p class="alert" style="width:300px">'.$this->l('Update impossible').'</p>';
|
|
} else {
|
|
Tools::redirectAdmin($currentIndex.'&id_order='.$id_order.'&vieworder&hookconf=1&token='.$token);
|
|
}
|
|
}
|
|
|
|
if (Tools::getIsset('hookconf')) {
|
|
echo '<br /><p class="conf">'.$this->l('Valid order with success').'</p>';
|
|
}
|
|
|
|
$reputation = FraudCore::getReputationOrder((int) $params['id_order']);
|
|
if ($reputation) {
|
|
if ($reputation['score'] >= 100) {
|
|
$info = json_decode($reputation['report']);
|
|
$data = '<br />
|
|
<fieldset style="width: 400px">
|
|
<p class="alert" style="width:300px">
|
|
<b>'.$this->l('Suspect Order').'</b>
|
|
<br />
|
|
'.$this->l('Score : ').' <strong style="color:red">'.$reputation['score'].'</strong>
|
|
</p>
|
|
<h4>'.$this->l('Details : ').'</h4>
|
|
<p>'.implode('<br />', $info).'</p>';
|
|
|
|
if ($reputation['pass'] == 0) {
|
|
$data .= '<a onclick="if(!confirm(\'Voulez-vous valider la commande ? \')) return false;" href="'.$_SERVER['REQUEST_URI'].'&validFraud=1" class="button">'.$this->l('Valid Order').'</a>';
|
|
} else {
|
|
$data .= $this->l('Order validate manually');
|
|
}
|
|
$data .= '</fieldset>';
|
|
echo $data;
|
|
}
|
|
}
|
|
}
|
|
|
|
public function hookAdminOrderNew($params)
|
|
{
|
|
global $currentIndex;
|
|
|
|
$data .= '';
|
|
$reputation = FraudCore::getReputationOrder((int) $params['id_order']);
|
|
if ($reputation) {
|
|
$data .= '
|
|
<div class="col-md-12">
|
|
<div class="panel">
|
|
<div class="panel-title">
|
|
<h2><span class="anticon anticon-shield"></span> '.$this->l('Suspect Order').''.($reputation['pass']!=0?' <span style="font-size:12px;" class="text-rose"><em>('.$this->l('Order validate manually').')</span></em>':'').'</h2>
|
|
<div class="clearfix"></div>
|
|
</div>
|
|
<div class="panel-content">';
|
|
|
|
if (Tools::getIsset('validFraud')) {
|
|
$token = Tools::getValue('token');
|
|
$id_order = Tools::getValue('id_order');
|
|
if (!FraudCore::validOrder($id_order)) {
|
|
$data .= '<br /><p class="alert">'.$this->l('Update impossible').'</p>';
|
|
} else {
|
|
Tools::redirectAdmin($currentIndex.'&id_order='.$id_order.'&vieworder&hookconf=1&token='.$token);
|
|
}
|
|
}
|
|
|
|
if (Tools::getIsset('hookconf')) {
|
|
$data .= '<br /><p class="conf">'.$this->l('Valid order with success').'</p>';
|
|
}
|
|
|
|
if ($reputation['score'] >= 100) {
|
|
$info = json_decode($reputation['report']);
|
|
$data .= '
|
|
<a class="btn btn-danger" role="button" data-toggle="collapse" href="#collapseFraudModule">
|
|
<b>'.$this->l('Score : ').'</b> <span class="badge">'.$reputation['score'].'</span>
|
|
</a>
|
|
<div class="collapse" id="collapseFraudModule">
|
|
<h4>'.$this->l('Details : ').'</h4>
|
|
<p>'.implode('<br />', $info).'</p>
|
|
</div>';
|
|
if ($reputation['pass'] == 0) {
|
|
$data .= '<a class="pull-right btn btn-primary btn-sm" onclick="if(!confirm(\'Voulez-vous valider la commande ? \')) return false;" href="'.$_SERVER['REQUEST_URI'].'&validFraud=1" class="button">'.$this->l('Valid Order').'</a>';
|
|
}
|
|
}
|
|
|
|
$data .= '</div>
|
|
</div>
|
|
</div>';
|
|
}
|
|
return $data;
|
|
}
|
|
|
|
/* This method is called after the response returned by paybox */
|
|
public function testPaybox($id_order, $ip_country)
|
|
{
|
|
$order = new Order($id_order);
|
|
$authorized = array('FRA','ESP','DEU','ITA','NLD','SWE','GBR','PRT','CHE','LUX','POL','AUT','BEL');
|
|
|
|
if (!in_array($ip_country, $authorized)) {
|
|
$total_score = 110;
|
|
$fraud_report = array();
|
|
$fraud_report[] = 'Pays de paiement hors EU (+110)';
|
|
|
|
$order_reputation = FraudCore::getReputationOrder((int)$id_order);
|
|
if ($order_reputation) {
|
|
$fraud_report = array_merge($fraud_report, json_decode($order_reputation['report']));
|
|
$total_score += (int)$order_reputation['score'];
|
|
}
|
|
|
|
Db::getInstance()->ExecuteS('
|
|
INSERT INTO `'._DB_PREFIX_.'order_reputation`
|
|
VALUES (
|
|
'.(int) $order->id_cart.',
|
|
'.(int) $total_score.',
|
|
'.((int) $total_score < 100? 1: 0).',
|
|
"'.pSQL(json_encode($fraud_report)).'"
|
|
)
|
|
ON DUPLICATE KEY UPDATE
|
|
`score` = '.(int) $total_score.',
|
|
`report` = "'.pSQL(json_encode($fraud_report)).'",
|
|
`pass` = '.((int) $total_score < 100? 1: 0).'
|
|
');
|
|
$this->_changeStatutFraud($order->id);
|
|
}
|
|
}
|
|
|
|
/* This method is called when a customer use account's paypal on a different address from previously */
|
|
public function testPaypalBilling($id_order)
|
|
{
|
|
$order = new Order($id_order);
|
|
$id_billing = Db::getInstance()->getValue('
|
|
SELECT `is_billing`
|
|
FROM `'._DB_PREFIX_.'paypal_order`
|
|
WHERE `id_order` = '.(int) $order->id
|
|
);
|
|
|
|
if ($id_billing !=0) {
|
|
$address = new Address($order->id_address_delivery);
|
|
$address_paypal = Db::getInstance()->getRow('
|
|
SELECT `city`, `address`
|
|
FROM `'._DB_PREFIX_.'paypal_customer_agreement`
|
|
WHERE id_paypal_agreement = '.(int) $id_billing.'
|
|
');
|
|
|
|
$new_address = false;
|
|
if ($address->city != $address_paypal['city']) {
|
|
$new_address = true;
|
|
} else if ($address->address1 != $address_paypal['address']) {
|
|
$new_address = true;
|
|
}
|
|
|
|
if ($new_address) {
|
|
$total_score = 110;
|
|
$fraud_report = array();
|
|
$fraud_report[] = 'Compte paypal enregistré utilisé sur une nouvelle adresse (+110)';
|
|
|
|
Db::getInstance()->ExecuteS('
|
|
INSERT INTO `'._DB_PREFIX_.'order_reputation`
|
|
VALUES (
|
|
'.(int) $order->id_cart.',
|
|
'.(int) $total_score.',
|
|
'.((int) $total_score < 100? 1: 0).',
|
|
"'.pSQL(json_encode($fraud_report)).'"
|
|
)
|
|
');
|
|
$this->_changeStatutFraud($order->id);
|
|
}
|
|
}
|
|
}
|
|
|
|
public function hookafterChangeStatus($params)
|
|
{
|
|
if ($params['newOrderState'] == 2) {
|
|
$order = new Order($params['order']['id']);
|
|
if (Validate::isLoadedObject($order)) {
|
|
|
|
if ($order->module != 'paybox') {
|
|
return FALSE;
|
|
}
|
|
|
|
// commande déjà test
|
|
$already_test = Db::getInstance()->getValue('
|
|
SELECT `id_cart`
|
|
FROM `ps_order_reputation`
|
|
WHERE `id_cart` ='.(int)$order->id_cart
|
|
);
|
|
if (!empty($already_test)) {
|
|
return true;
|
|
}
|
|
|
|
$fraud_detection = new FraudCore($order);
|
|
$fraud_detection->setFraudScore();
|
|
$fraud_score = $fraud_detection->getFraudScore();
|
|
$fraud_report = $fraud_detection->getFraudReport();
|
|
|
|
$current_reputation = 0;
|
|
$i = 0;
|
|
$query = Db::getInstance()->ExecuteS('
|
|
SELECT *
|
|
FROM `'._DB_PREFIX_.'reputation`
|
|
WHERE `id_customer` = '.(int) $order->id_customer);
|
|
|
|
if ($query && count($query) > 0) {
|
|
foreach($query as $r) {
|
|
$current_reputation += $r['score'] - floor((time() - strtotime($r['date_upd'])) / (86400 * 7)) * 20;
|
|
$i++;
|
|
}
|
|
}
|
|
// paiement ok
|
|
$reputation_change = 0;
|
|
if ($i) {
|
|
$current_reputation = floor($current_reputation / $i);
|
|
}
|
|
$final_reputation = max($current_reputation + $reputation_change, 0);
|
|
$total_score = max($fraud_score, 0) + $final_reputation;
|
|
|
|
$cart_info = Db::getInstance()->getRow('
|
|
SELECT *
|
|
FROM ps_cart_fraud
|
|
WHERE id_cart = '. (int)$order->id_cart);
|
|
|
|
Db::getInstance()->ExecuteS('
|
|
INSERT INTO `'._DB_PREFIX_.'order_reputation`
|
|
VALUES (
|
|
'.(int) $order->id_cart.',
|
|
'.(int) $total_score.',
|
|
'.((int) $total_score < 100? 1: 0).',
|
|
"'.pSQL(json_encode($fraud_report)).'"
|
|
)
|
|
');
|
|
|
|
// check fraud score
|
|
if ($total_score < 100) {
|
|
Db::getInstance()->ExecuteS('
|
|
INSERT INTO `'._DB_PREFIX_.'reputation`
|
|
VALUES (
|
|
'.(int) $order->id_customer.',
|
|
"'.pSQL($cart_info['ip_cart']).'",
|
|
0,
|
|
NOW()
|
|
)
|
|
ON DUPLICATE KEY
|
|
UPDATE
|
|
`score` = 0,
|
|
`ip_address` = "'.pSQL(Tools::getRemoteAddr()).'",
|
|
`date_upd` = NOW()
|
|
');
|
|
} else {
|
|
$reputation_change += 50;
|
|
Db::getInstance()->ExecuteS('
|
|
INSERT INTO `'._DB_PREFIX_.'reputation`
|
|
VALUES (
|
|
'.(int) $order->id_customer.',
|
|
"'.pSQL($cart_info['ip_cart']).'",
|
|
'.(int) $reputation_change.',
|
|
NOW()
|
|
)
|
|
ON DUPLICATE KEY
|
|
UPDATE
|
|
`score` = `score` + '.(int) $reputation_change.',
|
|
`ip_address` = "'.pSQL($cart_info['ip_cart']).'",
|
|
`date_upd` = NOW()
|
|
');
|
|
|
|
$this->_changeStatutFraud($order->id);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
private function _changeStatutFraud($order_id)
|
|
{
|
|
$history = new OrderHistory();
|
|
$history->id_order = $order_id;
|
|
$history->changeIdOrderState(18, $order_id);
|
|
$history->addWithemail();
|
|
}
|
|
}
|