0
1
Fork 0
hedera-web-mindshore/lib/vn/tpv/tpv.php

273 lines
6.1 KiB
PHP
Executable File

<?php
namespace Vn;
require_once ('vn/hedera/init.php');
require_once ('vn/db/db.php');
require_once ('vn/tpv/soap-method.php');
use Vn\Lib\Log;
class Tpv
{
static $conn;
/**
* Initializes the class.
**/
static function init ()
{
global $conf;
$conf = require (Hedera\_CONFIG_DIR .'/config.my.php');
openlog ('hedera-web', LOG_ODELAY, LOG_LOCAL0);
self::$conn = new Db\Conn ();
self::$conn->open (
$conf['db']['host']
,$conf['db']['user']
,base64_decode ($conf['db']['pass'])
,$conf['db']['schema']
,$conf['db']['port']
);
}
/**
* Deinitializes the class.
**/
static function deinit ()
{
self::$conn->close ();
closelog ();
}
/**
* Gets transaction confirmations from the IMAP mailbox.
**/
static function getFromMailbox ()
{
self::init ();
$imap = NULL;
if (self::$conn->isOpen ())
{
$imapConf = self::$conn->getRow (
'SELECT host, user, pass, clean_period, success_folder, error_folder '
.'FROM tpv_imap_config'
);
if ($imapConf)
{
$mailbox = sprintf ('{%s/imap/ssl/novalidate-cert}INBOX',
$imapConf['host']);
$imap = imap_open ($mailbox
,$imapConf['user']
,base64_decode ($imapConf['pass'])
);
}
}
if ($imap)
{
// Fetchs and confirms new transaction mails
$inbox = imap_search ($imap, 'ALL');
if ($inbox)
foreach ($inbox as $msg)
{
// Decodes the mail body
$params = [];
$body = imap_fetchbody ($imap, $msg, '1');
$strings = explode (';', $body);
foreach ($strings as $string)
{
$x = explode (':', $string);
$params[trim ($x[0])] = trim ($x[1]);
}
// Confirms the transaction
$success = self::confirm ($params);
// Moves the processed mail to another folder
if ($success)
$folder = $imapConf['success_folder'];
else
$folder = $imapConf['error_folder'];
$folder = sprintf ('INBOX.%s', $folder);
if (!imap_mail_move ($imap, $msg, $folder))
trigger_error (sprintf ('TPV: IMAP: Can\'t move message to %s: %s'
,$folder
,imap_last_error ()
), E_USER_WARNING);
}
if ($inbox && ($count = count ($inbox)) > 0)
trigger_error (sprintf ('TPV: %d mails processed.', $count));
imap_expunge ($imap);
// Cleans the old mails
if (rand (1, 20) == 1)
{
$folders = array (
$imapConf['success_folder']
,$imapConf['error_folder']
);
$deleted = 0;
$date = new \DateTime (NULL);
$date->sub (new \DateInterval ($imapConf['clean_period']));
$filter = sprintf ('BEFORE "%s"', $date->format('D, j M Y'));
foreach ($folders as $folder)
if (imap_reopen ($imap, $mailbox.'.'.$folder))
if ($messages = imap_search ($imap, $filter))
{
foreach ($messages as $message)
imap_delete ($imap, $message);
imap_expunge ($imap);
$deleted += count ($messages);
}
trigger_error (sprintf ('TPV: Cleaner: %d mails deleted.', $deleted));
}
imap_close ($imap);
}
else
trigger_error (sprintf ('TPV: IMAP: %s', imap_last_error ()), E_USER_ERROR);
self::deinit ();
}
/**
* Gets transaction confirmation from HTTP POST.
**/
static function getFromPost ()
{
self::init ();
if (self::$conn->isOpen ())
self::confirm ($_POST);
self::deinit ();
}
/**
* Gets transaction confirmation from SOAP service.
**/
static function getFromSoap ()
{
ini_set ('soap.wsdl_cache_enabled', FALSE);
$server = new \SoapServer (__DIR__ .'/soap.wsdl');
$server->addFunction ('procesaNotificacionSIS');
$server->handle ();
}
/**
* Tryes to confirm a transaction with the given params.
**/
static function confirm ($params)
{
if (isset ($params['Ds_Amount'])
&& isset ($params['Ds_Order'])
&& isset ($params['Ds_MerchantCode'])
&& isset ($params['Ds_Currency'])
&& isset ($params['Ds_Response']))
{
if (isset ($params['Ds_ErrorCode']))
$error = $params['Ds_ErrorCode'];
else
$error = NULL;
try {
return self::$conn->query (
'CALL transaction_confirm (#, #, #, #, #, #)',
[
$params['Ds_Amount']
,$params['Ds_Order']
,$params['Ds_MerchantCode']
,$params['Ds_Currency']
,$params['Ds_Response']
,$error
]
);
}
catch (\Exception $e)
{
trigger_error (sprintf ("TPV: DB: %s", $e->getMessage ()), E_USER_WARNING);
}
}
return FALSE;
}
static function transactionStart ($conn, $amount, $urlOk, $urlKo, $companyId, &$url, &$signature)
{
$row = $conn->getRow ('CALL transaction_start_sha256 (#, #)',
[$amount, $companyId]);
if (!isset($row))
throw new Exception ('Transaction error');
$transactionId = str_pad ($row['transaction_id'], 12, '0', STR_PAD_LEFT);
$urlOk = empty ($urlOk) ? '' : sprintf ($urlOk, $transactionId);
$urlKo = empty ($urlKo) ? '' : sprintf ($urlKo, $transactionId);
$merchantUrl = $row['merchant_url'] ? $row['merchant_url'] : '';
$params = [
'Ds_Merchant_Amount' => $amount
,'Ds_Merchant_Order' => $transactionId
,'Ds_Merchant_MerchantCode' => $row['merchant']
,'Ds_Merchant_Currency' => $row['currency']
,'Ds_Merchant_TransactionType' => $row['transaction_type']
,'Ds_Merchant_Terminal' => $row['terminal']
,'Ds_Merchant_MerchantURL' => $merchantUrl
,'Ds_Merchant_UrlOK' => $urlOk
,'Ds_Merchant_UrlKO' => $urlKo
];
$encodedParams = base64_encode (json_encode ($params));
$key = base64_decode ($row['secret_key']);
$bytes = array (0, 0, 0, 0, 0, 0, 0, 0);
$iv = implode (array_map ("chr", $bytes));
$key = mcrypt_encrypt (MCRYPT_3DES, $key, $transactionId, MCRYPT_MODE_CBC, $iv);
$signature = base64_encode (hash_hmac ('sha256', $encodedParams, $key, TRUE));
$url = $row['url'];
return $encodedParams;
}
/**
* Tests the confirmation process. The corresponding record
* must exist in the `tpv_transaction` table.
**/
static function test ($order)
{
self::init ();
if (self::$conn->isOpen () && isset ($order))
self::$conn->query ('CALL transaction_confirm_by_id (#)', [$order]);
self::deinit ();
}
}
?>