License Key Plugin

The License Key plugin is something I knew I had to write once I decided to start selling my First Data payment plugin.  The FirstData plugin uses a license key to verify if the store it is running on has paid for the full use.  It does this by decrypting the license key with a secret key.  The resulting string is then a letter to indicate if it's good for a single URL or the full domain followed by the URL it's enabled for.  An example for my website would be "" which means the license is good for any subdomain of

The hassle comes in when someone decides to purchase the plugin, they expect to be able to use it right away.  They don't want to wait for me to get home from my day job so that I can create their encrypted key.  The License Key plugin solves this by subscribing to the OrderPaidEvent in NopCommerce.  Once someone completes an order that has 1 or more products that require keys, the license plugin will take their info, generate the keys, and email them immediately.  It also places them in the order notes for future reference.

I'm releasing the full source code for this plugin to the entire NopCommerce community and will explain how it works here.  You can download the plugin from it's product page here.  The plugin has 3 major areas:  The encryption key for each product, the configuration page, and generating licenses when an order is paid.

Product Key

Each plugin you will sell needs its own unique Product Key that will be used in encryption/decryption.  If you didn't use a unique key, someone could purchase Plugin A and then use the same license for Plugin B without paying you.

We handle this by subscribing to the AdminTabStripCreated event which will let you know whenever someone loads up any admin page with a tab strip. 

public void HandleEvent(AdminTabStripCreated eventMessage)
    if (eventMessage.TabStripName == "product-edit")
        ProductKeyController controller = new ProductKeyController(_productService, _genericAttributeService, _permissionService);
        string html = controller.GetProductKey();

You have to make sure you check the TabStripName because you'll get called for all tabstrips in the entire admin site.  We're calling the ProductKeyController manually which means we need to pass in its constructor arguments ourself.  It's outside of the normal MVC lifecycle so we don't get the benefit of dependency injection here.  We get the HTML and add it to the tabstrip.

public string GetProductKey()
    if (ControllerContext == null)
        ControllerContext context = new ControllerContext(System.Web.HttpContext.Current.Request.RequestContext, this);
        ControllerContext = context;

    var model = new ProductKeyModel();

    int productId = Convert.ToInt32(ControllerContext.RequestContext.RouteData.Values["id"]);
    var product = _productService.GetProductById(productId);
    model.ProductKey = product.GetAttribute(Constants.LicenseKeyAttribute); return this.RenderPartialViewToString("BitShift.Plugin.Misc.Licenses.Views.EditProductKey", model); } 

Since the ControllerContext will most likely not be loaded, we need to nudge it along.  We'll also figure out what our product id is based on the RouteData in the URL.  After that it's just a matter of looking up what our existing product key is for this product and passing it to the View.  Since we are returning the View as a string instead of ActionResult, we use the RenderPartialViewToString method.

@model BitShift.Plugin.Misc.Licenses.Models.ProductKeyModel

<table class="adminContent">
        <td class="adminTitle">
            @Html.NopLabelFor(model => model.ProductKey):
        <td class="adminData">
            @Html.EditorFor(model => model.ProductKey)
            <span id="licensekey-save" class="t-button">@T("Admin.Common.Save")</span>
            <span id="licensekey-message" style="color:#009900"></span>

<script type="text/javascript">
    $(document).ready(function () {
        $("#licensekey-save").click(function () {
            var model = {id: $("#Id").val(), productKey: $("#ProductKey").val() };
            $.post("@(Url.RouteUrl("Plugin.Misc.Licenses.SaveKey"))", model, function() {

The View is pretty simple.  It's just a single field for our ProductKey and then a jQuery function to post it back to our ProductKeyController when we want to save it. 

public void SaveKey(int id, string productKey)
    if (!_permissionService.Authorize(StandardPermissionProvider.ManageProducts))

    var product = _productService.GetProductById(id);
    _genericAttributeService.SaveAttribute(product, Constants.LicenseKeyAttribute, productKey); } 

The SaveKey function just takes in the new key and adds it to the products Attributes.


To configure the plugin, you just need to determine what Product Attributes will designate your URL mode and Domain mode.  This is how the plugin will recognize what products should get a license key when they are ordered. 

This page also has a tool to create a license key manually.  You can use this for occassions where the customer makes a typo and you need to create a new key.

Generating Licenses

The meat of the plugin happens when a customer orders an item that needs a license.  The LicenseService will loop through all of the OrderItems and determine if any use our Url or Domain attributes.  If they do, it will pull the value the customer entered and the ProductKey for that product and encrypt them together to create the license key.  If there is at least 1 license key generated, they will be added to the OrderNotes and also email directly to the customer using a MessageTemplate that was created when the LicenseKey plugin was installed.

A future blog post will detail how your other plugins should decrypt the license key and verify that is valid for where they are installed.

Leave your comment
10/10/2013 1:28 PM

This was just what I needed, I have modified your excellent plugin a little to allow me to offer free trial key's.

I can now offer time limited keys as well as full version key's  

Thank you for offering your code as open source.