Magento 2 Payment Gateway Integration: Stripe Example

Magento 2 Payment Gateway Integration: Stripe Example

November 16, 2025 · By Magento Company
Magento 2 Payment Gateway Integration: Stripe Example

Building a payment integration is the most trust-sensitive code a Magento developer writes: mistakes here lose money or leak card data. Fortunately Magento’s payment gateway framework does the heavy lifting if you follow its patterns. Using Stripe as the example, here is how a proper integration fits together - and a candid note on when you should not build one at all.

First: Do You Need to Build It?

Stripe maintains an official Magento 2 module, and it is good. Custom gateway development is justified when the provider has no module (common with regional acquirers), when you need orchestration the official module lacks, or when you are the PSP building the module. If a maintained official module exists, start there - PCI scope alone is reason enough.

The Gateway Framework

Magento’s payment integration is declarative. In etc/di.xml you wire commands, validators and handlers rather than writing a monolithic authorize() method:

<virtualType name="AcmeStripeFacade" type="Magento\Payment\Model\Method\Adapter">
    <arguments>
        <argument name="code" xsi:type="string">acme_stripe</argument>
        <argument name="formBlockType" xsi:type="string">Magento\Payment\Block\Form\Cc</argument>
        <argument name="infoBlockType" xsi:type="string">Acme\Stripe\Block\Info</argument>
        <argument name="valueHandlerPool" xsi:type="object">AcmeStripeValueHandlerPool</argument>
        <argument name="commandPool" xsi:type="object">AcmeStripeCommandPool</argument>
    </arguments>
</virtualType>

The command pool maps payment actions - authorize, capture, void, refund - to command classes. Each command calls the Stripe API, and a response handler transfers fields onto the payment object via payment.setAdditionalInformation().

Tokenisation and PCI

Never let card numbers touch your server. Stripe.js (or Payment Element) tokenises in the browser; your integration passes only the resulting token or PaymentMethod ID to Magento. The payment action then attaches that token to the charge request. This keeps you in SAQ-A territory - the difference between a simple compliance questionnaire and an audit programme.

Webhooks Are Not Optional

Payment state changes asynchronously: 3DS completions, disputes, delayed captures. A webhook controller (Controller/Webhook/Index.php) must:

  1. Verify the Stripe signature header with your webhook secret - unsigned payloads are an attack vector
  2. Be idempotent: Stripe retries, and double-processing a capture event is a real bug class
  3. Map events to Magento order state transitions through the order payment API, not direct status writes

Configuration Surface

Use Magento’s standard payment.xml and config.xml so credentials live in encrypted config, scoped per website - essential for merchants running EU and US entities on one install. Never hardcode keys; never log payloads containing payment data.

Testing Properly

  • Stripe test mode with its full card matrix: success, decline, 3DS challenge, insufficient funds
  • Webhook testing with the Stripe CLI’s listen --forward-to
  • End-to-end: place real test orders, refund them from the admin, verify the refund in the Stripe dashboard

A gateway integration done by the book is boring code: declarative wiring, thin API commands, verified webhooks. That boringness is the goal - checkout is the one place excitement is always bad news.

Payments Development Magento 2