Как получить current_user_id из WordPress в Node.js?

Вопрос или проблема

Есть сайт на WordPress, в папке плагинов у меня есть проект на Node.js. В index.html (клиентская часть, в основном js) есть контент, который я должен показывать только зарегистрированным пользователям. Мне нужно получить данные о пользователе, зарегистрированном в WordPress, и передать их в Node.js.

Используя Ajax, я передаю ID пользователя из PHP в файл js. Вот часть моего кода: WP / function.php

add_action('wp_ajax_cur_user_id', 'get_cur_user_id'); 
function get_cur_user_id(){
    check_ajax_referer( 'wt_nonce', 'wt_nonce_code' );

    $wt_name = esc_attr($_POST['wt_name']);
    $wt_user_id = esc_attr($_POST['wt_user_id']);

    wp_die();
}

add_action( 'wp_enqueue_scripts', 'wt_ajax_data' );
function wt_ajax_data() {

    wp_enqueue_script('ajax_get_cur_user_id', plugins_url('/js/ajax_get_cur_user_id.js'), array( 'jquery' ));

    wp_localize_script( 'ajax_get_cur_user_id', 'wt_data_user', array(
        'ajaxurl' => admin_url('admin-ajax.php'),
        'wt_nonce' => wp_create_nonce('wt_nonce'),
        'wt_name' => wp_get_current_user()->display_name,
        'wt_user_id' => wp_get_current_user()->id
    ));
}

В JS файле я получаю данные и отправляю их в Node.js, который, как я понимаю, вообще не знает о существовании WordPress. Код: JS / ajax_get_cur_user_id.js

(function($) {
    $.getScript( "/socket.io/socket.io.js", function( data, textStatus, jqxhr ) {

        var socket = io("https://wordpress.stackexchange.com/", {path : '/trade/socket.io'});
        var data = {
            action: 'cur_user_id',
            wt_nonce_code: wt_data_user.wt_nonce,
            wt_name: wt_data_user.wt_name,
            wt_user_id: wt_data_user.wt_user_id
        };

        $.post( wt_data_user.ajaxurl, data, function(response) {
            socket.emit('validate', wt_data_user);
        });
    });
})(jQuery);

Таким образом, я получаю ID зарегистрированного пользователя на странице “index.html” – (node.js). Это то, что я хотел, но когда я все сделал, я увидел следующую проблему. index.html – это страница, ссылка на которую находится в личном кабинете каждого зарегистрированного пользователя. В данный момент index.html выглядит как общая группа чата. То есть, если пользователь зашел в личный кабинет, его ID отображается в index.html, последний человек, который загрузил / обновил страницу WordPress, и этот ID показывается всем на странице index.html. Для моих целей этого быть не должно. Мне нужно, чтобы на странице index.html отображались только данные активного пользователя, то есть user_id = 1 видит только ID – 1, для user_id = 2 отображается ID – 2 независимо от того, кто последний вошел или обновил страницу.

ОБНОВЛЕНИЕ
Я уточню свою задачу. Я создаю торговую платформу. В WordPress зарегистрированы пользователи, у которых есть свои личные кабинеты, баланс и история транзакций.

Используя Node.js и WebSocket, я реализую торговую платформу. В index.html (node.js) есть таблица с валютными парами и две кнопки: Купить и Продать. Когда пользователь нажимает кнопку, мне нужно зафиксировать сумму на момент нажатия. Для этого мне нужно получить user_id, чтобы установить связь с его личным кабинетом и иметь возможность пополнить его баланс или вывести средства с его счета в зависимости от результата торговли.

Теоретически: используя wp_ajax_, я могу передать current_user_id в файл JS, и оттуда я могу отправить данные на сервер Node.js с помощью AJAX POST. На сервере мне все еще нужно как-то получить текущего пользователя, обратиться к базе данных и изменить его личный кабинет. Но я не знаю, как это можно сделать и с какими модулями.

Вот серверная часть:
node / app.js

const redis = require('redis');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http, {path: '/trade/socket.io'});

const settings = {
    REDIS: {
        HOST: 'localhost'
    }
}

var mysql      = require('mysql');
var connection = mysql.createConnection({
  host     : 'localhost',
  user     : 'my_user',
  password : 'my_password',
  database : 'my_database'
});

let redisClient = new redis.createClient(settings.REDIS);

var trade = function(req, res, next) {

   function getQuote(symbol, callback) {
        redisClient.get(symbol, (error, quote) => {
            if (error) {
                throw new Error(error);
            }
            quote = JSON.parse(quote);
            callback(quote);
        });
    }
    io.on('connection', function(socket){

        var quotes = ['EURUSD','GBPUSD','USDJPY','USDCAD','EURGBP','USDCHF',
                      'AUDUSD','NZDUSD','GBPJPY','USDMXN','USDRUB','USDZAR','BTCUSD'];
        quotes.forEach(function(item, i, quotes) {
            setInterval(() => {
                getQuote(item, (q) => {io.emit('get_quote_'+item, q);});
            }, 3500);
        });
    });
    res.sendFile(__dirname + '/index.html');
}
app.get('/trade/:uid', trade);

http.listen(3000, function(){});

Сначала я работаю с js node. Если бы я знал раньше, что это будет так сложно для меня, я бы отказался от этой идеи, но я работаю более двух месяцев и не хочу сдаваться 🙂 Я чувствую, что не смогу справиться без помощи.

Прежде всего, вам не следует изменять значения в базе данных, позволяя пользователям отправлять вызовы AJAX на ваш сервер с указанием ID пользователя, который следует использовать, так как это позволит любому отправить вызов AJAX с nonce для изменения данных любого пользователя.

Если вы хотите сделать вызов AJAX, чтобы получить ID пользователя, это должно выглядеть так:

add_action( 'wp_ajax_cur_user_id', 'get_cur_user_id' );
function get_cur_user_id() {

    check_ajax_referer( 'wt_nonce', 'wt_nonce_code' );
    $user_id = get_current_user_id();

    if( empty( $user_id ) ){
        wp_send_json_error( array( 'not_logged_in' => 'Пользователь не вошел в систему' ) );
    } else {
        wp_send_json_success( $user_id );
    }

    die();
}

Но вы не должны использовать это для передачи на ваш сервер для изменения данных, вы должны отправить измененные данные в WordPress через AJAX, а затем использовать get_current_user_id, чтобы получить ID пользователя, не позволяя ему передаваться через AJAX.

ОБНОВЛЕНИЕ:

Вот пример того, как я бы это сделал, делая вызов AJAX из Node.js, не позволяя передавать ID пользователя, но проверяя его внутри WordPress.

Это предполагает, что вы отправите POST в AJAX с суммой для покупки в buy или суммой для продажи в sell.

Это также предполагает, что баланс сохраняется в метаданных пользователя.

add_action( 'wp_ajax_update_cur_user_balance', 'update_cur_user_balance' );
function update_cur_user_balance() {
    global $wpdb;

    check_ajax_referer( 'wt_nonce', 'wt_nonce_code' );
    $user_id = get_current_user_id();

    if ( empty( $user_id ) ) {
        wp_send_json_error( array( 'not_logged_in' => 'Пользователь не вошел в систему' ) );
        return;
    }

    $buy  = array_key_exists( 'buy', $_POST ) ? floatval( $_POST['buy'] ) : false;
    $sell = array_key_exists( 'sell', $_POST ) ? floatval( $_POST['sell'] ) : false;

    $user_balance = get_user_meta( $user_id, 'user_balance', true );
    $user_balance_float = $user_balance ? floatval( $user_balance ) : 0;
    $transacted = false;

    if( $buy ){

        if( $buy > $user_balance_float ){
            wp_send_json_error( array( 'not_enough_funds' => 'Недостаточно средств для покупки!' ) );
            return;
        }

        // Вычитаем сумму покупки из баланса
        $user_balance_float = $user_balance_float - $buy;
        $transacted = true;
    } elseif( $sell ){

        // Добавляем к балансу пользователя
        $user_balance_float = $user_balance_float + $sell;
        $transacted = true;
    }

    if( $transacted ){
        update_user_meta( $user_id, 'user_balance', $user_balance_float );
        wp_send_json_success( array( 'completed' => 'Транзакция завершена', 'new_balance' => $user_balance_float ) );
        return;
    }

    wp_send_json_error( array( 'no_transact' => 'Транзакция не была завершена!' ) );
    die();
}

Вам, конечно, нужно будет придумать, как убедиться, что пользователи не просто отправляют свои собственные покупки/продажи, используя ваш nonce, но это будет вне сферы данного вопроса.

Или если делать SQL-запрос, что-то вроде этого:

 // Для выполнения пользовательского SQL-запроса в WordPress (просто пример, должен соответствовать таблице, полю, значению и т.д.)
$some_table="your_table";
$something = '123456789';
$query = $wpdb->prepare( "UPDATE `%s` SET something='%s' WHERE `userid` = %d", array( $some_table, $something, $user_id ) );
$wpdb->query( $query );

Ответ или решение

Вопрос о том, как получить идентификатор текущего пользователя (current_user_id) из WordPress в Node.js, требует комплексного подхода, так как эти две технологии функционируют в разных средах. Давайте подробно рассмотрим решение данной задачи.

Использование AJAX для получения user_id

Основной идеей является использование AJAX-запросов для передачи данных о текущем пользователе из WordPress в Node.js. Ниже приведен оптимизированный подход, учитывающий безопасность и правильность обработки пользовательских данных.

Шаг 1: Настройка AJAX-запроса в WordPress

В файле functions.php вашего плагина необходимо прописать функцию, которая будет отвечать на AJAX-запрос и возвращать идентификатор текущего пользователя:

add_action('wp_ajax_cur_user_id', 'get_cur_user_id'); 
function get_cur_user_id() {
    check_ajax_referer('wt_nonce', 'wt_nonce_code');

    $user_id = get_current_user_id();

    if (empty($user_id)) {
        wp_send_json_error(array('not_logged_in' => 'User is not logged in'));
    } else {
        wp_send_json_success($user_id);
    }

    wp_die();
}

Такой подход минимизирует возможность манипуляции идентификатором пользователя, так как сервер самостоятельно определяет текущего пользователя.

Шаг 2: Подключение скрипта и передача данных в клиенте

Вам нужно подключить JavaScript, который будет отправлять AJAX-запрос и ожидать ответ:

add_action('wp_enqueue_scripts', 'wt_ajax_data');
function wt_ajax_data() {
    wp_enqueue_script('ajax_get_cur_user_id', plugins_url('/js/ajax_get_cur_user_id.js'), array('jquery'));

    wp_localize_script('ajax_get_cur_user_id', 'wt_data_user', array(
        'ajaxurl' => admin_url('admin-ajax.php'),
        'wt_nonce' => wp_create_nonce('wt_nonce')
    ));
}

Шаг 3: JavaScript для обработки AJAX-ответа

В файле ajax_get_cur_user_id.js выполняем AJAX-запрос:

(function($) {
    $(document).ready(function() {
        var data = {
            action: 'cur_user_id',
            wt_nonce_code: wt_data_user.wt_nonce
        };

        $.post(wt_data_user.ajaxurl, data, function(response) {
            if (response.success) {
                var userId = response.data;

                // Теперь передаем userId в Node.js
                var socket = io("https://your-domain.com", {path: '/trade/socket.io'});
                socket.emit('validate_user', { user_id: userId });
            } else {
                console.error(response.data.not_logged_in);
            }
        });
    });
})(jQuery);

Шаг 4: Обработка данных на стороне Node.js

В вашем Node.js приложении вам нужно обрабатывать validate_user, чтобы использовать идентификатор пользователя для дальнейших операций, например, для обновления баланса:

io.on('connection', function(socket) {
    socket.on('validate_user', function(data) {
        // Здесь вы можете использовать data.user_id для дальнейших операций
        console.log(data.user_id);
    });
});

Шаг 5: Обновление данных пользователя

Вместо того чтобы отправлять user_id из клиента, делайте операции через AJAX-запросы в WordPress. Например, если пользователь хочет выполнить торговлю:

add_action('wp_ajax_trade_action', 'execute_trade');
function execute_trade() {
    check_ajax_referer('wt_nonce', 'wt_nonce_code');
    $user_id = get_current_user_id();

    // Здесь вы получите данные торговли и выполните необходимые операции
    // Обновляйте базу данных здесь, используя $user_id
    wp_send_json_success('Торговля выполнена');
}

На стороне клиента вы можете отправить запрос для выполнения торговли с соответствующими данными, а WordPress будет проверять аутентификацию.

Заключение

Учитывая все вышесказанное, данный подход минимизирует любые риски безопасности, так как вы не передаете user_id напрямую из клиента. Вместо этого, все операции выполняются от имени пользователя на стороне сервера WordPress, а Node.js лишь получает данные для начала взаимодействия, основываясь на аутентификации пользователя. Это гарантирует, что каждый пользователь видит только свои данные и может взаимодействовать с платформой безопасным образом.

Оцените материал
Добавить комментарий

Капча загружается...