I’m working with a custom XML-RPC method to capture some information for a plugin I am building. When activated the user has to authenticate themselves by entering there user/password given to them when purchasing the plugin on my WP site.
The plugin uses this code:
if ( isset( $_POST['username'] ) && isset( $_POST['password'] ) ) {
/* check against remote server */
require_once( ABSPATH . WPINC . '/class-IXR.php' );
$this->client = new IXR_Client( trailingslashit( CUSTOMLOGIN_UPDATE_API ) . 'xmlrpc.php' ); //*/
$url = ( ( is_multisite() ) ? network_site_url() : site_url() );
$client_request_args = array(
'username' => $_POST['username'],
'password' => $_POST['password'],
'plugin' => CUSTOMLOGINPRO_BASENAME,
'url' => $url
);
if ( !$this->client->query( 'thefrosty.is_user_authorized', $client_request_args ) ) {
add_action( 'admin_notices', array( $this, 'error_notice' ) );
return false;
}
$this->settings = get_option( CUSTOMLOGINPRO . '_settings', array() );
$this->settings['api-key'] = $this->client->getResponse();
update_option( CUSTOMLOGINPRO . '_settings', $this->settings );
header( 'Location: ' . admin_url( 'options-general.php?page=' . CUSTOMLOGINPRO ) );
die();
}
The form submits and looks like its kinda working, getting a 200 error when working locally, but tested with another plugin that send same error code, but is sending responses from host (no worries yet).
What I am stuck on is the back end code. I’ve created a class in a core plugin on my WP install. I am assuming this is where it needs to be. I am missing some fault code and error message responses, not sure how to do those. Just looking for a little push in the right direction..
As you can see I am also testing the user against a WooCommerce order (code from WC, should be good) but then trying to update the order meta meta might need to fixes to save the users URLs.
class frosty_core {
function __construct() {
add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
}
/**
* Create our custom XML-rpc method.
* @ref http://kovshenin.com/2010/04/custom-xml-rpc-methods-in-wordpress-2151/
*/
function xmlrpc_methods( $methods ) {
$methods['thefrosty.is_user_authorized'] = array( $this, 'thefrosty_plugin_callback' );
return $methods;
}
/**
* XML-prc mothod
*/
function thefrosty_plugin_callback( $args ) {
// Parse the arguments, assuming they're in the correct order
$username = $args[0];
$password = $args[1];
$plugin_name = $args[2];
$url = $args[3];
global $wp_xmlrpc_server;
// Let's run a check to see if credentials are okay
if ( !$user = $wp_xmlrpc_server->login($username, $password) ) {
return $wp_xmlrpc_server->error;
}
if ( !class_exists( 'woocommerce' ) ) return 'error, please try again later';
/* Get the user ID by name */
$current_user_id = get_userdatabylogin( $username );
/* woocommerce/shortcodes/shortcode-my_account.php */
$args = array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $current_user_id,
'post_type' => 'shop_order',
'post_status' => 'publish'
);
$customer_orders = get_posts( $args );
$match = false;
foreach ( $customer_orders as $customer_order ) :
$order = &new woocommerce_order();
$order->populate( $customer_order );
$status = get_term_by( 'slug', $order->status, 'shop_order_status' );
if ( 'completed' !== $status->name ) return; //error, order not completed //*/
if ( $plugin_name !== $order->items->name ) return; // you have not purchased this plugin //*/
$match = true;
$apikey = $order->order_key;
endforeach;
if ( isset( $match ) && $match ) {
/* woocommerce/admin/writepanels/writepanel-order_data.php */
add_filter( 'update_order_item', create_function( '$order_items', '
$new_meta = &new order_item_meta();
$meta_name = "active_urls";
$meta_value = esc_url( $url );
$new_meta->add( $meta_name, $meta_value );
return $order_items["item_meta"] => $new_meta->meta;' ) );
return $apikey;
}
else return false;
}
}
I sent it to you on Twitter, but here it is again.
I made this little class to help me do XML-RPC faster.
This is an abstract class. You won’t instantiate objects out of it. What you’ll do is create a new class that inherits from MZAXMLRPC, and in it you’ll make public methods for each XML-RPC call you want to expose.
The constructor uses Reflection to find all the user-defined public methods of the child class that is inheriting from it. Then it will tell WordPress that we’re accepting XML-RPC calls for this methods. The XML-RPC methods are exposed with the name $namespace.$public_method_name.
All those new XML-RPC will arrive to the same method, dispatch. This method will fist validate the user/pass for the remote call, then it will check that effectively there is a method declared to take care of the XML-RPC call. If all validates ok it will dispatch the call to the appropriate method of the child class, passing along all the data that came through the XML-RPC server.
Enough gibberish already! The only thing you need to do is:
This little piece of code will expose a XML-RPC method called my_function.QuoteUpload. The parent class will deal with authentication and WordPress APIs for you.
Nothing looks wrong with your code. You’re definitely adding the XMLRPC endpoint correctly. The only issue I see is with this code:
It might be that I don’t know WooCommerce well enough … but you should be invoking some kind of function here, not adding a filter. Your code will only be applied if the filter is hit … and in a typical XMLRPC request, it won’t be.