open ( $conf['db']['host'] ,$conf['db']['user'] ,base64_decode ($conf['db']['pass']) ,$conf['db']['schema'] ); } /** * 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']) && isset ($params['Ds_Signature'])) { if (isset ($params['Ds_ErrorCode'])) $error = $params['Ds_ErrorCode']; else $error = NULL; try { return self::$conn->query ( 'CALL transaction_confirm_with_check (#, #, #, #, #, #, #)', [ $params['Ds_Amount'] ,$params['Ds_Order'] ,$params['Ds_MerchantCode'] ,$params['Ds_Currency'] ,$params['Ds_Response'] ,$params['Ds_Signature'] ,$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 (); } } ?>