Skip to content

Configuration

config/billing.php — publish it with php artisan vendor:publish --tag=billing-config. Keys without an env variable can only be changed in the published file.

KeyEnvDefaultDescription
debugBILLING_DEBUGfalseDriver-level debug log (AbstractGateway::log()) through the default log channel. Dev/staging only — a driver may log request data
return_urls.successBILLING_RETURN_URL_SUCCESSnullYour page the customer lands on after checkout, see Return pages
return_urls.failedBILLING_RETURN_URL_FAILEDnullYour page for a failed/cancelled checkout. Only Stripe and Paddle ever use it
reconcile_after_minutesBILLING_RECONCILE_AFTER_MINUTES60How long a pending payment must stay unchanged (updated_at) before billing:reconcile-pending-payments polls the gateway for it (or writes it off)
schedule.enabledBILLING_SCHEDULE_ENABLEDfalseRegisters the package’s scheduled commands. Off: nothing is renewed, reconciled or expired
KeyEnvDefaultDescription
max_recurring_attemptsBILLING_MAX_RECURRING_ATTEMPTS4Charge attempts a renewal gets in total — the first one plus the retries — before the subscription is cancelled
retry_intervals—['6 hours', '24 hours', '48 hours']Wait after each failed renewal. Entry n paces the wait after failure n; a shorter list repeats its last entry; [] = no retries, the first failure cancels. Per-price override prices.retry_intervals
grace_period_daysBILLING_GRACE_PERIOD_DAYS3grace_ends_at is stamped at next_retry_at + this many days
grace_accessBILLING_GRACE_ACCESStrueWhether a past_due subscription keeps access (isActive()) while retries run. Per-price override prices.grace_access
trial_ending_notices—['3 days']When TrialWillEnd fires before trial_ends_at. Per-price override prices.trial_ending_notices
period_ending_notices—[]When SubscriptionPeriodEnding fires before current_period_ends_at. Empty = off. Per-price override prices.period_ending_notices
renewal.receipt_itemsBILLING_RENEWAL_RECEIPT_ITEMSfalseGive every scheduled renewal a one-line fiscal basket, see Fiscal receipt items

Interval entries (retry_intervals, trial_ending_notices, period_ending_notices) are a CarbonInterval string ('3 days', '15 minutes') or an int meaning minutes. An unparsable, zero or negative entry throws. A per-price override of null means “use the global list”, [] means “none for this price”.

With the defaults a failed renewal is retried after 6 h, 24 h and 48 h, then cancelled. A list of n intervals wants max_recurring_attempts = n + 1 — fewer attempts leave the last entries unused. Details — Renewals and dunning.

KeyEnvDefaultDescription
queue.connectionBILLING_QUEUE_CONNECTIONnull (app default)Connection for ProcessWebhookJob, the package’s only queued job
queue.queueBILLING_QUEUEnull (app default)Queue name for it
KeyEnvDefaultDescription
webhook.pathBILLING_WEBHOOK_PATHbilling/webhooks/{gateway}Path of the single webhook route. Must contain {gateway} — otherwise the provider throws on boot
webhook.middleware—[]Middleware for the webhook route. Deliberately outside the web group (no CSRF, no session)
webhook.prune_after_daysBILLING_WEBHOOK_PRUNE_AFTER_DAYS30Stored webhook calls older than this are deleted by the daily model:prune. Pruning drops their dedup claims too — keep it beyond every gateway’s retry horizon (WayForPay retries for 4 days)

The route name billing.webhook never changes, so callback URLs follow a changed path automatically.

Opt-in, see Invoices and receipts.

KeyEnvDefaultDescription
invoices.enabledBILLING_INVOICES_ENABLEDfalseRegisters the settle-on-payment listener and the PDF/preview routes. Needs the billing-migrations-invoices tables
invoices.auto_receiptBILLING_INVOICES_AUTO_RECEIPTfalseIssue a receipt on every PaymentSucceeded
invoices.auto_invoiceBILLING_INVOICES_AUTO_INVOICEfalseGive a payment paid without an invoice one, issued already paid
invoices.seller.nameBILLING_SELLER_NAMEnullSeller’s name. Nothing is issued automatically while it is empty
invoices.seller.tax_idBILLING_SELLER_TAX_IDnullЄДРПОУ / ІПН, Steuernummer, NIP — whatever identifies the seller for tax
invoices.seller.vat_idBILLING_SELLER_VAT_IDnullVAT registration, VAT payers only
invoices.seller.addressBILLING_SELLER_ADDRESSnullMay span lines
invoices.seller.ibanBILLING_SELLER_IBANnull
invoices.seller.bankBILLING_SELLER_BANKnull
invoices.seller.emailBILLING_SELLER_EMAILnull
invoices.seller.phoneBILLING_SELLER_PHONEnull
invoices.seller.logoBILLING_SELLER_LOGOnullA local file (absolute, or relative to public/, up to 1 MB) is embedded as data:; a URL is left as is — dompdf won’t fetch it
invoices.seller.brandBILLING_SELLER_BRANDnullName printed next to a logo that doesn’t carry one
invoices.localeBILLING_INVOICES_LOCALEukDefault document language
invoices.number_format.invoice—INV-{Y}-{000000}{Y} year, a run of zeros in braces = the counter padded to that width, {N} = unpadded counter
invoices.number_format.receipt—RCP-{Y}-{000000}
invoices.number_per_tenantBILLING_INVOICES_NUMBER_PER_TENANTtrueA sequence per tenant (each tenant is a seller). false — one sequence for everybody
invoices.date_format—nullnull = each language’s own (uk d.m.Y, en M j, Y); a format here applies to all
invoices.due_daysBILLING_INVOICES_DUE_DAYS5Due date of an unpaid invoice, days from issue
invoices.footerBILLING_INVOICES_FOOTERnullFooter text
invoices.storage.diskBILLING_INVOICES_DISKnullKeep a copy of every generated PDF on this disk (per status)
invoices.storage.path—billing/invoicesDirectory on that disk
invoices.pdf_routeBILLING_INVOICES_PDF_ROUTEtrueThe signed PDF route behind invoicePdfUrl(). false removes it
invoices.pdf_middleware—[]Extra middleware in front of the signed route, e.g. ['web', 'auth']
invoices.link_ttl_minutesBILLING_INVOICES_LINK_TTL_MINUTES10080Lifetime of a signed PDF link (a week)

gateways.{name} blocks are read by the default credential resolver (Support\DefaultCredentialResolver — config("billing.gateways.{$name}"), tenant ignored). Bind your own CredentialResolverContract for per-tenant or database-stored credentials, see Tenants and multiple accounts.

An unset gateway stays unconfigured: its webhook route answers 403 and it fails only when something charges through it.

KeyEnvDefault
gateways.monobank.tokenMONOBANK_TOKEN—
gateways.monobank.link_ttl_minutesMONOBANK_LINK_TTL_MINUTES60
gateways.liqpay.public_keyLIQPAY_PUBLIC_KEY—
gateways.liqpay.private_keyLIQPAY_PRIVATE_KEY—
gateways.liqpay.link_ttl_minutesLIQPAY_LINK_TTL_MINUTES60
gateways.wayforpay.merchant_accountWAYFORPAY_MERCHANT_ACCOUNT—
gateways.wayforpay.merchant_domainWAYFORPAY_MERCHANT_DOMAIN—
gateways.wayforpay.secret_keyWAYFORPAY_SECRET_KEY—
gateways.wayforpay.link_ttl_minutesWAYFORPAY_LINK_TTL_MINUTES1440
gateways.hutko.merchant_idHUTKO_MERCHANT_ID—
gateways.hutko.secret_keyHUTKO_SECRET_KEY—
gateways.hutko.link_ttl_minutesHUTKO_LINK_TTL_MINUTES1440
gateways.stripe.secret_keySTRIPE_SECRET_KEY—
gateways.stripe.webhook_secretSTRIPE_WEBHOOK_SECRET—
gateways.stripe.proration_behaviorSTRIPE_PRORATION_BEHAVIORcreate_prorations
gateways.paddle.api_keyPADDLE_API_KEY—
gateways.paddle.client_tokenPADDLE_CLIENT_TOKEN—
gateways.paddle.checkout_urlPADDLE_CHECKOUT_URL—
gateways.paddle.webhook_secretPADDLE_WEBHOOK_SECRET—
gateways.paddle.tax_categoryPADDLE_TAX_CATEGORYstandard
gateways.paddle.proration_billing_modePADDLE_PRORATION_BILLING_MODEprorated_immediately
gateways.paddle.link_ttl_minutesPADDLE_LINK_TTL_MINUTES1440

What each key means — on the gateway pages. Two optional keys work in any gateway block:

  • currencies — ['UAH', 'USD'] replaces the driver’s built-in currency list (narrow it to what your merchant account has, or extend it), see Money and currencies
  • seller — an array with the same keys as invoices.seller, the issuer of documents for payments through this gateway (a merchant account of another legal entity), see Invoices

link_ttl_minutes is the checkout-link lifetime each driver sends to the gateway and mirrors into payments.payment_url_expires_at. Stripe has no such key — its Checkout Session reports its own expires_at.

The same field list is available at runtime for a settings UI: MonobankGateway::credentialFields(), or Billing::gateways()[$name]['credential_fields'] — see Gateways overview.