定制XMLRPC方法加上用户和WooCommerce订单的身份验证

时间:2012-01-19 作者:Austin Passy

我正在使用一个自定义XML-RPC方法来捕获我正在构建的插件的一些信息。激活后,用户必须通过输入在我的WP网站上购买插件时提供给他们的用户/密码来验证自己。

插件使用以下代码:

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();

    } 
表单提交后看起来很正常,在本地工作时出现200个错误,但使用另一个插件进行测试,该插件发送相同的错误代码,但正在从主机发送响应(现在不用担心)。

我一直坚持的是后端代码。我在WP安装的核心插件中创建了一个类。我想这就是它需要的地方。我缺少一些故障代码和错误消息响应,不知道如何执行这些操作。只是想在正确的方向上推动一下。。

正如您所见,我也在针对WooCommerce订单测试用户(WC的代码应该很好),但是尝试更新订单元数据可能需要修复以保存用户URL。

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;
}
}

2 个回复
SO网友:MZAweb

我在推特上发给你的,但又在这里了。

我创建了这个小类来帮助我更快地执行XML-RPC。

abstract class MZAXMLRPC {
    protected $calls = Array();
    protected $namespace = "myxmlrpc";

    function __construct($namespace){
        $this->namespace = $namespace;
        $reflector = new ReflectionClass($this);
        foreach ( $reflector->getMethods(ReflectionMethod::IS_PUBLIC) as $method){
            if ($method->isUserDefined() && $method->getDeclaringClass()->name != get_class()){
                $this->calls[] = $method->name;
            }
        }
        add_filter(\'xmlrpc_methods\', array($this, \'xmlrpc_methods\'));
    }

    public function xmlrpc_methods($methods)
    {
        foreach ($this->calls as $call){
            $methods[$this->namespace . "." . $call] = array($this, "dispatch");
        }
        return $methods;
    }

    public function dispatch($args){
        global $wp_xmlrpc_server;

        $username   = $args[1];
        $password   = $args[2];
        $data = $args[3];

        if ( !$wp_xmlrpc_server->login($username, $password) )
            return $wp_xmlrpc_server->error;

        $call = $this->get_called_method();

        if (method_exists($this, $call)){
            $status = call_user_func_array(array($this, $call), array($data));
            return $status;
        }else{
            return "Method not allowed";
        }

    }

    private function get_called_method(){
        global $wp_xmlrpc_server;
        $call = $wp_xmlrpc_server->message->methodName;
        $pieces = explode(".", $call);
        return $pieces[1];
    }

}
这是一个抽象类。您不会从中实例化对象。您要做的是创建一个从MZAXMLRPC继承的新类,并在其中为每个要公开的XML-RPC调用提供公共方法。

构造函数使用反射来查找从其继承的子类的所有用户定义的公共方法。然后它会告诉WordPress我们正在接受此方法的XML-RPC调用。XML-RPC方法以名称$namespace公开$public\\u method\\u名称。

所有这些新的XML-RPC都将使用相同的方法dispatch。此方法将首先验证远程调用的用户/过程,然后检查是否有效地声明了一个方法来处理XML-RPC调用。如果all验证正常,它将向子类的相应方法分派调用,传递通过XML-RPC服务器传递的所有数据。

胡言乱语已经够多了!您唯一需要做的是:

class MY_XMLRPC extends MZAXMLRPC{

    public function QuoteUpload($data){

        if (!isset($data["author"]))
            return "Missing \'author\' parameter";

        if (!isset($data["quote"]))
            return "Missing \'quote\' parameter";

        $author = $data["author"];
        $quote = $data["quote"];

        $new_post = array(
            \'post_status\' => \'publish\',
            \'post_type\' => \'mzaquotes\',
            \'post_title\' => $quote
        );

        $new_post_id = wp_insert_post($new_post);
        wp_set_post_terms( $new_post_id, $author, \'quote_author\' );

        return "OK";
    }
}

new MY_XMLRPC(\'my_function\');
这段代码将公开一个名为my\\u函数的XML-RPC方法。QuoteUpload。父类将为您处理身份验证和WordPress API。

SO网友:EAMann

您的代码看起来没有问题。您确实正确添加了XMLRPC端点。我看到的唯一问题是此代码:

 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;
}
可能是因为我对WooCommerce了解不够。。。但您应该在这里调用某种函数,而不是添加过滤器。您的代码将仅在命中筛选器时应用。。。在一个典型的XMLRPC请求中,它不会是。

结束

相关推荐

函数deactive_plugins不存在

我正在function deactivate_plugins does not exist 调用此函数时出错function deactivateSelf(){ deactivate_plugins(RSD_PLUGIN, true); //gives error: function deactivate_plugins does not exist header(\"Location: plugins.php?deactivate=true\"); //redirect