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

Smartcode Bundle Laravel Package

intracto/smartcode-bundle

Symfony bundle for generating unique, human-friendly codes such as vouchers, coupons, or activation keys. Configure character sets, length, and patterns, then generate codes in PHP services or directly in Twig templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: it is a Symfony bundle, not a Laravel package. There is no SmartCodeServiceProvider, no config/smartcode.php, and Laravel's package discovery will ignore it. composer require intracto/smartcode-bundle in a Laravel app will install the code but nothing will be wired up. Plan for one of two shapes:

  1. A tiny Symfony service (recommended) — a 50-line Symfony 6 app exposing POST /licenses and POST /licenses/verify, called from Laravel over HTTP. Keeps the bundle in its natural habitat and isolates the licensing secret from your app servers.
  2. Vendor the algorithm — the bundle is MIT, so you may legally copy the core signing/verification classes into app/Support/Licensing/ and drop the Symfony DependencyInjection/ and Resources/config/ folders. Do this only if the underlying intracto/smartcode logic is a single self-contained class — read the source before committing.

Minimal steps for the Symfony route:

composer require intracto/smartcode-bundle
// config/bundles.php
Intracto\SmartCodeBundle\SmartCodeBundle::class => ['all' => true],

Generate the keypair before anything else — the private key signs the payload into a license string, the public key verifies it and is the only half that ships with the licensed software:

openssl genrsa -out config/licenses/private.pem 4096
openssl rsa -in config/licenses/private.pem -pubout -out config/licenses/public.pem

Then look at the source before writing config. With 4 stars and 0 dependents there is no README you can trust and no blog posts to copy. Do this in order:

vendor/intracto/smartcode-bundle/DependencyInjection/Configuration.php   # the real config tree
vendor/intracto/smartcode-bundle/Resources/config/services.xml          # the real service IDs
bin/console debug:config smart_code
bin/console debug:container --show-private | grep -i smartcode

Your first use case should be the narrowest one that proves the round trip: sign a single string (a domain, e.g. acme.example.com), verify it in a second process that has only the public key, and print valid/invalid. Do not build an issuance endpoint until that round trip works, because most failure modes in this package are key-format problems, not logic problems.

Implementation Patterns

Separate the issuer from the verifier at the process level, not just the class level. The whole security model collapses if the private key path is reachable from the licensed application. In Laravel terms: the private key lives in the license server's .env/secrets manager; the public key is a constant baked into the distributed customer artifact. Never put the private key in the app that ships to customers, and never let it appear in a Laravel config cache dump.

Issuance endpoint (Symfony side) — keep the payload canonical:

#[Route('/licenses', methods: ['POST'])]
public function issue(Request $request, LicenseIssuer $issuer): JsonResponse
{
    $payload = $request->toArray()['payload'];   // e.g. ['domain' => 'acme.example.com', 'tier' => 'pro']
    ksort($payload);                             // canonical ordering is on you
    $payload = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);

    return $this->json(['license' => $issuer->generate($payload)]);
}

Laravel-side client — wrap it, don't scatter it:

// app/Services/Licensing/LicenseClient.php
final class LicenseClient
{
    public function issue(array $payload): string
    {
        $payload = Arr::sortRecursive($payload);

        return retry(3, fn () => Http::baseUrl(config('services.licensing.url'))
            ->timeout(5)
            ->post('/licenses', ['payload' => $payload])
            ->throw()
            ->json('license'), 200);
    }
}

Verification belongs in a middleware, not in a controller. Offline verification is cheap (one signature check), so it can run per-request on the license-bound endpoints, but cache the result for the request lifetime:

// app/Http/Middleware/EnsureValidLicense.php
public function handle(Request $request, Closure $next)
{
    $license = config('licensing.key');
    $expected = ['domain' => $request->getHost(), 'tier' => config('licensing.tier')];

    if (! app(LicenseVerifier::class)->verify($license, Arr::sortRecursive($expected))) {
        abort(403, 'Invalid or mismatched license');
    }

    return $next($request);
}

Bind the payload to something that changes with the customer. A license with an empty or constant payload is a license you have given to the entire internet. Domain, instance UUID, tier, and an expiry timestamp are the useful fields. Including expiry lets you do time-limited trials without implementing revocation.

Version the payload schema. {"v": 1, "domain": ...} costs nothing now and lets you add fields later without invalidating every license already issued. Without it, every payload change is a mass re-issue event.

Store issued licenses as rows, not as a blob on the customer record. A licenses table (id, customer_id, payload_json, license_string, issued_at, revoked_at) gives you re-issue, audit, and a manual revocation path even though the algorithm itself is offline-only.

Gotchas and Tips

  • Key format is the #1 failure. OpenSSL 3 emits PKCS#8 (BEGIN PRIVATE KEY); older PHP/phpseclib paths expect PKCS#1 (BEGIN RSA PRIVATE KEY). If signing throws, convert with openssl rsa -in private.pem -traditional -out private-pkcs1.pem and retry before you debug anything else.
  • Payload serialization must be byte-identical between sign and verify. json_encode key order, trailing newlines, float formatting (1.0 vs 1), and unicode escaping all change the bytes and invalidate the signature. ksort + JSON_UNESCAPED_SLASHES on both sides, or the license fails only for some customers and you'll chase it for a week.
  • Encoding is almost certainly base64 of a binary signature. Base64 contains + and /; if the license travels through a URL path, a query string, or an email client, it will be mangled. Use base64url or transport it in a JSON body, and validate the string round-trips locally before shipping.
  • Maintenance risk is real. Last release March 2023, 4 stars, 0 dependents. Check composer.json for the symfony/framework-bundle constraint — it likely pins ^5.4|^6.0 and will fight a modern Symfony. Pin the bundle version and treat upgrades as a manual project, not a composer update.
  • It is not a licensing system. This generates and verifies signed strings. There is no revocation, no seat counting, no activation server, no expiry enforcement — expiry only works if the verifying app compares the payload timestamp to its own clock, and a user can move that clock. Pair it with a periodic online check-in if you need hard revocation.
  • The public key is public. Anyone can read it out of your binary and verify licenses and craft payloads that verify — but not sign new ones. That asymmetry is the point; don't add a "secret" check in the client that assumes otherwise.
  • Debug by isolating the layers. Log the exact payload bytes, the exact license string, and the raw signature; then verify with a standalone openssl dgst -verify call outside PHP. If OpenSSL succeeds and the bundle fails, the bug is in your payload serialization, not in cryptography.
  • Extension point to look for: whether the bundle exposes a signer/validator interface you can implement, versus a concrete class. If it's a concrete class bound in services.xml, you can override the service definition in your Symfony app's services.yaml to swap in your own implementation (e.g. Ed25519 instead of RSA) without forking. That is the cleanest escape hatch when RSA-4096 signatures make your license strings unmanageably long.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core