Licensing

If you like to charge customers for your app, you need to implement some kind of software licensing mechanism and sell the licenses. This article describes the different options that you have.

If you distribute your app on the innovaphone App Store, you need to specify which option your app uses.

Content

innovaphone licensing model
Paid apps that use the same per-user licenses as the innovaphone apps. The licenses are sold by innovaphone.
Your own licensing model
Paid apps using your own licenses.
Free apps
Free apps that do not require a license.

innovaphone licensing model

Overview

License types App and Service

In most cases a license of type App can be used to implement a per user licensing scheme - an App License for specific App can be enabled on a PBX user and a check in the App Service and in the App running in the myApps cleint can be performed.

The license of a type Service can be used to assign some specific number of licenses to an App Service via the parameter Licenses on the App Object. A check of the amout of licenses granted can be performed in the App Service.

Naming scheme

A license refers to a single app. If your app service provides multiple apps, they are licensed individually.

The license name contains the name of the HTML file of the app without the extension. So your HTML file name must be unique and follow the scheme manufacturer-appname.htm.

Example: Switchbard by innovaphone

HTML file: innovaphone-switchboard.htm
License name: App(innovaphone-switchboard)

Example: Calculator by ACME

HTML file: acme-calculator.htm
License name: App(acme-calculator)

Example: Conference by ACME

HTML file: acme-conference.htm
License name: Service(acme-conference)

Checking the license

The actual license check for the license type App is done by the PBX when a user requests a login for your app. The following conditions must be met that the PBX marks the login as licensed:

The information if the user got a license is then transmitted to the app as part of the login. This is done using the unlicensed property in the info object of the AppLogin message. The structure is protected by the login digest.

In the client JavaScript code of your app, you can check the App license after an AppWebsocket connection is established by accessing the property unlicensed (no check for Service license available here):

var app = new innovaphone.appwebsocket.Connection(start.url, start.name);
app.onconnected = app_connected;

function app_connected(domain, user, dn, appdomain) {
    if (app.logindata.info.unlicensed) {
        // unlicensed mode
    }
    else {
        // licensed mode
    }
}

In the C++ code of an app service, you can do the same check on incoming AppWebsocket connections. Note that you might need to distinguish between the connections from different apps.

bool NewApp1Session::AppWebsocketConnectComplete(class json_io & msg, word info)
{
    bool unlicensed = msg.get_bool(info, "unlicensed");

    if (app && !strcmp(app, "manufacturer-newapp1")) {
        if (unlicensed) {
            // unlicensed mode
        }
        else {
            // licensed mode
        }
    }
    else if (app && !strcmp(app, "manufacturer-newapp1admin") {
        // no license needed
    }
    
    // amount of Service licenses 
    int licenses = msg.get_int(info, "lics");
    
    return true;
}

In the JavaScript code of an app service you can check the JsonApiConnection.unlicensed attribute of the AppWebsocket connection from the myApps client to the app service. Note that you might need to distinguish between the connections from different apps.

new JsonApi("test").onconnected(function(conn) {
    if (conn.app === "manufacturer-newapp1") {
        if (conn.unlicensed) {
            // unlicensed mode
        }
        else {
            // licensed mode
        }
    }
    else if (conn.app === "manufacturer-newapp1admin") {
        // no license needed
    }

    // amount of Service licenses
    var licenses = conn.lics;
});

It is also possible to check if a specific user object has a valid specific app license assigned. This check require access to the PbxAdminApi in order to use message CheckAppLic for this purpose. This must be done on the AppWebsocket connection from the PBX to the app service, therefore PbxApi library of the JavaScript environment is used.

new PbxApi("PbxAdminApi").onconnected(function (conn) {
    conn.send(JSON.stringify({ api: "PbxAdminApi", mt: "CheckAppLic", cn: "Atlantis", lic: "App(manufacturer-newapp1)" }));

    conn.onmessage(function (msg) {
        var obj = JSON.parse(msg);

        if (obj.mt === "CheckAppLicResult") {
            if (obj.ok === true) {
                // licensed mode
            } else {
                // unlicensed mode
            }
        }
    }

});

Unlicensed mode

It's up to you, what your app does without a license. Some ideas:

Other license checks

Depending on license requirements other license information available form the PBX can be used, like overall number of Port Licenses. The messages GetPbxLicenses and GetAppLics are a good starting point to implement a custom license requirement.

Your own licensing model

If you don't want to use the innovaphone licensing model, you can use your own one. In that case you need to sell and check the licenses yourself.

Note: Your app must ignore the unlicensed attribute in the info object of the AppLogin message. It will always be true, as the PBX does not find an innovaphone app license for the user.

Free apps

If your app is for free, you don't need to do something special.

Note: Your app must ignore the unlicensed attribute in the info object of the AppLogin message. It will always be true, as the PBX does not find an innovaphone app license for the user.