Skip to content
TilloTech Docs

Domain Overview

This document describes the key business and technical domains, how they interact, and where to find the most important code.

For platform context (Tillo, Core, Buyers, purchase schemes), see the documentation index. For sequence and flow diagrams, see key flows.


Domain Map

LayerMembers
Tenant Storefront (Inertia/Vue)Auth, Catalogue / Product, Basket, Checkout, Order Success
Core Commerce (legacy app/Models, app/Service, app/Http)Tenant Domain, Order / Fulfillment, Product, Pricing
DDD Modules (app/PaymentGateway, app/Tillo, app/Hub, app/Auth, app/Auditing, app/Webhook, app/Reporting, app/Shared)PaymentGateway, Tillo, Hub (admin API), Auth Providers, Auditing, Webhook (outbound), Reporting, Shared
External SystemsTillo API, Stripe, Checkout.com, TrueLayer, PPS / LeisureChoice, DynamoDB (audit), Redis (queues)

Domains in Detail

Tenant

What it does: Resolves the current tenant from the HTTP host, initialises a shared Tenancy context for the request, and provides Eloquent scoping so that all queries are automatically filtered to the current tenant.

Hosting and DNS: Production runs on EKS under giftstorefront.com. Buyers point a custom domain at StoreFront—historically via a reverse proxy to giftstorefront.com with X-Forwarded-Host (or equivalent) set to their domain, which middleware uses to look up the tenant. Domain management is increasingly in-house (e.g. Cloudflare entries created for the Buyer’s domain).

Key files:

FilePurpose
app/Tenant/Middleware/TenantDomainMiddleware.phpMatches the HTTP host to a Tenant model and calls Tenancy::init()
app/Tenant/Tenancy.phpSingleton container; holds the resolved Tenant for the request
app/Tenant/BelongsToTenant.phpTrait; automatically applies the tenant scope to any model that uses it
app/Tenant/Scopes/TenantScope.phpGlobal Eloquent scope that adds WHERE tenant_id = ? to all queries
app/Tenant/Events/TenantAssigned.phpDispatched after tenant resolution; lets other parts of the system react
app/Http/Middleware/HandleInertiaRequests.phpShares tenant theme, locale, and deferred wallet data with every Vue page

Journey middleware: The tenant middleware group additionally includes JourneyMiddleware, which controls whether an anonymous customer is allowed to browse or is redirected to log in first (depending on the tenant's configuration).


Product

What it does: Manages the gift card catalogue—brands, denominations (fixed or open), categories, images, discounts, cashback rates, and tenant-specific overrides. The mall (catalogue) page exposes a hero banner, promoted-brand carousel, and searchable/filterable catalogue with discount/cashback labels. The product (brand) page shows denominations or open value, brand details and terms, and scheme rates; Buyers can deep-link authenticated users to a brand URL from their own site. A separate Buy as a Gift path on the brand page checks out a single brand in isolation (similar to Amazon’s gift flow), outside the mixed basket journey.

Key files:

FilePurpose
app/Models/Product.phpCore product model; relationships to Tenant, denominations, categories
app/Service/ProductService.phpBusiness logic for querying and mutating products
app/Service/PricingService.phpCalculates the final price a customer pays (discount / cashback / face value)
app/Http/Controllers/CatalogueController.phpServes the mall Inertia page (product listing)
app/Http/Controllers/ProductController.phpServes the product Inertia page (product detail)

Product data is synced from Tillo via background jobs (see the Tillo section).


Order

What it does: The Order domain spans the entire customer purchase journey, from the basket through payment to post-purchase fulfilment.

Customer journey (self-purchase): catalogue → brand page (value + add to basket) → basket → checkout (name, email, payment method) → hosted payment (Stripe, Checkout.com, TrueLayer, etc.) or tenant-specific flows (voucher sync, tenant wallet) → success page with order confirmation and async gift-card redemption links once fulfilment completes (typically within seconds). Buyers control experience before and after StoreFront (campaigns, deep links, cashback in their app) even though StoreFront UI is not white-label editable.

Key files:

FilePurpose
app/Models/Order.phpCore order model; tracks status, payment, customer, items
app/Models/OrderItem.phpOne row per gift card line in the order
app/Service/OrderService.phpCentral orchestrator: creates/updates orders, triggers payment and fulfilment
app/Http/Controllers/BasketController.phpBasket page and basket mutations
app/Http/Controllers/CheckoutController.phpSelects the checkout variant and delegates to the active payment gateway
app/Http/Controllers/ConfirmationController.phpResolves the post-payment success or fraud-verification page
app/Order/Services/OrderItemService.phpBuilds the Tillo order card request for each order item
app/Console/Commands/Order/Artisan commands for order lifecycle steps (CreateFulfillment, CompleteOrder, ExpireOrder, …)
app/Jobs/Order/Queued jobs (OrderGiftCard, CheckFulfillment, SyncGiftCard, …)

Order lifecycle states: awaiting payment → paid → fulfillment → completed / refunded / cancelled


PaymentGateway

What it does: An abstraction layer over multiple payment processors. Each gateway implements the same abstract base class and is wired in as the active gateway via the tenant's configuration.

Key files:

FilePurpose
app/PaymentGateway/PaymentGateway.phpAbstract base class all gateways extend; defines checkout(), renderSuccessPage(), refund()
app/Service/PaymentGatewayService.phpResolves the active gateway for a tenant and coordinates payment operations
app/PaymentGateway/Shared/Enums/PaymentGatewayName.phpEnum of all supported gateway names

Supported gateways:

GatewayCheckout page variantWebhook entry point
StripestripePayment (Inertia page)Cashier WebhookReceivedCheckoutSessionCompleted / CheckoutSessionExpired / ChargeDispute* listeners
Checkout.comcheckout (embedded)app/PaymentGateway/CheckoutCom/Http/Controllers/WebhookController.php
TrueLayerRedirect (HPP)app/PaymentGateway/TrueLayer/Http/WebhookController.php
PPScheckoutVoucher— (synchronous card issuance)
LeisureChoicecheckoutVoucher— (synchronous card issuance)
TenantWalletcheckoutTenantWallet— (internal balance debit); also used for Salary Finance-style flows where the Buyer exposes an authorisation endpoint (customer ID from auth, amount, brand) and StoreFront completes the sale on approval, then sends fulfilment webhooks

Fulfillment & Tillo

What it does: After payment is confirmed, fulfilment creates gift card records and calls the Tillo API to issue real card codes to the customer. Tillo exposes both synchronous and asynchronous fulfilment endpoints; StoreFront uses only the asynchronous API—a retryable job places the order, then another job checks status until the card is ready. Tillo also provides product catalogue data (brands, denominations, statuses) kept in sync via Core webhooks and background jobs.

Key files:

FilePurpose
app/Models/Fulfillment.phpTop-level fulfilment record per order
app/Models/FulfillmentItem.phpOne record per gift card line; tracks issuance status and the card code
app/Service/FulfillmentService.phpCreates Fulfillment / FulfillmentItem rows and dispatches OrderGiftCard jobs
app/Jobs/Order/OrderGiftCard.phpQueued job that calls Tillo\Http\ApiClient::orderCard() for a single item
app/Tillo/Http/ApiClient.phpHTTP client for all Tillo API requests (order card, order status, list brands)
app/Tillo/Http/Controllers/WebhookController.phpReceives Tillo-originated webhook events and dispatches TilloWebhookReceived
app/Tillo/Listeners/TilloWebhookListener.phpHandles TilloWebhookReceived; updates fulfilment item status
app/Tillo/Jobs/SyncProductStatusJob.phpSyncs Tillo brand active/inactive statuses to local products
app/Tillo/Jobs/SyncProductDenominationsJob.phpSyncs denomination lists from Tillo to local products
config/tillo.phpTillo API credentials and environment config

Hub (internal admin API)

What it does: A JSON REST API used by the new Hub admin UI (Nuxt), which replaces the legacy Hub embedded in Core for StoreFront operations. It provides read/write operations for orders, fulfilment items, tenants, policies, and audit record viewing— including end-customer and payment detail that Core’s Hub cannot show.

Access pattern: All Hub routes are under /api/internal/hub/v1/. Requests must carry a Bearer JWT issued by the Hub platform. The TenantLookupMiddleware maps a Tillo Core user ID to their permitted tenant IDs.

Key files:

FilePurpose
app/Hub/Shared/routes/api.phpAll Hub API route definitions
app/Hub/Shared/Services/JWTService.phpVerifies and decodes Hub JWTs
app/Hub/Shared/Http/Middleware/TenantLookupMiddleware.phpResolves tenant list from the JWT caller identity
app/Hub/Orders/Http/Controllers/OrderController.phpList, view, and manage orders
app/Hub/Orders/Http/Controllers/FulfillmentItemController.phpRefund / cancel fulfilment items
app/Hub/Orders/Http/Controllers/ViewOrderAuditRecordsController.phpReturn DynamoDB audit trail for an order
app/Hub/Tenants/Http/Controllers/TenantController.phpManage tenant configuration
app/Hub/Tenants/Http/Controllers/PolicyController.phpManage tenant policy sections (terms/privacy)
app/Hub/config/hub.phpHub-specific configuration

Auth

What it does: Storefront authentication is pluggable per tenant. After tenant resolution, the configured protocol (JWT, OAuth, or OIDC) is loaded from encrypted credentials in the database. On success, StoreFront creates a session (and cookie) keyed by the IdP’s sub (or equivalent) as the external user ID. Sessions expire after two hours; the customer is sent back to the Buyer’s site and, if still logged in there, returns to StoreFront with a fresh token. The Hub uses a completely separate JWT-based auth path.

Key files:

FilePurpose
app/Auth/AuthProviderFactory.phpCreates the correct AuthProvider implementation for the current tenant
app/Auth/AuthProviderInterface.phpContract all storefront auth providers implement
app/Auth/JWTProvider.phpJWT-based storefront auth (most tenants)
app/Auth/OIDCProvider.phpOIDC-based storefront auth
app/Auth/OAuthProvider.phpOAuth-based storefront auth
app/Http/Controllers/AuthController.phpHandles storefront login/callback; upserts Customer
app/Tillo/Http/Controllers/TenantLoginController.phpTillo staff tenant-picker and signed cross-tenant login
app/Hub/Shared/Services/JWTService.phpHub JWT verification (separate from storefront auth)

Auditing

What it does: Records an immutable, versioned audit trail for domain events. Audit records are stored in AWS DynamoDB (a local DynamoDB container is available via Sail). PII in audit payloads is tokenised before storage.

Key files:

FilePurpose
app/Auditing/Listeners/EventAuditingListener.phpQueued listener (queue: auditing) that persists audit DTOs for each registered domain event
app/Auditing/Services/AuditingService.phpBuilds and stores audit records via DynamoDbService
app/Auditing/Services/DynamoDbService.phpDynamoDB read/write wrapper
app/Auditing/Dtos/V1/Versioned audit DTO classes (one per audited event)
app/Events/Interfaces/SupportsAuditingInterface.phpMarker interface; events that implement it will be audited
app/Auditing/config/auditing.phpDynamoDB table names and other auditing configuration

Events registered for auditing can be found in app/Providers/EventServiceProvider.php.


Outbound Webhooks

What it does: After key order events, the application sends signed webhook payloads to the tenant's configured endpoint (e.g. ItemFulfilled, FulfillmentItemRefunded). This is optional per Buyer but critical for real-time cashback and loyalty integrations—typically one webhook per fulfilled gift card, carrying order ID, item ID, brand, amount, user ID, and discount/cashback metadata. Payloads are versioned (V1 / V2) and dispatched via a dedicated webhooks queue.

Key files:

FilePurpose
app/Webhook/Listener/SendWebhookListener.phpReacts to domain events and schedules a webhook dispatch
app/Webhook/WebhookJob.phpQueued job that performs the HTTP POST to the tenant endpoint
app/Webhook/WebhookSigner.phpSigns payloads with the tenant's webhook secret
app/Webhook/Dto/WebhookHandlerFactory.phpResolves the correct versioned handler (V1/V2) for an event type
config/webhook-server.phpDefault queue name (webhooks) and retry / backoff configuration

Reporting

What it does: Generates and emails monthly transaction reports directly to Buyers (alongside separate monthly invoicing from Tillo finance). Also contains billing/fee scheme logic for calculating monthly revenue and dispute reporting.

Key files:

FilePurpose
app/Reporting/Service/ReportingService.phpEntry point for report generation
app/Reporting/Service/ReportBuilder/Concrete report builders per tenant/type
app/Reporting/Billing/Fees/FeeService.phpCalculates fees owed based on a tenant's fee scheme
app/Reporting/Cashback/CashbackHandler.phpRecords cashback transactions

Shared

What it does: Cross-cutting utilities used by multiple domains.

Key files:

FilePurpose
app/Shared/Dtos/ActorDto.phpIdentifies the actor (user or system job) responsible for a domain action
app/Shared/Providers/ActorDtoProvider.phpResolves the ActorDto from the current request or job context
app/Shared/Traits/HasOccurredAtData.phpTimestamp trait for events and DTOs