Lizenzierung¶
Plugin- und Template-Lizensierung (ab Shop 5.0.0)¶
Voraussetzung:
Als Erstes müssen Sie Ihr neues Plugin/Template im JTL-Kundencenter anlegen und eine EsxID
für dieses
Plugin/Template generieren.
Loggen Sie sich hierzu in Ihr Kundencenter in den Bereich Erweiterungen verwalten ein und legen Sie dort eine neue Erweiterung des gewünschten Typs (JTL-Shop 5 Plugin oder JTL-Shop 5 Template) an. (Bitte Beachten Sie, dass Sie das Onboarding für Seller durchlaufen haben müssen, um Ihre Plugins und Templates im JTL-Extension Store anbieten zu können)
Mit Erstellung der neuen Erweiterung wird auch sofort eine dazugehörige ExsID generiert.
ExsID¶
Die ExsID
tragen Sie in der info.xml
Ihres Plugins, bzw. in der template.xml
Ihres Templates, ein.
Beispiel für ein Plugin:
<?xml version="1.0" encoding="UTF-8"?>
<jtlshopplugin>
<Name>Mein Beispielplugin</Name>
<Description>Tut überhaupt rein gar nichts</Description>
<Author>Max Mustermann</Author>
<URL>https://www.example.com</URL>
<XMLVersion>100</XMLVersion>
<ShopVersion>5.0.0</ShopVersion>
<PluginID>my_example</PluginID>
<CreateDate>2020-05-18</CreateDate>
<Version>1.2.3</Version>
<ExsID>175a1eb9-1234-4f87-b0e3-63bf782d37ba</ExsID>
<Install>
<empty></empty>
</Install>
</jtlshopplugin>
Beispiel für ein Template:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Template isFullResponsive="true">
<Name>MeinTemplate</Name>
<Description>Beispiel</Description>
<Author>Max Mustermann</Author>
<URL>https://www.example.com</URL>
<MinShopVersion>5.0.0</MinShopVersion>
<Version>1.0.0</Version>
<Framework>Bootstrap4</Framework>
<Parent>NOVA</Parent>
<ExsID>175a1eb9-1234-4f87-b0e3-63bf782d37ba</ExsID>
<Boxes>
<Container Position="left" Available="1"></Container>
<Container Position="right" Available="0"></Container>
<Container Position="top" Available="0"></Container>
<Container Position="bottom" Available="1"></Container>
</Boxes>
</Template>
Falls Sie Ihr Plugin oder Template kostenlos zur Verfügung stellen wollen, sind ab hier keine weiteren Schritte erforderlich. Das Plugin ist nun über das Backend von JTL-Shop installierbar und updatebar.
Falls Sie Testlizenzen ausgestellt haben, werden Plugins mit abgelaufenen Testlizenzen automatisch deaktiviert. Produktive Lizenzen werden vom JTL-Shop niemals automatisch deaktiviert, um Darstellungfehler oder sonstige Probleme für die Kunden des betroffenen Shops zu vermeiden. Stattdessen erhält ein eingeloggter Admin im Backend regelmäßige Warnungen angezeigt, dass eine Lizenz ungültig ist. In dieser Warnung hat er dann die Möglichkeit, das entsprechende Plugin zu deaktivieren oder die Lizenz zu erneuern.
Da der JTL-Shop prinzipbedingt unverschlüsselt und quelloffen ist, sollte die Lizenzprüfung nicht als 100%iger Schutz vor Lizenzmissbrauch verstanden werden. Sollten weitere Schutzmaßnahmen gewünscht sein, so können in Eigenverantwortung weitere Überprüfungen eingebaut werden, die im Folgenden erläutert werden. Eine Verschlüsselung oder Obfuskierung des Plugincodes mit allen ihren Nachteilen für Entwickler und Kunden obliegt dann ebenso im Ermessen des Pluginentwicklers.
Die PluginID beim Updaten¶
Mit der korrekten Pflege der Plugin ID können Sie sicherstellen, dass Ihr Plugin korrekt geupdatet wird. Eine
versionsübergreifend identische Benennung der PluginID
und des dazugehörigen Installationsordners gewährleisten,
dass Plugins sich aktualisieren können.
Wenn die Benennungen der PluginID und des dazugehörigen Installationsordners zwischen 2 Versionen Unterschiede aufweisen, wird JTL-Shop keine Aktualisierung des bestehenden Plugins vornehmen, sondern eine separate Neuinstallation vornehmen, so dass am Ende 2 unterschiedliche Versionen desselben Plugins installiert sind.
Stellen Sie daher sicher, dass über alle Versionen Ihres Plugins hinweg Die PluginID
in der info.xml
, der
Installationsorder des Plugins sowie das Feld PluginID
bei der Pflege der Erweiterung im Kundencenter immer exakt
identisch benannt sind, um derartige Fehler zu vermeiden.
Lizenzprüfung¶
Für den Fall dass die Lizenz/Subscription manuell geprüft werden soll, bietet der Shop einige Möglichkeiten.
Bootstrapping¶
In der Bootstrap.php
des Plugins oder Templates kann die Methode
BootstrapperInterface::licenseExpired(ExsLicense $license): void
implementiert werden. Diese Methode wird immer dann
aufgerufen, wenn JTL-Shop auf abgelaufene Extensions prüft. Dies findet via Cronjob alle 4 Stunden statt, sowie bei
jeder Aktualisierung der Lizenzübersicht im Backend.
Getter für Plugins¶
Am License-Objekt von Plugin-Instanzen gibt es stets einen Getter für die zugehörige Lizenz.
/** @var \JTL\Plugin\Plugin $plugin */
$subscription = $plugin->getLicense()->getExsLicense()->getLicense()->getSubscription();
Getter für Templates¶
Auch an Templatemodel-Instanzen gibt es einen entsprechenden Getter.
/** @var \JTL\Template\Model $template */
/** @var \JTL\License\Struct $subscription */
$subscription = $template->getExsLicense()->getLicense()->getSubscription()
License-Manager¶
Um an beliebigen Stellen die Lizenz für eine beliebige Extension zu erhalten (insbesondere hilfreich bei "InApp Purchases") existiert der License-Manager.
$manager = new JTL\License\Manager(\JTL\Shop::Container()->getDB(), \JTL\Shop::Container()->getCache());
$subscription = $manager->getLicenseByExsID('some_exs_id');
Komplexe Beispiele¶
Die verschiedenen Möglichkeiten in der Bootstrap.php
eines (Child-)Templates zeigt das folgende Codebeispiel.
<?php declare(strict_types=1);
namespace Template\mychildtemplate;
use JTL\License\Manager;
use JTL\License\Struct\ExsLicense;
use JTL\Shop;
class Bootstrap extends \Template\NOVA\Bootstrap
{
public function boot(): void
{
parent::boot();
$this->customLicenseCheck();
$this->checkViaManager();
}
private function customLicenseCheck(): void
{
$license = $this->getTemplate()->getExsLicense();
if ($license === null) {
die('Nanu? Keine Lizenz.');
}
if ($license->getLicense()->getSubscription()->getDaysRemaining() < 14) {
echo 'Achtung! Subscription läuft bald aus!';
} elseif ($license->getLicense()->getDaysRemaining() < 14) {
echo 'Achtung! Lizenz läuft bald aus!';
} elseif ($license->getLicense()->isExpired()) {
// FALLBACK to default template
Shop::Container()->getTemplateService()->setActiveTemplate('NOVA');
die('Bitte erwerben Sie eine neue Lizenz!');
} elseif ($license->getLicense()->getSubscription()->isExpired()) {
die('Bitte erwerben Sie eine neue Subscription!');
}
}
private function checkViaManager(): void
{
$manager = new Manager($this->getDB(), $this->getCache());
$license = $manager->getLicenseByItemID('some_item_id');
if ($license !== null && $license->getLicense()->getSubscription()->isExpired()) {
// do something
}
$otherLicense = $manager->getLicenseByExsID('exsidOfAnotherPlugin');
if ($license !== null && $license->getLicense()->getSubscription()->isExpired()) {
// do something else
}
}
public function licenseExpired(ExsLicense $license): void
{
echo 'Argh! Meine Lizenz ist abgelaufen!';
// FALLBACK to default template
Shop::Container()->getTemplateService()->setActiveTemplate('NOVA');
}
}
Analog dazu funktionieren die Methoden aus der Bootstrap.php
eines Plugins. Hier besteht zusätzlich die Möglichkeit,
auch Plugins über den Aufruf von JTL\Plugin\Plugin::selfDescruct()
hart zu deaktivieren.
<?php declare(strict_types=1);
namespace Plugin\my_example;
use JTL\Events\Dispatcher;
use JTL\Plugin\Bootstrapper;
use JTL\Plugin\State;
class Bootstrap extends Bootstrapper
{
public function boot(Dispatcher $dispatcher)
{
parent::boot($dispatcher);
$license = $this->getPlugin()->getLicense()->getExsLicense();
if ($license === null || $license->getLicense()->getSubscription()->isExpired()) {
$this->getPlugin()->selfDestruct(State::EXS_SUBSCRIPTION_EXPIRED, $this->getDB(), $this->getCache());
}
}
}