WordPress Process $_POST Inside Parse Request - wordpress

I'm writing an application to receive and process an Instant Payment Notification message in wordpress. It is a POST request made to a "virtual" url with rewrite rules. The problem however is that only GET vars are acessible, I cannot access the post variable:
Both:
print_r($wp->query_vars['ccustfirstname']);
print_r($_POST);
Result in an empty array
I've modified existing code to match my case:
function ao_add_rewrite_rule() {
print_r($_REQUEST);
$ipn_parameters=array("ccustfullname","ccustfirstname", ... );
foreach ($ipn_parameters as $key => $value) {
add_rewrite_tag("%$value%",".");
}
add_rewrite_tag("%arevico_api%",".","");
add_rewrite_rule( 'ipn', 'index.php?&arevico_api=ipn', 'top');
add_rewrite_rule( 'hoplink', 'index.php?&arevico_api=hop', 'top');
add_rewrite_rule( 'pay', 'index.php?&arevico_api=pay', 'top');
flush_rewrite_rules();//TODO: call only when needed
}
add_action( 'parse_request', 'wpse9870_parse_request' );
function wpse9870_parse_request( &$wp )
{
if (!empty($wp->query_vars['arevico_api'])) {
switch ($wp->query_vars['arevico_api']){
case "ipn":
print_r($wp->query_vars['ccustfirstname']);
print_r($_POST);
die();
// require_once(AREVICO_PLG_BP . "ipn.php");
// $ArevicoIPN=new ArevicoIPN();
break ;
default:
break;
}
}
return;
}
Please note that the arevico_api get parameter does get trough, but the POST parameters don't. I'm testing the application by sending a sample post data trough Simple Rest Client for chrome. How do I get to access thhe post parameters

Related

Wordpress REST Api: add_action( 'rest_api_init', callback) does not call the callback

Problem:
I'm trying to register a custom endpoint for a Wordpress plugin. The problem I face is that when I call the add_action('rest_api_init', callback), the callback function is not being called. In that callback function lives the "register_rest_route()" method, which in it's turn is not being called and I am unable to register any custom endpoints.
I'm using docker for development
No errors are being thrown
Code:
public function register()
{
$this->setup_init();
}
public function setup_init()
{
var_dump('print1');
add_action('rest_api_init', array($this, 'register_custom_endpoints'));
}
public function register_custom_endpoints()
{
var_dump('print2');
die();
register_rest_route('test', '/test', array(
'methods' => 'GET',
'callback' => 'menu_setup',
));
}
Question:
The code reaches the "var_dump('print1')", but the the "var_dump('print2')" is never reached. Am I missing something here?
After trying many options I found out that changing: "Setting -> permalinks -> common settings" to anything else then the option "Plain" solved the issue. The callback method is now being reached, and my custom endpoints are being registered.

Ninja Forms server-side validation not working

I have spent two days trying to figure this out. I have wordpress page with a four field Ninja Form. One of the fields is an Email. I created an API (in our .NET Core project) that checks and then throws a 400 error if a already with that email address exists in our DB. I am using the Ninja Forms Webhook feature to submit the form to my API. I just want to display my 400 error message to the user.
I am using the documentation below from Ninja Forms but it is not working:
https://developer.ninjaforms.com/codex/custom-server-side-validation/
More specifically, I am getting a 500 with the the following error in the console:
Uncaught Error: Call to undefined function my_nf_validation() in \/home\/site\/wwwroot\/wp-content\/themes\/hello-elementor\/functions.php:245\nStack trace:\n#0 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(287): {closure}(Array)\n#1 \/home\/site\/wwwroot\/wp-includes\/plugin.php(206): WP_Hook->apply_filters(Array, Array)\n#2 \/home\/site\/wwwroot\/wp-content\/plugins\/ninja-forms\/includes\/AJAX\/Controllers\/Submission.php(132): apply_filters('ninja_forms_sub...', Array)\n#3 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(287): NF_AJAX_Controllers_Submission->submit('')\n#4 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(311): WP_Hook->apply_filters('', Array)\n#5 \/home\/site\/wwwroot\/wp-includes\/plugin.php(478): WP_Hook->do_action(Array)\n#6 \/home\/site\/wwwroot\/wp-admin\/admin-ajax.php(175): do_action('wp_ajax_nf_ajax...')\n#7 {main}\n thrown<\/pre>"},"last":{"type":1,"message":"Uncaught Error: Call to undefined function my_nf_validation() in \/home\/site\/wwwroot\/wp-content\/themes\/hello-elementor\/functions.php:245\nStack trace:\n#0 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(287): {closure}(Array)\n#1 \/home\/site\/wwwroot\/wp-includes\/plugin.php(206): WP_Hook->apply_filters(Array, Array)\n#2 \/home\/site\/wwwroot\/wp-content\/plugins\/ninja-forms\/includes\/AJAX\/Controllers\/Submission.php(132): apply_filters('ninja_forms_sub...', Array)\n#3 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(287): NF_AJAX_Controllers_Submission->submit('')\n#4 \/home\/site\/wwwroot\/wp-includes\/class-wp-hook.php(311): WP_Hook->apply_filters('', Array)\n#5 \/home\/site\/wwwroot\/wp-includes\/plugin.php(478): WP_Hook->do_action(Array)\n#6 \/home\/site\/wwwroot\/wp-admin\/admin-ajax.php(175): do_action('wp_ajax_nf_ajax...')\n#7 {main}\n thrown","file":"\/home\/site\/wwwroot\/wp-content\/themes\/hello-elementor\/functions.php","line":245}},"debug":[]}
I placed the code in the function.php file in Themes Editor. This is my first time working with wordpress so I hope I am doing this right. This is my code and is taken directly from the above documentation:
add_filter( 'ninja_forms_submit_data', function( $form_data ){
if( ! my_nf_validation( $form_data ) ) { // Add check here.
$errors = [
__( 'An unexpected error occurred.', 'my-plugin' )
];
$response = [
'errors' => $errors,
];
echo wp_json_encode( $response );
wp_die(); // this is required to terminate immediately and return a proper response
}
// If no errors, be sure to return the $form_data.
return $form_data;
});
I would really appreciate anyone's help with this.
Try the following Code, It will work.
function validateCode($field){
if( checkCondition ){
// let it go
return true;
}
else{
return false;
}
}
add_filter( 'ninja_forms_submit_data', 'my_ninja_forms_submit_data' );
function my_ninja_forms_submit_data( $form_data ) {
$form_settings = $form_data[ 'settings' ]; // Form settings.
if($form_data['id'] == '2'){
foreach( $form_data[ 'fields' ] as $field ) { // Field settigns, including the field key and value.
if( 'unique_code' == $field[ 'key' ] ){
if(!validateCode($field)){
$form_data['errors']['fields'][$field['id']] = "INVALID CODE";
}
}
}
}
return $form_data;
}
The documentation references a custom WordPress filter, as defined by the Ninja Forms plugin. Filters are a feature of WordPress Hooks, which allow a theme or plugin to modify the functionality of another theme or plugin. See https://developer.wordpress.org/plugins/hooks/filters/
To your question, the Webhooks add-on plugin (an official extension of Ninja Forms) is not required to use the filter that you reference from the documentation.
Instead, you'll need to replace "my_nf_validation()" with your own defined function, as the documentation shows an example.
Your function needs to handle the API request and response handling. In the documentation example, the custom function returns a Boolean value.

Woocommerce WC API callback for custom payment gateway don't work for me

I'm actually writing a custom plugin to connect a payment gateway to Woocommerce, and I've been stuck on a problem for several hours:
I cannot get the callback of the payment processing.
I googled a lot to find an issue but no success yet.
The environment is as follows:
Site on a dedicated server - Ubuntu 12.04 ;
PHP 7.1 ;
WordPress 5.3.2 ;
Woocommerce 3.8.1 ;
A lot of plugins are loaded too ;
My class look like this:
add_filter('woocommerce_payment_gateways', 'woogatewaypro_add_gateway_class');
function woogatewaypro_add_gateway_class($gateways){
$gateways[] = 'WC_Gateway_Pro';
return $gateways;
}
add_action('plugins_loaded', 'woogatewaypro_init_gateway_class');
function woogatewaypro_init_gateway_class(){
class WC_Gateway_Pro extends WC_Payment_Gateway{
public function __construct(){
global $wpdb;
global $woocommerce;
$this->id = 'woogatewaypro';
$this->icon = '';
$this->has_fields = true;
$this->method_title = 'Gateway Pro payment gateway';
$this->method_description = __('Allow payment from Gateway Pro gateway.','woogatewaypro');
$this->supports = array(
'products',
'subscriptions',
'subscription_cancellation',
'subscription_suspension',
'subscription_reactivation',
'subscription_amount_changes',
'subscription_date_changes',
'subscription_payment_method_change',
'subscription_payment_method_change_customer',
'subscription_payment_method_change_admin',
'multiple_subscriptions'
);
$this->init_form_fields();
$this->init_settings();
$this->title = $this->get_option('title');
$this->description = $this->get_option('description');
$this->enabled = $this->get_option('enabled');
$this->testmode = 'yes' === $this->get_option('testmode');
$this->private_key = $this->testmode ? $this->get_option('test_private_key') : $this->get_option('private_key');
$this->publishable_key = $this->testmode ? $this->get_option('test_publishable_key') : $this->get_option('publishable_key');
/* some code... */
add_action('woocommerce_api_'.strtolower(get_class($this)), 'woogatewaypro_payment_callback');
add_action('woocommerce_api_woogatewaypro_cancel_payment', array($this, 'woogatewaypro_cancel_payment'));
add_action('woocommerce_api_woogatewaypro_payment_ko', array($this, 'woogatewaypro_payment_ko'));
add_action('woocommerce_api_woogatewaypro_payment_ok', array($this, 'woogatewaypro_payment_ok'));
add_action('woocommerce_update_options_payment_gateways_'.$this->id, array($this, 'process_admin_options'));
add_action('wp_enqueue_scripts', array($this, 'payment_scripts'));
/* some code... */
}
public function init_form_fields(){
/* some code... */
}
public function payment_scripts(){
/* some code... */
}
public function process_payment($order_id){
/* some code... */
}
public function woogatewaypro_cancel_payment(){
wp_redirect(get_permalink(get_option('woocommerce_checkout_page_id')).'?woogatewaypro=cancelled-payment');
}
public function woogatewaypro_payment_ko(){
wp_redirect(get_permalink(get_option('woocommerce_checkout_page_id')).'?woogatewaypro=payment-ko');
}
public function woogatewaypro_payment_ok(){
/* some code... */
wp_redirect(get_permalink(get_option('woocommerce_checkout_page_id')).'?woogatewaypro=payment-ok');
}
}
}
function add_wc_gateway_pro_gateway($methods){
$methods[] = 'WC_Gateway_Pro';
return $methods;
}
add_filter('woocommerce_payment_gateways', 'add_wc_gateway_pro_gateway');
function woogatewaypro_payment_callback(){
mail('user#mydomain.tld','Check callback','Enter func');
// wp_die();
exit;
}
What I'm doing wrong?
I tried to place my woogatewaypro_payment_callback function in my class, but it doesn't work.
My URL to callback is like this:
if('' == get_option('permalink_structure')){
$callback = site_url().'/?wc-api=WC_Gateway_Pro';
}else{
$callback = site_url().'/wc-api/WC_Gateway_Pro/';
}
I look the logs on my server, and the data seem to be posted: I get 200 status with POST.
When I try to access the function by GET, I still have a 1 on a blank page.
Could some plugin(s) create the problem?
Thanks in advance for your help ;).
I had the same issue and this is what works for WooCommerce 2.0+
//register the callback hooks which we will use to receive the payment response from the gateway
add_action( 'woocommerce_api_custom_gateway', array( $this, 'payment_callback'));
The callback link can be accessed as http://yoursite.com/wc-api/custom_gateway/
I'm still on my problem (I'm going crazy...).
I use WP Cerber Security to protect my site, and no problem with it: WP Cerber Security allows posting to wc-api/WC_Gateway_Pro/, and the request is in 200 status.
The fact is that the callback function isn't executed: I don't receive any mail. I tried to save a string in the debug.log file of WordPress (debug set to true), and no log was saved.
I have read and reread all the topics to build a custom payment gateway for Woocommerce, and I don't understand what's the problem with my code: everything seems to be good in the code construction, but no possibility to execute the callback.
The WC_API execute correctly the cancel, ko and ok functions of my class, but not the callback function (why?).
Must I activate any setting on Woocommerce?
If someone has had the same problem or has an idea to solve this problem, I will be very grateful :)
Thanks a lot for your replies ;)
After reading again my cde, I detected I have missed something to correctly declare my add_action() on callback function. SO it look like this now:
add_action('woocommerce_api_'.strtolower(get_class($this)), array($this,'woogatewaypro_payment_callback'));
But it not works yet.
I'll try to install a new WordPress to test on a fresh environment, because I really don't understand why it doesn't work.
I hope a "Woo'pro" will pass here to help me a little :).

Get current user inside register_rest_route method

How to retrive wp_get_current_user() inside a register_rest_route callback (Wordpress site)?
I'm just trying to do a simple hello wp_get_current_user()->user_login on a php test page:
add_action('rest_api_init', 'helloTest');
function helloTest() {
register_rest_route('hello', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
));
}
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
But wp_get_current_user() is null and wp_get_current_user->ID is 0;
I dont want to authenticate the user again. I just want to retrieve his username. If he is not logged in, just show empty an empty string.
If I have to authenticate again, how to add a "nonce" to it? On internet I just have examples using javascript, but not directly on PHP methods.
Issues in your code
First off, you should understand properly how to add custom WP REST API endpoints:
An endpoint's namespace (the first parameter passed to register_rest_route()) should be in this format: your-plugin/v<version>. E.g. hello/v1 or hello-world/v1 and not just hello or hello-world.
$someVariable (the first parameter passed to your endpoint callback function) is not just any variable — it's an instance of the WP_REST_Request class — and shouldn't be echo-ed like what you did here:
function showHello($someVariable) {
echo "Hello " . wp_get_current_user()->user_login . $someVariable;
}
And normally, the $someVariable is better be changed to $request (i.e. rename it to "request").
And you should return a valid WP REST API response. For example, to return just the username:
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
And know your own API endpoint URL..
(based on your original namespace)
/wp-json/hello/hello/1 <- correct
/wp-json/hello/?John <- incorrect
because in your code, the parameter is a number and not string: (?P<id>\d+)
I hope those help you, and once again, do read the handbook for a more detailed guide.
The Corrected Code
add_action( 'rest_api_init', 'helloTest' );
function helloTest() {
register_rest_route( 'hello/v1', 'hello/(?P<id>\d+)', array(
'methods' => WP_REST_SERVER::READABLE,
'callback' => 'showHello'
) );
}
function showHello( $request ) {
return new WP_REST_Response( wp_get_current_user()->user_login, 200 );
}
Now about getting the user (from the API endpoint — showHello())
If I have to authenticate again, how to add a "nonce" to it?
Just because the user is logged-in/authenticated to the (WordPress) site, it doesn't mean the user is automatically logged-in to the WP REST API. So yes, you'd need to either provide a nonce along with your API request, or use one of the authentication plugins mentioned right here.
Now in most cases, GET (i.e. read-only) requests to the API do not need any authentication, but if you'd like to retrieve the data of the currently logged-in user on your site, then one way is via the _wpnonce data parameter (either POST data or in the query for GET requests).
Example for a GET request:
http://example.com/wp-json/wp/v2/posts?_wpnonce=<nonce>
So based on your comment and the corrected code (above):
Theres no "code" that make the request. Its is just an anchor that
calls my route: Hello
You can add the nonce as part of the URL query string like so: (the namespace is hello/v1 and the <id> is 1)
// Make request to /wp-json/hello/v1/hello/<id>
$nonce = wp_create_nonce( 'wp_rest' );
echo 'Hello';
So try that out along with the corrected code and let me know how it goes. :)
And once again, be sure to read the REST API authentication handbook.

WP REST API how to check header basic authentication

A custom endpoint like this
add_action( 'rest_api_init', function () {
register_rest_route( 'myplugin/v1', '/author/(?P<id>\d+)', array(
'methods' => 'GET',
'callback' => 'my_awesome_func',
) );
} );
Using basic authentication in headers, let's say 'Authorization: Basic some64basePass'
How I can check the value of Authorization in the header is valid or not?
Here is my solution.
Inside the callback function I validate Authorization from the header like this:
function my_awesome_func($data) {
//Get HTTP request headers
$auth = apache_request_headers();
//Get only Authorization header
$valid = $auth['Authorization'];
// Validate
if ($valid == 'Basic Base64UsernamePassword') {
//Do what the function should do
} else {
$response = 'Please use a valid authentication';
}
return json_encode($response);
}
Maybe there is a better way.
WordPress has a hook for adding your own authentication handler.
add_filter( 'rest_authentication_errors', 'rest_basic_auth_check_errors', 99 );
Your rest_basic_auth_check_errors() should return true if basic authentication succeeds or WP_Error if it fails. Since the default REST authentication handler runs at priority 100 your rest_basic_auth_check_errors() will override the default handler.
See the function WP_REST_Server::check_authentication() in file ...\wp-includes\rest-api\class-wp-rest-server.php to understand how WordPress handles REST authentication and how to add your own authentication handler.
Also, you should read about $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] in http://php.net/manual/en/features.http-auth.php

Resources