{"id":366925,"date":"2026-10-06T02:51:18","date_gmt":"2026-10-06T02:51:18","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/equashop\/"},"modified":"2026-10-06T02:51:00","modified_gmt":"2026-10-06T02:51:00","slug":"equashop","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/equashop\/","author":23540548,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.4.0","stable_tag":"1.4.0","tested":"7.1.3","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"EquaShop","header_author":"EquaDev","header_description":"Generic Stripe-powered subscription shop for WordPress: multilingual catalogue, plans and storefront. Runs standalone; part of the EquaSuite range. Works with the optional EquaFulfil companion plugin, and can display content from the optional EquaMarket remote service (a web service, not an installed plugin).","assets_banners_color":"4c6076","last_updated":"2026-10-06 02:51:00","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/equasuite.equadev.fr\/shop\/equashop","header_author_uri":"https:\/\/equasuite.equadev.fr","rating":0,"author_block_rating":0,"active_installs":0,"downloads":200,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","faq","changelog"],"tags":{"1.4.0":{"tag":"1.4.0","author":"equadev","date":"2026-10-06 02:51:00","revision":3729911}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3729914,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3729914,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3729914,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3729914,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.4.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3729914,"resolution":"1","location":"assets","locale":"","width":1532,"height":891},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3729914,"resolution":"2","location":"assets","locale":"","width":1322,"height":4924},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3729914,"resolution":"3","location":"assets","locale":"","width":601,"height":1151},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3729914,"resolution":"4","location":"assets","locale":"","width":1874,"height":6244}},"screenshots":{"1":"The storefront \u2014 your product catalog, built from your Stripe products.","2":"Product page \u2014 image, description, price and one-click checkout.","3":"Secure checkout powered by Stripe, with buyer consent handling.","4":"Product setup in the admin \u2014 Stripe price, image and per-product coupon."}},"plugin_section":[],"plugin_tags":[282,99,1242,5349,4079],"plugin_category":[41,45,48],"plugin_contributors":[279745],"plugin_business_model":[],"class_list":["post-366925","plugin","type-plugin","status-publish","hentry","plugin_tags-ecommerce","plugin_tags-multilingual","plugin_tags-shop","plugin_tags-stripe","plugin_tags-subscriptions","plugin_category-communication","plugin_category-ecommerce","plugin_category-language-tools","plugin_contributors-equadev","plugin_committers-equadev"],"banners":{"banner":"https:\/\/ps.w.org\/equashop\/assets\/banner-772x250.png?rev=3729914","banner_2x":"https:\/\/ps.w.org\/equashop\/assets\/banner-1544x500.png?rev=3729914","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/equashop\/assets\/icon-128x128.png?rev=3729914","icon_2x":"https:\/\/ps.w.org\/equashop\/assets\/icon-256x256.png?rev=3729914","generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/equashop\/assets\/screenshot-1.png?rev=3729914","caption":"The storefront \u2014 your product catalog, built from your Stripe products."},{"src":"https:\/\/ps.w.org\/equashop\/assets\/screenshot-2.png?rev=3729914","caption":"Product page \u2014 image, description, price and one-click checkout."},{"src":"https:\/\/ps.w.org\/equashop\/assets\/screenshot-3.png?rev=3729914","caption":"Secure checkout powered by Stripe, with buyer consent handling."},{"src":"https:\/\/ps.w.org\/equashop\/assets\/screenshot-4.png?rev=3729914","caption":"Product setup in the admin \u2014 Stripe price, image and per-product coupon."}],"raw_content":"<!--section=description-->\n<p>EquaShop turns WordPress into a clean subscription storefront. You define products, billing plans (monthly \/ every 6 months \/ yearly), and rich multilingual marketing content, then sell them through Stripe.<\/p>\n\n<p>It ships a complete selling engine: a multilingual catalogue admin, a public storefront via shortcodes, a Stripe-powered checkout tunnel (subscriptions and one-off), a self-owned versioned consent referential, and native order management. The product catalogue is always unlimited and the ability to sell is never limited.<\/p>\n\n<h4>Two-layer internationalisation<\/h4>\n\n<ul>\n<li><strong>Admin strings<\/strong> \u2014 standard WordPress gettext (text domain <code>equashop<\/code>), driven by the admin's WordPress locale. The admin ships in English (source); a translation template (<code>languages\/equashop.pot<\/code>) is included, and community translations are served through translate.wordpress.org.<\/li>\n<li><strong>Storefront content &amp; strings<\/strong> \u2014 fully translatable by you in the five shipped languages (English, French, Spanish, German, Portuguese). Strings resolve in three steps: your admin override \u2192 a built-in default for the shipped languages \u2192 fall back to your default shop language.<\/li>\n<\/ul>\n\n<h4>Admin<\/h4>\n\n<ul>\n<li><strong>Products<\/strong> \u2014 multilingual catalogue: non-translatable fields (slug, logo, reference price), billing plans, and per-language label \/ description \/ features \/ benefits.<\/li>\n<li><strong>Languages<\/strong> \u2014 configure your shop languages among the five shipped ones and pick exactly one default (fallback).<\/li>\n<li><strong>Storefront translations<\/strong> \u2014 override every storefront string per language.<\/li>\n<li><strong>Settings<\/strong> \u2014 Stripe keys, cart &amp; storefront behaviour, demo data management.<\/li>\n<\/ul>\n\n<h4>Standalone, with optional companions<\/h4>\n\n<p>EquaShop requires no other plugin to run \u2014 it works as a generic shop for any vendor. It is part of the EquaSuite range: when the optional EquaFulfil companion plugin is installed, EquaShop delegates order fulfilment to it. It can also, entirely optionally and off by default, display content from the EquaMarket service \u2014 a remote HTTPS service, not an installed plugin (see External services). Neither is required; without them the shop stays fully functional.<\/p>\n\n<h4>Fonts<\/h4>\n\n<p>The storefront embeds the open-source fonts <strong>Plus Jakarta Sans<\/strong> and <strong>Inter<\/strong> (SIL Open Font License 1.1), so it never depends on a theme or a CDN.<\/p>\n\n<h3>External services<\/h3>\n\n<p><strong>Stripe (payment processing \u2014 required to sell).<\/strong> EquaShop uses Stripe (<code>api.stripe.com<\/code>) for everything money-related. It contacts Stripe:<\/p>\n\n<ul>\n<li>at <strong>checkout<\/strong>, to create the Stripe customer and the subscription or one-off payment (sending the buyer's name and e-mail, the cart contents and amount);<\/li>\n<li>to <strong>read prices<\/strong>, on demand and on a scheduled <strong>WP-Cron price sync<\/strong> you configure in <em>Settings \u203a Stripe sync<\/em> (refreshing the cached amounts of your tariffs);<\/li>\n<li>during <strong>product import<\/strong>, to list your Stripe products and to <strong>download each product's image<\/strong> into your Media Library;<\/li>\n<li>on the <strong>\"Test connection\"<\/strong> button in <em>Settings \u203a Stripe keys<\/em>, to query your Stripe account.<\/li>\n<\/ul>\n\n<p>Stripe also notifies your site by <strong>webhook<\/strong> (Stripe \u2192 your site) to record paid orders and renewals. Stripe Terms: https:\/\/stripe.com\/legal \u2014 Stripe Privacy: https:\/\/stripe.com\/privacy<\/p>\n\n<p><strong>EquaMarket content service \u2014 marketing.equadev.fr (optional, opt-in \u2014 OFF by default).<\/strong> EquaShop can display EquaSuite news and offers as an admin banner and an \u201cEquaSuite\u201d page inside the WordPress admin. This feature is <strong>off by default<\/strong> and only makes a request if you explicitly authorise it in <em>Settings \u203a EquaSuite<\/em> \u2014 a technical server-call authorisation, distinct from any marketing consent, revocable at any time. When enabled, and only while viewing an EquaShop admin screen, the plugin requests this content over HTTPS from <code>https:\/\/marketing.equadev.fr<\/code>. It sends the technical values needed to serve the right content: the plugin identifier (<code>equashop<\/code>), the content edition it runs (<code>free<\/code>), and the language of the plugin's admin display. In addition, WordPress's own HTTP user-agent carries your site's URL and WordPress version, and \u2014 as with any request \u2014 your server's IP address is visible to the server it contacts; none of these transport values is used. No personal data is collected for marketing or prospecting when querying the <code>marketing.equadev.fr<\/code> server. The content is display-only (admin-only, never on the storefront). Terms of use for this service are the EquaShop End-User Licence Agreement \u2014 https:\/\/equasuite.equadev.fr\/contrat-de-licence\/ .<\/p>\n\n<h3>For developers<\/h3>\n\n<p>EquaShop exposes a small, stable set of public extension points so other code can react to its lifecycle and integrate with it. None of them are required to run the shop; each is simply a documented moment (a hook or a method) you may use.<\/p>\n\n<h4>Payment signal<\/h4>\n\n<ul>\n<li><code>equashop_payment_processed<\/code> (action) \u2014 fires once a paid order has been recorded, on both the subscription and the one-off checkout paths. Listeners receive one associative-array payload with a fixed, versioned key shape (the payment hook, contract v4). Use it to react to a completed sale \u2014 fulfilment, CRM, accounting, and so on.<\/li>\n<\/ul>\n\n<h4>PHP API fa\u00e7ade<\/h4>\n\n<ul>\n<li><code>EquaShop_Api<\/code> (class) \u2014 a read-mostly, static-method integration surface for in-process consumers; always call it under your own <code>class_exists( 'EquaShop_Api' )<\/code> guard. Catalogue identity: <code>enumerate()<\/code>, <code>get_product()<\/code>, <code>count()<\/code>. Availability verdict: <code>set_availability()<\/code> (a binary in-stock \/ out-of-stock verdict). Order read and sync: <code>get_order()<\/code>, <code>get_orders_by_ids()<\/code>, <code>orders_cursor()<\/code>, <code>orders_delta()<\/code>, <code>set_order_status()<\/code>, <code>update_order_field()<\/code>. Method names and return shapes are kept stable (contract version 3).<\/li>\n<\/ul>\n\n<h4>Lifecycle &amp; data hooks<\/h4>\n\n<ul>\n<li><code>equashop_after_create_tables<\/code> (action; args: table prefix, charset\/collate) \u2014 fires after the base tables are created or upgraded, on both fresh install and upgrade. A moment to create your own related tables.<\/li>\n<li><code>equashop_after_seed<\/code> (action) \u2014 fires after the base seed data is written. A moment to seed your own related data.<\/li>\n<li><code>equashop_before_product_delete<\/code> (action; arg: product id) \u2014 fires just before a product (and its i18n and price rows) is deleted.<\/li>\n<li><code>equashop_before_price_delete<\/code> (action; args: product id, months) \u2014 fires just before a single tariff row is deleted.<\/li>\n<li><code>equashop_product_save_columns<\/code> (filter; args: columns map, submitted data) \u2014 filter the column\/value map written when a product is saved. With no listener the map is unchanged.<\/li>\n<li><code>equashop_product_price_saved<\/code> (action; args: tariff row id, tariff data) \u2014 fires after each tariff row is upserted during a product save.<\/li>\n<li><code>equashop_demo_installed<\/code> (action; arg: array of product ids) \u2014 fires after the demo products are installed.<\/li>\n<li><code>equashop_demo_removed<\/code> (action) \u2014 fires after the demo data is removed.<\/li>\n<li><code>equashop_fulfilment_active<\/code> (filter; default false) \u2014 return true to take over the native Orders screen; used by a fulfilment companion plugin (returns false when none is present).<\/li>\n<li><code>equashop_checkout_finalize_error<\/code> (action; args: stage, product slug, WP_Error or null) \u2014 fires when a checkout line cannot be finalised (coupon or subscription), for logging or alerting.<\/li>\n<li><code>equashop_content_slot<\/code> (filter; default <code>free<\/code>) \u2014 the opaque content-set key sent to the EquaMarket content service (see External services); it names which content set the server should return. Return a different key to request another content set.<\/li>\n<\/ul>\n\n<!--section=faq-->\n<dl>\n<dt id=\"can%20i%20sell%20already%3F\"><h3>Can I sell already?<\/h3><\/dt>\n<dd><p>Yes. On first activation you review and accept the End-User Licence Agreement and the liability limits on a one-time screen (EquaShop's own admin pages wait behind it; your site and storefront are unaffected). Then publish the storefront with the shortcodes, add your Stripe keys in <em>Settings \u203a Stripe keys<\/em>, and buyers can subscribe or buy through the Stripe checkout tunnel; paid orders are recorded and shown in the Orders screen.<\/p><\/dd>\n<dt id=\"how%20are%20stripe%20keys%20protected%3F\"><h3>How are Stripe keys protected?<\/h3><\/dt>\n<dd><p>The publishable key is stored as-is (it is public). The secret key and webhook secret are encrypted at rest with a key (<code>EQUASHOP_KEK<\/code>) kept only in <code>wp-config.php<\/code>, never in the database. From <em>Settings \u203a Stripe keys<\/em> you generate this key with one click and the plugin writes it to <code>wp-config.php<\/code> for you (through WordPress's file API); when the file is not writable, the same screen shows the exact line to add by hand. Nothing is written at activation, and until a key is set the admin warns you that the secrets are stored in plain text. On uninstall the line is left in place \u2014 remove it by hand if you wish.<\/p><\/dd>\n<dt id=\"does%20uninstalling%20delete%20my%20data%3F\"><h3>Does uninstalling delete my data?<\/h3><\/dt>\n<dd><p>Only if you tick <em>\u201cDelete data on uninstall\u201d<\/em> in the settings (OFF by default).<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>Maintenance and refinement release \u2014 no change to how your shop sells, and no database change. Internal source clean-up (comments and identifiers) for a tidy submission. On the Withdrawal notice screen, switching the behaviour (blocking waiver \/ display-only notice) now fills each language with the wording that matches the chosen mode, and never overwrites text you have already edited. The encryption key (<code>EQUASHOP_KEK<\/code>) is generated and written to <code>wp-config.php<\/code> from the Stripe settings screen with one click, through WordPress's file API (<code>WP_Filesystem<\/code>); nothing is written at activation. It never overwrites an existing key, is staged through a private temporary file in the same directory as <code>wp-config.php<\/code> that is always removed, shows the exact line to add by hand when <code>wp-config.php<\/code> is read-only, and never stores the key in the database; the line is left in place on uninstall. The payment hook (v4) keeps its byte-identical contract.<\/li>\n<\/ul>\n\n<h4>1.0.4<\/h4>\n\n<ul>\n<li>Maintenance release: internal comment and admin-label tidy-up only \u2014 no change to how your shop works, and no database change. The payment hook (v4) keeps its byte-identical contract.<\/li>\n<\/ul>\n\n<h4>1.0.3<\/h4>\n\n<ul>\n<li>Documentation and refinement release \u2014 no change to how your shop sells, and no database change. The in-product help was corrected to match the plugin exactly (out-of-stock behaviour, consents and the delivery-mode field). The payment hook (v4) keeps its byte-identical contract.<\/li>\n<\/ul>\n\n<h4>1.0.2<\/h4>\n\n<ul>\n<li>Refinement and non-destructive-downgrade release \u2014 no change to how your shop sells. New products now default to the \"Immediate execution\" withdrawal regime, so a product is compliant out of the box (fully editable afterwards). Order management is now driven by a single \"Physical order management\" setting, and its help was rewritten to match. The in-product help was tidied and de-duplicated. No database change; the payment hook (v4) keeps its byte-identical contract.<\/li>\n<\/ul>\n\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Security and refinement release \u2014 no change to how your shop works. Values submitted on the product form are sanitised before they are stored. This release also leaves wp-config.php untouched, adding the encryption key by hand from the settings screen (the automatic, writable-only write with a manual fallback is reinstated in 1.4.0). Fixed a broken documentation link in this readme. No database change; the payment hook (v4) keeps its byte-identical contract.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First public WordPress.org release. The complete selling engine: an unlimited multilingual catalogue, storefront shortcodes, and Stripe checkout for both subscriptions and one-time products. A self-owned, versioned consent referential (marketing and transactional texts, each edit archived and transmitted with the order) and a single, editable withdrawal notice (blocking waiver or informational) shown at the cart. Native order management with manual handling statuses. The storefront and the dedicated product page render inside your active theme on both classic and block themes (with an accessibility skip-link on block themes). English is the source language; community translations are served through translate.wordpress.org. Hardened for the directory: consistent input sanitisation and output escaping, and capability + nonce checks on every admin action; fixed a fatal error that could occur when refreshing a product's Stripe prices. No database change; the payment hook (v4) and PHP API fa\u00e7ade keep byte-identical contracts.<\/li>\n<\/ul>","raw_excerpt":"A generic, multilingual Stripe subscription shop for WordPress \u2014 build a catalogue of plans and sell them, with no other plugin required.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/366925","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=366925"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/equadev"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=366925"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=366925"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=366925"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=366925"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=366925"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=366925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}