Как вам такой код?

IP
На сайте с 16.01.2008
Offline
24
1089

Камрады, если не сложно - с профессиональной точки зрения оцените качество кода плз:

<?php

class CPaiment {
/*
Перевод суммы, заданной строкой с точкой или запятой
для разделения рублей и копеек.
Возвращает сумму в копейках.
При ошибке в записи суммы - вернет -1.
*/
function parseSum( $sum ) {
if ( !isset($sum) ) return -1;
$sum = trim( $sum );

// проверка на целое число
if ( preg_match( '/^[\d]+$/', $sum ) ) {
return IntVal($sum) * 100;
}

// проверка на сумму с копейками
if ( preg_match( '/^(\d+)[\.,](\d+)$/', $sum, $matches ) ) {
if ( !isset( $matches[2] ) ) return -1;
return IntVal($matches[1]) * 100 + IntVal($matches[2]);
}

// нет ДОПУСТИМЫХ разделителей
return -1;
}

/*
Перевод строки, содержащей дату в формате dd.mm.YY[YY],
в хеш отдельных полей даты, либо false в случае ошибки.
*/
function parseDate( $date ) {
if ( !isset($date) ) return false;
$date = trim( $date );

if ( preg_match( '/^(\d{1,2})\.(\d{1,2})\.(\d{2}(\d{2})?)$/', $date, $matches ) ) {
return array( 'd' => $matches[1], 'm' => $matches[2], 'y' => $matches[3] );
}

return false;
}
} // class CPaiment

class CMobW {
/*
Получение номера телефона, указанного участником
как номер в системе Мобильного Кошелька.
*/
function getPhoneFromUserId( $userId ) {
// platform-specified
return '9101234567';
}

/*
Получение параметров сайта в системе Мобильный Кошелек.
*/
function getParams() {
// platform-specified
return array( 'id' => '',
'pass' => '',
'commit' => '' );
}

/*
Преобразование строки в формат, допустимый для XML-запроса
*/
function safe( $str ) {
return str_replace( "\r", '', str_replace( "\n", '<br>', addslashes( $s ) ));
// htmlspecialchars // ???
}

/*
Выставление счета участнику с $userId на сумму $sum (float-value)
с комментарием перевода $comment по системе Мобильный Кошелек.
Вернет -1 в случае ошибки парсинга ответа, 0 при корректном выставлении счета,
либо код ошибки ( $this->error2string() для получения текстового описания ошибки )
*/
function invoicing( $userId, $sum, $comment ) {
if ( !is_numeric($userId) || !is_numeric($sum) ) return false;
if ( !$user ) return false;
$sum = (float)$sum;
$comment = $this->safe( $comment );

$phone = trim( $this->getPhoneFromUserId( $userId ) );
if ( strlen($phone) < 10 ) return false;

list( $mobw_id, $mobw_pass, $mobw_commit ) = $this->getParams();

$data_string = '<?xml version="1.0" encoding="utf-8"?>
<request>
<protocol-version>4.00</protocol-version>
<request-type>30</request-type>
<extra name="password">'.iconv('Windows-1251', 'UTF-8', $mobw_pass).'</extra>
<terminal-id>'.$mobw_id.'</terminal-id>
<extra name="serial">'.$mobw_commit.'</extra>
<extra name="comment">'.iconv('Windows-1251', 'UTF-8', $comment).'</extra>
<extra name="to-account">'.$phone.'</extra>
<extra name="amount">'.$sum.'</extra>
<extra name="trm-id">'.md5(time()).'</extra>
<extra name="ALARM_SMS">0</extra>
<extra name="ACCEPT_CALL">0</extra>
<extra name="ltime">60</extra>
</request>';
// Взял из руководства >>>
$URL_Info = parse_url("https://www.mobw.ru/term2/xmlutf.jsp");
if ( !isset($URL_Info["port"]) ) $URL_Info["port"] = 80;
$request .= "POST ".$URL_Info["path"]." HTTP/1.1\n";
$request .= "Host: ".$URL_Info["host"]."\n";
$request .= "Content-type: application/x-www-form-urlencoded\n";
$request .= "Content-length: ".strlen($data_string)."\n";
$request .= "Connection: close\n";
$request .= "\n";
$request .= $data_string."\n";
$fp = fsockopen( $URL_Info["host"], $URL_Info["port"] );
fputs( $fp, $request );
while ( !feof($fp) ) {
$result .= fgets($fp, 1024);
}
fclose($fp);
// Взял из руководства <<<

// парсинг ответа для выделения кода ответа
$result = explode( "\r\n\r\n", $result );
$result = explode( '>', $result[1] );
$result = explode( '<', $result[2] );
if ( ( strlen($result) > 0 ) && isset($result[0]) && is_numeric( $result[0] ) ) {
return intval($result[0]);
}
else {
return -1;
}
}

/*
Получение строкового описания ошибки выполнения выставления счета по ее коду,
т.е. результат выполнения $this->invoicing().
*/
function error2string( $code ) {
require_once( /*$_SERVER["DOCUMENT_ROOT"].*/'mobw_error_codes.php' );
if ( array_key_exists( $code, $MOBW_CODES ) )
return $MOBW_CODES[$code];
else
return 'Неизвестная ошибка #'.$code;
}
} // class CMobW

class CElecsNet {

/*
Получение кошелька продавца из БД.
12 знаков ( WMM )
*/
function getPurchase() {
// platform-specified
}

/*
Проверка проведенности платежа по системе ElecsNet.
Вернет (=== true) при проведенном платеже,
( == false) при ошибке в ответе сервера,
( < 0) при ошибке в параметрах или БД.
*/
function checkPay( $term_id, $check_n, $amount, $date ) {
$amount = CPaiment::parseSum( $amount );
if ( $amount <= 0 ) return -1;
$date = CPaiment::parseDate( $date );
if ( !$date ) return -2;

// формирую хеш 4х полученных полей в формате ElecsNet Gateway + дату в PHP-формате
$params = array( 'term_id' => $term_id, 'check_n' => $check_n, 'amount' => $amount,
'tdate' => implode( '', array_reverse( $date )), 'php_date' => implode( '.', $date ) );

// провека правильности данных по ElecsNet Gateway

$WMM_PROJECT_PURSE = $this->getPurchase();
if ( strlen($WMM_PROJECT_PURSE) < 12 ) return -3;
// удаляю из кошелька первый символ ('R')
$WMM_PROJECT_PURSE = substr( $WMM_PROJECT_PURSE, 1 );

// формирую запрос к gateway
$query = 'https://services.elecsnet.ru/checkpayment/service.asmx/check?reqid='.$WMM_PROJECT_PURSE.
'&tdate='.$params['tdate'].'&check_n='.$params['check_n'].'&term_id='.$params['term_id'].
'&amount='.$params['amount'];
$ch = curl_init( $query );
ob_start();
curl_exec( $ch );
$content = ob_get_contents();
ob_end_clean();
curl_close( $ch );

// проверка кода ошибки в полученном ответе
if ( !preg_match( "/<err_code>(.+)<\/err_code>/i", $content, $matches ) ) {
// Сервер ElecsNet Gateway не отвечает
return -4;
}

return ( IntVal($matches[1]) == 0 );
}
} // class CElecsNet

class CWebMoney {

/*
WebMoney Merchant
Обработка POST данных в случае, если это ответ о проведенном платеже.
Метод должен вызываться на странице, указанной в полях LMI_SUCCESS_URL и LMI_FAIL_URL.
*/
function processPaimentResult( $log_path ) {
// есть ли данные о переводе средств?
if ( !isset( $_POST['LMI_PAYMENT_NO'] ) ) return false;
// формирую уникальное имя файла (копия кода из wmm_check.php)
$filename = $_POST['LMI_PAYMENT_NO'] . $_POST['LMI_SYS_INVS_NO'] .
$_POST['LMI_SYS_TRANS_NO'] . $_POST['LMI_SYS_TRANS_DATE'];
$filename = md5( $filename );

$filename = $log_path . $filename;
$handle = fopen($filename, 'r');
$data = fread( $handle, filesize($filename) );
fclose( $handle );
$data = unserialize( $data );

if ( !(
( $data['LMI_PAYMENT_NO'] == $_POST['LMI_PAYMENT_NO'] ) &&
( $data['LMI_SYS_INVS_NO'] == $_POST['LMI_SYS_INVS_NO'] ) &&
( $data['LMI_SYS_TRANS_NO'] == $_POST['LMI_SYS_TRANS_NO'] ) &&
( $data['LMI_SYS_TRANS_DATE'] == $_POST['LMI_SYS_TRANS_DATE'] ) ) ) {

// Ошибка в данных платежа
return -1;
}

// файл похож на правильный. чтобы в этом убедиться следует сравнить хеши.

// секретное слово
$WMM_SECRET_WORD = '';

// формирую хеш
$hash = $data['LMI_PAYEE_PURSE'] . $data['LMI_PAYMENT_AMOUNT'] . $data['LMI_PAYMENT_NO'] . $data['LMI_MODE'] .
$data['LMI_SYS_INVS_NO'] . $data['LMI_SYS_TRANS_NO'] . $data['LMI_SYS_TRANS_DATE'] . $WMM_SECRET_WORD .
$data['LMI_PAYER_PURSE'] . $data['LMI_PAYER_WM'];
$hash = md5( $hash );

if ( strtoupper($hash) != strtoupper($data['LMI_HASH']) ) {
// хеши различаются
// Ошибка в данных платежа
return -2;
}

// платеж подтвержден.

// удаляю log-файл
unlink( $filename );

// возвращаю сумму в копейках
return IntVal( $data['LMI_PAYMENT_AMOUNT'] ) * 100;
}

/*
Получение параметров для выставления счета:
WMID участника, WMID проекта, R-кошелек проекта
*/
function getInvoiceParams( $userId ) {
// platform-specified
return array( 'user_wmid' => '',
'syte_wmid' => '',
'syte_pursh' => '' );
}

/*
Выставление счета участнику $userId на сумму $cost
*/
function invoice( $userId, $cost, $description ) {
$description = 'Близкие.ру: '.$description;

require( 'wmsigner.php' );
require( 'keys/data.php' );

list( $customerwmid, $wmid, $storepurse ) = $this->getInvoiceParams( $userId );

концовка обрезана, не влазит, форум ругаиццо.

Z-Den
На сайте с 30.06.2007
Offline
25
#1

Я имею опыт в этом деле чуть более двух лет, но профессионалом себя не считаю. В суть кода влазить не хочется(многа букав:)). Так, поверхностно посмотрел: очень радует понятность кода, отличные комменты. Увидел обработки ошибок, это тоже хорошо.

IP
На сайте с 16.01.2008
Offline
24
#2

Z-Den, Спасибо.

LEOnidUKG
На сайте с 25.11.2006
Offline
1774
#3

Нормальный код написанный PHP с использованием ООП + комментарии, вообще отлично.

✅ Мой Телеграм канал по SEO, оптимизации сайтов и серверов: https://t.me/leonidukgLIVE ✅ Качественное и рабочее размещение SEO статей СНГ и Бурж: https://getmanylinks.ru/ ✅ Настройка и оптимизация серверов https://getmanyspeed.ru/
IP
На сайте с 16.01.2008
Offline
24
#4

LEOnidUKG, Спасибо!

dkameleon
На сайте с 09.12.2005
Offline
386
#5

Форматирование вцелом хорошее.

Несоответствие описания и названия функции:

/*
Получение кошелька продавца из БД.
12 знаков ( WMM )
*/
function getPurchase() {

Слово с орфографической ошибкой: CPaiment

В одних местах конкатенация слитная, в других через пробел:

<terminal-id>'.$mobw_id.'</terminal-id>
$filename = $log_path . $filename;

Лично я отказался бы от таких громозких конструкций:

if ( !(
( $data['LMI_PAYMENT_NO'] == $_POST['LMI_PAYMENT_NO'] ) &&
( $data['LMI_SYS_INVS_NO'] == $_POST['LMI_SYS_INVS_NO'] ) &&
( $data['LMI_SYS_TRANS_NO'] == $_POST['LMI_SYS_TRANS_NO'] ) &&
( $data['LMI_SYS_TRANS_DATE'] == $_POST['LMI_SYS_TRANS_DATE'] ) ) ) {

Местами параметры отделяются пробелами от скобок, местами нет:

$handle = fopen($filename, 'r');
fclose( $handle );
$data = unserialize( $data );
if ( strtoupper($hash) != strtoupper($data['LMI_HASH']) ) {

Тут, если не ошибаюсь, при несоответствии кол-ва параметров, будет вылетать варнинг или нотис:

list( $customerwmid, $wmid, $storepurse ) = $this->getInvoiceParams( $userId );

Так же функция "getInvoiceParams" возвращает ассоциативный массив, который совершенно не нужен для list( $customerwmid, $wmid, $storepurse ), так как ключи теряются.

ПС.

require( 'wmsigner.php' );
require( 'keys/data.php' );

Что-то до боли знакомое :))))))

Дизайн интерьера (http://balabukha.com/)
MuXo
На сайте с 14.04.2008
Offline
18
#6

Посмотрел только первую функцию... parseSum( $sum )

if ( !isset($sum) ) return -1; - проверка лишняя, переменная $sum всегда будет существовать, иначе будет parser error...

Дальше в ней же можно написать короче...

$sum = str_replace( ',', '.', trim( $sum ) );
if( !is_numeric( $sum) ) return false;
return intval( $sum*100 );

А так вроде бы код красивый, с коментариями.. :)

Биржа ссылок, статей, контекстных ссылок. Бесплатное определение позиций сайтов в поисковиках. (http://www.setlinks.ru) Представитель системы SetLinks.ru (http://www.setlinks.ru).
Dreammaker
На сайте с 20.04.2006
Offline
569
#7

Есть впечатление, что ООП использовано ради ООП, и классы больше хранилище для функций. Я думаю было бы более логично сделать классы конкретных видов платежей как наследников CPayment.

Не нравится использование require внутри класса, это не учитывая того, что обработки нету, если файла не будет.

Где-то смутно не нравится формирование html-а (xml-a) внутри класса.

Это навскидку :)

Ins1ght
На сайте с 05.10.2007
Offline
22
#8

            // проверка на целое число 

if ( preg_match( '/^[\d]+$/', $sum ) ) {
return IntVal($sum) * 100;
}

на целое можно просто через is_int попробывать проверить

if ( !is_int($sum) ) return IntVal($sum) * 100;

$amount = CPaiment::parseSum( $amount );

но начало parseSum

function parseSum( $sum ) {

разве parseSum объявлен как static ? или я что-то пропустил

эти вещи в самом начале увидел, потом может еще присмотрюсь )

dkameleon
На сайте с 09.12.2005
Offline
386
#9
Dreammaker:
Не нравится использование require внутри класса

Кстати да, при повторном require там походу вылетит эксепшен class wmsigner already exists :)

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий