- Вопрос или проблема
- Ответ или решение
- Использование AJAX для получения user_id
- Шаг 1: Настройка AJAX-запроса в WordPress
- Шаг 2: Подключение скрипта и передача данных в клиенте
- Шаг 3: JavaScript для обработки AJAX-ответа
- Шаг 4: Обработка данных на стороне Node.js
- Шаг 5: Обновление данных пользователя
- Заключение
Вопрос или проблема
Есть сайт на 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 лишь получает данные для начала взаимодействия, основываясь на аутентификации пользователя. Это гарантирует, что каждый пользователь видит только свои данные и может взаимодействовать с платформой безопасным образом.