Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Netlicensingclient Php Laravel Package

labs64/netlicensingclient-php

A PHP SDK for the Labs64 NetLicensing API, letting you manage products, licenses, customers, and entitlements programmatically. Easily add flexible licensing and entitlement checks to any PHP application.

Deep Wiki
Context7

Getting Started

Install the client (it is a plain library — no Laravel service provider or facade is auto-discovered):

composer require labs64/netlicensingclient

Before writing code, create the objects you will reference from PHP in the NetLicensing UI: a product (with its number), one or more license templates (the actual licensing models/modules), and an API key under your account. Those numbers are configuration, not something the client generates for you.

Read these classes first:

  • NetLicensing\Context — credentials, base URL, security mode
  • NetLicensing\Client — every API operation (getProduct, createLicensee, validate, createToken, …)
  • NetLicensing\ValidationParameters / ValidationResult — the hot path for entitlement checks
  • NetLicensing\Product, Licensee, License, LicenseTemplate, Token, PaymentMethod, Transaction — thin attribute bags

The first useful call is a server-side validation for an existing licensee:

use NetLicensing\Context;
use NetLicensing\Client;
use NetLicensing\ValidationParameters;

$context = new Context(
    config('services.netlicensing.username'),
    config('services.netlicensing.password'),
    null,
    Context::DEFAULT_BASE_URL,
    Context::BASIC_AUTHENTICATION
);
$client = new Client($context);

$params = new ValidationParameters();
$params->setProductNumber(config('services.netlicensing.product_number'));
$params->setLicenseeNumber($user->netlicensing_licensee_number);

$result = $client->validate($params);

if ($result->getValid() === 'true') {
    // entitlement granted
}

For production use API-key auth instead of a human login (Context::API_KEY, empty username/password). Note the === 'true' — valid comes back as a string (see Gotchas).

Implementation Patterns

Bind the client as a container singleton. Keep credentials in config/services.php and build one Context/Client per process:

// AppServiceProvider::register()
$this->app->singleton(Client::class, function () {
    $context = new Context();
    $context->setApiKey(config('services.netlicensing.api_key'));
    $context->setBaseUrl(config('services.netlicensing.base_url'));
    $context->setSecurityMode(Context::API_KEY);

    return new Client($context);
});

Constructor-argument and setter styles have both existed across majors; use whichever your installed tag exposes.

Provision a licensee at registration. Create the licensee once, store its number on your users table, and use it for every later call. Do not use the email as the number:

$licensee = new NetLicensing\Licensee();
$licensee->setProductNumber(config('services.netlicensing.product_number'));
$licensee->setName($user->email);
$licensee->setActive('true');

$licensee = $client->createLicensee($licensee);

$user->update(['netlicensing_licensee_number' => $licensee->getNumber()]);

Attach licenses through templates. A licensee alone grants nothing until a license referencing a license template is created:

$license = new NetLicensing\License();
$license->setLicenseeNumber($licenseeNumber);
$license->setLicenseTemplateNumber($templateNumber);
$license->setActive('true');

$client->createLicense($license);

Wrap the client behind a small gateway. The client is concrete and network-bound, so hide it behind an interface you can fake in tests and cache in front of:

interface LicenseGateway
{
    public function isValid(string $licenseeNumber, ?string $module = null): bool;
}

Implementation with caching:

public function isValid(string $licenseeNumber, ?string $module = null): bool
{
    $key = "netlicensing:{$licenseeNumber}:".($module ?? 'all');

    return Cache::remember($key, now()->addMinutes(15), function () use ($licenseeNumber, $module) {
        $params = new ValidationParameters();
        $params->setProductNumber(config('services.netlicensing.product_number'));
        $params->setLicenseeNumber($licenseeNumber);
        if ($module) {
            $params->setProductModuleNumber($module);
        }

        return $this->client->validate($params)->getValid() === 'true';
    });
}

Use it in middleware or a Gate. Check the gateway in a EnsureLicense middleware for premium routes, or in a Gate ability so Blade/controllers can use @can. Keep the call site boolean — don't leak ValidationResult into controllers.

Token-based validation for devices. For desktop/mobile/IoT clients that cannot hold your API key, issue a token server-side and have the device validate anonymously:

$token = new NetLicensing\Token();
$token->setTokenType('APIKEY');
$token->setProductNumber($productNumber);
$token->setLicenseeNumber($licenseeNumber);
$token->setActive('true');
$token = $client->createToken($token);

return $token->getToken(); // treat as a secret

The device then validates with Context::ANONYMOUS and ValidationParameters::setToken(...).

Payment/transaction flows. For paid licenses, the pattern is: create a PaymentMethod for the licensee, create a Transaction referencing it and a source, then create the License with the transaction number. Drive this from a queued job or a webhook handler so the checkout request doesn't block on two or three API round trips.

Testing. Bind a fake LicenseGateway in the test container rather than mocking the concrete client:

$this->app->instance(LicenseGateway::class, new FakeLicenseGateway(valid: true));

If you must test the wrapper itself, inject a Guzzle MockHandler into a Client built for tests and assert that entity attributes are serialized correctly.

Gotchas and Tips

  • getValid() returns the string 'true'/'false'. if ($result->getValid()) is always true. Always compare === 'true' or cast deliberately.
  • Booleans are strings on the wire. Set active as 'true'/'false'; the same applies to other boolean attributes. Passing real booleans works in some versions and silently serializes wrong in others.
  • number vs licenseeNumber/productNumber. Product and Licensee use setNumber(); child entities (License, Token, PaymentMethod) reference parents via setLicenseeNumber()/setProductNumber(). Mixing these up produces 400 Entity reference not found.
  • Pick the right security mode. Basic auth wants username/password; API-key auth wants the key and empty credentials; anonymous validation requires a token and will 401 without one. A mismatched mode is the usual cause of unexplained 401s.
  • API errors hide in infos. Guzzle throws ClientException/ServerException on 4xx/5xx, while the wrapper may throw NetLicensingException. In both cases the useful reason is in the response body's infos array — decode it before logging, or your logs will just say "400 Bad Request".
  • Deletes cascade. Deleting a product removes its templates, licenses, and licensees. Deactivate with active=false (or updateLicense) instead of deleting, especially for churn.
  • Validation is a network call. Don't call it on every request. Cache per licensee with a short TTL, but accept that revocation is only visible after the TTL expires — size the TTL to your billing semantics, and provide a cache-bust path for support.
  • No timeout knob on the client surface. If Context/Client doesn't let you inject a Guzzle client in your version, keep validation out of latency-critical paths or wrap it with your own timeout/retry guard.
  • License templates come from the UI. You cannot create a working license template purely from PHP without a configured licensing model; seed template numbers via config after setting up the product in NetLicensing.
  • Version skew matters. Older tags target Guzzle 5/6 and PHP 5.6; modern Laravel needs the current major. If Composer resolves an old tag, run composer why-not labs64/netlicensingclient <version> to see the conflict.
  • Self-hosted NetLicensing? Point the base URL at your instance's /core/v2/rest endpoint. A trailing segment missing here yields 404s that look like auth failures.
  • Treat licensee numbers and device tokens as data, not identifiers you derive. Store them in dedicated columns, exclude tokens from logs and serialized models, and deactivate them when a user or device is removed.
  • Expiration times are UTC. Parse with Carbon::parse() and compare in UTC; don't assume the app timezone.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource