Показать сообщение отдельно
  #2 (permalink)  
Старый 23.04.2024, 22:24
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,787

Расширение mysql (и все функции mysql_* соответственно) было помечено устаревшим еще в php5.5 и с версии php7.0 было удалено.
Версия 5.5 перестала поддерживаться с 21 июля 2016 года.
Вы используете какой-то очень не свежий софт.

Далее по делу.
Обычно платежные системы ожидают от вашего endpoint'а, который принимает хуки, определенных действий, в кач-ве подтверждения успешной обработки запроса, в противном случае "бомбят" уведомлениями еще определенное кол-во раз.
Перво-наперво стоит определиться, что от вашего сервера ожидает платежная система, чтобы она не отправляла одни и те же уведомления по нескольку раз.

Второе, но не менее важное: все транзакции лучше всего в хранить системе.
У вас на таблицу transactions похожа таблица stat_pay, но ей не хватает колонки с номером (id) самой транзакции. Номер транзакции обычно также передается платежной системой в уведомлении. Если по какой-то причине у вас нет номера транзакции, то можно хранить подпись (hash) уведомления, однако в случае проблем подпись уведомления (или возможно самой транзакции) вряд ли поможет найти проблемный платеж.
Благодаря табличке по списком обработанных транзакций, вы сможете проверить уведомление от платежной системы на "уникальность". Если в системе уже есть зарегистрированная транзакция с пришедшим из уведомления номером, то просто отправляем ответ "все хорошо" и не производим дальнейшую обработку уведомления.

Вместе с текстом об ошибке стоит также отправлять и соответствующий status code. Вызов функции die выведет текст на страницу, но status code при этом будет "200 - ok".

Код не проверял даже на наличие синтаксических ошибок:
<?php

include '../setup.php';

$OK_RESPONSE_STATUS_CODE = 200;
$OK_RESPONSE_MESSAGE = 'OK';

$rbConfig['api_key'] = 'e7ebd';
$rbConfig['project_id'] = 1000;// unused value

$con = mysql_fetch_array(
    mysql_query('select * from seting')
);

$hash = md5(
    $_POST['project_id'] .
    $_POST['order_id'] .
    $_POST['payment_id'] .
    $_POST['amount'] .
    $_POST['currency'] .
    $_POST['status'] .
    $rbConfig['api_key']
);


if ($hash !== $_POST['hash']) {
    http_response_code(400);
    
    echo 'Incorrect signature';
    exit;
}

if (empty($_POST['payment_id'])) {
    http_response_code(400);
    
    echo 'Missing [payment_id] field';
    exit;
}

// Предполагается, что транзакции хранятся в табличке `stat_pay` в колонке `payment_id`,
// а номер транзакции передается в поле 'payment_id'
$paymentId = mysql_real_escape_string($_POST['payment_id']);
$paymentDetails = mysql_fetch_assoc(
    mysql_query(
        sprintf(
            "select * from stat_pay where payment_id = '%s'",
            $paymentId
        )
    )
);
if (!empty($paymentDetails)) {
    http_response_code($OK_RESPONSE_STATUS_CODE);
    
    echo $OK_RESPONSE_MESSAGE;
    exit;
}

$orderNumberSegments = explode('-', $_POST['order_id']);
if (count($orderNumberSegments) < 2) {
    http_response_code(400);
    
    echo 'Passed [order_id] is invalid';
    exit;
}

$paymentAmount = $_POST['amount'];
$originalPaymentAmount = $paymentAmount;
$bonus = 0;

$userLogin = mysql_real_escape_string($orderNumberSegments[1]);

// Вместо `mysql_fetch_array` лучше использовать `mysql_fetch_assoc`,
// но я не знаю названия полей таблички.
// Гадать не буду, т.к. дальше по коду используются ну совсем уж "специфические" названия полей
$partner = mysql_fetch_array(
    mysql_query(
        sprintf("select * from partner where user='%s'", $userLogin)
    )
);
if (!$partner) {
    http_response_code(400);
    
    echo 'Partner not found';
    exit;
}

$paymentAmount += $bonus;

$internalPaymentSize = $paymentAmount / 100 * $con['pcash'];

mysql_query(
    sprintf(
        "update partner set cash=cash+'%s' where user='%s'",
        $internalPaymentSize,
        $userLogin
    )
);

mysql_query(
    sprintf(
        "update users set pcash=pcash+'%s' where login='%s'",
        $internalPaymentSize,
        $partner[0]
    )
);

mysql_query(
    sprintf(
        "update users set cash=cash+'%s', cashin=cashin+'%s' where login='%s'",
        $paymentAmount,
        $paymentAmount,
        $userLogin
    )
);
// Тут неплохо было бы знать названия полей, чтобы не пытаться случайно угадать их порядок, но...
// Предполагается, что первым полем в табличке `stat_pay` будет поле `payment_id`
mysql_query(
    sprintf(
        "insert into stat_pay values('%s', '%s','%s','%s','%s','0.00')",
        $paymentId,
        $userLogin,
        // Вместо подобного хранения даты-времени
        // лучше добавить timestamp поле со значением по умолчанию CURRENT_TIMESTAMP
        date('d.m.y'),
        date('H:i:s'),
        $paymentAmount
    )
);

// У нас уже есть конфигурационные данные из этой таблички,
// полученные именно с помощью `mysql_fetch_array`
/*$con = mysql_fetch_array(
    mysql_query('select * from seting')
);*/

// Т.к. $con - number[] | false,
// предполагаю, что `paymail` - константа хранящая индекс колонки,
// которую нужно проверить для отправки уведомления.
// Однако это может быть и названием глобальной функции,
// поэтому проверку defined('paymail') добавлять не стал, хотя хотелось
if (!empty($con[paymail]) && $con[paymail] == 'yes') {
    include '../mail/in.php';
    $to = $con['adm_email'];
    $subject = $reg_reg_mail_subject;
    $msg = $reg_reg_mail;
    $mailheaders = "Content-Type: text/plain; charset=Windows-1251\n";
    $mailheaders .= "From: $con[adm_email]\n";
    mail($to, $subject, $msg, $mailheaders);
}

http_response_code($OK_RESPONSE_STATUS_CODE);

echo $OK_RESPONSE_MESSAGE;
exit;

Последний раз редактировалось Nexus, 23.04.2024 в 22:27.
Ответить с цитированием