Use Case: Connecting WooCommerce to a Mobile App

Overview

Connecting with customers on their mobile device– especially through the use of a branded, mobile application– is considered the holy grail of customer engagementPeople live on their phones these days. So store owners, naturally, want to be where their customers live for many stores.

 

In this topic, we’ll examine the example of a Product Review App.

 

If you prefer, you can jump to the Knowledge check to see what you already know

Requirements

In this example, we’ll customize the API to accommodate requests from a Mobile App limited to the following requirements:

  • The App can connect with the store and obtain API keys for a logged in Customer.We’ll assume an app that can temporarily access browser cookies for an initial login to obtain keys.
  • The App can retrieve a list of the users orders and purchased products.
  • The App can create product reviews for products that the customer has purchased.

It’s worth noting, up front, that this is a “toy” example and a full fledged production app would have several additional considerations.

Data Flow

Key Considerations

For many portions of the application, default REST functionality can be used. However, for full functionality, we will need custom code to implement some of the use cases:

Use Case Approach
AuthenticationBy default, WooCommerce does not permit customer level authentication to obtain API keys Permit specific user capabilities during authentication requests
Retrieving Customer Orders Because orders are a post type, the REST API only permits access to those with view_others_private_orders capability Custom REST Controller that extends default Woo functionality
Creating a Product Review By default only accessible to those with moderate_comments capability Custom REST Controller that extends default Woo functionality

WC-Auth Process

WooCommerce allows remote Apps, that are logged in as a site user, to to create and obtain API keys.

 

However, as a security measure, this capability is limited to the users that have the ‘manage_woocommerce’ capability.

 

In order to have a useful, personalized experience in the mobile app, Without allowing each customer to obtain his own API key, WooCommerce won’t be able to individually identify each userwe will need to modify this behavior.

Customizing the Auth Process

add_filter("user_has_cap", "cwpdev_wc_app_athunetication", 15, 3);

function cwpdev_wc_app_athunetication($allcaps, $cap, $args){
  //bail if not doing a WC Auth Request
  global $wp;
  if( !isset($wp->query_vars['wc-auth-route']) || !isset( $wp->query_vars['wc-auth-version'] ) ){
    return $allcaps;
  }
  //validate the app return url and callback url
  if(!cwpdev_custom_validate_app_url($_REQUEST['callback_url']) ){
    return $allcaps;
  }
  //bail for those who can already manage_woocommerce or if not asking about woocommerce
  if( $allcaps['manage_woocommerce'] || 'manage_woocommerce' !== $args[0]){
    return $allcaps;
  }
  //we're only going to allow one key per customer
  global $wpdb;
  $user_id=get_current_user_id();
  if( 0 < $wpdb->get_var( $wpdb->prepare(
      "SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_api_keys WHERE `user_id`=%d", $user_id) )
    ){
      return $allcaps;
    }
  //now that we've cleared all gaurd statments
  $allcaps[ 'manage_woocommerce' ]=true;
  return $allcaps;
}

For mobile apps to obtain API keys, we will cautiously allow customers to manage_woocommerce Note the large amount of guard statements in this example code. Here’s an example filter for user_has_cap:

Mobile Requests

In this example, we’ll focus on two requests from the mobile app:

  1. Getting the Customer orders
  2. Creating a review

Here are two examples of these requests (modified from the REST API Docs We’re omitting fields that Customers shouldn’t have access to, such as user_id and reviewer_id) using the npm library.

const data = {
  product_id: 22,
  review: "Nice album!",
  rating: 5
};

WooCommerce.post("products/reviews", data)
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.log(error.response.data);
  });
WooCommerce.get("orders")
  .then((response) => {
    console.log(response.data);
  })
  .catch((error) => {
    console.log(error.response.data);
  });

Customizing the Controller: Orders

In order to select a product for review, the App will need to be able to see what products the customer has purchased.

 

So we’ll need to open the up the permissions, but restrict customers to their own ordersLine 17 accomplishes this by overriding the customer_id parameter with the authenticated user id

  class Cwpdev_REST_Order_Controller extends WC_REST_Orders_Controller{
    public function get_items_permissions_check( $request ){
      if( wc_rest_check_post_permissions( $this->post_type, 'read' ) ){
        return true;
      }

      if( in_array('customer', $wp_get_current_user()->roles)){
        return true;
      }

      return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
    }

    public function get_items($request){
      //if user cannot normally read order, add controls
      if( !wc_rest_check_post_permissions( $this->post_type, 'read' ) ){
        $request['customer_id']=get_current_user_id();
      }
      return parent::get_items($request);
    }
  }

Customizing the Controller: Product Reviews

The default product reviews controller, bases access on the ability of a user to manage_comments.

 

We’ll need to open it up for customer, but restrict their ability to only review products that they’ve purchasedThe wc_customer_bought_product function is a nice check for this (Line 11)

class Cwpdev_REST_Product_Review_Controller extends WC_REST_Product_Reviews_Controller{

 public function create_item_permissions_check( $request ) {

    //if they can normally create a review, let 'em
    if ( wc_rest_check_product_reviews_permissions( 'create' ) ) {
      return true;
    }
    //check if user bought the product
    $user=wp_get_current_user();
    if( wc_customer_bought_product($user->user_email,$user->ID, (int) $request['product_id']) ){
      return true;
    }

    return new WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
  }

  public function create_item($request){
    //If they don't "moderate_comments" put some controlled values in.
    if ( !wc_rest_check_product_reviews_permissions( 'create' ) ) {
      $user=get_current_user();
      $request['status']  = 'hold';
      $request['reviewer'] = $user->user_nicename;
      $request['reviewer_email']= $user->user_email;
      $request['verified']=true;
    }
    return parent::create_item($request);
  }
	// Additional Methods can be added for controlling
    // the updating of product reviews, as well
}

Hooking in Your Custom Controllers

Finally, be sure to hook your custom controllers into WooCommerce’s rest namespaces.

add_filter('woocommerce_rest_api_get_rest_namespaces', function($namespaces){
  $namespaces['wc/v3']['product-reviews']="Cwpdev_REST_Product_Review_Controller";
  $namespaces['wc/v3']['orders']="Cwpdev_REST_Order_Controller";

  return $namespaces;
});

Conclusion

You now have a general overview of some of the techniques you can use to bend the REST API to your will.

In a general sense, the Woo REST API is extremely capable, yet fairly restrictiveThis helps to put security at the forefront. when it comes to user permissions. For many use cases, you will likely need to open up the controllers default permissions, and then restrict the data that specific user types can access.

 

 

This concludes the topic and the lesson! Be sure to, check your knowledge before you go. Remember this course is designed to be searchable, nimble, and is continuously updated, so keep this material in your back pocket and use it to breeze through your next WooCommerce project!

Knowledge Check

Hint: All the custom code in the lesson has been prefixed with “cwpdev”. Use CTRL+Shift+F to search this snippet to quickly jump to the examples.

References

×

Keyboard shortcuts

CTRL+Shift+F Search slideshow
F Fullscreen view
CTRL+Click Zoom in
Esc Topic overview
Right arrow,
Down arrow
Next slide
Left arrow,
Up arrow
Previous slide

Color codes

Tooltip
Hover over text more additional info
Link to an external resource
Link to an internal slide
If buttons aren't working, click in the screen to "focus" your browser
RSS
LinkedIn
Share