Saga Payments for WooCommerce
Saga Payments for WooCommerce
Description
Saga Payments for WooCommerce is a full-featured payment gateway built for Nordic merchants. Accept secure payments through multiple payment methods with enterprise-grade features:
Payment Methods
- Card Payments – Visa, Mastercard, American Express, Discover
- Vipps – Norway’s most popular mobile payment app
- Klarna – Buy now, pay later
- Apple Pay – Fast checkout for Apple users
- Google Pay – Fast checkout for Android users
- Swish – Sweden’s most popular mobile payment app
- MobilePay – Denmark and Finland’s popular mobile payment app
Features
- Easy Setup – Just enter your Merchant ID, Terminal ID, and Public Key
- Saved Payment Methods – Customers can save cards for faster checkout
- WooCommerce Subscriptions – Full support for recurring payments with automatic renewals
- WooCommerce Pre-Orders – Charge customers when pre-ordered products become available
- Authorize & Capture – Authorize payments and capture later, or capture immediately
- Auto-Capture – Automatically capture when order status changes to Processing/Completed
- Auto-Void – Automatically void authorizations when orders are cancelled
- Express Checkout – Apple Pay/Google Pay buttons on product pages and cart
- WooCommerce Blocks – Full support for Blocks Checkout including saved cards
- HPOS Compatible – Full support for High-Performance Order Storage
- Refunds – Full and partial refunds directly from WooCommerce admin
- Professional Design – Clean, responsive payment widget
Plugin Integrations
- WooCommerce Subscriptions – Automatic recurring payments
- WooCommerce Pre-Orders – Charge on release
- WooCommerce Blocks – Full Blocks checkout support
- WooCommerce HPOS – High-Performance Order Storage
- Saga Product Sync – Bidirectional product catalogue synchronisation
- Compatible with all major WordPress themes
Product Sync (Saga)
Automatic bidirectional synchronisation between your WooCommerce store and Saga:
- Saga is master – pull products, prices, images, VAT rates and stock from Saga into WooCommerce
- Push changes back – WooCommerce product edits are automatically pushed to Saga in real-time
- Inventory sync – relative stock deltas (STOCK_DOWN / STOCK_UP) on order completion, refund and cancellation
- Auto-retry – failed inventory adjustments are queued and retried every 5 minutes (up to 20 attempts)
- Full field mapping – prices (øre <-> kroner), VAT rates (25 / 15 / 12 / 0 %), units, barcodes, cost price, images
- Admin panel – WooCommerce -> Saga Product Sync with connection test, manual sync, and status dashboard
- Configure via WooCommerce -> Saga Product Sync
Requirements
- WordPress 5.8 or later
- WooCommerce 7.0 or later
- PHP 7.4 or later
- SSL certificate (HTTPS)
- Saga Payments merchant account
External services
This plugin relies on the following external services. A Saga Payments merchant account is required. Each entry says when the service is called and what is sent to it.
Saga Payments API
All payment operations (order creation, payment verification, refunds, captures, voids, and subscription management) are handled through the Saga Payments API proxy server. When a customer initiates a checkout, order data including amount, currency, line items, and customer billing/shipping information is sent to this service via server-side HTTP requests.
The same service is also called server-side:
- To confirm that your server belongs to your Saga store, when the store is set up or its server changes: the merchant ID, the store ID and a random installation secret generated by this plugin are sent, and the service e-mails a confirmation code to the address registered for the store. The code the administrator enters is sent back to it.
- For the shop’s own access credential for this service: requested with the merchant ID, the store ID and the installation secret, and revoked when the administrator disconnects the shop.
-
When a guest customer pays with a previously saved card: the customer’s e-mail address, a generated one-time code, the store name and the cart total are sent, and the service e-mails the code to the customer through the Resend e-mail service. No card data is sent.
-
Service URL: https://sagapay-api-v3.kristoffer-afc.workers.dev/api
- Provider: Saga Payments (Cloudflare Worker proxy to Surfboard Payments)
- Website: https://sagapay.no
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga Account Connection
Used only when an administrator connects the shop to Saga, or disconnects it, from the Saga Payments settings. “Connect” sends the administrator’s browser to Saga’s sign-in page with the address of this site’s settings page to return to, a one-time state value, a PKCE code challenge and, when the shop already has one, its store ID. After the administrator approves, the plugin exchanges the one-time code for the store’s credentials in a server-side request (the code, the same return address and the PKCE code verifier are sent). “Disconnect” sends a server-side request that revokes the store’s API key, signed with the shop’s connection secret. Nothing is sent to this service during checkout.
- Service URL: https://auth.sagapay.no (authorize, token and revoke)
- Provider: Saga Payments
- Website: https://sagapay.no
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga Checkout
Used only when Saga Checkout is chosen as the checkout in the Saga Payments settings. Shops that use the standard payment form do not call these addresses.
- Checkout sessions (server-side): when a customer opens the checkout, the plugin creates a checkout session with Saga. It sends the store and terminal IDs, the order number, the order lines with their prices and tax, the shop’s shipping options, the addresses to return to after payment, the shop’s name, web address, support e-mail address, terms and privacy page addresses and accent colour, and, when the customer has already entered them in the shop, the customer’s e-mail address, name and shipping address. The plugin then reads the session’s payment status, and the order’s contact and delivery details, back from the same API. Test API keys (sg_test_) use the sandbox address.
- Checkout script and stylesheet (in the customer’s browser): Saga’s checkout script and its stylesheet are loaded from Saga’s CDN on the checkout page and display Saga’s checkout form. What the customer enters in that form goes directly to Saga. In Redirect mode the customer is sent to the checkout page address Saga returns for the session.
-
Settings screen: the “live test” in the Saga Checkout settings creates a test session with the same API and asks Saga which payment methods it would offer for it (the session ID is sent).
-
Service URL: https://carbon.sagapay.no/v1 (sandbox: https://sandbox-carbon.sagapay.no/v1)
- Script URL: https://cdn.sagapay.no/sdk/v2/sagapay.min.js
- Stylesheet URL: https://cdn.sagapay.no/checkout/v2/sagapay-checkout.css
- Payment methods URL: https://checkout.sagapay.no/v1/payment/methods/
- Provider: Saga Payments
- Website: https://sagapay.no
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga Store Details
Saga’s checkout and payment pages show the terms and privacy links registered for your store. The Saga Payments settings screen reads them from Saga when an administrator opens it, at most every 12 hours (every 10 minutes while Saga has not answered), so it can tell you when one of them leads nowhere. The merchant ID and the store ID are sent server-side. Nothing is sent from the storefront.
- Service URL: https://checkout.sagapay.no/v1/store/
- Provider: Saga Payments
- Website: https://sagapay.no
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga Payments Merchant Dashboard and Documentation
The plugin settings screen links store administrators to Saga Payments dashboard and documentation pages for API key, webhook, and product catalogue setup. These links open only when an administrator clicks them. No customer or payment data is sent automatically by these documentation links.
- Dashboard URL: https://dashboard.sagapay.no
- API key documentation URL: https://docs.sagapay.no/guides/getting-started/opprett-api-nokler
- Webhook documentation URL: https://docs.sagapay.no/guides/getting-started/webhooks
- Product catalogue documentation URL: https://docs.sagapay.no/api-reference/api-reference/product-catalogue/
- Provider: Saga Payments
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga Regnskap (Accounting) Integration
Registration: the plugin sends a registration request to the Saga Regnskap accounting service when the store owner completes merchant OTP verification or clicks the “Koble til regnskap” button in the gateway settings, so the merchant’s bookkeeping can be reconciled against the store. For a store that has a Saga merchant ID and store ID but is not connected to the accounting service (including a store that was told it has no accounting agreement), the registration is also retried once in the background after each plugin update, the next time an administrator opens the WordPress admin. Only store-level facts are sent: the Surfboard merchant ID, the store URL, the activation reference, plugin/WordPress/WooCommerce versions, currency, tax display setting and which gift card system is installed. The accounting service answers by calling this site’s /wp-json/saga-accounting/v1/handshake to confirm the domain. For a store without an agreement the plugin keeps only that answer, and no access is granted.
Seller details: once connected, the plugin asks the accounting service once a day, and when an administrator clicks “Hent selger på nytt”, for the seller’s company details that are printed on sales documents. The merchant ID and the store URL are sent.
What the accounting service reads (connected stores only, that is merchants with a Saga Regnskap agreement): order and refund totals (amounts, tax rates, Saga payment references), from a read-only, token-authenticated REST endpoint served by this plugin at /wp-json/saga-accounting/v1/. These totals contain no customer names, e-mail addresses, phone numbers, addresses or IP addresses. When sales documents are enabled, whether this plugin issues them or an invoice plugin it serves them from, the accounting service also downloads every issued sales document and credit note as a PDF from the same endpoint. A sales document identifies the buyer as the bookkeeping rules require: name, company, billing address, postcode, city, country, e-mail address and, where it applies, VAT number, together with the order lines. No payment credentials are sent.
- Service URL: https://regnskap.sagapay.no (fallback: https://saga-regnskap-api.kristoffer-afc.workers.dev)
- Provider: Saga Payments (Cloudflare Worker)
- Website: https://sagapay.no
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Surfboard Online SDK
The payment form displayed on your checkout page is rendered by the Surfboard Online SDK. This JavaScript library is loaded from an external server into the customer’s browser and handles the secure payment UI including card input fields, Vipps/MobilePay popups, Klarna widget, and Apple Pay / Google Pay buttons. Card data is entered directly into Surfboard-hosted iframes and never touches your server.
- SDK URL: https://thorium.surfgw.com/OnlineSDK.js
- Provider: Surfboard Payments
- Website: https://www.surfboardpayments.com
- Terms of Service: https://www.surfboardpayments.com/terms-and-conditions
- Privacy Policy: https://www.surfboardpayments.com/privacy-policy
Surfboard Hosted Payment Page
When the plugin is configured in redirect mode, or for certain subscription flows, the customer’s browser is redirected to a hosted payment page operated by Surfboard Payments. The order amount, currency, and return URLs are passed via the redirect. All payment data is entered on the hosted page.
- Service URL: https://pay.withsurfboard.com
- Base URL used by redirects: https://pay.withsurfboard.com/
- Provider: Surfboard Payments
- Terms of Service: https://www.surfboardpayments.com/terms-and-conditions
- Privacy Policy: https://www.surfboardpayments.com/privacy-policy
Surfboard Vipps/MobilePay Intermediary
For Vipps and MobilePay payment flows, the Surfboard SDK loads an intermediary page in an iframe to handle the mobile payment authorization. This is managed automatically by the Surfboard Online SDK and serves as the bridge between your store and the Vipps/MobilePay apps.
- Service URL: https://vipps.withsurfboard.com
- Provider: Surfboard Payments
- Terms of Service: https://www.surfboardpayments.com/terms-and-conditions
- Privacy Policy: https://www.surfboardpayments.com/privacy-policy
Google Pay API
When Google Pay is enabled as a payment method, the Google Pay JavaScript SDK is loaded in the customer’s browser to render the Google Pay button and handle the payment sheet. Payment token data is returned to your store and forwarded to the Saga Payments API for processing.
- SDK URL: https://pay.google.com/gp/p/js/pay.js
- Provider: Google
- Website: https://pay.google.com
- Terms of Service: https://payments.google.com/payments/apis-secure/get_legal_document?ldo=0&ldt=googlepaytos
- Privacy Policy: https://policies.google.com/privacy
QR Code Generation
For Swish payments, if the payment gateway does not return a pre-rendered QR code image, the plugin generates a QR code locally using the bundled qrcode-generator library (MIT license, by Kazuhiko Arase). No external service is called for QR code generation.
Saga Product Sync API
If the optional product synchronization feature is enabled, the plugin sends product data (name, description, price, VAT rate, SKU, barcode, images, categories and variants) and stock changes from your WooCommerce catalog to the Saga Payments product catalogue, and reads products, prices and stock back from it. Requests are server-side, run on a schedule and when a product is saved or an order changes stock, and use the store’s API key. Test API keys (sg_test_) use the sandbox address. This is an opt-in feature configured in the plugin settings.
- Service URL: https://carbon.sagapay.no (sandbox: https://sandbox-carbon.sagapay.no)
- Provider: Saga Payments
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Saga POS Order Sync
If the optional pickup order sync is switched on (it is off by default), an order with local pickup is sent to the shop’s Saga till so staff can prepare and hand it over. The plugin sends:
* the order lines (Saga catalogue product and variant IDs, quantity and price after discount);
* the customer’s name and phone number;
* the customer’s order note;
* whether the order is paid online or will be paid in the store.
It also reads the order’s status back. The till reports accepted, ready, picked up, paid in store or cancelled, and those reports reach the plugin’s webhook through Saga. When switched on, the plugin also adds the till’s order events to the shop’s own Saga webhook subscription. Requests are server-side and use the store’s API key. No e-mail address and no card data is sent.
- Service URL: https://carbon.sagapay.no
- Provider: Saga Payments
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Inventory Diagnostics (Administrators Only)
The Saga Payments diagnostics page has an inventory check that an administrator can run for one product. It reads that product’s stock from the Saga catalogue (and, when asked, lists the merchant’s stores and catalogues), and changes the product’s stock there only when an administrator explicitly asks for that. It sends the store’s API key and the merchant, store, catalogue and product IDs, server-side. It never runs by itself and sends no customer data.
- Service URL: https://api.sagapay.no
- Provider: Saga Payments
- Terms of Service: https://www.sagapay.no/terms-of-service
- Privacy Policy: https://www.sagapay.no/personvernserklaering
Payment Method Logos
Payment method logos (Visa, Mastercard, Amex, Vipps, Klarna, Apple Pay, Google Pay, Swish, MobilePay) are bundled locally within the plugin in SVG format. No external CDN is used for logo display.
SVG files and inline SVG markup use the standard SVG namespace URI http://www.w3.org/2000/svg and xlink namespace URI http://www.w3.org/1999/xlink as static XML identifiers; these are not external network requests.
Installation
- Upload the
saga-paymentsfolder to the/wp-content/plugins/directory - Activate the plugin through the ‘Plugins’ menu in WordPress
- Go to WooCommerce > Settings > Payments > Saga Payments
- Enter your Merchant ID and Store ID (from your Saga Payments dashboard at https://dashboard.sagapay.no) and click Save changes
- The plugin will automatically provision your Terminal ID and Public Key on save – no manual key handling required
- Enable the payment method and save
Faq
Contact Saga Payments at support@sagapayments.com to set up your merchant account.
Yes! Enable test mode in the plugin settings to test without processing real payments.
The plugin supports NOK (Norwegian Krone), SEK (Swedish Krona), DKK (Danish Krone), EUR and other currencies supported by Saga Payments.
Yes! When “Enable Saved Cards” is turned on in settings, logged-in customers can save their cards for faster future checkout.
Yes! Full integration with WooCommerce Subscriptions for automatic recurring payments, payment method changes, and subscription lifecycle management.
Yes! Set “Capture Mode” to “Authorize only” in settings. Payments are authorized at checkout and captured automatically when the order is marked Processing or Completed — or, with “Capture when: Only when the order is marked Completed”, only at Completed. You can also capture from the order page.
Reviews
Kjempe bra og enkel å bruke
By ingarb on September 28, 2026
Testet Saga Pay på en av våre kunder. Super enkelt å bli kunde, enkelt å sette opp - og alt fungerte knirkefritt og ordrene kommer inn i nettbutikken som bare det. Og alle brukerne virker veldig fornøyd også.
10/10
Changelog
4.0.802
- Improved: Saga Checkout shows the American Express logo when American Express is on for the shop, as the WooCommerce checkout does. The plugin tells Saga Checkout which card brands to show; this changes logos only, never which payment methods can be used.
4.0.801
- Fix: with American Express on, a checkout that sends the customer to the Saga payment page asked Saga to limit the page to “AMEX” among the methods. Saga refuses that, so the page was created a second time with no limit at all, and showed methods the shop had not chosen. American Express is now sent as part of card payments.
- Fix: the American Express logo is also shown in the «Sikker betaling» box under the payment method, not only next to its name. The box left it out in both the block checkout and the classic checkout.
4.0.800
- Fix: the American Express logo is shown when American Express is registered on the Saga merchant account. Before, only an “activated” status counted, so the logo was missing although American Express was enabled.
4.0.799
- Improved: pickup orders sent to the Saga till.
- A cash or split payment rounded to whole kroner at the till is no longer reported as a different amount.
- An order with an item at a 100 % discount is not sent to the till, and the order says what to do instead.
- Refunding such an order in WooCommerce no longer puts stock back, because the return at the till does that.
4.0.798
- New: pickup orders can be sent to your Saga till (off by default). When switched on, an order with local pickup appears in the till, the till reports when it is ready, picked up or paid in the store, and the customer is told when the order is ready. Orders paid in the store are documented by the till’s receipt.
- New: one-click setup from the Saga merchant portal. The portal can install, connect and configure the plugin with WooCommerce’s own checkout and Saga in redirect mode.
- Improved: the Connect button tells Saga which plugin version is connecting.
4.0.797
- Security: on a shop without a webhook secret, a payment notification no longer decides which payment an order captures or refunds. The payment id is only recorded once Saga lists it for that order.
- Security: a Saga Checkout order held for review because the payment does not match it (another country, VAT or shipping zone than the address) is no longer completed automatically by the background payment checks.
- Security: Express checkout from the cart is refused when the cart was priced for another country than the address, and an address given without a country gets the country the cart was priced for. Express now also follows the shop’s payment method rules and maximum order amount.
- Security: a link sent to an administrator can no longer put its own text into the Saga connection card or cancel a connection in progress.
- Fix: when several requests start at the same moment right after an update, the shop no longer risks losing its connection to the payment service.
- Fix: the background registration for Saga Regnskap now runs when an administrator opens the admin, not from the public WordPress scheduler, and the sales document catch-up can no longer run twice at once.
- Fix: Saga Checkout status checks are rate limited, and a customer’s name or address is no longer mistaken for a payment status when old payment attempts are cleaned up.
4.0.796
- Security: the payment id a browser reports when it finishes a payment is now only accepted if Saga confirms it belongs to that order. Before, a crafted request could make a held authorisation capture a different payment.
- Security: a payment notification only captures a held payment automatically once the payment has been confirmed with Saga.
- Security: the daily refresh of your company details for Saga Regnskap now runs when an administrator opens the admin, not from the public WordPress scheduler.
- Security: deleting a guest’s personal data no longer removes a card that a customer account has saved, or that an active subscription still uses.
- Security: messages from payment pages are checked more strictly, so another page cannot interrupt a Klarna payment or change the recorded payment method.
- Fix: stock management is only switched off for products the Saga till does not count when the stock figure was written by the sync itself. A stock count you keep in WooCommerce is never changed.
- Fix: Saga Regnskap and the sales document catch-up now agree on refunds of a sale that is still waiting for its document, never document a sale another invoice plugin already numbered, and never run twice at once.
- Improved: the American Express check no longer switches American Express on or off on an unclear answer from Saga.
4.0.795
- Fix: products from the Saga till that the till does not keep stock for are no longer shown as “Out of stock” on the web. They sell without a stock count, as at the till. Products the till created before this update are corrected automatically on the next sync, unless you have set their stock yourself in WooCommerce.
- Fix: the American Express logo now shows at checkout when American Express is activated for your Saga account, and Apple Pay and Google Pay accept American Express cards there too.
4.0.794
- Fix: when Saga Payments issues your sales documents, a paid order that could not get its document at the time of the sale (for example while the seller details were still being fetched) now gets it automatically within the hour, instead of never, and your customer receives it by e-mail in your shop’s usual order e-mail, with a line saying it was issued after the purchase. Refunds made in the meantime get their credit notes the same way. Each order gets exactly one document.
- Improved: an order whose sales document cannot be produced no longer uses up a document number when it fails.
- Fix: sales documents Saga Payments has already issued stay available to your customers and to Saga Regnskap after you install another invoice plugin.
- Improved: Saga Regnskap can now see, for every order, whether Saga Payments will issue its sales document, whether another invoice plugin does, or whether nobody in the shop does — so a sale is never documented twice.
4.0.793
- New: “Capture when” setting for authorised payments (Authorize only, and Klarna): when the order is marked Processing or Completed (as before), or only when it is marked Completed — for shops that invoice at Processing and ship later.
- Changed: authorised payments are now captured, and released when an order is cancelled, also when the order status is changed from the WooCommerce app, the REST API, a shipping or ERP integration, WP-Cron or WP-CLI — not only in wp-admin. If you set orders to Processing that way and do not want the money taken then, choose “Capture when: Only when the order is marked Completed”.
- Fix: reconnecting to Saga no longer switches “Authorize only” back to immediate capture.
- Fix: when your own system creates the order as Processing and asks Saga to capture later, the authorisation is now recorded on the order, so it is captured when the order is completed.
- Improved: the Saga Regnskap connection now reports when an order was completed, and the VAT rate of every refunded line, including refunded delivery and fees.
- Fix: product and category names reach the Saga till without HTML codes such as “&”.
- Improved: works alongside other payment methods and checkout plugins the standard WooCommerce way. Shipping, taxes and fees are recalculated as usual while you type your address, no Saga payment is prepared for shoppers who choose another payment method, and Saga’s styles only apply to Saga’s own payment windows.
- Improved: reliability of subscriptions and renewals, saved cards, captures, refunds, express checkout and the product sync with the Saga till.
- Improved: the connection between your shop and Saga is now tied to your own server. If Saga asks you to confirm your server, enter the code sent to the merchant e-mail in the Saga Payments settings.
- Fix: no more notices on PHP 8.2+ and WordPress 6.7+.
4.0.792
- Security: hardened several checkout endpoints so order details, status and payment links can only ever be seen or changed by the shopper the order belongs to.
4.0.791
- Fix: Saga Checkout embedded in your checkout page no longer changes the look of the rest of the page — your theme’s fonts, colours, links and spacing stay as they are, on desktop and phone.
4.0.789
- Fix: Saga Checkout embedded in your checkout page now looks the same on every theme. Themes that style form fields could squeeze the fields so the text you typed sat on top of the field’s label.
4.0.788
- Please update: this release strengthens how your shop connects to Saga and is required to keep taking payments — older versions are being phased out. Updating is all that is needed; if Saga Payments asks you to confirm your server after updating, it e-mails a code to the address registered with Saga.
- Improved reliability and hardening across checkout, saved cards, express checkout and product sync.
- Fix: a paid Saga Checkout order is completed as soon as Saga confirms it.
4.0.786
- New: Saga Checkout. Choose it on the Saga Payments card, right under your connection, and Saga’s checkout replaces the checkout form: the customer gives their details, chooses delivery from your own shipping rates and pays in one place, embedded in your checkout page (Inline) or on Saga’s hosted page (Redirect). Your order summary with each line’s options, a coupon field and a note to the shop stay beside it, and customers can still choose your other payment methods. Orders are created by WooCommerce’s own checkout from the cart, so product options, coupons, taxes, stock, e-mails and reports behave as with any order. The settings screen shows whether the shop is ready and can run a live test against Saga.
- New: the Saga Payments card asks where the customer pays — in your checkout page (Inline) or on Saga’s page (Redirect) — and saves with your usual Save changes button.
- Fix: the “terms and conditions” and “privacy policy” links in Saga’s checkout and payment page lead to your own pages. Saga shows the addresses registered for your store (your-shop/terms and your-shop/privacy), which led to “page not found” on shops without pages there; the shop now sends them to the terms page chosen in WooCommerce and the privacy page chosen in WordPress, and the Saga Payments card says when one still leads nowhere.
4.0.770
- Fixed: on shops where WooCommerce stores its visitor-tracking cookies base64-encoded, Saga orders still showed “Origin: Unknown”. The plugin has recorded where customers came from since 4.0.453, but read those cookies in a way that only worked for the default encoding. It now reads them exactly as WooCommerce’s own tracking script writes them, and also records the three newer campaign fields (source platform, creative format, marketing tactic).
- Fixed: “Buy now” on a product page lost what the customer chose in the product form — a customiser’s design, add-on fields and the prices they add, and attributes such as a colour picked from “any”. It now goes through the cart exactly as “Add to cart” does, with the customer’s existing cart set aside and put back untouched, and refuses with WooCommerce’s own message when a required option is missing.
- Fixed: a customer who paid with Vipps and skipped the checkout’s optional phone field left the order with no phone number, so no shipping label could be printed. The phone the payment carries is now added to any paid order that has none, before the new-order e-mail is sent. A number the customer typed is never replaced.
- Setup: connecting now includes the last step it used to leave out. Saga only accepts payments from a server it has confirmed belongs to the shop, and that confirmation was hidden at the bottom of the advanced settings, so a shop could read “ready to take payments” while its payments were refused. The code is now e-mailed as part of connecting and asked for in the connection card itself, and the card says “one step left” until it is done.
4.0.768
- Fixed: pressing Disconnect could do nothing at all, for ever. Disconnecting proves who your shop is by signing a request with its Saga secret, and that secret was only ever kept in the product sync settings. Deleting and reinstalling the plugin wipes those, so a shop that came back from a reinstall looked connected, could not prove it, and was refused by Saga every single time with nothing changed and nothing to press. The secret is now kept with the connection and restored alongside it.
- The confirmation screen now says what went wrong instead of leaving you on a dead end. It tells you whether Saga refused your shop’s identity or simply could not be reached, offers to try again, and — if it keeps failing — lets you disconnect the shop here anyway. That last option says plainly that it does not revoke the key at Saga, so you know to revoke it in the Saga portal yourself.
- Also fixed on the way: the link back to that screen was being built with its ampersands written out as HTML, which is right for a link on a page and wrong for a redirect. The browser then looked for a parameter that did not exist and reported that the link had expired.
4.0.766
- Fixed: the Disconnect button on the confirmation screen did nothing. It was being filtered through a function that allows the tags of a blog post, and a form is not one of them, so the button was stripped down to plain text before the page was sent. The question was there; there was simply no way left to answer it. Affects 4.0.765.
4.0.765
- Fixed a critical error when opening the Disconnect confirmation. The screen loaded the WordPress admin header from a context that has no admin screen, which made WordPress fire a hook without a page name and crash the site with a 500. The confirmation is now a standalone page that needs none of that. Affects 4.0.763 and 4.0.764.
- Hardened: the product sync admin no longer fatals if WordPress fires the script hook without a page name. Any plugin or theme reaching that state would have taken the whole site down with it, not just this screen.
4.0.764
- Connecting now sets capture to Immediate, so a payment is taken when the order is placed rather than authorised and captured by hand later. Shops that prefer authorise-only can still change it under Advanced.
4.0.763
- Fixed: disconnecting could happen without anyone pressing it. For one release Disconnect was an ordinary link, and anything that follows links in wp-admin — a browser prefetching, a hosting panel scanning, a crawler with an admin session — could fire it and stop the shop taking Saga payments. It now asks first on a page of its own and only acts on a submitted form. Affects 4.0.759-4.0.762; if your shop disconnected on its own, reconnect from the payment settings screen.
4.0.762
- The connection panel was redrawn: one card, the Saga mark, a single line for the account and store, and one button. Status is a quiet line rather than a badge, and Disconnect and Advanced are plain text actions. Nothing decorative.
4.0.761
- Setup: a busy moment while connecting no longer costs you the whole journey. If Saga’s sign-in service is briefly busy or unreachable at the last step, the plugin waits and asks again instead of sending you back to start. A real refusal is still reported straight away.
4.0.760
- Setup: connecting to Saga is now standard OAuth 2.0 with PKCE against Saga’s own sign-in service, instead of a bespoke handoff through the merchant portal. The secret that proves the connection belongs to this shop never leaves your server; only its hash is sent. Cancelling at the sign-in screen is reported as a cancellation, not an error.
- Setup: a newly issued key takes up to a minute to become valid everywhere, so the plugin finishes its domain and terminal setup again shortly after connecting. A connection can no longer be left half-finished by that timing.
4.0.759
- Checkout: Saga Payments no longer disappears from checkout in silence. A setup that rules out the inline card form — a missing public key, for instance — now falls back to the hosted payment page instead of hiding the payment method, and the gateway is only hidden when no payment can be taken at all.
- Admin: when the gateway really cannot take a payment, every screen says exactly why and what to do, instead of “Please complete the configuration”. One decision now answers that question, so the settings screen and the checkout can never disagree.
4.0.758
- Setup: the connection panel now states whether product sync is on or off. Connecting writes the catalogue credentials but deliberately does not start a two-way product sync, which creates, updates and retires products in both your shop and your Saga catalogue — that stays your decision. Saying so means nobody finishes a setup believing everything was switched on when one half was not.
4.0.757
- Setup: the terminal list is now read where it can actually be read. The payments connection has no route for listing a store’s terminals, which is why the reuse added in the previous release still could not see them; the plugin now asks with the merchant API credentials instead, and pages through the whole list. One test store had 226 terminals across three pages, so reading only the first page would still have missed the right one.
4.0.756
- Setup: the plugin now reuses the terminals a store already has instead of creating new ones. The route it used to list a store’s terminals answered 404 on every call, so the “find an existing terminal first” check had never actually run: every setup, and every reconnection, registered a fresh set. One test store had accumulated 100 terminals. An inline terminal is only adopted together with its own public key, so the two can never drift apart.
- Logging: which terminal was chosen, and whether it was reused or created, now reaches the log. A reuse previously left no trace at all.
4.0.755
- Setup is now one button. “Connect to Saga” sends you to the Saga merchant portal, you log in with the account you already have and pick a store, and you come back to a shop that is ready to take payments: merchant and store, API credentials, webhook and its secret, domain verification and the terminals your store is allowed to have. Nothing is typed in by hand. The defaults are redirect checkout, express buttons off, and exactly the payment methods your merchant account actually has.
- The full settings screen is still there, behind “Advanced” under the connect panel, and a shop that was set up by hand keeps showing it.
- A connected shop can be disconnected from the same panel: the key is revoked and the webhook removed at Saga before anything is cleared here.
- Product sync: a store-scoped API key (the kind the connect flow creates) requires a STORE-ID header on every catalogue call. It is now sent on every request; keys created by hand answer identically with it (measured).
4.0.754
- Setup: on a store verified for redirect payments only, whatever sits in the inline terminal field no longer hides the gateway or triggers a “public key missing” warning (availability check, settings nag, Blocks status). A redirect-only merchant who pasted the PaymentPage terminal into the inline field is now offered at checkout and pays through the payment page.
4.0.753
- Setup: a store verified for redirect payments only is set up as one. Saga verifies a store’s domain either for redirect payments only (the webshop domain alone) or for redirect and inline (the SDK host domain as well); on a redirect-only store no inline (SelfHostedPage) terminal and no public key can exist, and the API refuses to create them (TM_0001). The plugin required the SDK host domain to call a store “verified” at all, so every redirect-only store was “Pending verification” for ever: no PaymentPage terminal was set up, the gateway was not enabled, the settings page nagged about verification and offered “Fix Store (Create New)” for a store that was approved, and the gateway stayed hidden from checkout. Now the store’s verification scope is read from the API on every status check; a redirect-only store gets its PaymentPage terminal, is locked to Redirect (every checkout mode option, and the mode resolver), is enabled, and the settings page, status badge, notice and email say “verified for redirect payments”. A store verified for inline whose inline terminal could not be created still gets its PaymentPage terminal and is enabled for redirect payments instead of being left with nothing.
4.0.752
- Checkout: when the Saga gateway is not offered for a basket (credentials, currency, an amount or country rule from another plugin), nothing of ours is drawn any more. Before, the checkout script still loaded because the gateway was enabled, and after ten seconds its fallback injected the Saga payment box — logos and “Sikker betaling” — inside another gateway’s description (measured on a live store: it appeared under Direct bank transfer, with no way to choose Saga). The script is now only loaded when WooCommerce itself lists the gateway, and the fallback only ever draws inside the gateway’s own list item.
- Checkout: a redirect-only store (PaymentPage terminal configured, no inline terminal) is no longer hidden from checkout for lacking a public key. The public key belongs to the inline SDK; the settings screen has not required it for redirect-only stores since 4.0.469, but the availability check still did, so such a store’s gateway silently vanished from the payment list. The availability check and the Blocks status now follow the same rule as the settings screen: the key is required exactly when an inline terminal is configured.
4.0.751
- Product sync: a WooCommerce sale is no longer frozen into the catalogue product. Since 4.0.556 the sale price was also written into productProperties (_campaignPrice / _campaignActive / salePrice) for the till to charge — but those properties are create-only upstream, so a product created while on sale kept the sale price in the catalogue after the sale had ended in the shop (measured 2026-09-17), and a till reading that field would keep charging it. The sale now travels only as the catalogue’s campaign entity (created and deleted with the sale since 4.0.748), which the till is being updated to read.
4.0.750
- Product sync: a SKU set at the till reaches WooCommerce. SagaPOS stores a product SKU of exactly 4, 6 or 8 digits as the catalogue’s hsnCode and any other SKU as productProperties._sku; the pull read neither, so every product created on the till arrived in WooCommerce without a SKU. Both are read now (confirmed with the SagaPOS team). A variation’s SKU is read from variantProperties._sku; a variation’s hsnCode is the till’s HSN column and is never taken as a SKU.
- Product sync: a SKU set in WooCommerce reaches the till by the same rule — 4/6/8 digits as hsnCode (unless a real HSN code is set on the product, in which case the SKU travels as productProperties._sku), anything else as productProperties._sku — so the register can show it. A variation’s SKU is sent as variantProperties._sku.
4.0.749
- Product sync: a variation deleted in WooCommerce now leaves the till. The catalogue has no DELETE on …/variants/{id}; a variant is removed by DELETE /catalog/{catalogue}/products/{variantId} — the variant id in the product slot, storeId as a query parameter. Measured with the Saga API team. The same call with the parent id would delete the whole product, so the plugin refuses to send it unless the id is a stored variant id that differs from the parent’s.
- Product sync: a variation’s barcode reaches the till. The catalogue drops the barcode on variant create in either casing and only takes it via a PATCH afterwards; the plugin now sends that PATCH right after the create.
- Product sync: the product barcode is sent under the lowercase key only — a camel-cased key in an update is rejected by the catalogue (PC_0038).
- Product sync: a product deleted at the till (or in the catalogue) no longer comes back from WooCommerce under a new id. The push’s link check unpinned every linked product whose id the catalogue list no longer held and re-created it — measured on panta.no: a product deleted upstream at 15:57 was back at 16:00:54 with a new id, while the orphan check was correctly waiting out its grace. The link check now only unpins products pinned to ANOTHER catalogue (a moved store); a product pinned to this catalogue and gone from it is left to the orphan check, which retires the shop’s copy — the till’s deletion wins, and restoring it from the trash re-creates it. Links without a catalogue stamp are not judged within 15 minutes of their last push (the list does not always show a product created seconds ago).
4.0.748
- Product sync: a WooCommerce sale now reaches the till. The campaign call used a portal-style path (…/product-catalogue/…/product/…/product-campaign) that the catalogue API answers with 404; the route is /catalog/{catalogue}/products/{product}/campaign with the campaign name and a fixed amount in minor units. Verified against the API together with the Saga API team.
- Product sync: the product barcode/GTIN now reaches the till. The catalogue stores it under
barcode(lowercase); the plugin sentbarCode, which the catalogue accepted and silently dropped, so every GTIN came back empty.
4.0.747
- Product sync: a product without a SKU is recognised by its name when pushed, the way the pull has always recognised it. The push’s duplicate check was SKU-only, so a SagaPOS-born product with no SKU that also existed in WooCommerce was pushed as a NEW catalogue product — the till showed it twice, and the shop was linked to the copy. Measured: thirteen such copies on the test store, now healed. Exactly one catalogue product with the same name that nobody else owns is linked; an ambiguous name is not guessed.
4.0.746
- Product sync: a product the shop put in the trash does not come back on its own. Every WooCommerce lookup the pull used to recognise a product is blind to the trash, so a catalogue row whose shop product had been trashed (the withdrawal failed, or the row was a second copy) matched nothing and was created again as a new product on the next pull — measured on 2026-09-10, two products trashed at 11:35 were back, published, at 11:36. A trashed product with the same SKU, or the same exact name, now stops the create; the log says which product and what to do (restore it in WooCommerce, or delete the row in SagaPOS).
4.0.745
- Product sync: a variation’s price now goes up through the tax lens like every other price. The variant payload was built outside the mapper and skipped the lens, so for a shop storing prices without tax the pull read a variant through the lens while the push sent it bare — the two disagreed by the rate on every run (measured on the live tax drive).
4.0.744
- Product sync: the catalogue’s VAT is the shop’s own echo when it is what the push sent. A product pushed in a tax class the nominal map does not know (a Norwegian shop’s
redusert-sats, say) while that class had no rate went up with “VAT 25”; the first pull read 25, had never seen a rate on the product, called that a change made at the till and set the class to standard — the merchant’s class gone, silently, and every later pull priced the product at the wrong rate. A rate that equals what the push would send for the class the product has is not a change and is not a mismatch; only a rate that differs from that, and from the last one seen, reaches the shop.
4.0.743
- Product sync: a variable product that manages one stock count for all its variations sent that count up once PER VARIANT (measured: a parent with 7 units and two variations put 14 on the till), and the pull then switched each variation to its own stock management with the parent’s number (the shop would have sold 21). The parent’s count now goes up once, on the product; a parent-managed variation is left as the merchant set it.
4.0.742
- Product sync: the tax lens on the pull is the class the product HAS in the shop, not the class the payload’s nominal VAT maps to. Measured on the live tax drive: a product in the reduced class was pushed at 80 × 1,15 = 92,00 and pulled back as 92,00, because the payload said VAT 25, the map said standard, and standard had no rate.
- Product sync: the till is told the VAT the shop …