Descripción
Pay4All Shop is a simple, focused order-form plugin for small shops, wineries, caterers, takeaways and clubs. It is intentionally lighter than WooCommerce: you create a form, pick products and delivery methods, and embed it via a shortcode.
Core features
- Drag-and-drop form builder with all common field types — default fields (first name, last name, e-mail, phone, address, etc.) are pre-translated in every activated language
- Products with photo, price, sale price, min/max/step quantities, short description
- Per-form photo size — pick Small (60 px), Medium (120 px), Large (200 px) or Custom (any pixel value between 20 and 1000) from the form editor. In List layout the value constrains the photo’s width, in Grid layout its height — so the cards keep tidy regardless of the source image dimensions.
- Two product types — Physical (default) and Virtual (downloadable file delivered after purchase)
- Hide a product — tick Hide this product to remove it from the order form entirely (useful for archiving a seasonal product without deleting it)
- Out-of-stock flag — the product stays visible in the form but the quantity field is greyed out and disabled
- Stock management (optional, per product) — tick Manage stock to track quantity available; stock is decremented when an order is placed and restored when an order is deleted; the customer cannot order more than the stock left; product flips to out of stock automatically at 0; an admin column shows the current stock at a glance
- Low-stock e-mail alert — set a global threshold in Settings › General; when any tracked product crosses it after a sale, an alert is e-mailed to the notification address
- Delivery methods — pickup, flat-rate, free, free over an amount, or no delivery; accepted payment methods are set per delivery so each delivery can expose its own payment choices to the customer
- Per-delivery customer-facing title and description in every activated language
- Virtual file delivery — the file is stored in a private folder (
.htaccessprotected), the customer receives a one-time link valid for 60 days, served by the plugin’s download endpoint - « Remember my information » opt-in — a checkbox at the bottom of the customer step lets the shopper store their contact details locally in the browser (via the native
localStorageAPI — no server-side cookie, no data leaves the browser) so a repeat visit pre-fills every field with one click. Unchecking the box and continuing wipes the memory immediately. - Order management — custom statuses, payment statuses, internal notes
- E-mails to the customer and the merchant — full content (subject, heading, intro, outro) editable per language
- CSV export of orders, filterable by date, form, status
- Privacy API integration for GDPR export/erase
- Honeypot anti-spam, nonces, server-side validation
- Internationalised (FR, DE, IT, EN)
Payments included for free
- Pickup payment
- Cash on delivery
- Bank transfer — merchant-configurable IBAN / BIC / beneficiary block, translated in every activated language, shown at checkout AND included in the customer confirmation e-mail. A fr / de / it / en shopper receives the bank details in the language they placed the order in.
- TWINT manual (textual instructions to the customer)
Pay4All Pro (optional)
Install Pay4All Pro to add automated TWINT payments: the customer pays through their TWINT app at checkout, and the order is marked as Paid automatically without merchant intervention.
Pay4All Shop works fully without Pay4All Pro. Pay4All Pro is sold separately at https://pay4all.ch/.
External services
This plugin does not connect to any external service. Orders, customer data, virtual downloads and e-mails are all handled locally.
Use cases
- Winemakers selling in the shop or at events
- Cheese makers with pickup ordering
- Caterers with weekly order windows
- Local shops with pickup-only ordering
- Clubs taking online registrations with payment
- Digital sellers delivering PDFs, mp3s or course material as virtual products
Capturas





Instalación
- Upload the plugin to
/wp-content/plugins/pay4all-form/or install via Plugins › Add New. - Activate the plugin from the Plugins menu.
- Open Pay4All Shop in the admin sidebar.
- Create your products, delivery methods, then a form.
- Copy the form shortcode into any page.
FAQ
-
Do I need WooCommerce?
-
No. Pay4All Shop is standalone. It does not depend on WooCommerce in any way.
-
Does it support online payments?
-
The free version supports manual payments only (pickup, on delivery, bank transfer, TWINT instructions). Automated TWINT payments are available via Pay4All Pro.
-
Is the plugin GDPR-friendly?
-
Yes. Customer data is included in WordPress’s Tools › Export / Erase Personal Data workflow.
-
Will my data be deleted if I uninstall?
-
No, unless you explicitly enable Réglages › Données › Supprimer les données lors de la désinstallation.
-
No HTTP cookies are set by the plugin. When the shopper ticks the « Se souvenir de mes informations pour ma prochaine commande » checkbox on the customer step, their contact fields are stored in the browser’s own
localStorage(client-side only, never uploaded to the server, one-year retention, scoped per form). Unticking the checkbox and clicking Suivant — or the browser’s Clear site data action — wipes the entry immediately. Nothing is stored when the checkbox stays off. -
How do virtual products work?
-
When you create a product of type Virtual, you upload one file per product. The file is stored in
wp-content/uploads/p4all-virtual/, protected by an automatically generated.htaccess(deny from all). After purchase, the customer’s e-mail contains a one-time download link served by the plugin endpoint (?p4all_dl={token}). The link is valid for 60 days. -
How does *Out of stock* work?
-
Tick the Rupture de stock checkbox on a product. The product stays visible in the form so the customer still sees what you usually offer, but the quantity field is greyed and disabled. A red badge labels the product as out of stock. Server-side validation rejects any tampered submission that tries to order an out-of-stock item.
-
How does *Stock management* work?
-
Tick Manage stock on a product and enter the quantity available. From that point on:
- Each order decrements the stock by the quantity ordered (one decrement per ticket / per unit). The decrement happens as soon as the customer validates the order, regardless of the payment status.
- The order form prevents the customer from ordering more than what is left — the quantity input’s max attribute is capped at the stock available, and a server-side check rejects any tampered submission.
- When the stock reaches 0, the product is automatically flagged out of stock: it stays visible but cannot be ordered.
- When an order is deleted from the admin (definitive delete, not just trashed), the stock is restored for every product still in the order. Status changes (paid, cancelled…) do NOT restore stock; only deletion does.
- If you set a Notify me when stock reaches threshold in Settings › General (under the shop address), an e-mail alert is sent to the notification address as soon as a tracked product crosses the threshold downwards after a sale.
- A Stock column in the products admin list shows the current quantity (or
—when stock management is off), highlighted in orange below the threshold and red when out of stock.
Reseñas
No hay reseñas para este plugin.
Colaboradores y desarrolladores
«Pay4All Shop – Simple order forms with TWINT & STRIPE Payment» es un software de código abierto. Las siguientes personas han colaborado con este plugin.
ColaboradoresTraduce «Pay4All Shop – Simple order forms with TWINT & STRIPE Payment» a tu idioma.
¿Interesado en el desarrollo?
Revisa el código , echa un vistazo al repositorio SVN o suscríbete al registro de desarrollo por RSS.
Registro de cambios
2.3.0
- New Bank transfer payment method with a per-language description block. The merchant edits the IBAN / BIC / beneficiary in Réglages › Paiement under each language accordion — the input is a multi-line textarea with a fake-data placeholder so an empty field at least shows the expected shape at checkout. The description is rendered with
white-space:pre-wrapat checkout (so the IBAN / BIC / beneficiary stay on their own lines) AND injected into the customer confirmation e-mail in the language the customer used to place the order (resolved via the_p4all_langmeta persisted at submission time). - Internal :
Mailer::payment_instructions()now takes an explicit$langargument and delegates toSchema::payment_description($method, $lang)for every method — so any future manual method inherits the same per-language override chain (per-lang primary-lang localised default FR default). - Translations : « Virement bancaire » label already shipped in the 2.1.0 batch — de : « Banküberweisung », it : « Bonifico bancario », en : « Bank transfer ». The multi-line default templates live in
Schema::PAYMENT_DESC_DEFAULTS['bank_transfer']as per-language constants.
2.2.0
- New Per-form photo size picker on the form editor (Affichage › Taille). Choose Petite (60 px), Moyenne (120 px), Grande (200 px) or Personnaliser… — the last one reveals a pixel input clamped between 20 and 1000. In List layout the value constrains the photo’s width; in Grid layout its height. Implemented via two CSS custom properties (
--p4all-photo-w,--p4all-photo-h) set on the form wrapper, no inline<style>block emitted. - Documentation : previously introduced « Remember my information » checkbox on the customer step is now clearly listed under Core features (persisted in
localStoragefor 1 year, per form, no HTTP cookie).
2.1.0
- New « Remember my information » opt-in checkbox on the customer step. When ticked, the customer’s contact fields are persisted in the browser’s own
localStorage(scoped per form, retention 1 year, no HTTP cookie set) and pre-filled on the next visit. Unticking + clicking Suivant clears the memory. Ships with FR / DE / IT / EN translations. - Pay4All Age integration : the « Vérification d’âge » step now auto-skips when the current cart carries no age-restricted product. The customer no longer has to click Suivant on an empty age-check step just because the form’s product catalogue happens to include an adult item they didn’t add to their order. Implemented via a generic
data-p4all-skip="1"contract on any.p4all-step, so companion plugins can use the same escape hatch. - Checkbox alignment polish : the standalone « Remember me » checkbox uses the same inline-flex layout as the existing checkbox fields (defensive against themes that turn every input into
display:block, e.g. Elementor / Astra Ecommerce).
2.0.0
- Breaking change — five features moved to a separate Pay4All Pro plugin. The free version keeps the form builder, products, deliveries, virtual downloads, orders and e-mails; the following move out:
- Product filter widget on the public form (categories / brands / sort dropdowns).
- Categories taxonomy (
p4all_product_cat) — including per-language names and per-category quantity rules (min / max / multiple / exact). - Brands taxonomy (
p4all_product_brand) — same shape as categories. - Abandoned cart capture, recovery e-mail and admin page.
- Ticket product type (QR codes for events) — including the Billets admin page and the public
/p4all-ticket/…validation URL.
- Automatic clean-up on upgrade — activating 2.0.0 once drops the
wp_p4all_ticketsandwp_p4all_abandoned_cartstables, deletes every term inp4all_product_cat/p4all_product_brand, deletes every ticket post, and un-schedules the hourlyp4all_abandoned_cart_tickcron event. Idempotent, guarded by an option so re-installs skip it. - XLSX export removed on both the orders CSV screen and the products import/export screen. CSV export is unchanged. XLSX moves to Pro.
- Product edit screen : the Billet (QR code) option is removed from the product-type dropdown. Existing tickets keep rendering as Physical until edited.
- Settings › General : Délai d’envoi du mail d’abandon de panier setting removed (no longer used).
- Help page : reworded to reflect the trimmed feature set.
- Internal : new
Domain\Languagehelper replacesDomain\Category::current_language()at every call site.
1.4.3
- New Content picker next to each URL field — a « 🔗 Rechercher » button opens a mini search panel that queries pages, posts, WooCommerce products, every public custom post type, and media attachments (PDFs, images, mp3…). Clicking a result drops the full URL into the input. WPML / Polylang are detected automatically: on the DE tab the search only returns DE pages, on IT only IT, etc. Media stays language-agnostic (a PDF is the same file in every locale). AJAX endpoint requires
edit_posts+ a nonce. - Full DE / IT / EN translations for the eleven new admin strings introduced by the « Learn more » link, the picker, and the photo lightbox (labels, placeholders, help text, status messages).
- Plugin Check compliance polish —
phpcs:disable/phpcs:enableblock around the$_FILESsanitisation inMetaBoxes::store_virtual_upload()(nonce is verified upstream insave()); documented ignores for WPML’s publicwpml_switch_languagehook (must be invoked verbatim to trigger their language switcher) and for the intentionalsuppress_filterson the media query used by the picker (language-agnostic search is the product decision).
1.4.2
- New « Learn more » link per product — two new fields (URL + link label) on each language tab of the product edit screen. When the URL is set, a link is rendered under the short description in the order form and opens in a new tab. The Link label field is pre-filled with a language-specific default on every tab (FR « Découvrez en plus… », DE « Erfahren Sie mehr… », IT « Scopri di più… », EN « Learn more… ») regardless of the admin’s own locale; the merchant is free to overwrite any of them. Same default kicks in on the front-end so a visitor in DE (or IT / EN) always sees the label in their language, even when the merchant left the field blank. URLs are validated at save with
esc_url_raw()(http / https / mailto / tel only,javascript:rejected). - New Product photo lightbox — clicking the product thumbnail on the first step of the form now opens the full-size photo in an overlay. Keyboard-accessible (Enter / Space to open, ESC to close), non-destructive to the form (body scroll is temporarily locked). No dependency added; pure vanilla JS.
- Security hardening — three fixes triggered by an internal security review:
- Path traversal fix in the virtual-download endpoint (
?p4all_dl=). The customer-facing streamer now rejects any filename containing directory separators,.., or NULL bytes, and enforces arealpath()boundary check that guarantees the resolved path lives inside the private uploads folder. Protects against manipulated_p4all_virtual_downloadsmeta on stores with a compromised admin account or a SQL injection introduced by a third-party plugin. - X-Frame-Options / CSP frame-ancestors now emitted on every front-end page rendering the
[pay4all_form]shortcode. Default:SAMEORIGIN— blocks brand impersonation via cross-origin iframes and closes the per-domain-licence bypass some agencies used by iframing a licensed shop on many client sites. Configurable via a new Réglages › Général option (sameorigin/deny/off). - Virtual-product upload allowlist — merchant-configurable list of accepted file extensions (default:
pdf, mp3, mp4, m4a, epub, zip, jpg, jpeg, png, gif, svg, doc(x), xls(x), ppt(x), txt, csv, html). Blocks executable uploads (.php,.phtml,.exe,.htaccess…) BEFOREwp_handle_upload()runs. Set the option to an empty value to restore the legacy behaviour of allowing anything. The private uploads folder is now also guarded by aweb.configdeny rule for IIS hosts, in addition to the existing.htaccess.
- Path traversal fix in the virtual-download endpoint (
- Admin menu badge polish — the «Commandes» count badge next to Pay4All SHOP now uses the same red (
#d63638) and compact sizing as WordPress core’s update available pill, and stays visible on every admin screen (previously the CSS only loaded on Pay4All Form pages, so the badge disappeared on the Dashboard). - Admin menu i18n — sub-entries Paramètres and Licences under Pay4All AGE, plus the WooCommerce entry-point label, are now localised in DE / IT / EN based on the admin locale.
- KYC tab visual polish — the accordion widget on Réglages › Protection des mineurs now matches the visual language of the Paiements tab (rounded card,
▾chevron, language pill), and the accordions honour the languages selected in Réglages › Langue (so a DE-only shop only shows the DE accordion here). - Plugin Check clean-up — nonce comments,
sanitize_text_field( wp_unslash() )on remaining$_POSTreads,esc_url()on the licence page form action,wp_delete_file()in the KYC storage purge, and Plugin Check ignore blocks documented for WPML hooks (wpml_element_trid,wpml_get_element_translations) that intentionally do not carry the plugin prefix.
1.4.1
- New Client-side product filtering — an optional filter bar can be enabled per form (Form editor › Affichage des produits › Afficher les filtres). Customers can narrow the product list on the first step by category, brand and sub-taxonomies, with an optional item-count next to each option. Fully client-side, no page reload.
- Multilingual category / brand labels — every category and brand can carry a customer-facing name in each activated language, plus a « Tous les… » label for filter dropdowns. Empty fields fall back to the WordPress canonical term name. Drag-and-drop reorder from the taxonomy list.
- Minimum order amount is now per-form — the Montant minimum de commande panel has moved from Réglages › Commandes to each form’s edit screen (right above Affichage des produits), so different forms can have different thresholds. Includes the per-language error message (with
%sfor the amount) and live validation on the product step: the Suivant button is blocked and a red alert appears as soon as the subtotal drops below the floor. Existing global setting is honoured as fallback for forms that haven’t set their own. - Compatibility with Pay4All Age plugin improved.
1.4.0
- New Compatible with Pay4All AGE Protection of minors (age verification) — enable per product with the Requires age verification checkbox on the product edit screen. At checkout the customer scans a QR code, opens a mobile page and captures their ID (recto + verso) and a selfie; the order cannot be validated until every required slot is present.
- Cross-device flow — the QR code embeds a short-lived session token (20 min); the desktop cart polls the server and unlocks automatically as soon as the mobile capture is complete, without asking the customer to reload.
- Encryption at rest — every photo is encrypted with AES-256-GCM using a per-order subkey derived via HMAC-SHA256 from a master key stored in
wp-content/uploads/p4all-secure/kyc.key(outside the database backup). Ciphertexts live in a private folder guarded by.htaccess+index.php+web.config. - Admin-only decrypted view — a Protection des mineurs section on the order page streams the decrypted photos through a nonce-protected admin endpoint (never served publicly, never written back to disk).
- Yellow warning banner in the admin new-order e-mail when the order requires age verification, with a Voir la commande button that links straight to the order edit screen.
- Auto-purge — deleting an order also deletes its KYC directory. A daily cron purges session buckets older than 24 h.
- All KYC-related strings translated in FR / DE / IT / EN.
1.3.1
- New Timezone setting in Settings › General — surfaces the WordPress global timezone selector for admins who don’t know where to find it. Defaults to Europe/Paris when not configured. Modifying it updates the standard WP
timezone_stringoption. - Dates in Pay4All Shop › Abandon panier admin page now use
get_date_from_gmt()for accurate conversion of UTC-stored timestamps to the site’s configured timezone. - Renamed menu label from Abandon de panier to Abandon panier for compactness; sub-menu translated in all four languages.
- Plugin Check / WP.org compliance: escaped
$cart_idoutput in the abandoned-cart view dialog, and addedWordPress.DB.PreparedSQL.InterpolatedNotPrepared+PluginCheck.Security.DirectDB.UnescapedDBParameterignores on thewp_p4all_abandoned_cartscustom-table queries (table name built from$wpdb->prefix+ literal suffix).
1.3.0
- New Abandoned cart capture and recovery — when a customer fills the contact-info step (with their e-mail) and clicks Next but never validates, the cart is stored. A recovery e-mail with a one-time link is automatically sent after a configurable delay (default 10 days). Clicking the link returns the customer to the form with all their items, contact fields, delivery and payment method already pre-filled.
- New admin page Pay4All Shop › Abandon panier (above Billets) — lists every captured cart with filters (pending / e-mail sent / recovered / converted), totals, dates and a delete action.
- New setting Réglages › Général › Délai d’envoi du mail d’abandon de panier (jours) — 0 disables, default 10. Carts older than 90 days are automatically purged (GDPR).
- New e-mail template Abandoned cart recovery in Réglages › E-mails, editable per language (subject / heading / intro / outro), with
{site_name},{customer_firstname},{customer_email}and{recover_url}placeholders. - GDPR exporter and eraser hooks include abandoned-cart rows in WordPress’s Tools › Export / Erase Personal Data.
- Hourly cron
p4all_abandoned_cart_ticksends due recovery e-mails and purges old rows.
1.2.0
- New Hide a product checkbox on the product edit screen — the product is omitted from the form entirely (no badge, no greyed-out field). Server-side rejects any tampered order containing a hidden product. Useful for archiving seasonal items without deleting them.
- Stock-related checkboxes reordered for clarity: Hide this product Out of stock Manage stock (+ quantity field).
- New Stock management (optional, per product) — tick Manage stock on a product to track its quantity. Stock is decremented at every order (one unit per ticket / per item), the customer cannot order more than what is left, and the product is automatically flagged out of stock when the stock hits 0.
- Stock restored on order deletion — deleting an order definitively (from trash or via the delete button) restores the stock of every product still present in that order. Status changes (paid, cancelled, etc.) do not restore stock; only deletion does.
- Low-stock e-mail alert — set Settings › General › Notify me when stock reaches (under the shop address) to a non-zero threshold; an alert is e-mailed to the notification address each time a tracked product crosses the threshold downwards after a sale.
- New Stock column in the products admin list — shows
—when stock management is off, the current quantity otherwise (orange if at or below threshold, red0 Out of stockwhen empty).
1.1.0
- New product type Virtual — upload one downloadable file per product, customer receives a one-time link valid 60 days, served by the plugin’s protected endpoint (files stored in a private folder with deny-all
.htaccess). - New product type Ticket — one QR code per seat ordered, sent in the order email, scannable from any smartphone, with a public validation page showing green (available) or red (already used).
- New admin page Pay4All Shop › Billets — list every QR ticket, search by first/last name / city / e-mail, validate manually, export to CSV.
- Out of stock flag on every product — product stays visible, quantity field is greyed and disabled, server-side rejects tampered orders.
- Default form fields (first name, last name, e-mail, phone, address, etc.) are now pre-translated in every activated language at form creation time.
- Per-delivery payment methods — accepted payment methods are now configured per delivery method (a delivery edit screen has a Modes de paiement acceptés section), so each delivery can show its own payment choices to the customer. Forms without any delivery still use the legacy per-form payment picker.
1.0.0
- Initial release.
