Introducing Downloadable Products for Solidshop — sell digital files, free

eBooks, software, sample packs, design assets — sold from your Joomla store and delivered through token-secured links on your own server. It is the first public release, and it is free.

A store that sells a physical thing has a clear job: take the money, print the label, hand the parcel to a courier. A store that sells a file has a harder one. The money is the easy half; the rest is making sure the buyer — and only the buyer — can get the file, for as long as you said they could, without you emailing a Dropbox link at midnight.

The Downloadable Products plugin is out today, and it does that half. It adds a Downloadable product type to Solidshop, a file manager to the product edit form, and two delivery channels for the buyer: an Account → Downloads page and direct links in their order emails.

It costs nothing. No licence key, no renewal, no per-order fee — the same deal as our PayPal plugin. Digital delivery is table stakes for a shopping cart rather than a premium feature, and putting a price on it would tax exactly the merchants we would rather have building their store on Solidshop. The source is GPL-3, the files live on your server, and there is no file-delivery service in the middle sending you a bandwidth bill.

A product type, not a separate catalogue

Enable the plugin and Downloadable joins Physical in the product type picker — the icon cards that Core 1.4.0 introduced yesterday. Pick it, save once, and a Downloads tab appears on the product.

Everything else about the product is unchanged: it has a price, a tax class, categories, custom fields, translations, SEO settings and a place in your listings, and it goes through the same cart and checkout as anything else you sell. Nothing about the storefront needs to know it is digital until the moment of delivery.

In the Downloads tab you add files one at a time, each with an optional display name — what the customer sees, which is not necessarily the sensible-but-ugly name on disk. A product can carry as many files as it needs: a book as PDF + ePub + MOBI, an album as MP3s plus cover art, a plugin as the ZIP plus its manual. Drag rows by the handle to reorder them; uploads, renames, deletes and reordering all happen inline, without a page reload.

Files belong to the product as a whole and are delivered for every variant of it. Where two buyers should genuinely receive different files — a Personal licence bundle versus a Team one — make them two products.

Download limits and link expiry

Two fields at the top of the tab decide how generous the delivery is:

  • Download limit — how many times each file can be downloaded per purchase. 0 means unlimited.
  • Download expiry — how long the links stay valid after purchase, in seconds (2592000 is 30 days). 0 means they never expire.

Both are per purchase, not per customer. Buying the same product again on a later order issues fresh links with a fresh counter and a fresh expiry date, which is also the simplest way to grant a customer more downloads when they email you about a lost laptop: place a zero-priced order for them. The expiry clock starts when the order is created, and changing the numbers on the product affects future purchases only — links already issued keep the terms they were sold under.

How the file actually reaches the buyer

When an order is placed, the plugin mints one token per file, per order line: a random 64-character key stored with its own download counter, limit and expiry date. The customer’s Download button asks for the token, never for a path — the location of the file on disk appears in no URL anywhere. The endpoint checks the token, the expiry and the remaining count, increments the counter and streams the file as an attachment. An expired or exhausted link answers with a plain “gone” rather than the file.

Downloads unlock on payment. Tokens exist from the moment the order is placed, but nothing is served until the order’s payment status is Paid — which matters if you accept bank transfer or cash on delivery. Until then the customer sees the row with an Awaiting payment badge and no button. A partial refund leaves access intact; a full refund removes it.

There are two ways for the buyer to reach their files, and the second one is why guests are not stranded:

  • Account → Downloads — every file the logged-in customer is entitled to, across every order they have placed, with the product, the order, the remaining downloads and the expiry date. Exhausted and expired rows stay in the list with the reason shown, so nobody is left guessing why a button is greyed out. One page to bookmark, instead of hunting through old order emails.
  • The order emails — when an order contains digital products, a Your downloads block is added to the order confirmation and to the payment-received email, listing every file as a direct link grouped by order line. The token is the credential, so these links work without a login: a guest checkout is delivered properly. If payment is still pending when the confirmation goes out, the block says so, and the same links start working the moment the order is marked paid.

For orders that carry downloads, the payment-received email is the “your files are ready” notice rather than a courtesy receipt, so it is sent even if you keep that email switched off for ordinary orders. And on an order with nothing to ship, it no longer promises a shipping confirmation that is never coming.

What shoppers see before they buy

The product page gains a Download info tab summarising the deal in the shopper’s terms: instant download, how many downloads they get per purchase, and how long the links stay valid. If you would rather have that in the body of the page than behind a tab, the plugin also registers a dedicated Downloadable option in the product’s Layout dropdown that renders it inline.

Both, plus the account Downloads page, are ordinary Joomla layout files. Override them in your template (html/com_solidshop/account/downloads.php and friends) and your changes survive plugin updates.

Where the files live, and who can reach them

Uploads are stored inside your Joomla installation, under files/shop/{store}/downloads/ by default and anywhere you like via the plugin’s storage-path setting. Because that default sits inside the web root, the plugin defends the directory in depth — the same scheme Solidshop uses for cached invoice PDFs:

  • Filenames are sanitised and given a random 16-character suffix, so the on-disk name cannot be guessed from the product. The display name the customer sees is stored separately, so renaming what they see never touches the file.
  • Deny-all guard files (.htaccess, web.config and a blank index.html) are dropped into the directory automatically and re-created if they go missing. On nginx, which honours neither, the random suffix is the protection — add a location block denying the directory, or point the storage path outside the web root.
  • Uploads are filtered twice: the configurable extension allowlist (PDFs, archives, audio, video, eBooks, office documents and installers by default — trim or extend it), and a content-type check that rejects server-executable files such as PHP or shell scripts even when the extension looks innocent. Uploading requires the Solidshop Manage Products permission.

The companion cleanup task

The download is one Joomla package holding two extensions: the plugin itself and a small scheduler plugin, plg_task_solidshopdownloads, which deletes tokens whose expiry has passed. One upload installs both, and one update notice refreshes both. Enable them, then add a Solidshop: Expired Download Token Cleanup task under System › Scheduled Tasks — daily is plenty. Expired links answer correctly whether or not you run it; the task simply stops the token table growing forever.

Setting it up

  1. Install Solidshop_Downloadable_v1.0.0.zip through System → Install → Extensions. It is a Joomla package, so the one upload installs both plugins.
  2. Enable Solidshop - Downloadable and Solidshop - Download Token Cleanup in the Plugin Manager — like every Joomla plugin, both arrive disabled.
  3. Open a product, set its type to Downloadable, save, and upload your files in the Downloads tab.

Every setting, the storage layout, the token rules and a troubleshooting section are covered in the Downloadable plugin documentation.

Requirements & availability

Downloadable 1.0.0 needs Solidshop 1.4.0 or later, Joomla 6.0+ and PHP 8.4+ — the installer checks first and refuses to run against an older core. Core 1.4.0, released yesterday, is the one that carries the product-type card picker, the capability-aware edit form and the email plumbing the download block rides on. Twenty-three admin locales ship in the package, and updates arrive through Joomla’s own updater like any other extension.

It is free, permanently — grab it from the extension page. The source is GPL-3 and you are welcome to fork it; support runs through the community forum rather than the ticket system that comes with the paid extensions.

Downloadable is the first of Solidshop’s product-type plugins to go public. Service & Bookings and Subscriptions build on the same architecture and follow when they are ready to carry their price — this one, being the type with no future obligations attached to it, goes out first and goes out free.