Skip to content

Configuration

After publishing the config file with php artisan vendor:publish --tag=tashil-config, you'll find everything in config/tashil.php. This page walks through each section in plain language. You can ignore all of it to start — the defaults are production-sensible — and return when you need to change something specific.

Database

Controls where Tashil's tables live and what they're called.

config/tashil.php
'database' => [
    // null = use your app's default connection. Set a named connection
    // (defined in config/database.php) to isolate Tashil on its own DB.
    'connection' => env('TASHIL_DB_CONNECTION', null),
 
    // Prepended to every table name below.
    'prefix' => 'tashil_',
 
    // Rename individual tables only if you have a naming conflict.
    'tables' => [
        'packages'              => 'packages',
        'features'              => 'features',
        'package_feature'       => 'package_feature',
        'subscriptions'         => 'subscriptions',
        'subscription_features' => 'subscription_features',
        'feature_usages'        => 'feature_usages',
        'usage_logs'            => 'usage_logs',
        'subscription_events'   => 'subscription_events',
        'invoices'              => 'invoices',
        'transactions'          => 'transactions',
    ],
],

Isolating Tashil on its own database

Set TASHIL_DB_CONNECTION=tashil and define a matching connection in config/database.php. Every model, repository, and the migration honor this connection — so you can keep billing data on a separate schema or server without touching any code.

Billing model

The single most important setting. activate_on_payment decides whether a newly created priced plan grants access immediately or only after its first invoice is paid.

config/tashil.php
'billing' => [
    // The CREATION-TIME default for a package's `requires_payment` flag.
    // true  (default) → new priced plans subscribe as `Pending` and gain
    //                   access only when the first invoice is paid.
    // false           → new plans use the legacy "access first, bill later".
    'activate_on_payment'      => env('TASHIL_ACTIVATE_ON_PAYMENT', true),
 
    // Due window (days) for the initial invoice of a gated subscription.
    'initial_invoice_due_days' => env('TASHIL_INITIAL_INVOICE_DUE_DAYS', 1),
 
    // Skip issuing a proration invoice below this amount (avoids dust invoices).
    'min_proration_amount'     => env('TASHIL_MIN_PRORATION', 0.50),
],

This is a creation-time default, not a runtime switch

activate_on_payment only seeds a package's requires_payment flag when the package is created and you didn't set it explicitly. At runtime, the package's own stored flag is authoritative. Flipping this config later affects only packages created afterward — existing rows keep their flag. See Billing Lifecycle for the full reasoning.

Trials

config/tashil.php
'trial' => [
    // How many days before trial_ends_at to dispatch the TrialEnding event.
    'warn_days'  => env('TASHIL_TRIAL_WARN_DAYS', 3),
 
    // Optional grace window after a trial expires (your app enforces it).
    'grace_days' => env('TASHIL_TRIAL_GRACE_DAYS', 0),
],

See Trials for the full lifecycle.

Renewal

What happens when a renewal comes due but a previous invoice is still unpaid.

config/tashil.php
'renewal' => [
    // Policy when an unpaid invoice already exists at renewal time:
    //   'cancel'       → grace-cancel the subscription (default)
    //   'skip'         → do nothing, retry next run
    //   'extend_grace' → push current_period_end forward and try again
    'on_pending_invoice'   => env('TASHIL_RENEWAL_ON_PENDING_INVOICE', 'cancel'),
 
    // Days added when policy is 'extend_grace'.
    'grace_days'           => env('TASHIL_RENEWAL_GRACE_DAYS', 3),
 
    // Cap on 'extend_grace' pushes — stops an unpaid invoice from
    // extending access forever.
    'max_grace_extensions' => env('TASHIL_RENEWAL_MAX_GRACE_EXTENSIONS', 3),
],

Dunning

The failed-payment recovery cycle. Tashil owns the state machine and schedule; your app performs the actual retry charge by listening to the events it fires.

config/tashil.php
'dunning' => [
    // Run the dunning lifecycle (tashil:process-dunning).
    'enabled'                    => env('TASHIL_DUNNING_ENABLED', true),
 
    // Days after due_date at which each retry milestone fires.
    'retry_days'                 => [1, 3, 5],
 
    // Suspend (cut access) once the attempt count reaches this.
    'suspend_after_attempts'     => env('TASHIL_DUNNING_SUSPEND_AFTER', 3),
 
    // Expire a still-unpaid suspended subscription this many days later.
    'cancel_after_suspend_days'  => env('TASHIL_DUNNING_CANCEL_AFTER', 7),
 
    // Soft dunning: keep access during the PastDue retry window.
    // Suspended never has access regardless of this flag.
    'keep_access_while_past_due' => env('TASHIL_PASTDUE_KEEP_ACCESS', true),
],

The escalation path:

Active
PastDue
Suspended
Expired

Read the full walkthrough in Billing Lifecycle.

Scheduler

config/tashil.php
'schedule' => [
    // Set false to skip auto-registration and wire commands yourself.
    'enabled'   => env('TASHIL_SCHEDULE_ENABLED', true),
 
    // Override the cron expression per command.
    'overrides' => [
        // 'tashil:expire-trials' => '*/15 * * * *',
    ],
],

See Scheduler & Jobs for every command and its default cadence.

Events

config/tashil.php
'events' => [
    // When true (default), domain events dispatch AFTER the DB commit using
    // DB::afterCommit(), so listeners never observe a half-written state.
    'async' => env('TASHIL_EVENTS_ASYNC', true),
],

Invoice & transaction numbering

Both invoice numbers and transaction ids are stamped automatically by an observer. The format uses a small token vocabulary.

config/tashil.php
'invoice' => [
    'prefix'    => 'INV',
    'format'    => '#-YYMMDD-NNNNNN',
    'generator' => Foysal50x\Tashil\Services\Generators\InvoiceNumberGenerator::class,
],
 
'transaction' => [
    'prefix'    => 'TXN',
    'format'    => '#-YYMMDD-NNNNNNAA',
    'generator' => Foysal50x\Tashil\Services\Generators\TransactionIdGenerator::class,
],

Format tokens:

TokenMeaning
#The prefix above
YY / MM / DDYear / month / day, 2 digits each
NRandom digit (0–9)
SRandom letter (A–Z)
ARandom alphanumeric (0–9, A–Z)

For example #-YYMMDD-NNNNNN renders to INV-260522-849021. To plug in your own scheme, see Extending Tashil.

Currency

config/tashil.php
// ISO 4217 code used when creating packages and issuing invoices.
'currency' => env('TASHIL_CURRENCY', 'USD'),

Middleware aliases

The names under which Tashil's three route middleware register on boot. Set one to null to skip registering it (e.g. if the name collides with an existing alias in your app).

config/tashil.php
'middleware' => [
    'aliases' => [
        'subscribed' => 'subscribed',
        'plan'       => 'plan',
        'feature'    => 'feature',
    ],
],

See Middleware & Blade.

Caching

A dedicated Redis store named tashil is auto-registered so cache traffic is isolated from your app's main store.

config/tashil.php
'redis' => [
    'host'     => env('TASHIL_REDIS_HOST', env('REDIS_HOST', '127.0.0.1')),
    'password' => env('TASHIL_REDIS_PASSWORD', env('REDIS_PASSWORD', null)),
    'port'     => env('TASHIL_REDIS_PORT', env('REDIS_PORT', 6379)),
    'database' => env('TASHIL_REDIS_DB', 5),
],
 
'cache' => [
    'prefix'  => env('TASHIL_CACHE_PREFIX', 'tashil_cache:'),
    'ttl'     => 3600, // seconds
    'enabled' => env('TASHIL_CACHE_ENABLED', true),
],

Only the cold catalog (plans, features) and analytics aggregates flow through the cache. Hot, frequently-mutating tables — the event log, feature snapshots, and usage counters — always bypass it for correctness.

Environment variable reference

Every tunable, in one place:

VariableDefaultControls
TASHIL_DB_CONNECTIONnullDatabase connection name
TASHIL_ACTIVATE_ON_PAYMENTtrueActivate-on-payment creation default
TASHIL_INITIAL_INVOICE_DUE_DAYS1Initial invoice due window
TASHIL_MIN_PRORATION0.50Minimum proration invoice amount
TASHIL_TRIAL_WARN_DAYS3Days before expiry to warn
TASHIL_TRIAL_GRACE_DAYS0Post-trial grace window
TASHIL_RENEWAL_ON_PENDING_INVOICEcancelRenewal-with-unpaid-invoice policy
TASHIL_RENEWAL_GRACE_DAYS3extend_grace push length
TASHIL_RENEWAL_MAX_GRACE_EXTENSIONS3extend_grace cap
TASHIL_DUNNING_ENABLEDtrueRun dunning
TASHIL_DUNNING_SUSPEND_AFTER3Attempts before suspension
TASHIL_DUNNING_CANCEL_AFTER7Days suspended before expiry
TASHIL_PASTDUE_KEEP_ACCESStrueSoft vs hard dunning
TASHIL_SCHEDULE_ENABLEDtrueAuto-register scheduled jobs
TASHIL_EVENTS_ASYNCtrueDispatch events after commit
TASHIL_CURRENCYUSDDefault currency
TASHIL_CACHE_ENABLEDtrueEnable the cache layer
TASHIL_CACHE_PREFIXtashil_cache:Cache key prefix
TASHIL_REDIS_HOST / _PORT / _DB127.0.0.1 / 6379 / 5Redis connection

Tashil — Subscription management for Laravel. Released under the MIT license.