I was develop a quick form, before deactivated the wordpress plugin. When the user fills out the form and clicks the "Submit" button, a nonce is generated. However, after the plugin is deactivated and the page refreshes, the data is no longer passing correctly through the REST API, and an error appears in the console. therefore, plugin author doesn't receive the quick information why user deactivate the plugin. How to fix this issue,I am showing my following script.The POST rest APi is define Author site.
Enqueue Script
add_action('admin_enqueue_scripts',
function ( $hook ) {
if ( 'plugins.php' !== $hook ) {
return;
}
// 2‑a. JS (register → localise → enqueue)
wp_register_script('otz-deact-js',plugins_url( 'assets/deactivate-confirm.js', __FILE__ ),[ 'jquery' ],'1.0.1',true // footer
);
wp_localize_script(
'otz-deact-js',
'otzConfirm',
[
'i18n' => [
'title' => __( 'Quick feedback (optional)', 'otz' ),
'body' => __( 'Let us know why you are deactivating:', 'otz' ),
/* HTML table with radio buttons – note `name="otz_reason"` */
'table' => '
',
'details' => __( 'More details (optional):', 'otz' ),
'anonymous' => __( 'Send anonymously', 'otz' ),
'cancel' => __( 'Skip & Deactivate', 'otz' ),
'submit' => __( 'Submit & Deactivate', 'otz' ),
],
'api' => [
'url' => 'https://lifestyleblogs.net/wp-json/otz/v1/deactivate',
'nonce' => wp_create_nonce( 'wp_rest' ),
],
'adminEmail' => get_option('admin_email'),
'site' => home_url(),
]
);
wp_enqueue_script( 'otz-deact-js' );
// 2‑b. CSS
wp_enqueue_style('otz-deact-css',plugins_url( 'assets/deactivate-overrides.css', __FILE__ ),[],'1.0.0');
}
);
jQuery submit
jQuery(document).on('submit', '#otz-form', function (e) {
e.preventDefault();
const payload = {
reason : jQuery('input[name="otz_reason"]:checked').val() || 'no_selection',
details : jQuery('#otz-details').val() || '',
anonymous : jQuery('#otz-anon').is(':checked'),
adminemail : otzConfirm.adminEmail,
site : otzConfirm.site
};
console.log(payload);
console.log(otzConfirm.api.nonce);
let redirected = false;
const fallback = setTimeout(() => {
if (!redirected && deactivateUrl) window.location.href = deactivateUrl;
}, 3000);
jQuery.ajax({
url : otzConfirm.api.url,
type : 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader( 'X-WP-Nonce', otzConfirm.api.nonce );
console.log('Set request header X-WP-Nonce:', otzConfirm.api.nonce);
},
contentType : 'application/json',
data : JSON.stringify( payload ),
complete : () => {
redirected = true;
clearTimeout( fallback );
if ( deactivateUrl ) window.location.href = deactivateUrl;
}
});
});
})(jQuery);
Rest API
add_action( 'rest_api_init', 'otz_register_deactivate_route');
function otz_register_deactivate_route() {
global $wpdb;
$table_name = $wpdb->prefix . 'deactivate_rules';
$date= date("Y-m-d h:i:sa");
register_rest_route(
'otz/v1',
'/deactivate',
[
'methods' => WP_REST_Server::CREATABLE, // POST
'callback' => function ( WP_REST_Request $request ) use ( $table_name, $wpdb ) {
$nonce = $request->get_header( 'x-wp-nonce' );
// 2. Verify the nonce (action = 'wp_rest').
if ( ! $nonce || ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
return new WP_Error(
'rest_invalid_nonce',
__( 'Security check failed.', 'otz' ),
[ 'status' => 403 ]
);
}
$p = (object) $request->get_json_params();
$required = [ 'reason', 'details', 'site', 'adminemail'];
foreach ( $required as $field ) {
if ( empty( $p->$field ) ) {
return new WP_REST_Response(
[ 'message' => "Missing field: {$field}" ],
400
);
}
}
$wpdb->insert(
$table_name,
[
'reason' => sanitize_text_field( $p->reason ),
'details' => wp_kses_post( $p->details ),
'anonymous' => sanitize_text_field( $p->anonymous ),
'site' => esc_url_raw( $p->site ),
'adminemail' => sanitize_email( $p->adminemail ),
'cu_datetime' => date_i18n( 'Y-m-d h:i:s a', current_time( 'timestamp' ) ),
],
[ '%s', '%s', '%s', '%s', '%s', '%s' ]
);
if ( ! $wpdb->insert_id ) {
return new WP_REST_Response(
[ 'message' => 'DB insert failed' ],
500
);
}
return [
'success' => true,
'id' => $wpdb->insert_id,
];
},
'permission_callback' => '__return_true',
]
);
}