Solidgate Payment Gateway for WooCommerce

Beskrivelse

Solidgate Payment Gateway for WooCommerce integrates the Solidgate payment platform into your WooCommerce store. Customers can pay by credit or debit card directly on your checkout page using an embedded payment form, or be redirected to a Solidgate-hosted payment page.

The plugin supports both the classic WooCommerce checkout and the modern Gutenberg block-based checkout out of the box.

Key features

  • Embedded payment form — card fields and APM buttons appear directly inside the checkout payment section as soon as the customer selects this gateway, no redirect required.
  • Hosted payment page — redirect customers to a Solidgate-hosted page to complete payment.
  • Classic and block checkout — fully compatible with both the legacy WooCommerce checkout and the WooCommerce Blocks (Gutenberg) checkout.
  • BLIK — automatically rendered for PLN orders with a Poland billing address.
  • MB Way — automatically rendered for EUR orders with a Portugal billing address.
  • Bizum — automatically rendered for EUR orders with a Spain billing address.
  • Webhook-based order updates — order status (authorized, settled, declined, refunded) is updated in real time via Solidgate webhooks.
  • Refunds from WooCommerce admin — issue full or partial refunds directly from the order screen.
  • HPOS compatible — fully supports WooCommerce High-Performance Order Storage (custom order tables).
  • Logging — optional debug logging to the WooCommerce log for troubleshooting.

How APMs work

BLIK, MB Way, and Bizum buttons are rendered automatically by the Solidgate SDK when the order currency and the customer’s billing country match the APM requirements. No extra configuration is needed — the SDK silently ignores button containers when conditions are not met, so enabling all three APMs has no visual impact on customers who are not eligible for them.

Third-Party Service

This plugin connects to the Solidgate payment platform (https://solidgate.com) to process payments. Solidgate is a third-party service — by using this plugin you are subject to their terms and privacy policy.

What data is sent to Solidgate:

  • Order details: amount, currency, order ID
  • Customer billing country and email address (used for payment form pre-fill and APM eligibility)
  • Payment method data entered by the customer inside the Solidgate-hosted iframe (card numbers are never processed by your server)
  • Webhook signatures sent from Solidgate to your site to confirm payment status

When data is sent: Data is transmitted at checkout when the customer initiates payment, and via webhooks when Solidgate sends order status updates (authorised, settled, declined, refunded).

  • Solidgate Terms of Service: https://solidgate.com/terms/
  • Solidgate Privacy Policy: https://solidgate.com/privacy-policy/

Requirements

  • WordPress 5.6 or later
  • WooCommerce 6.0 or later
  • PHP 7.4 or later
  • A Solidgate merchant account — sign up at solidgate.com

Installation

  1. Upload the solidgate-payment-gateway-for-woocommerce folder to /wp-content/plugins/, or install via Plugins > Add New in WordPress admin.
  2. Activate the plugin through the Plugins screen.
  3. Go to WooCommerce > Settings > Payments and click Set up next to “Solidgate Payment Gateway for WooCommerce”.
  4. Enter your credentials from the Solidgate merchant dashboard:
    • Public Key
    • Private Key
    • Webhook Public Key
    • Webhook Private Key
  5. Choose your integration type: Integrated form or Payment page.
  6. In the Solidgate dashboard, set your webhook URL to:
    https://yoursite.com/?wc-api=solid_hook

FAQ

Where do I get my API keys?

Log in to your Solidgate merchant dashboard and navigate to Settings > API Keys.

What is the difference between “Integrated form” and “Payment page”?

With Integrated form, the Solidgate card form appears directly inside the checkout payment section as soon as the customer selects this gateway — no redirect, no modal. Customers fill their card details inline and click Pay to authorize the payment, then WooCommerce finalizes the order. With Payment page, customers are redirected to a Solidgate-hosted page to complete payment and then returned to your store.

How do I set up the webhook?

In your Solidgate merchant dashboard, add a webhook endpoint pointing to https://yoursite.com/?wc-api=solid_hook. Solidgate will send order status events (authorize, settle, decline, refund) to this URL, and the plugin will update the corresponding WooCommerce order automatically.

Does the plugin support refunds?

Yes. You can issue full or partial refunds directly from the WooCommerce order screen (WooCommerce > Orders > [order] > Refund). The plugin calls the Solidgate refund API automatically.

Which countries and currencies are supported for APMs?

  • BLIK — PLN (Polish Zloty), billing country: Poland
  • MB Way — EUR, billing country: Portugal
  • Bizum — EUR, billing country: Spain

APM buttons appear automatically when the order matches the required currency and country. No extra configuration is needed.

Is the plugin compatible with WooCommerce HPOS?

Yes. The plugin declares compatibility with WooCommerce High-Performance Order Storage (custom order tables) and uses wc_get_orders() for all order lookups.

Does the plugin work with the block-based checkout?

Yes. The plugin registers a WooCommerce Blocks payment method integration via AbstractPaymentMethodType. In Integrated form mode the card form renders inline in the payment method area. After the customer authorizes their card, WooCommerce’s Place Order button finalizes the order.

Is PCI compliance maintained?

Yes. Card data is entered directly inside a Solidgate-hosted iframe served from cdn.solidgate.com. Your server never handles raw card numbers.

Anmeldelser

Der er ingen anmeldelser for denne widget.

Bidragsydere & udviklere

“Solidgate Payment Gateway for WooCommerce” er open source-software. Følgende personer har bidraget til dette plugin.

Bidragsydere

Ændringslog

2.8.6

  • Fixed: Integrated form mode on block checkout failed every payment attempt with “Invalid cart amount.” rest_init_payment() previously tried to resolve the charge amount from WC()->cart or a WooCommerce session value read inside the /solid/v1/init REST callback. Neither is reliable there: WC()->cart‘s contents only hydrate via a hook (wp_loaded) that has already fired by the time a REST route dispatches, and on affected environments the WooCommerce session cookie does not reliably reach PHP on /wp-json/ routes even though the browser sends it — WooCommerce was minting a new anonymous session on every call instead of resuming the checkout page’s real one. The amount is now computed once, server-side, at normal checkout-page render time (when the cart is always fully available) and passed to the frontend as an HMAC-signed, short-lived amountToken (WC_Solid_Gateway::generate_amount_token() / verify_amount_token(), keyed with wp_salt('nonce')). The client relays this opaque token back unchanged; the server never trusts a client-supplied amount. Used by both classic and block checkout.
  • Fixed: process_payment()‘s token-transient check additionally bound each token to a session-identity hash captured at /solid/v1/init time, and rejected the payment if that hash didn’t match at consumption time. On environments affected by the cookie issue above, /solid/v1/init and the later checkout submission are independent REST requests that can each get a different anonymous session identity, so this check could reject a fully legitimate payment — including cases where the customer had already been shown a “Payment successful” confirmation by the Solidgate SDK itself. The check has been removed; the existing single-use, unguessable (wp_generate_uuid4()), short-lived (1 hour) transient already provides the meaningful replay protection, and the amount is separately tamper-proof via amountToken.
  • Changed: In Integrated form mode, the native WooCommerce “Place order” button on block checkout is now hidden while Solidgate is the selected payment method, matching the behavior already shipped for classic checkout in 2.8.1. The SDK’s own PAY button authorizes the card and auto-submits checkout on success, so the native button is redundant while this method is selected; it is shown again if the customer switches to a different payment method.
  • Added: A new /solid/v1/update REST endpoint plus a call to the Solidgate SDK’s own form.update() method (https://docs.solidgate.com/payments/integrate/payment-form/update-payment-form/) so the already-rendered card form’s own email field is refreshed if the customer types their billing email in after the form has already appeared, instead of staying blank. Purely a UX improvement — if it fails for any reason, the customer can still type their email directly into the SDK’s own field.

2.8.2

  • Fixed: Added a missing/misplaced translators: comment for two translatable strings with placeholders in class-wc-solid-gateway.php (refund pending-confirmation notice and refund-failure order note), per WordPress.org Plugin Check.
  • Fixed: Shortened the 2.8.0 and 2.6.0 Upgrade Notice entries to comply with WordPress.org’s 300-character limit.

2.8.1

  • Changed: In Integrated form mode, the native WooCommerce “Place order” button is now hidden on the classic checkout while Solidgate is the selected payment method. The SDK’s own PAY button already authorizes the card and auto-submits the checkout on success, so the native button never did anything useful — it either blocked with an error before the card form was completed, or was redundant after. Hidden/shown dynamically as the customer switches payment methods or WC re-renders the payment box.

2.8.0

  • Changed: Plugin renamed from “Solidgate Payment Form for WooCommerce” back to “Solidgate Payment Gateway for WooCommerce”. Slug, main plugin file, and text domain updated to solidgate-payment-gateway-for-woocommerce to match. Existing merchant settings (stored under the solid gateway ID) are unaffected.

2.7.4

  • Fixed: A refund submission that came back “pending” (see 2.7.3) left no trace on the order and nothing stopped a second click on Refund from submitting a duplicate request to Solidgate. process_refund() now writes an order note for every outcome (submitted/pending, confirmed, declined, or request error), and blocks a new refund attempt while an earlier one is still awaiting confirmation, with a clear note explaining not to retry. The webhook handler clears that pending marker once it confirms the refund’s final status, so a genuinely new refund attempt afterward isn’t blocked.

2.7.3

  • Fixed: Admin-initiated refunds (WooCommerce > Orders > Refund) were confirmed as soon as Solidgate’s refund API responded with any order object, without checking whether the refund transaction itself had actually cleared. For APM methods (iDEAL, confirmed in testing) the API response is frequently still “processing” at that point, so WooCommerce recorded the refund as successful before Solidgate had confirmed it. process_refund() now only reports success once the refund transaction’s status is “success”; a “processing” result is reported back to WooCommerce as a pending error (so WooCommerce does not record a premature refund) and the confirmed refund is created automatically by the webhook handler once Solidgate reports “success” (see 2.7.2). A “fail” status is reported to the admin immediately.
  • Note: because WooCommerce’s refund screen is synchronous, a “pending” result surfaces as a WooCommerce error notice rather than a success message, even though the refund was actually submitted and accepted by Solidgate — the order will show as refunded automatically once the webhook confirms it, with no action needed.

2.7.2

  • Fixed: process_webhook_charge_refunded() created the WooCommerce refund as soon as a refund webhook arrived, even though the refund transaction itself could still be “processing” (or later fail) — e.g. an iDEAL refund isn’t final the moment it’s initiated. Now waits for the refund transaction’s own status to reach “success” before creating the WC refund; a “fail” status is logged as an explicit order note instead of being silently ignored, and pending statuses are logged and left for a follow-up webhook.
  • Added: idempotency guard against duplicate refund webhooks (Solidgate’s own webhook docs note duplicates can occur) — each processed refund transaction ID is recorded on the order so a repeated “success” webhook for the same refund can’t create a second WooCommerce refund on a partially-refunded order.

2.7.1

  • Fixed: APM (BLIK, iDEAL, etc.) refunds initiated from the Solidgate Hub never appeared in WooCommerce. Unlike card refunds, alt_gate refund webhooks never change order.status to “refunded” — it stays at the order’s last payment status (e.g. “approved”) — and only add a type: "refund" entry to the transactions array. The dispatcher now checks for that entry before treating an “approved”/”settle_ok” webhook as a new charge, and routes it to the refund handler instead.
  • Fixed: process_webhook_charge_refunded() read the refund amount and transaction ID from transaction.amount/transaction.id, fields that only exist in card_gate payloads. APM refund webhooks have no singular transaction object, so the refund amount resolved to nothing. Now falls back to the matching transactions[] entry when the singular field isn’t present.

2.7.0

  • Fixed: Refunds initiated from the WooCommerce admin (Orders > Refund) always called Solidgate’s card API (pay.solidgate.com), regardless of how the order was actually paid. Solidgate’s v1 API uses domain-specific hosts — APM orders (BLIK, iDEAL, MB Way, Bizum, etc.) live on gate.solidgate.com, not pay.solidgate.com — so refunding an APM order returned a “Blocked by WAF” error. The payment method is now parsed from the webhook (order.payment_method for card, order.method for APMs) and stored on the order, so process_refund() routes the request to the correct host: pay.solidgate.com for card/Apple Pay/Google Pay, gate.solidgate.com for everything else.
  • Fixed: The webhook’s transaction ID capture read transaction.id directly, which doesn’t exist in APM (alt_gate) webhook payloads — only a transactions array does. This meant set_transaction_id() / payment_complete() received an empty transaction ID for every APM order. Now resolves the ID from either shape.
  • Fixed: The “Solid charge complete” order note always logged “Method: default” for card orders, because it only checked order.method (the APM field name) and never order.payment_method (the card field name).

2.6.5

  • Fixed: solid_order_success_callback() (the browser redirect to success_url) always re-verified payment with a live status() API call, even when the webhook had already confirmed and completed the order moments earlier. This caused false “Payment could not be verified” rejections on successful APM (iDEAL, tested) payments where the follow-up status() call didn’t return the same result as the webhook. Now checks whether the order is already processing/completed/refunded (webhook-confirmed) first, and only falls back to the live status() call when no completing webhook has landed yet — same server-side verification guarantee, no redirect is trusted blindly.

2.6.4

  • Debug: solid_order_success_callback() now logs the raw status() API response. Seen in the field: for an APM order (iDEAL, alt_gate), the webhook confirms status “approved” but the browser-redirect status check comes back with an empty status, incorrectly rejecting a successful payment. Root cause not yet confirmed — this logs the actual response shape so the fix can target the real cause instead of guessing.

2.6.3

  • Fixed: order_description / order_items sent to Solidgate were built with esc_html() (HTML-entity encoding, the wrong tool for a plain-text API field) and a Name ( qty ); format, producing values like Test product ( 1 ); — special symbols like parentheses and semicolons are not safe in these fields. Both the Hosted Payment Page and Integrated form flows now sanitize product names and descriptions to letters, numbers, spaces, and basic safe punctuation only, and use a plain Name xQty format.

2.6.2

  • Fixed: Webhook handler read the Solidgate event type from $_GET['type'], a query parameter Solidgate never sends (the type is sent as the SOLIDGATE-EVENT-TYPE header). This made every incoming webhook resolve to an empty event type, so no webhook was ever processed and paid orders stayed stuck on “on-hold” indefinitely despite the webhook request itself succeeding (200 OK). Now reads the type from the header.
  • Fixed: The webhook dispatcher only matched the literal event types order.updated / alt_order.updated, but Solidgate’s actual webhook payloads are gate-prefixed (e.g. card_gate.order.updated). Now matches any *.order.updated suffix as well as the older bare values.

2.6.1

  • Fixed: Hosted Payment Page flow generated its Solidgate order ID as {order_id}_{time()} — second-resolution only, so a quick retry (failed payment, reloaded tab) within the same second could produce a duplicate ID that webhooks use as their order lookup key. Now uses wp_generate_uuid4(), matching the Integrated form flow’s uniqueness guarantee.
  • Fixed: solid_order_failture_callback() (the browser redirect Solidgate sends the customer to on decline) unconditionally set the order to “failed” with no check of current status. Because the webhook and this browser redirect are independent, unordered channels, a webhook that already completed the order before the browser finished redirecting could get overwritten back to “failed”. The callback now skips orders already in processing/completed/refunded, mirroring the guard added to the webhook handler in 2.6.0.

2.6.0

  • Changed: Plugin renamed from “Solidgate Payment Gateway for WooCommerce” to “Solidgate Payment Form for WooCommerce”. Slug, main plugin file, and text domain updated to solidgate-payment-form-for-woocommerce to match. Existing merchant settings (stored under the solid gateway ID) are unaffected.
  • Fixed: Removed a dead webhook route (?wc-api=solid_refund) that was wired to a solid_wh_refund_callback() method that did not exist anywhere in the plugin; refunds are already handled correctly via the main solid_hook webhook route.
  • Fixed: process_refund() used intval( $amount * 100 ) to convert to minor units, which truncates instead of rounding and can silently refund the wrong amount on certain floating-point totals (e.g. 19.999999999998); now uses (int) round( $amount * 100 ), consistent with the rest of the codebase.
  • Fixed: A late or duplicate “declined” webhook arriving after an order was already marked processing/completed/refunded by an earlier webhook could incorrectly cancel that already-paid order. process_webhook_charge_declined() now skips orders in those statuses.
  • Fixed: Blocks checkout and classic checkout used a stale “Visa/Mastercard” fallback title that no longer matched the gateway’s actual default title (“Card payments & Other”); both now use the same default.

2.5.0

  • Changed: Integrated form mode now renders the card form inline in the payment section immediately when the gateway is selected, instead of opening a modal after clicking Place Order (Stripe/Braintree-style UX).
  • Changed: Classic checkout no longer depends on jQuery Modal — removed that dependency.
  • Changed: Both classic and block checkout share the same token-based flow through process_payment().
  • Changed: /solid/v1/init REST endpoint now reads cart totals from the WC session when called without body parameters (classic checkout), so no extra AJAX is needed for amount/currency.
  • Added: Loading shimmer animation while the payment form initializes.
  • Added: Auto re-initialization when cart totals change (coupon or shipping update).

2.4.0

  • Fixed: Plugin slug renamed to solidgate-for-woocommerce for WP.org compliance.
  • Fixed: Plugin name updated to “Solidgate Payment Gateway for WooCommerce”.
  • Fixed: Text domain updated throughout to match plugin slug.
  • Fixed: jQuery Modal bundled locally — removed CDN dependency.
  • Fixed: $_POST['solid_token'] now uses wp_unslash() before sanitization.
  • Fixed: $_GET['order_id'] validated with isset() before use in callbacks.
  • Fixed: print_r() replaced with wp_json_encode() in all log calls.
  • Fixed: Missing translators comments added to all sprintf/__() calls.
  • Fixed: Removed load_plugin_textdomain() (auto-loaded since WP 4.6).
  • Fixed: Webhook nonce check suppressed with explanation (server-to-server, no WP nonce).
  • Fixed: Slow DB query phpcs notices suppressed with explanation.
  • Added: License and License URI headers.
  • Added: readme.txt and composer.json.

2.3.0

  • Added: BLIK, MB Way, and Bizum APM support for classic and block checkout.
  • Added: geo_country (ISO 3166-1 alpha-3) in order body for APM auto-rendering.
  • Added: future_usage: { payment_type: one-time } globally (required by MB Way and Bizum).
  • Fixed: APM container divs now output inline in payment_fields() for classic checkout.

2.2.0

  • Added: WooCommerce Block checkout support via AbstractPaymentMethodType.
  • Added: REST endpoint /wp-json/solid/v1/init for pre-order payment initialization.
  • Added: React portal overlay for block checkout (bypasses WC processing-state opacity).
  • Added: Billing email and country pre-filled in Solidgate form from WC store data.

2.1.0

  • Initial public release.