SIMPLE STACK GUIDE

Sell Digital Downloads with PHP and Stripe

Payment-confirmed access to files outside the web root.

What you get

The digital-downloads profile uses Stripe Checkout for one-time purchases. A settled purchase unlocks the signed-in buyer’s download library. Files live outside public/ and are streamed only after an access check; a copied download URL alone does not grant access.

The tradeoffs

Purchase-first checkout can create the buyer account after payment and send a sign-in code and link. Refund and dispute events can revoke access. The template records download events and a durable order confirmation. Email configuration is part of delivery, so test failures and recovery too.

What to try first

Configure the product and Stripe price, add protected files, then complete a test purchase and download. Also test an unpaid session, another account, a refund and a repeated webhook. You remain responsible for selling terms, tax configuration, customer support and backups.

Try the downloads demo

Payment is only one part of file delivery

A useful digital-download implementation connects a confirmed payment to a purchase record, an authenticated buyer and a protected file. Each boundary needs its own check. A successful-looking return page or an unguessable filename does not establish that the current visitor owns the purchase.

1. Treat Checkout’s return as a pointer to verify

Use the returned session identifier to fetch and verify the payment state on the server. Match the configured product and expected purchase context. An unpaid or pending payment must not unlock the file. Delayed payment methods can complete later, so the return page and webhook path need to converge on the same settled purchase without duplicating access or confirmation messages.

2. Verify webhooks and plan for repeats

Verify Stripe’s signature against the raw request body before accepting an event. Store the event identity, claim its processing work and mark it complete only after the relevant durable changes succeed. A repeated completed event should not repeat a grant. A failed attempt must remain recoverable; an event arriving later must not demote an already settled payment merely because it describes an older pending state.

Simple Stack’s webhook tests exercise duplicate delivery, failed confirmation retry and delayed pending/expired events. Real provider configuration is still part of launching your own store. Use the official Stripe webhook guidance to configure the endpoint and exercise your selected payment methods.

3. Authorise every download request

Keep sale files outside the public document root. The download route must require a signed-in user, resolve that user’s purchase and confirm its paid status before streaming the allowed file. The file-serving helper alone is not the account-ownership check. Resolve the file against protected storage, reject paths outside that directory and send private, non-cacheable download headers.

Test a copied download URL in a logged-out browser and in a different account. Both must fail. Also request an unknown file identifier and a revoked purchase. Obscuring a URL, disabling a button or hiding a link in the account page is not a substitute for these server checks.

4. Exercise the unglamorous recovery paths

  1. Complete a test purchase and open the file from the buyer’s library.
  2. Repeat the event and revisit the payment return. Confirm one purchase and no duplicate credit or fulfilment effects.
  3. Try an unpaid session and a delayed payment. Access should follow settlement rather than the browser redirect.
  4. Simulate a mail failure. The paid purchase should survive and the confirmation should remain retryable.
  5. Apply the supported refund and dispute events, then retry the protected download.
  6. Delete or rename the configured file in a disposable install. Verify a clear failure without exposing filesystem paths.
  7. Replace a release with a new immutable filename, retain the previous archive and verify the new checksum before changing its product-file mapping.

Make the buyer’s next step explicit

The receipt, return page and account library should agree on where the file lives and how to sign in again. State the software requirements before payment, put the first-run instructions at the top of the archive and distinguish local setup from connecting live providers. A source-code product also needs clear licence, update and support terms; the template cannot choose those business commitments for you.

The public downloads demo uses simulated payment data. It lets you inspect the interface without paying, but it does not prove a production payment or SMTP delivery. Before promoting your own store, run a provider-configured purchase, account sign-in and download, and check the refund path with the same care.

Try before choosing

The live demos use sample data and simulated payments. The download includes the source and setup guides; your own launch still needs provider configuration and end-to-end testing.

Explore the demos · Price, licence and requirements · All guides