CreateIT
CreateIT
BLOG

WooCommerce API – how to start?

WooCommerce API sign and a ninja pointing to banners behind him

WooCommerce API – how to start?

SHARE

Challenge:
configure the development environment for Woo REST API
Solution:
set up API keys, example API route endpoint and Postman GET requests

Woo REST API version 3 is the way to connect to the popular ecommerce WordPress plugin. By configuring API keys you can easily share your shop orders with external services, such as shipping providers. Follow these easy steps to set up WooCommerce API credentials.

Configure WooCommerce API keys

To give somebody “access” to our API, we need to generate 2 random strings: ‘Customer Key’ and ‘Customer secret’. Each pair of keys is connected to a particular WordPress user. You can give permission to Read data only, or also to Write. If an external service is using only ‘GET’ requests, ‘Read’ will be enough. To set up the keys:

  • register a new WordPress user (only for the purpose of API access )
  • generate a pair of keys ( wp-admin / WooCommerce / Settings / Advanced – REST API – Add key )

Sharing API credentials: ‘Customer secret’ should be kept private. You can use the privnote.com service for sharing credentials with third-party. After receiving it, the note will self-destruct.

Testing route with Postman

Postman is a convenient tool for connecting to API and performing tests. We will try GET request /wp-json/wc/v3/orders that will fetch all shop orders. If we have a shop with an https connection, we will use: Auth 1.0 Authorization, signature Method HMAC-SHA1. Now, fill in the 2 fields for ‘Consumer Key’ and ‘Consumer Secret’. After clicking ‘Send’ in Postman, we will see all orders in json format.

Using endpoint parameters

The built in WooCommerce Routes often offer parameters that can be used to filter the request data. To get all orders with status processing, we can add a param to the url: /wp-json/wc/v3/orders?status=processing

Postman on localhost

When working with WordPress in the development environment on localhost, a website often uses the http:// protocol, which might be a problem when doing authorization using Auth 1.0. The solution will be to change the Type of Authorization to: Basic Auth. As Username and Password just use wp_user credentials. This is recommended only for local development, on production servers proper authorization protocol type should be used.

Custom Woo Endpoint

Let’s say we would like to create our custom endpoint that will return order details, but with additional shipping data added to the GET request. We will register a custom API route. There are 2 help methods: add_data_to_order() and filter_order_data(), one will be adding extra data, the other one will strip unnecessary data from array. Instead of quering order data ourselves – we will just use the WooCommerce built-in endpoint: /wc/v3/orders/[order_id] and call it internally.

// functions.php
class WC_REST_CUSTOM_1_Orders_Controller {
    
    public function get_extra_order_details(WP_REST_Request $request_params ){
        $order_number = $request_params['order_number'];
        if(empty($request_params['order_number'])){
            return new WP_Error( 'incorrect_data', 'order_number param required' );
        }
        // Internal Woocommerce API call
        $api_route_name = '/wc/v3/orders/'.$order_number;
        $request = new WP_REST_Request( 'GET', $api_route_name );
        $response = rest_do_request( $request );
        $server = rest_get_server();
        $order_data = $server->response_to_data( $response, false );
        if(isset($order_data['code'])){
            return new WP_REST_Response( $order_data, 401 );
        }
        if(empty($order_data)){
            return new WP_Error( 'incorrect_data', 'order does not exist' );
        }
        // make single order - as array element
        $temp_array = array();
        $temp_array[] = $order_data;
        $temp_array = $this->add_data_to_order($temp_array);
        if(!isset($request_params['full'])){
            $temp_array = $this->filter_order_data($temp_array);
        }
        return $temp_array;
    }

    /**
     * @param $orders
     * Add extra data to woocommerce order
     */
    private function add_data_to_order($orders){
        foreach($orders as $mainkey => $order) {
            $additionalShippingData = array();
            $shipping_type = 'address';
            foreach($order['shipping_lines'][0]['meta_data'] as $shipping_row_item){
                if($shipping_row_item['key'] == 'wcus_city_ref'){
                    $additionalShippingData['RecipientCityRef'] = $shipping_row_item['value'];
                    if(!empty($additionalShippingData['RecipientCityRef'])){
                        $shipping_type = 'warehouse';
                    }
                }
                if($shipping_row_item['key'] == 'wcus_warehouse_ref'){
                    $additionalShippingData['RecipientWarehouseRef'] = $shipping_row_item['value'];
                }
                if($shipping_row_item['key'] == 'wcus_settlement_name'){
                    $additionalShippingData['RecipientCityName'] = $shipping_row_item['value'];
                }
            }
            if(isset($order['billing']['phone'])){
                $additionalShippingData['RecipientsPhone'] = $order['billing']['phone'];
                $additionalShippingData['RecipientsPhone'] = kirillbdev\WCUkrShipping\Helpers\WCUSHelper::preparePhone($additionalShippingData['RecipientsPhone']);
            }
            $additionalShippingData['RecipientType'] = 'PrivatePerson';
            if($shipping_type == 'address') {
                $additionalShippingData['ServiceType'] = 'WarehouseDoors';
            } elseif ($shipping_type == 'warehouse'){
                $additionalShippingData['ServiceType'] = 'WarehouseWarehouse';
            }
            if($order['payment_method'] == 'cod'){
                $additionalShippingData['AfterpaymentOnGoodsCost'] = $order['total'];;
            }
            // assign value
            $orders[$mainkey]['additional_shipping_data'] = $additionalShippingData;
        }
        return $orders;
    }

    private function filter_order_data($orders){
        foreach($orders as $mainkey => $order){
            unset($orders[$mainkey]['billing']);
            // unset not-needed keys
            unset($orders[$mainkey]['id']);
            unset($orders[$mainkey]['parent_id']);
            unset($orders[$mainkey]['version']);
            unset($orders[$mainkey]['prices_include_tax']);
            unset($orders[$mainkey]['date_modified']);
            unset($orders[$mainkey]['discount_tax']);
            unset($orders[$mainkey]['shipping_tax']);
            unset($orders[$mainkey]['cart_tax']);
            unset($orders[$mainkey]['order_key']);
            unset($orders[$mainkey]['total_tax']);
            unset($orders[$mainkey]['customer_id']);
            // more
            unset($orders[$mainkey]['customer_ip_address']);
            unset($orders[$mainkey]['customer_user_agent']);
            unset($orders[$mainkey]['created_via']);
            unset($orders[$mainkey]['cart_hash']);
            // remove not needed meta_data
            unset($orders[$mainkey]['meta_data']);
            // clean up line_items
            foreach($orders[$mainkey]['line_items'] as $line_items_key => $line_items_data){
                $orders[$mainkey]['line_items'][ $line_items_key] = array();
                $orders[$mainkey]['line_items'][ $line_items_key]['name'] = $line_items_data['name'];
                $orders[$mainkey]['line_items'][ $line_items_key]['quantity'] = $line_items_data['quantity'];
                $orders[$mainkey]['line_items'][ $line_items_key]['sku'] = $line_items_data['sku'];
            }
            // clean up more details
            unset($orders[$mainkey]['tax_lines']);
            unset($orders[$mainkey]['fee_lines']);
            unset($orders[$mainkey]['coupon_lines']);
            unset($orders[$mainkey]['refunds']);
            unset($orders[$mainkey]['date_created_gmt']);
            unset($orders[$mainkey]['date_modified_gmt']);
            unset($orders[$mainkey]['date_completed_gmt']);
            unset($orders[$mainkey]['date_paid_gmt']);
            unset($orders[$mainkey]['currency_symbol']);
            unset($orders[$mainkey]['_links']);
            // unset shipping lines
            unset($orders[$mainkey]['shipping_lines']);
        }
        return $orders;
    }
    public function register_routes() {
        /**
         * Define custom WooCommerce routes
         */
        register_rest_route(
            'wc/v3',
            '/get_extra_order_details',
            array(
                'methods' => 'GET',
                'callback' => array( $this, 'get_extra_order_details' ),
                'permission_callback' => function($request){
                    return true;
                },
                'args' =>
                    array(
                        'order_number' => array(
                            'required' => true,
                            'type' => 'string',
                            'description' => 'Shop order number',
                        ),
                        'full' => array(
                            'required' => false,
                            'type' => 'string',
                            'description' => 'Display all order details, use value: 1',
                        ),
                )
            )
        );
    }
}
/**
 * Register endpoints
 */
add_filter( 'woocommerce_rest_api_get_rest_namespaces', 'ct_custom_api' );
function ct_custom_api( $controllers ) {
    $controllers['wc/v3']['ct-my-endpoints-123'] = 'WC_REST_CUSTOM_1_Orders_Controller';
    return $controllers;
}

Usage and example response

Our custom route is ready. We can test the GET request using:

/wp-json/wc/v3/get_extra_order_details?order_number=565 . This will show order details with some data stripped. The full data in json format is available using: /wp-json/wc/v3/get_extra_order_details?order_number=565&full=1

Example API response:

[
    {
        "status": "completed",
        "currency": "USD",
        "date_created": "2021-09-02T09:56:55",
        "discount_total": "0",
        "shipping_total": "50",
        "total": "1503",
        "shipping": {
            "first_name": "test",
            "last_name": "test",
            "company": "",
            "address_1": "abc",
            "address_2": "",
            "city": "testing",
            "state": "",
            "postcode": "",
            "country": "USA"
        },
        "payment_method": "cod",
        "transaction_id": "",
        "customer_note": "",
        "date_completed": "2021-09-16T11:19:01",
        "date_paid": "2021-09-16T11:19:01",
        "number": "565",
        "line_items": [
            {
                "name": "Product1",
                "quantity": 2,
                "sku": "3145"
            },
            {
                "name": "Product2",
                "quantity": 4,
                "sku": "3144"
            },
        ],
        "additional_shipping_data": {
            "RecipientCityRef": "abc1",
            "RecipientWarehouseRef": "abc2",
            "RecipientsPhone": "321321321",
            "RecipientType": "PrivatePerson",
            "ServiceType": "WarehouseWarehouse",
            "AfterpaymentOnGoodsCost": "1503"
        }
    }
]

WooCommerce API documentation

We would like to share the details about WooCommerce API documentation, route parameters, and enable the ability to make API requests in the browser. This will be automatically handled by the WP API SwaggerUI plugin. After plugin activation and simple config in Settings / Swagger, the entire API documentation will be visible using the following url: /rest-api/docs/

Next steps

It’s important to remember that a third party company that received API Keys for our WooCommerce shop will have access to all built-in woo endpoints. For example, the list of all customers ( /wp-json/wc/v3/customers ) is available for every authorized API user. If we would like to restrict access to only some routes or blacklist particular endpoints, WooCommerce provides filters for this: ‘rest_endpoints’ and  ‘rest_authentication_errors’.

We hope you find these solutions useful. Make sure to follow us for more tips and guidelines.

Need help?

  • Looking for support from experienced programmers?

  • Need to fix a bug in the code?

  • Want to customize your webste/application?

ADD COMMENT

Your email address will not be published.

createIT Contact