I've redacted some info that's not relevant.
I have a WordPress site and I've made a plugin meant for updating a database I've created. To put it simply I have a tool and I want to limit the amount of times a user can use that tool. So to do this I created a database with a user id and usage count column. I have another script which checks this database and if the usage column is a certain amount it won't let the user use the tool and that works fine.
The issue I am facing is when I open the link to the plugin in the browser that's https://REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php it gets the user id and updates the database successfully with no problem but when I try and make it request the php script from a simple javascript/html script I created for a test it says success but doesn't update the database.
Here is my PHP plugin with some stuff redacted:
<?php
/*
Plugin Name: Track User Usage
Plugin URL: REDACTED
Description:
Version: 1.0
Author: REDACTED
*/
define('DB_SERVER2', 'REDACTED');
define('DB_USERNAME2', 'REDACTED');
define('DB_PASSWORD2', 'REDACTED');
define('DB_NAME2', 'REDACTED');
// Establish a persistent database connection
$conn = new mysqli(DB_SERVER2, DB_USERNAME2, DB_PASSWORD2, DB_NAME2);
$conn->autocommit(TRUE);
$conn->real_query("SET NAMES 'utf8'");
// Checking connection
if ($conn->connect_error) {
die('Database connection failed: ' . $conn->connect_error);
}
function process_request() {
global $conn;
if ( ! defined( 'ABSPATH' ) ) {
define( 'ABSPATH', '/home/REDACTED/REDACTED.com/' );
}
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
return;
}
include_once ABSPATH . '/wp-load.php';
$userid = get_current_user_id();
if ($userid == 0) {
return;
}
$user_id = $userid;
$created_at = date('Y-m-d H:i:s');
// Check if the user already exists in the table
$sql_check_user = "SELECT * FROM tool_usage WHERE user_id = ?";
$stmt_check_user = $conn->prepare($sql_check_user);
$stmt_check_user->bind_param("i", $user_id);
$stmt_check_user->execute();
$result = $stmt_check_user->get_result();
if ($result->num_rows > 0) {
// User exists, update the usage count
$sql_update_usage = "UPDATE tool_usage SET usage_count = usage_count + 1 WHERE user_id = ?";
$stmt_update_usage = $conn->prepare($sql_update_usage);
$stmt_update_usage->bind_param("i", $user_id);
if ($stmt_update_usage->execute()) {
} else {
}
} else {
// User doesn't exist, insert a new record
$usage_count = 1; // Initial usage count
$sql_insert = "INSERT INTO tool_usage (user_id, usage_count, created_at) VALUES (?, ?, ?)";
$stmt_insert = $conn->prepare($sql_insert);
$stmt_insert->bind_param("iis", $user_id, $usage_count, $created_at);
if ($stmt_insert->execute()) {
} else {
}
}
$stmt_check_user->close();
}
process_request();
$conn->close();
?>
If you are wondering why there are some else statements with nothing there it's because there was echo statements but those were causing some issues for some reason so I just deleted them because I don't really need them, but they were saying success.
And here is my simple test HTML/Javascript code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Track User Usage</title>
<script>
function trackUserUsage() {
fetch('https://www.REDACTED.com/wp-content/plugins/track_user_usage/track_user_usage.php')
.then(data => {
if (data.success) {
console.log('PHP script called successfully:', data);
} else {
console.error('PHP script error:', data);
}
})
.catch(error => {
console.error('Error calling PHP script:', error);
});
}
</script>
</head>
<body>
<button onclick="trackUserUsage()">Track User Usage</button>
</body>
</html>
I've tried a bunch of different ways for the Javascript and PHP for the past few hours with no success.
Thanks for the help everyone I used the rest api endpoint and nonce and some cookie thing and all is working well.
I used this in the PHP script + some other changes to the main function
function set_nonce_cookies($request) {
$cookie_name = 'rest_nonce';
$cookie_value = wp_create_nonce('wp_rest');
$cookie_exp = 0;
$cookie_path = "/";
$cookie_domain = "";
$cookie_secure = true;
$cookie_http_only = false;
setcookie($cookie_name, $cookie_value, $cookie_exp, $cookie_path, $cookie_domain, $cookie_secure, $cookie_http_only);
}
add_action('rest_api_init', 'set_nonce_cookies');
function register_track_user_usage_endpoint() {
register_rest_route('wp/v2', '/track-usage', array(
'methods' => 'GET',
'callback' => 'track_user_usage',
));
}
add_action('rest_api_init', 'register_track_user_usage_endpoint');
function track_user_usage($request) {
$nonce = $request->get_header('X-WP-Nonce');
if (!wp_verify_nonce($nonce, 'wp_rest')) {
return new WP_Error('rest_forbidden', 'Invalid nonce.', array('status' => 403));
}
if (!is_user_logged_in()) {
return new WP_Error('rest_forbidden', 'User is not logged in.', array('status' => 403));
}
$userid = get_current_user_id();
if ($userid == 0) {
return new WP_Error('unauthorized', 'User is not logged in', array('status' => 401));
}
$response_data = array(
'nonce' => $nonce
);
// Rest of code
And I used this for the Javascript:
function trackUserUsage() {
const url = 'https://www.REDACTED.com/wp-json/wp/v2/track-usage';
const nonce = Cookies.get('rest_nonce');
fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': nonce
},
credentials: 'include'
})
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(error => console.error('Error:', error));
}