Implementing payment gateway in Magento 2

Implementing payment gateway in Magento 2

This is a revised article originally written in September 2014 when I started to play with Magento 2 for the first time. Since there were a lot of changes in Magento 2, this article also needed some refreshment. We will glance over the backend, and proceed with the development of a simple module. For this task, I picked up the payment gateway API integration. This relatively simple task will help us demonstrate some key changes in Magento 2.

More precisely, we will be focusing on implementation of Stripe payment gateway. Even though Stripe has a rich set of features, here we will be focusing only on most basic functionalities to get you started with Magento 2 extension development.

NOTE: Magento 2 source code is under constant changes. Although code was tested on early Magento 2.1., it is now outdated. Stay tuned for an update.

Module setup

As you probably already know, a lot has changed in Magento 2, and Module setup and code structure is not an exception. One of the first things you will notice is absence of code pools that we are used to from previous version. Inside the app/code folder we will create our namespace folder. In the end, our file/folder structure would look like this:


Stripe folder structure

Before we proceed, there is one more thing that needs to be taken care of. Stripe comes with its own set of PHP libraries for integration, and they need to be included as well. This, however, should be managed by Composer. If you take a look at composer.json, you will notice require line. By installing this sample extension through composer, Stripe library will be placed under vendor/stripe folder, and will be available through autoloader in our code.

Next big change has been introduced in XML configuration files. Magento 2 has introduced XML scheme for each configuration type that needs to be followed, or otherwise the module will not work. First one that we will create, is module.xml that replaces configuration which was previously placed under app/etc/modules/namespace_modulename.xml. As in magento 1, it is used to declare module and its dependencies:

<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Inchoo_Stripe" setup_version="1.0.0">
            <module name="Magento_Sales" />
            <module name="Magento_Payment" />
            <module name="Magento_Directory" />
            <module name="Magento_Config" />

There are also some changes in other config files, but I’ll let you have fun exploring them yourselves.

Payment implementation

So far, we have created our module file structure, we have created module configuration files and we have integrated our library files. It is now time to proceed with the payment integration.
Anyone who integrated payment gateway in Magento knows the importance of implementing proper admin settings, since the system will handle most of the things automatically. Lets take a look at our etc/adminhtml/system.xml file:

<config xmlns:xsi="" xsi:noNamespaceSchemaLocation="../../../../Magento/Config/etc/system_file.xsd">
        <section id="payment">
            <group id="inchoo_stripe" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1">
                    <![CDATA[<a href="" target="_blank">Click here to sign up for Stripe account</a>]]>
                <field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0">
                <field id="title" translate="label" type="text" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1">
                <field id="api_key" translate="label" type="obscure" sortOrder="3" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Api Key</label>
                <field id="debug" translate="label" type="select" sortOrder="4" showInDefault="1" showInWebsite="1" showInStore="0">
                <field id="cctypes" translate="label" type="multiselect" sortOrder="5" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Credit Card Types</label>
                <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Sort Order</label>
                <field id="allowspecific" translate="label" type="allowspecific" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Applicable Countries</label>
                <field id="specificcountry" translate="label" type="multiselect" sortOrder="51" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Payment from Specific Countries</label>
                <field id="min_order_total" translate="label" type="text" sortOrder="98" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Minimum Order Total</label>
                <field id="max_order_total" translate="label" type="text" sortOrder="99" showInDefault="1" showInWebsite="1" showInStore="0">
                    <label>Maximum Order Total</label>
                    <comment>Leave empty to disable limit</comment>

There are only three fields that we need to handle through our code: api_key, min_order_total and max_order_total. As I previously said, Magento will handle the rest through abstract classes by default.

Speaking of classes, it is finally time to implement our Payment class. Due to the nature of Stripe, we will be extending \Magento\Payment\Model\Method\Cc. Besides setting usual config through protected variables, we also have to pass Stripe library to our class to respect dependency injection and testability. Therefore we will begin our class with the following snippet:

namespace Inchoo\Stripe\Model;
class Payment extends \Magento\Payment\Model\Method\Cc
    const CODE = 'inchoo_stripe';
    protected $_code = self::CODE;
    protected $_isGateway                   = true;
    protected $_canCapture                  = true;
    protected $_canCapturePartial           = true;
    protected $_canRefund                   = true;
    protected $_canRefundInvoicePartial     = true;
    protected $_stripeApi = false;
    protected $_countryFactory;
    protected $_minAmount = null;
    protected $_maxAmount = null;
    protected $_supportedCurrencyCodes = array('USD');
    protected $_debugReplacePrivateDataKeys = ['number', 'exp_month', 'exp_year', 'cvc'];
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
        \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
        \Magento\Payment\Helper\Data $paymentData,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Payment\Model\Method\Logger $logger,
        \Magento\Framework\Module\ModuleListInterface $moduleList,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
        \Magento\Directory\Model\CountryFactory $countryFactory,
        \Stripe\Stripe $stripe,
        array $data = array()
    ) {
        $this->_countryFactory = $countryFactory;
        $this->_stripeApi = $stripe;
        $this->_minAmount = $this->getConfigData('min_order_total');
        $this->_maxAmount = $this->getConfigData('max_order_total');

At this point, we have covered almost all differences in module development between Magento 2 and 1. From this point on, most of the code would be the same between those two versions, as far as our Stripe integration is concerned.

Lets proceed with implementation of our most important function, capture():

 * Payment capturing
 * @param \Magento\Payment\Model\InfoInterface $payment
 * @param float $amount
 * @return $this
 * @throws \Magento\Framework\Validator\Exception
public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
  //throw new \Magento\Framework\Validator\Exception(__('Inside Stripe, throwing donuts :]'));
  /** @var \Magento\Sales\Model\Order $order */
  $order = $payment->getOrder();
  /** @var \Magento\Sales\Model\Order\Address $billing */
  $billing = $order->getBillingAddress();
  try {
      $requestData = [
          'amount'        => $amount * 100,
          'currency'      => strtolower($order->getBaseCurrencyCode()),
          'description'   => sprintf('#%s, %s', $order->getIncrementId(), $order->getCustomerEmail()),
          'card'          => [
              'number'            => $payment->getCcNumber(),
              'exp_month'         => sprintf('%02d',$payment->getCcExpMonth()),
              'exp_year'          => $payment->getCcExpYear(),
              'cvc'               => $payment->getCcCid(),
              'name'              => $billing->getName(),
              'address_line1'     => $billing->getStreetLine(1),
              'address_line2'     => $billing->getStreetLine(2),
              'address_city'      => $billing->getCity(),
              'address_zip'       => $billing->getPostcode(),
              'address_state'     => $billing->getRegion(),
              'address_country'   => $billing->getCountryId(),
              // To get full localized country name, use this instead:
              // 'address_country'   => $this->_countryFactory->create()->loadByCode($billing->getCountryId())->getName(),
      $charge = \Stripe\Charge::create($requestData);
  } catch (\Exception $e) {
      $this->debugData(['request' => $requestData, 'exception' => $e->getMessage()]);
      $this->_logger->error(__('Payment capturing error.'));
      throw new \Magento\Framework\Validator\Exception(__('Payment capturing error.'));
  return $this;

As usual, we will fetch billing information through payment object. Credit card info is than passed to Stripes API which handles the rest. In case of success, we will add this transaction to Magento’s list of transactions, and we are basically done here. It is important to note here, that transaction id should be set to transaction ID received by the payment gateway, since this will be used later on.

Another important feature for payment method is ability to issue a refund from Magento admin. So lets proceed and implement our refund() function:

 * Payment refund
 * @param \Magento\Payment\Model\InfoInterface $payment
 * @param float $amount
 * @return $this
 * @throws \Magento\Framework\Validator\Exception
public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
  $transactionId = $payment->getParentTransactionId();
  try {
  } catch (\Exception $e) {
      $this->debugData(['transaction_id' => $transactionId, 'exception' => $e->getMessage()]);
      $this->_logger->error(__('Payment refunding error.'));
      throw new \Magento\Framework\Validator\Exception(__('Payment refunding error.'));
      ->setTransactionId($transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND)
  return $this;

Basically, we are fetching transaction ID, which is then passed to API which handles refund communications. All we need to do here is to properly handle errors and mark transactions. And yes, by handling errors I do mean throwing Exception from inside catch block, in order to notify Magento of an error. Reason for try..catch block in the first place was to sanitize data, since response from server might have sensitive information. This also applies to capture functionality.

In Magento 2, checkout has been rewritten as JS client side application, that is communicating with core system through API. Considering that, PHP part itself is not enough for integration to work. We will proceed by adding two more JS files through layout update XML(check link, it is to large to be listed here). Following files have been added:

Their purpose is to provide configuration for UI component used in checkout. For now, we will leave like that, explaining how this works, requires its own article.

And that is basically it. There may be a few more things to tune up, but our module is ready. Full code can be retrieved at our GIT repository here. An don’t forget to keep an eye on our repository. We plan to implement integration with tokens to avoid sending credit card info to server.

So far we have covered most of the basic things that are required for module development. However, our module is really simple: it lacks any template files, controllers, blocks, composer config, etc. But we will cover all that in our future articles. This is just a warmup to get you started. I hope it was useful, and that you enjoyed reading it.

In case you feel you need some extra help regarding Magento 2, we can offer you a detailed custom report based on our technical audit – feel free to get in touch and see what we can do for you!

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

Inchoo & Magento in 2024 and Beyond Lucija Majstrovic
, | 0

Inchoo & Magento in 2024 and Beyond

3 best open-source eCommerce platforms in 2021 Zrinka Antolovic
Zrinka Antolovic, | 8

3 best open-source eCommerce platforms in 2021

Moving the validation error message, this time globally Danijel Vrgoc
, | 0

Moving the validation error message, this time globally


  1. i want to know that, how we can only display payment method logo(image) instead of payment method name on checkout page? my magento version is 2.2.5.

  2. Hi Stjepan,

    It’s a nice tutorial.
    However, if instead of Strip API gateway, I want to send information to some external api url using say POST request, and perform some action based on the response that I get, how can I achieve that?
    I am using Magento 2.2.


  3. Here you explain about stripe payment method,i have other API.

    But How can we include in our files like in controller or Model etc… ?

  4. This is not Magento 2 payment gateway,
    This is deprecated, in old format Magento 1 payment method

  5. Hello stjepan,
    I liked you tutorial and managed to get this extension installed. It comes on frontend and backend. But when I click place order with Stripe selected as payment method I get an error which says “An error occurred on the server. Please try to place order again.”
    My magento version is : 2.1.5
    I’ve added stripe library.
    Have enabled on backend.
    Used secret API key genereated on Stripe dashboard.

  6. Hi Stjepan Udovicic,
    I have integrated the same module in magento 2.1.5.

    Module is running, also getting shown in adminend.

    But it is not getting shown in checkout page, it is displaying as no payment methods shown.

    Thanks and regards

  7. How to add stripe library in this extension?Can you please tell me folder structure of adding the stripe libraries?

  8. HI,

    I am using your module for integrating the securepay payment gateway but i am not getting any credit card detail data in assignData of payment.php.My magento version is 2.0.4
    i am working on it since last twqo weeks to get credit card data in assignData function in Payment.php model file.
    Please help.Any Help will be appreciated


  9. i have installed the module and enable it. But it doesn’t show up on the checkout page. Can anyone help ??

  10. When I run command : php bin/magento setup:upgrade . In Frontend I got error : Invalid block type: Magento\Checkout\Block\Onepage.

  11. Hi Stjepan,
    thanks for the snippet of code! It is really simple and clear. Me like an other user in this thread have found a problem. I’ve installed this module on magento 2.1 , installed also the library throught composer , got it working in backend and frontend , but when I try to make a payment , I get this error please insert a valid credit card expiration date
    I am using the Testing Credit Cards ( as suggested by you and an expiration date in the future but the problem persists. I am debugging the code and I have discovered that the line


    are empty! I don’t understand the reason.

  12. I have used this extension with Magento ver. 2.1.1,working fine in admin panel but method does not showing on front end.
    No luck after installing stripe library as well

  13. Hi Stjepan,

    i need to add checkoutConfig js about installments at my module, but, everything i try, gots errors, can you help me please?

  14. hello I am trying the same module in Magento ver. 2.1.0 getting following error message on shopping cart page.

    Exception #2 (ReflectionException): Class Stripe\Stripe does not exist

    Please let me know how to resolve this issue. this is very urgent.


  15. Is the new Payment service contracts applicable for redirection based payment (like paypal standard) also or only for API based ones?

  16. Hi Stjepan!

    I have a question for you, I hope you can help me.

    I recent changed to use Magento 2, in the past I had been using osCommerce.

    The website only use as a payment method a gateway with a local bank.

    This is the map:
    osCommerce->Checkout->Payment Method->Using Credit Card

    When select a credit card, osCommerce begins a session with the bank, so firts I need to send via WebService the credentials to the bank and the bank return a token session, so when the “Make Payment” button is clicked, the transaction is redirected to a gateway site of the bank with the information of the payment. Then, in this page, when the payment is processed the user client have to click in a “Return” button and go back to the osCommerce site with the result of the transaction and using some variables posted in the returned URL the site display the result of the payment and generate or deny the shopping product.

    Do you have an example on how to implement this way in Magento 2?

    Thanks for your help.

  17. Hi Stjepan,

    \Magento\Payment\Model\Method\AbstractMethod and \Magento\Payment\Model\Method\Cc has been deprecated in magento 2.1.0.
    Will you update this example with new class???

  18. hi Stjepan, I install this module just follow the instruction. Everything seems good at backend. just has problem when I checkout. I used local server to test and magento version is 2.1. Any suggestions? Thank you.

    1. I just try again and get error from system log:
      [2016-06-28 07:42:25] main.CRITICAL: Broken reference: No element found with ID ‘checkout.header.wrapper’. [] []
      [2016-06-28 07:42:25] main.CRITICAL: Class Stripe\Stripe does not exist [] []
      [2016-06-28 07:42:25] main.CRITICAL: Invalid block type: Magento\Checkout\Block\Onepage [] []

      Please have a look. thanks

    2. That is because extension was not properly installed, you need to install it with composer. Read the instructions here

      Otherwise, Stripe library will not be added, and you will receive notification that Stripe/Stripe is missing.

      If you are installing this extension manually(by copy/paste), you need to manually add Stripe library.

    3. Hello,

      I have found issue in checkout page. I am not able to seems page and also face issue like

      Invalid block type: Magento\Checkout\Block\Onepage

      If it’s possible to solve this issue urgent

  19. Hi,

    I have tried this module with Magento 2.0.7 in front end it is not displaying, how can i display this module in front end.
    I have tried different solution but it is not showing front end. an you help me on this.


  20. Hey,
    I am still facing the first most problem with other Payment module examples. I can see payment module in backend but I am not able to see on frontend. I am trying simple offline payment module first. Can someone guide me please how to install module through composer. I made repositories on gitz hub and now trying to package through packagist. but I am getting below error,
    ” A package with the name magento/project-community-edition already exists.
    The vendor is already taken by someone else. You may ask them to add your package and give you maintainership access. The packages already in that vendor namespace can be found at magento

    A package with the name magento/project-community-edition already exists.
    The vendor is already taken by someone else. You may ask them to add your package and give you maintainership access. The packages already in that vendor namespace can be found at magento”

    Please guide me on this.

    1. Hello,
      I figured out to install the module via composer and it worked perfectly but still the same issue persists, I can see my module installed and I can see back end part, but I am not able to see on front end checkout page.

      Can someone please help me in this? I will really aprreciate your help.


    2. I had the same problem and noticed the file “Inchoo\Stripe\Model\Payment” is hard coded for USD currency, and I am outside the US.

    3. As luke pointed out, this module is hardcoded to USD currency. Reason behind this is that Stripe works only USD. Please check if this is causing issues for you.

  21. Hello , I’ve installed this module on magento 2.0.6 , installed also the library throught composer , got it working in backend and frontend , but when I try to make a payment , I get this error please insert a valid credit card expiration date

  22. Hello Inchooers

    I should appreciate your great work for Magento Community , always found your post helpfull for issues and learning new about Magento .

    I am building module on top on this blog post , but I got into some strange issue most of time the Stirpe and my method method dont show up on checkout , did refresh the cache , removed var and pub/static folders reinstall the stripe module but it dont load

    Any idea how to solve this ?

    1. I Had this same issue and I also faced “Exception error: Invalid block type.”
      Please use composer to install the module completely. Manually placing the stripe folders under Vendor folder wont resolve the issue Because composer adds the class map on vendor/composer/autoload_psr4.php and vendor/composer/autoload_static.php files.
      After installing the module via composer. User setup:upgrade command. The issue will be resolved

    2. It has been brought to my attention that this happens due to bug previously present in Magento. I am not sure when this happen, and when it was resolved, but the code is working with Magento 2.1. could you please try with latest version and let me know if you still experience any issues with it? Also, plesae check if your base currency is USD.

    1. got solution.Download stripe library from and put the code at app/code/stripe-php.Am i right ?

    1. You need to install extension via composer, or add Stripe library manually. Otherwise, it won’t work. Also, the link from comment is a 404

  23. hi this module working good for me at backend, however in frontend the issue is with di.xml which is producing error as :
    Object DOMDocument should be created.

    On this object

    Please help me. What could be possible issue behind it?

  24. Hello,
    Module is working fine in front end and back end.
    When i refund partial it refunds the total amount instead the partial amount.
    please check and let me know if you have solution for that issue.

    1. Hello Stjepan,
      There is bug in module:
      Refund is not working properly.
      i have solution for that issue.
      you have to pass amount in refund function otherwise it will not working.
      ‘amount’ => $amount * 100,

  25. Hi,

    Its not showing validation message on checkout page. Only returns in AJAX.
    I want to display message on checkout page.

  26. This error is showing tell me how to correct it.
    Class Stripe\Stripe does not exist [] []
    Invalid block type: Magento\Checkout\Block\Onepage [] []

    1. You have to include stripe library in your magento 2 setup. Or just comment it in payment model for time being.

  27. OK – regarding that error I think I found the problem:

    Line 165 of payment.php reads:

    public function isAvailable($quote = null)......

    it should read:

    public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null)......
  28. I’m having the same issue mentioned earlier:

    Declaration of Inchoo\Stripe\Model\Payment::isAvailable() must be compatible with Magento\Payment\Model\MethodInterface::isAvailable(Magento\Quote\Api\Data\CartInterface $quote = NULL)

    I have included the registration.php file:


    so I don't think that is causing the issue. It seems to be related to the isAvailable function on line 165 of Payment.php. Any ideas?

  29. Man, do you know a way to build an url (…) in a model and after that use this information to redirect customer to the external payment gateway?

  30. /var/www/html/magento2# php bin/magento setup:upgrade
    PHP Fatal error: Declaration of Inchoo\Stripe\Model\Payment::isAvailable() must be compatible with Magento\Payment\Model\MethodInterface::isAvailable(Magento\Quote\Api\Data\CartInterface $quote = NULL) in /var/www/html/magento2/app/code/Inchoo/Stripe/Model/Payment.php on line 194

    I am facing this error any one can help

  31. after this cmd php bin/magento setup:upgrade, then i got
    Fatal error: Declaration of Inchoo\Stripe\Model\Payment::isAvailable($quote = NULL) must be compatible with Magento\Payment\Model\MethodInterface::isAvailable(Magento\Quote\Api\Data\CartInterface $quote = NULL) in /var/www/html/magento2/app/code/Inchoo/Stripe/Model/Payment.php on line 194

  32. Hi , I am working on the development on the payment gateway in magento 2 backend work all completed but in frontend i want when user click our payment gateway option then it will be directed to our gateway page and post all parameter like amount, email, name etc after when the transaction is completed then it will redirected to magento 2 success page or cancel page so, that i follow that structure /var/www/html/magento/app/code/Payubiz/Payubiz/Model in model i make PayubizPaymentMethod.php file but i don’t which class i am extends or which function i can use? Please guide me provide your mail id i will send the zip of the module and code of model is

    class PayubizPaymentMethod extends \Magento\Payment\Model\Method\AbstractMethod
    * Payment code
    * @var string
    protected $_code = 'payubizpaymentmethod';
    * Availability option
    * @var bool
    protected $_isOffline = true;
    1. Hi Ayush,

      What you are describing is redirected gateway. I’m not sure are there any Magento2 examples for this, since I haven’t played with it for a while.

    2. Hey !
      I need your help How did u solve this issue?, I am having hard time to show my custom Payubiz in frontend how to do that it in Admin .

    3. Hi Ayush,
      Were you able to configure PayUbiz payment gateway for Magento 2? I’ve migrated the PayUbiz extension from Magento 1.9 to Magento 2.x, but it is throwing error during compilation process.

  33. Hello,

    interestng article, however, I got stuck in the very beginning of it. In last Magento version, there is no code folder under app folder. Can you update your tutorial to consider this case? thanks


    1. Hi Jamie,

      You are missing app/code because you installed magento through composer. You can either create it yourself, or follow guidelines for creating modules through composer. Either way, I will update my post soon.

  34. Is there a way to install the extension manually (FTP or local package), without using the composer commands?

    1. Hi Tom,

      Yes, you can download it from Github and manually place it in app/code. In such case, do not forget to download stripe library as well.

  35. Hello,
    i am run this command php bin/magento module:enable Inchoo_Stripe –clear-static-content
    after showing issue
    Unknown module(s): ‘Inchoo_Stripe’

    1. After adding Register.php, i get following error:
      PHP Fatal error: Declaration of Inchoo\Stripe\Model\Payment::isAvailable($quote = NULL) must be compatible with Magento\Payment\Model\MethodInterface::isAvailable(Magento\Quote\Api\Data\CartInterface $quote = NULL) in /var/www/html/magento2/app/code/Inchoo/Stripe/Model/Payment.php on line 194

      Any suggestions?


  36. Hello,
    I have installed repository version but i cant see anything about this in admin panel or in frontside.Is there anything else we need to do?

    Thanks for information,

    1. Hi Pratik,
      Since Magento 2 released merchant beta, code has been revised. Could you check now? You will find install instructions on Github repoistory.

  37. Hi what’s your thoughts on Magento 2 for production? Have you guys made the switch or is it not quite ready yet?

  38. Stjepan, have you tried or thought about BrainTree payment gateway as well? OR since BrainTree is acquired by PayPal and that company holds a big share in Magento, so BrainTree will be available by default?

    1. Reason behind choosing Stripe is it’s simplicity which was important for educational purposes and since we already had Stripe implementation for Magento 1.x, we decided to stick with it. Regarding the BrainTree, I’m not sure about PayPal’s or Magento’s plans for it..

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.