By woocommerce-sl, posted on July 8, 2024

Selling licensed products online has never been easier or more integrated. Whether you’re offering software licenses, digital content, or other licensed goods, the process is designed to be as seamless as selling any regular product. This approach not only simplifies the setup for store owners but also ensures a smooth shopping experience for customers.

Seamless Integration with all existing Products

One of the standout features of this system is its ability to seamlessly integrate licensed products with regular products in the same store. This means that a customer can add both types of products—licensed and non-licensed—to their cart in a single transaction without any disruptions or complications. For example, a customer might purchase a piece of physical hardware (a non-licensed product) alongside a software license or a digital download (licensed products) in the same order.

This seamless integration eliminates the need for multiple transactions and makes the shopping process more efficient. Customers appreciate the convenience of being able to purchase everything they need in one go, whether they’re buying a combination of licensed and non-licensed products or just one type. This also opens up the possibility for store owners to create bundles or special offers that mix and match these types of products, enhancing sales potential. (more…)

Read more

By woocommerce-sl, posted on August 2, 2017

Set Pre-Generated License Keys with WooCommerce Software License

The WooCommerce Software License plugin introduces a powerful new feature: the ability to assign and manage pre-generated license keys—also known as manual or admin-provided keys—alongside the plugin’s automated licensing system.

This feature is especially valuable for resellers, software distributors, and developers who already have a pool of license keys generated by third-party systems or external software platforms. Now, you can easily import and manage those existing keys directly within your WooCommerce store.

Why Use Pre-Generated Keys?

There are many cases where automatic key generation may not fit your business needs. For example:

  • You’re distributing licenses for a third-party app or SaaS.

  • You already purchased or generated license keys from a software vendor.

  • You want to handle activation offline or outside of the automated system.

  • You need full control over key formatting and delivery.

Pre-generated keys allow you to bring your own keys into the licensing workflow—without giving up the advanced features offered by the WooCommerce Software License plugin.

Seamless Integration with Existing Features

Even when using your own manually created license keys, you can still benefit from all the existing licensing controls, such as:

  • Allowed Clients – Restrict license usage to specific customer accounts.

  • Instances per Key – Limit the number of activations per license.

  • Expiration Settings – Apply validity periods to keys.

  • License Status Tracking – Monitor which keys are used, remaining, or pending.

Your pre-generated keys are fully compatible with the system’s licensing groups, activation tracking, and customer email delivery features.

Combine Manual and Automated Keys

The plugin allows you to create multiple Licensing Groups, which makes it easy to mix and match key types. For example, you can:

  • Deliver a bundle that includes both a pre-generated key and an auto-generated one.

  • Use automated keys for standard purchases, and pre-generated keys for volume licensing or enterprise clients.

  • Segment key pools by product line or platform (e.g., Mac vs. Windows keys).

This flexibility makes WooCommerce Software License an ideal solution for both direct software sellers and resellers managing external license inventories.

Getting Started with Pre-Generated Keys

  1. Go to WooCommerce Products → Product → Product Data → License → Predefined Keys.

  2. Add your license keys.

  3. Assign them to the appropriate Licensing Group.

  4. Optionally set usage limits, expiration dates, and customer access rules.

  5. When a customer purchases a product associated with that group, the next available key will be automatically assigned and delivered.

Use Case Highlights

  • Software Resellers: Easily upload vendor-provided license batches and sell them through WooCommerce.

  • Educational Licensing: Distribute license keys in bulk to schools or students with usage tracking.

  • Enterprise Clients: Offer pre-arranged keys with customized limits and expiration.

  • Offline Sales: Sell licenses at trade shows or events, and activate them later within WooCommerce.

With the new Pre-Generated License Key support, WooCommerce Software License gives you the best of both worlds—automation where you need it, and manual control where it matters. Whether you’re selling your own software or acting as a reseller for others, this feature empowers you to deliver licenses in the exact format your business requires.

 

Read more

By woocommerce-sl, posted on August 1, 2017

Any customer can manage the license keys through default WooCommerce MyAccount Page. Once a purchase is completed a new button Licence Manage appear within the Recent Orders table.

(more…)

Read more

By woocommerce-sl, posted on August 1, 2017

The shop administrator can manage any licence aspects of a product purchase through the WooCommerce Orders interface. Administrators can delete keys, generate new ones, un-assign etc.

Main Licence Keys interface consist of a list of all keys from all orders. This facilitate an easy management through the interface functions which include filters and search.

Full control of each license is available through an additional metabox interface at the admin order page.

Admin can modify order license details individually from original data.

Read more

By woocommerce-sl, posted on August 1, 2017

The built-in API interface is a convenient way to allow your software to communication with the WooCommerce Software License API. Calls are initiated through GET/POST method. Additional code examples are included within the plugin download, also in our documentation area Software API Integration code example.
The following methods are available:

  • activate
  • deactivate
  • status-check
  • plugin_update
  • plugin_information
  • theme_update
  • code_version
  • key_delete

Each function generally requires some combination of the following input values:

  • woo_sl_action: plugin function requested
  • licence_key: the license key that was sent to the user
  • product_unique_id: the Software Unique ID as defined in the WooCommerce product License tab
  • domain: the URL to a WordPress site using a plugin or a unique hash for standalone software
  • api_version: an API version to use, if not specified 1.0 will be used. Latest available is 1.1

For each function, the returned values are:

  • status => error or success message (string)
  • status_code => result code (integer)
  • message => explanation of result (string)
  • update_data ( specific methods ) => code update details (object)

 

The domain input ( unique hash ) is processed on API calls using regex, so it should be also validated on the client, before sending the request, to include the following allowed chars:

  • alphanumeric characters ( lowercase and uppercases)
  • dots
  • minus
  • underlines
  • forward slashes
  • spaces

 

activate

This method allows a license key to be synchronized with your software for activation. The following arguments are required for a typical software-license call:

  • woo_sl_action = ‘activate’
  • product_unique_id
  • licence_key
  • domain

deactivate

This method facilitate a licence key de-activation. Once de-activated a key is released from being set as used status, and it can be integrated with another domain / hash. The following arguments are required for a call:

  • woo_sl_action = ‘deactivate’
  • product_unique_id
  • licence_key
  • domain

status-check

The status-check API method allow a certain software key to be verified for being still active, valid, assigned to a certain domain. The following arguments are required for a call:

  • woo_sl_action = ‘status-check’
  • product_unique_id
  • licence_key
  • domain

plugin_update

The plugin_update API method return basic details regarding software update. The following arguments are required for a call:

  • woo_sl_action = ‘plugin_update’
  • product_unique_id
  • licence_key
  • version
  • domain

theme_update

The theme_update API method return basic details regarding theme software update. The following arguments are required for a call:

  • woo_sl_action = ‘theme_update’
  • product_unique_id
  • licence_key
  • version
  • domain

plugin_information

The plugin_information API method return detailed information’s regarding software as download link, latest software, upgrade notice, requires, description details, installation, faq, screenshot, changelog etc. The following arguments are required for a call:

  • woo_sl_action = ‘plugin_information’
  • product_unique_id
  • licence_key
  • version
  • domain

code_version

The method return detailed information’s regarding a licenced product, latest version, upgrade notice, requires, description details, installation, faq, screenshot, changelog etc. The difference from other API methods,this does not require a key, but there’s no download / update link provided.
The following arguments are required for a call:

  • woo_sl_action = ‘code_version’
  • product_unique_id

key_delete

Through this API method a key can be removed from the customer dashboard. By deleting a key, a new slot will be open so another licence key can be generated. The following arguments are required for a call:

  • woo_sl_action = ‘key_delete’
  • product_unique_id
  • licence_key

Read more

By woocommerce-sl, on , posted on March 5, 2018

On site interaction using any API methods, the system reply through an JSON encoded message including a status code to makes interpretation easier.

Success

  • s100
    Licence Key Successfully activated for ‘domain’
  • s101
    Licence Key Successfully activated for ‘domain’ – *first pass
  • s201
    Licence Key Successfully Unassigned
  • s203
    Licence Key Is Unassigned
  • s205
    Licence key Is Active and Valid for Domain ( when assign_domain_to_key_on_status_check option active )
  • s215
    Licence key Is Active and Valid for Domain
  • s401
    *a full response with code metadata on calling plugin_update or theme_update methods
  • s402
    *a full response with code metadata on calling plugin_information method
  • s403
    *a full response with code metadata on calling code_information method
  • s610
    *Licence Key Successfully Deleted

Error

  • e001
    Invalid provided data
  • e002
    Invalid licence key
  • e003
    Order does not exist anymore
  • e004
    Order status not allowed
  • e110
    Invalid licence key or licence not active for domain
  • e111
    Invalid Data
  • e112
    You had reached the maximum number of domains for this key
  • e204
    Licence key not active for current domain
  • e301
    Licence Key does not match this product
  • e312
    Licence is not Active, current status is ‘STATUS’
  • e419
    Invalid Product Unique ID

Read more

By woocommerce-sl, posted on August 1, 2017

Any software can use API functionality. We can provide full code in a form of WordPress plugin which can be used as staring base for further implementation.

This is a sample usage on a licence key activation call:

The first part of the code consist of few constants definition which are being used later within the code.


//the url where the WooCommerce Software License plugin is being installed
define('SL_APP_API_URL',      'http://YourDomainWhereSoftwareManagement.com/index.php');

//the Software Unique ID as defined within product admin page
define('SL_PRODUCT_ID',           'APTO');


$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
define('SL_INSTANCE',             str_replace($protocol, "", get_bloginfo('wpurl')));

A simple activation calls will looks like this:

    $args = array(
                    'woo_sl_action'         => 'activate',
                        'licence_key'       => $license_key,
                        'product_unique_id'        => SL_PRODUCT_ID,
                        'domain'          => SL_INSTANCE
                    );
    $request_uri    = SL_APP_API_URL . '?' . http_build_query( $args );
    $data           = wp_remote_get( $request_uri );

    if(is_wp_error( $data ) || $data['response']['code'] != 200)
        {
            //there was a problem establishing a connection to the API server
        }

    $response_block = json_decode( wp_remote_retrieve_body( $data ) );
                      
    if(!is_array($response_block) || count($response_block) < 1)
        return $checked_data;

    //retrieve the last message within the $response_block
    $response_block = $response_block[count($response_block) - 1];
    if(isset($response_block->status))
        {
            if( $response_block->status == 'success' && ( $response_block->status_code == 's100' || $response_block->status_code == 's101' ) )
                {
                    //the license is active and the software is active
                    //doing further actions like saving the license and allow the plugin to run

                }
                else
                {
                    //there was a problem activating the license
                }
        }
        else
        {
            //there was a problem establishing a connection to the API server
        }

The API $data_body response include also a ‘message’ argument with detailed text information of the response. This is always an English text, which can be translated to the local site language using _e, __ and other WordPress translation functions.

Read more

By woocommerce-sl, posted on August 1, 2017

The first part of the code consist of few constants definition which are being used later within the code.


//the url where the WooCommerce Software License plugin is being installed
define('SL_APP_API_URL',      'http://YourDomainWhereSoftwareManagement.com/index.php');

//the Software Unique ID as defined within product admin page
define('SL_PRODUCT_ID',           'APTO');

//A code variable constant is required, which is the user application code version. This will be used by API to compare against the new version on shop server.
define('SL_VERSION', '1.4.2');

$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
define('SL_INSTANCE',             str_replace($protocol, "", get_bloginfo('wpurl')));

A plugin auto-update code can be inserted within the plugin, here is an example:


        class WOOSL_CodeAutoUpdate
        {

            // URL to check for updates, this is where the index.php script goes

            public $api_url;

            private $slug;
            public $plugin;
            
            private $API_VERSION;


            function __construct($api_url, $slug, $plugin)
                {
                    $this->api_url  =   $api_url;
                    $this->slug     =   $slug;
                    $this->plugin   =   $plugin;
                    
                    //use laets available API 
                    $this->API_VERSION =   1.1;
                    
                }

            public function check_for_plugin_update($checked_data)
                {
                     if ( !is_object( $checked_data ) ||  ! isset ( $checked_data->response ) )
                        return $checked_data;
                     
                     $request_string = $this->prepare_request('plugin_update');
                     if($request_string === FALSE)
                        return $checked_data;
                     
                     global $wp_version;
                     
                     // Start checking for an update
                     $request_uri = $this->api_url . '?' . http_build_query( $request_string , '', '&');
                     
                     //check if cached
                     $data  =   get_site_transient( 'my-custom-plugin-check_for_plugin_update_' . md5( $request_uri ) );
                     if  ( $data    === FALSE )
                         {
                             $data = wp_remote_get( $request_uri, array(
                                                                                'timeout'     => 20,
                                                                                'user-agent'  => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ),
                                                                                ) );
                             
                             if(is_wp_error( $data ) || $data['response']['code'] != 200)
                                return $checked_data;
                                
                             set_site_transient( 'my-custom-plugin-check_for_plugin_update_' . md5( $request_uri ), $data, 60 * 60 * 4 );
                             
                         }
                                                  
                     $response_block = json_decode( wp_remote_retrieve_body( $data ) );
                      
                     if(!is_array($response_block) || count($response_block) < 1)
                        return $checked_data;
                     
                     //retrieve the last message within the $response_block
                     $response_block = $response_block[count($response_block) - 1];
                     
                     $response  =   $this->postprocess_response( $response_block );
                     if ( $response ) 
                        {
                            //update any licensing data
                            if ( $refresh )
                                {
                                    if ( isset ( $response_block->licence_status ) )
                                        $this->licence['licence_status']    =   $response_block->licence_status;
                                    if ( isset ( $response_block->licence_expire ) )
                                        $this->licence['licence_expire']    =   $response_block->licence_expire;
                                        else
                                        $this->licence['licence_expire']    =   '';
                                    
                                     WooGC_licence::update_licence_data( $this->licence );
                                }
                            
                            if ( ! isset ( $response->new_version ) )
                                return $checked_data;
                            
                            //check if the returned version is higher
                            if ( isset ( $response->new_version )   &&  version_compare( $response->new_version, WOOGC_VERSION, '<'  ) )
                                return $checked_data;
                                
                            $checked_data->response[$this->plugin] = $response;
                            
                            
                        }
                        
                     return $checked_data;
                }

            public function plugins_api_call($def, $action, $args)
                {
                     if (!is_object($args) || !isset($args->slug) || $args->slug != $this->slug)
                        return $def;
    
                     $request_string = $this->prepare_request($action, $args);
                     if($request_string === FALSE)
                        return new WP_Error('plugins_api_failed', __('An error occour when try to identify the pluguin.' , 'woo-global-cart') . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>'. __( 'Try again', 'woo-global-cart' ) .'&lt;/a>');;
                     
                     global $wp_version;
                     
                     $request_uri = $this->api_url . '?' . http_build_query( $request_string , '', '&');
                     $data = wp_remote_get( $request_uri, array(
                                                                        'timeout'     => 20,
                                                                        'user-agent'  => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ),
                                                                        ) );
                     
                     if(is_wp_error( $data ) || $data['response']['code'] != 200)
                        return new WP_Error('plugins_api_failed', __('An Unexpected HTTP Error occurred during the API request.' , 'woo-global-cart') . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>'. __( 'Try again', 'woo-global-cart' ) .'&lt;/a>', $data->get_error_message());
                     
                     $response_block = json_decode( wp_remote_retrieve_body( $data ) );
                     
                     if( ! is_array($response_block) || count( $response_block ) < 1 )
                        return $def;
                        
                     //retrieve the last message within the $response_block
                     $response_block = $response_block[ count( $response_block ) - 1 ];
                     
                     $response  =   $this->postprocess_response( $response_block );
                     if ( $response ) 
                        return $response;
                }

            public function prepare_request($action, $args = array())
                {
                    global $wp_version;
                    
                    return array(
                        'woo_sl_action'         => $action,
                        'version'               => SL_VERSION,
                        'product_unique_id'     => SL_PRODUCT_ID,
                        'licence_key'           => LICENSE_KEY,
                        'domain'                => SL_INSTANCE,
                        'wp-version'            => $wp_version,
                        
                        'api_version'           => $this->API_VERSION
                    );
                }
            
            private function postprocess_response( $response_block )
                 {
                     $response = isset( $response_block->update_data ) ? $response_block->update_data : '';
                     
                     if ( is_object( $response ) && ! empty ( $response ) )
                         {
                             //include slug and plugin data
                             $response->slug    =   $this->slug;
                             $response->plugin  =   $this->plugin;
                             
                             //if sections are being set
                             if ( isset ( $response->sections ) )
                                $response->sections = (array)$response->sections;
                             
                             //if banners are being set
                             if ( isset ( $response->banners ) )
                                $response->banners = (array)$response->banners;
                               
                             //if icons being set, convert to array
                             if ( isset ( $response->icons ) )
                                $response->icons    =   (array)$response->icons;
                             
                             return $response;
                         }
      
                     return FALSE;
                     
                 }
        }

        function WOOSL_run_updater()
            {
                $wp_plugin_auto_update = new WOOSL_CodeAutoUpdate(SL_APP_API_URL, 'plugin-slug', 'plugin-folder/plugin-filename.php');

                // Take over the update check

                add_filter('pre_set_site_transient_update_plugins', array(
                    $wp_plugin_auto_update,
                    'check_for_plugin_update'
                ));

                // Take over the Plugin info screen

                add_filter('plugins_api', array(
                    $wp_plugin_auto_update,
                    'plugins_api_call'
                ) , 10, 3);
            }

        add_action('after_setup_theme', 'WOOSL_run_updater');

Read more

By woocommerce-sl, posted on August 1, 2017

This is an API example on how to use the Theme AutoUpdate functionality.

    
        define('WOO_SLT_APP_API_URL',      'http://YourDomainWhereSoftwareManagement.com/index.php');
        define('WOO_SLT_PRODUCT_ID',       'Unitque Software ID #@3');
        define('WOO_SLT_VERSION',          '1.0');
        
        define('WOO_SLT_INSTANCE',         str_replace(array ("https://" , "http://"), "", network_site_url()));;
        define('WOO_SLT_THEME_SLUG',        'my-theme-slug' );
        define('WOO_SLT_CHANGELOG_URL',     'http://YourDomainWhereSoftwareManagement.com/changelog/');

            class WOO_SLT_CodeAutoUpdate
                {
                    # URL to check for updates, this is where the index.php script goes
                    public $api_url;

                    private $slug;

                    public function __construct( $api_url, $slug )
                    {
                    $this->api_url = $api_url;

                    $this->slug    = $slug;                 
                    }


                    public function check_for_theme_update($checked_data)
                        {
                            if ( !is_object( $checked_data ) ||  ! isset ( $checked_data->response ) )
                                return $checked_data;

                            $request_string = $this->prepare_request('theme_update');
                            if($request_string === FALSE)
                                return $checked_data;

                            // Start checking for an update
                            $request_uri = $this->api_url . '?' . http_build_query( $request_string , '', '&');
                            $data = wp_remote_get( $request_uri );

                            if(is_wp_error( $data ) || $data['response']['code'] != 200)
                                return $checked_data;

                            $response_block = json_decode( wp_remote_retrieve_body( $data ) );

                            if(!is_array($response_block) || count($response_block) < 1)
                                return $checked_data;
                             
                             //retrieve the last message within the $response_block
                             $response_block = $response_block[count($response_block) - 1];
                             
                             $response  =   $this->postprocess_response( $response_block );
                             if ( $response ) 
                                {                                    
                                    if ( ! isset ( $response->new_version ) )
                                        return $checked_data;
                                    
                                    //check if the returned version is higher
                                    if ( isset ( $response->new_version )   &&  version_compare( $response->new_version, WOOGC_VERSION, '<'  ) )
                                        return $checked_data;
                                        
                                    $checked_data->response[$this->plugin] = $response;                                    
                                }
                                
                             return $checked_data;
                        }


                    public function theme_api_call($def, $action, $args)
                        {
                            if (!is_object($args) || !isset($args->slug) || $args->slug != $this->slug)
                                return $def;
                             
                            $request_string = $this->prepare_request($action, $args);
                            if($request_string === FALSE)
                                return new WP_Error('theme_api_failed', __('An error occour when try to identify the pluguin.' , 'wooslt') . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>'. __( 'Try again', 'wooslt' ) .'&lt;/a>');;

                            $request_uri = $this->api_url . '?' . http_build_query( $request_string , '', '&');
                            $data = wp_remote_get( $request_uri );

                            if(is_wp_error( $data ) || $data['response']['code'] != 200)
                            return new WP_Error('theme_api_failed', __('An Unexpected HTTP Error occurred during the API request.' , 'wooslt') . '&lt;/p> &lt;p>&lt;a href=&quot;?&quot; onclick=&quot;document.location.reload(); return false;&quot;>'. __( 'Try again', 'wooslt' ) .'&lt;/a>', $data->get_error_message());

                            $response_block = json_decode( wp_remote_retrieve_body( $data ) );
                     
                             if( ! is_array($response_block) || count( $response_block ) < 1 )
                                return $def;
                                
                             //retrieve the last message within the $response_block
                             $response_block = $response_block[ count( $response_block ) - 1 ];
                             
                             $response  =   $this->postprocess_response( $response_block );
                             if ( $response ) 
                                return $response;
                        }

                        
                    public function prepare_request($action, $args = array())
                        {
                            global $wp_version;

                            $license_data = get_site_option('slt_license'); 

                            return array(
                                         'woo_sl_action'        => $action,
                                         'version'              => WOO_SLT_VERSION,
                                         'product_unique_id'    => WOO_SLT_PRODUCT_ID,
                                         'licence_key'          => $license_data['key'],
                                         'domain'               => WOO_SLT_INSTANCE,
                                         
                                         'wp-version'           => $wp_version,
                                         'api_version'          => '1.1'
                                         
                            );
                        }


                    private function postprocess_response( $response_block )
                         {
                             $response = isset( $response_block->update_data ) ? $response_block->update_data : '';
                             
                             if ( is_object( $response ) && ! empty ( $response ) )
                                 {
                                     //include slug and plugin data
                                     $response->slug    =   $this->slug;
                                     $response->plugin  =   $this->plugin;
                                     
                                     //if sections are being set
                                     if ( isset ( $response->sections ) )
                                        $response->sections = (array)$response->sections;
                                     
                                     //if banners are being set
                                     if ( isset ( $response->banners ) )
                                        $response->banners = (array)$response->banners;
                                       
                                     //if icons being set, convert to array
                                     if ( isset ( $response->icons ) )
                                        $response->icons    =   (array)$response->icons;
                                     
                                     return $response;
                                 }
                             
                             return FALSE;
                             
                         }

                }
             
             
        function WOO_SLT_run_updater()
             {
             
                 $wp_theme_auto_update = new WOO_SLT_CodeAutoUpdate( WOO_SLT_APP_API_URL, WOO_SLT_THEME_SLUG );
                 
                 // Take over the update check
                 add_filter('site_transient_update_themes',                                        array($wp_theme_auto_update, 'check_for_theme_update'));
                 
                 // Take over the Plugin info screen
                 add_filter('theme_api',                                                          array($wp_theme_auto_update, 'theme_api_call'), 10, 3);
             
             }
        add_action( 'after_setup_theme', 'WOO_SLT_run_updater' );
    

Read more

By woocommerce-sl, on , posted on May 28, 2024

The WooCommerce Software License plugin is an essential tool for licensing downloadable software and applications. It offers a comprehensive solution for integrating a licensing system with your code, ensuring secure and efficient management of software licenses.

This plugin package comes with a sample integration code that demonstrates all the main features, including license activation, deactivation, and status verification on the server side. These capabilities make it easy to implement and manage licensing for your products, providing a seamless experience for both developers and end-users. (more…)

Read more