Over August the sparrow_ecommerce module went from "a cart that talks to Stripe" to a shop you can actually run: carriers and pickup points, four payment methods, order e-mails, a proper Orders desk in the admin and a billing layer that issues numbered invoices. Everything ships inside the base image from Sparrow 7.4.22 on; sites turn the pieces on in settings.
Shipping methods and pickup points
Shipping is now data, not code. Editors create shipping methods in the admin - flat rate, free above a threshold, per-country availability - and the checkout offers them automatically. Three Czech carriers come with pickup-point widgets built in: Packeta (Zásilkovna), PPL ParcelShop and Balíkovna. The customer picks a branch on the map, the choice is stored on the order together with the carrier metadata, and it prints on the packing slip.
Cash on delivery is a payment backend with its own rules: a COD fee per method, a maximum order value, and the ability to disable it for specific countries or carriers.
Four ways to get paid
Payment backends are registered per site and toggled per legal entity from the admin, so a shop can offer a different mix without a redeploy:
- Bank transfer - the confirmation page and the order e-mail carry a Czech SPAYD QR code (account, amount, variable symbol), so paying from a banking app is one scan.
- Stripe - cards, Google Pay and Apple Pay, webhook-confirmed.
- PayPal - hosted checkout with webhook reconciliation.
- Comgate - the Czech gateway for cards and bank buttons.
Wiring is a settings dictionary; secrets stay in the namespace, never in the image:
SPARROW_ECOMMERCE_PAYMENT_BACKENDS = {
"bank_transfer": {
"class": "sparrow_ecommerce.payments_bank_transfer.backend.BankTransferBackend",
"label": "Bank transfer",
},
"stripe": {
"class": "sparrow_ecommerce.payments_stripe.backend.StripeBackend",
"label": "Card / Google Pay (Stripe)",
"api_key": os.environ.get("STRIPE_SECRET_KEY", ""),
"webhook_secret": os.environ.get("STRIPE_WEBHOOK_SECRET", ""),
},
"comgate": {
"class": "sparrow_ecommerce.payments_comgate.backend.ComgateBackend",
"label": "Comgate",
"merchant": os.environ.get("COMGATE_MERCHANT", ""),
"secret": os.environ.get("COMGATE_SECRET", ""),
},
}
Orders you can work with
Orders get sequential numbers instead of random tokens, and every status change sends an e-mail - confirmation, paid, shipped - from templates the site can override. The Orders listing in the admin got an inspect view and one-click actions: mark paid, mark shipped (with tracking number), cancel, refund. Shipments and internal notes live on the order; the customer never sees the notes.
Prices finally read like prices: the new money template filter formats amounts with the currency (79 Kč, 1 234,50 Kč), the cart shows formatted totals and a proper Continue to checkout button.
Invoicing and the back office
The same module now carries the back-office billing we use for hosting: persistent customers with tax IDs, subscriptions and their renewal invoices, domain registrations, one-off invoices for project work, and store identities - several legal entities, each with its own invoice number sequence and bank details. Invoices render to PDF with the SPAYD QR code and can be issued from a "New invoice" menu without leaving the admin.
Two new documentation pages walk through it: Running the E-shop and Payment & Shipping Integrations.