Release notes SKM Client API (v.4.0.1)
For current users
There are many significant changes since the previous release. First of all, we've made
Web API 3 the primary layer of communication, thereby avoiding Web API 2 in all aspects.
However, you can still upgrade to this version of SKGL Extension (or SKM Client API),
as it still has support for Web API 2. If you've already used the Web API 3 (eg. ExtendLicense,
AddFeature methods), you will have to change your code a little bit. For example, before we had
the methods in the same class, i.e. SKM
class. Now, however, there are three separate classes:
Key
, Product
, and Data
. In addition, we've completely removed the AuthDetails
;
instead you only need to specify the token string. Shortly:
We have taken everything we've learned from user feedback (pros and cons), combined it with Web API 3, with the aim to make implementation very simple and time inexpensive.
So, even if you don't want to change now, please go ahead and check the examples below!
Access tokens
This is a new concept in the Web API that it is important to get used to.
Web API 3 provides a new powerful way of communicating with SKM. Instead of having different access levels (where permission is given on a global level), Web API 3 provides a uniform way of authentication and authorization.
Please read more here: https://serialkeymanager.com/docs/api/v3/auth
Three concepts
In the new version of SKM API, we essentially mimic the Web API 3. There are three main groups of methods: Key Methods, Data Object Methods, and Product Methods. In addition, there is also a group called Auth Methods, but it's only used to improve security in specific use cases.
Each of the three categories of methods work with a certain object. For example, Key Methods 'work' with a LicenseKey object, so it is natural to find methods such as Activation, AddFeature, etc, in that group, since all of the methods affect a license key. Similar can be said about the remaining groups.
Fortunately, you will most likely not need to use these methods right away (they are located in SKM.V3.Methods
).
Instead, you will use methods that are associated with the object. In this way, many things will be abstracted away.
License Key
In most scenarios, this will be enough for a simple licensing solution. To access this object, you need to include
SKM.V3
. We can do things like blocking the license, adding features, activating, and more.
Data Object
A data object can be thought of as an additional variable that we can associate with a key, a product or our entire account. For example, it might be the customer name, the number of times a certain feature has been used, etc. In the latter case, we can, for instance, set up a scenario where a certain license key may only be used say 300 times. Each time it is used, we decrement the counter until a value is reached. For old SKM users, this is the same as the OptionalField.
Product
A product is a container of license keys. At this point, there is little support for product operations, as they are not essential in most of the use cases.
Examples
Get license information
Let's suppose that you've created a new product and your first license key at skmapp.com. There are three things you need to be able to access the license key in your application:
- The product id: you can find it here, by
selecting it from the list and then looking in the ProductId parameter, eg.
3349
. - The key string, eg.
LEPWV-FOTPG-MWBEO-FBFPS
. - An access token that has the GetKey permission, eg.
WyIxNzIiLCJhak9OT1g3NW90YlQyRFFVUzBWdnlGSHJYdUpMdDA0REMxNzNOa2duIl0=
. You can generate a new access token here.
The simplest way to get license key data is by using Refresh
that each license key object has.
string token = "{an access token with GetKey permission}";
string key = "LEPWV-FOTPG-MWBEO-FBFPS";
var license = new LicenseKey { ProductId = 3349, Key = key };
if(!license.Refresh(token))
// could not refresh. check the permissions. It's GetKey, not GetKeys!
Now, all the missing fields will be replaced with the ones found in the SKM platform. If this is not intuitive,
you can also use Key.GetKey
found in the SKM.V3.Methods
. But the solution above is better, right?
Checking properties
Another common task is to check the license key details and decide whether some features in the
application should work or not. To solve this, we have extension methods (located in SKM.V3
namespace).
Let's reuse the variable license
from the example above. We will check that feature 1 is set to true,
and that it has not expired.
if(license.HasFeature(1)
.HasNotExpired()
.IsValid())
{
// do something
}
else
{
// invalid license.
}
There are many methods, such as HasFeature()
, HasNotFeature()
, HasNotExpired()
, IsOnRightMachine()
,
IsBlocked()
, IsNotBlocked()
, HasValidSignature()
. These allow you to express complex logic using
simple terms. However, to decide whether it is true or not (eg. satisfied), we need to call the
IsValid()
method in the end.
Storing a license key in a file
There are many ways to store a license key on the client device. If this scenario is used, it's recommended to store a signed version of the license key object. SKM Client API comes with methods to achieve this task, but you can also use Settings variables to store this information. Please read the following articles at MSDN:
- Creating a new setting - you need one only, eg. to store a LicenseKey object.
- Writing to a setting - after activation/refresh, you would store the result inside the setting
- Reading a setting - when user restarts the application, you can use this setting to reload the license key object.
The alternative is to use the LoadFromFile
and SaveToFile
methods. Let's assume we keep the
license key object declared previously.
In order to save the object:
license.SaveToFile()
And, once you've restarted the app, simply run:
license.LoadFromFile()
If you plan to have many license key objects, you could also specify a unique name for each of them. Once again, please sign them if you plan to use this use case.
Activating a device
Key activation is the central method that empowers licensing solutions. The core idea is:
Key Activation is a way to restrict the usage of a license key to a limited amount of devices (aka machines)
The opposite of activation is deactivation.
SKM's activation method is very configurable as to support as many use cases as possible. Below, we will only focus on the simple use case, that is, only use the hardware lock feature.
Assuming that you've created a key in the SKM platform that has maximum number of machines set to anything greater than zero, we can run the following code:
var auth = "{access token with permission to access the activate method}"
var result = Key.Activate(token: auth, parameters: new ActivateModel()
{
Key = "GEBNC-WZZJD-VJIHG-GCMVD",
ProductId = 3349,
Sign = true,
MachineCode = SKGL.SKM.getMachineCode(SKGL.SKM.getSHA1);
});
if(result == null || result.Result == ResultType.Error)
{
// an error occured or the key is invalid or it cannot be activated
// (eg. the limit of activated devices was achieved)
}
// everything went fine if we are here!
This will activate the license key with the current device id, i.e. SKM.getMachineCode(SKM.getSHA1);
.
Once the key has been activated on more than 10 devices, the license won't be usable unless the
machine code is deactivated. A simple use case where this is used is as follows:
Suppose a customer of yours purchases access to your software to be used on 10 computers/tablets/apps). You only need to give them one key with the maximum number of machines set to 10 and use the code above.
Floating licenses
Now that we know about activation, the only piece of information we need is how to use the deactivation method. Let's start by defining a problem:
Imagine you want your customers to be able to use your application on 10 devices at once. That is, they may have the software installed on 100 devices, but they can only use it on 10 of them at the same time.
We can achieve this by activating the license key during start up and deactivate when the application closes or releases the license in another way.
Application start
When the application starts, you would run:
var auth = "{access token with permission to access the activate method}"
var result = Key.Activate(token: auth, parameters: new ActivateModel()
{
Key = "GEBNC-WZZJD-VJIHG-GCMVD",
ProductId = 3349,
Sign = true,
MachineCode = SKGL.SKM.getMachineCode(SKGL.SKM.getSHA1);
});
if(result == null || result.Result == ResultType.Error)
{
// an error occured or the key is invalid or it cannot be activated
// (eg. the limit of activated devices was achieved)
}
// everything went fine if we are here!
Application closes
Once the application is about to close, could run the following:
var auth = "{access token with permission to access the deactivate method}"
var result = Key.Deactivate(token: auth, parameters: new DeactivateModel()
{
Key = "GEBNC-WZZJD-VJIHG-GCMVD",
ProductId = 3349,
MachineCode = SKGL.SKM.getMachineCode(SKGL.SKM.getSHA1);
});
if(result == null || result.Result == ResultType.Error)
{
// could not deactivate. maybe it has already been deactivated.
// more information can be found in the message.
}
// everything went fine if we are here!
What happens if the application crashes
Imagine a very hypothetical example: the application crashes on all of the 10 computers, leaving
all the others not being able to access the license key. In this case, we can grab a machine code
from the list in license.ActivatedDevices
and remove it from the list (by deactivating). Since each activation
has a timestamp, we could check which activation is the oldest one. In this case, we could ask the user
if it is ok to deactivate that device. If this solution is chosen, keep in mind that it is important
to check periodically whether the license key can be activated (i.e. execute the start up code), as to
ensure that the limit has not been reached while the application was open.
Custom variables (aka Data Objects)
There many interesting things you can do with data objects. The simplest case would be to just store additional data such as the customer name, email, etc. However, thanks to the specialized methods, we can, for instance, set up a usage quote:
Image you distribute trial keys and you want to restrict the number of times a certain feature can be used. Let’s assume that you’ve developed the application below, and you want your trial users to be able to record 10 videos at most.
The code below can achieve that:
var token = "{acesstoken to GetKey, IncrementIntValue, ListDataObjects, AddDataObjects, and Key Lock = -1 (or zero)}".
var license = new LicenseKey { ProductId = 3349, Key = "GEBNC-WZZJD-VJIHG-GCMVD" };
if(!license.Refresh(token))
// could not refresh. check the permissions. It's GetKey, not GetKeys!
if(license.DataObjects.Contains("usagecount"))
{
// attempt to increment. true means we succeed.
var dataObj = license.DataObjects.Get("usagecount");
if (dataObj.IncrementIntValue(token: token,
incrementValue: 1,
enableBound: true,
upperBound: 10))
{
// success, we can keep using this feature
}
else
{
// fail, the the user has already used it 10 times.
}
}
else
{
// if it does not exist, add a new one.
license.AddDataObject(tokenDObj, new DataObject { Name = "usagecount", IntValue = 0 });
}
Please keep in the following:
To make this safer, please start at the
Int.MinValue
(i.e. instead of0
). The new upper bound will beInt.MinValue+10
. This is to ensure that if the access token for creating new data objects would leak out, it won't give the unauthorized party the ability to extend the usage of a particular feature. Alternatively, you can create the data object at the same time as key generation (i.e. unavailable to the user).