GatewayChanger for Magento 2
The GatewayChanger_Payment module gives a Magento 2 or Mage-OS store the same two roles as the WooCommerce plugin:
seller and charger. It speaks exactly the same protocol, with the same field names, endpoints and error codes, so a
Magento store can sell to a WooCommerce charger and the other way round.
Status: in development. Built and tested against Magento 2.4.8 / Mage-OS on PHP 8.3 and 8.4, Luma checkout first. Hyvä compatibility is a documented follow-up.
Requirements
| Magento | 2.4.8 / Mage-OS (2.4.7 should work; not yet part of the test matrix) |
| PHP | 8.3 or 8.4 with ext-sodium |
| Checkout | Luma (Knockout) checkout; Hyvä is a follow-up |
| Transport | HTTPS, and /rest/V1/gatewaychanger/* reachable from the internet |
| Cron | Magento cron running — it sends the five-minute heartbeat |
Install
composer require gatewaychanger/module-payment
bin/magento module:enable GatewayChanger_Payment
bin/magento setup:upgrade
bin/magento setup:di:compile # production mode
bin/magento cache:flush
To install from a zip or a Git checkout instead, place the module at app/code/GatewayChanger/Payment and run the same
commands from module:enable onwards.
Connect the shop
Stores → Configuration → Sales → Payment Methods → GatewayChanger, or from the command line:
bin/magento gatewaychanger:connect --key=shk_test_…
The module generates its Ed25519 key pair, registers the public key with the SaaS, and reports its roles and
capabilities. The configuration page then shows the shop name, the environment badge, the verification status and the
last heartbeat. Our verification probe calls
https://your-store.example/rest/V1/gatewaychanger/capabilities; until it succeeds the shop cannot act as a charger.
Flush the configuration cache after changing anything (bin/magento cache:flush config).
Seller role
Enable the payment method and set:
- title and description shown on the checkout step;
- the consent label, and the CMS page holding your terms;
- payment mode —
embed(default) orredirect; - the order status used for authorizations;
- what to do when no route is available.
The checkout renderer draws the consent checkbox and the charger's iframe, creates the session through
/rest/V1/gatewaychanger/checkout/session (guest and customer variants), re-routes on finalize when the total changed,
and passes the session id, the payment token and the consent hash in the payment additional_data.
Authorize, capture, void and refund run through the standard Magento gateway command pool, so invoices and credit memos behave normally. The order view shows a GatewayChanger block with the charger, the processor, the references and a link to the decision.
Charger role
Enable the charger role, set the legal name, and configure at least one processor:
- Test processor — no credentials, deterministic outcomes, ideal for the first run.
- Stripe — publishable key, secret key and webhook signing secret, in test mode first. The credentials stay in Magento's configuration (encrypted where Magento supports it) and are never sent to GatewayChanger.
Charger endpoints are exposed through etc/webapi.xml as anonymous resources whose real authentication is the
GatewayChanger request signature and grant verification. Sessions live in the gatewaychanger_session table. The embed
page is /gatewaychanger/embed/index and the hosted pay page is /gatewaychanger/pay/index; both are CSRF-exempt
controllers with the correct frame-ancestors policy.
Each charge creates a mirror order from a programmatic quote with a single virtual line — "GatewayChanger payment on behalf of {seller}" — invoiced on capture and credit-memoed on refund.
Testing
Use the test cards with the test processor, and drive the flow as described in the getting started guide. A useful pairing while you develop: Magento as seller against a WooCommerce charger, then the reverse, which proves both sides of the protocol.
Troubleshooting
setup:di:compile fails after an update. Clear generated/ and recompile.
The probe cannot reach the store. Check that /rest/V1/gatewaychanger/capabilities returns JSON to an anonymous
request, that no WAF blocks it, and that the base URL in the shop record matches Magento's web/secure/base_url.
No heartbeat. Magento cron is not running, or the gatewaychanger cron group is disabled. Fifteen minutes of
silence removes the shop from routing.
The checkout step does not render. Clear pub/static and the full page cache after enabling the module, and check
the browser console for a failing RequireJS dependency.