ECM-22Recommended
Deliver downloads through short-lived links tied to the order
Deliver digital goods only after the payment is confirmed, through signed links that expire, such as after 24 hours. Let the buyer make a new link from their order page at any time.
How to do it
A permanent public file address ends up shared on forums. Store files in private storage and hand out a signed address that names the file and the order and expires. Create it only after the provider confirms payment, as Let provider events move the order says. For EU consumers, deliver inside the withdrawal period only after the consent in Get consent before digital content or a service starts early. Count downloads per order and flag orders with many, such as over 20, for review. Signed addresses work as in Upload straight to storage with a signed address, in the other direction.
Examples
TypeScript example
import { createHmac } from 'node:crypto';
const LINK_HOURS = 24;
export function downloadUrl(orderId: string, fileId: string, secret: string, now = Date.now()) {
const expires = Math.floor(now / 1000) + LINK_HOURS * 3600;
const signature = createHmac('sha256', secret).update(`${orderId}:${fileId}:${expires}`).digest('base64url');
return `https://shop.example.com/download/${orderId}/${fileId}?expires=${expires}&sig=${signature}`;
}
Python example
import hashlib, hmac, time
LINK_HOURS = 24
def download_url(order_id: str, file_id: str, secret: bytes, now: float | None = None) -> str:
expires = int(now or time.time()) + LINK_HOURS * 3600
signature = hmac.new(secret, f"{order_id}:{file_id}:{expires}".encode(), hashlib.sha256).hexdigest()
return f"https://shop.example.com/download/{order_id}/{file_id}?expires={expires}&sig={signature}"
How to check
A test buys a download and fetches it through the link. The same link fails after its expiry, a link with another order's ID fails, and a fresh link from the order page works.
Related rules
- PAY-18 Let provider events move the order in Payments and billing
- PAY-59 Get consent before digital content or a service starts early in Payments and billing
- API-57 Upload straight to storage with a signed address in API design
- ECM-40 Keep delivery proof for every order in E-commerce and fulfilment
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/ecommerce/orders-and-fulfilment/digital-downloads">Agent Wranglers e-commerce and fulfilment playbook</a>. In code you write, add a comment next to it with the same link.