Hello Magento Friends,
Shopping is no more constrained by geographic borders as online Ecommerce stores are ruling the global market. Whenever online shopping is considered, payment methods prove to be the most vital factor. According to a survey, the lack of a preferred payment method is the most common cause of cart abandonment, which needs to be taken seriously. Hence, E-commerce needs a custom payment method to increase the user experience.
When it comes to Magento 2, being the most popular E-commerce platform, it provides many default payment methods. However, sometimes you may need to create a custom payment method in Magento 2 store to integrate with your choice of payment gateway if it’s not already available.
Step 1: Create app\code\Vendor\Extension\registration.php to register your payment gateway extension.
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'Vendor_Extension', __DIR__ );
Step 2: Create app\code\Vendor\Extension\composer.json
{ "name": "Vendor\module-Extension", "description": "Vendor Extension Payment Gateway", "require": { "php": "~5.5.0|~5.6.0|~7.0.0|~7.1.0|~7.2.0|~7.3.0|~7.4.0" }, "type": "magento2-module", "version": "1.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "autoload": { "files": [ "registration.php" ], "psr-4": { "Vendor\\Extension\\": "" } } }
Step 3: Create app\code\Vendor\Extension\etc\module.xml to define your module name.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="Vendor_Extension" setup_version="1.0.0"> <sequence> <module name="Magento_Payment" /> <module name="Magento_Checkout"/> <module name="Magento_Sales"/> <module name="Magento_Quote"/> </sequence> </module> </config>
Step 4: Create app\code\Vendor\Extension\etc\config.xml to define your Extension payment method.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> <default> <payment> <Extension> <active>1</active> <model>Vendor\Extension\Model\Payment</model> <payment_action>authorize_capture</payment_action> <title>Vendor Extension Payment Gateway</title> <api_key backend_model="Magento\Config\Model\Config\Backend\Encrypted" /> <cctypes>AE,VI,MC,DI,JCB</cctypes> <allowspecific>0</allowspecific> <min_order_total>1</min_order_total> </Extension> </payment> </default> </config>
Step 5: Create app\code\Vendor\Extension\etc\adminhtml\system.xml to display the payment method in the admin payment method section.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <section id="payment"> <group id="Extension" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Vendor Extension Payment Gateway</label> <field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> <field id="title" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Title</label> </field> <field id="api_key" translate="label" type="obscure" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>API Secret Key</label> <backend_model>Magento\Config\Model\Config\Backend\Encrypted</backend_model> <comment>Test/Live Secret Key</comment> </field> <field id="cctypes" translate="label" type="multiselect" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Credit Card Types</label> <source_model>Vendor\Extension\Model\Source\Cctype</source_model> </field> <field id="allowspecific" translate="label" type="allowspecific" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Payment from Applicable Countries</label> <source_model>Magento\Payment\Model\Config\Source\Allspecificcountries</source_model> </field> <field id="specificcountry" translate="label" type="multiselect" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Payment from Specific Countries</label> <source_model>Magento\Directory\Model\Config\Source\Country</source_model> </field> <field id="min_order_total" translate="label" type="text" sortOrder="80" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Minimum Order Total</label> <comment>$1 is the minimum amount allowed by Extension Payment</comment> </field> <field id="max_order_total" translate="label" type="text" sortOrder="90" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Maximum Order Total</label> <comment>If customer tries to checkout with basket value greater than the maximum allowed they will be prevented from completing the order.</comment> </field> <field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Sort Order</label> </field> </group> </section> </system> </config>
Step 6: Create app\code\Vendor\Extension\etc\frontend\di.xml for dependency Injection configuration.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Payment\Model\CcGenericConfigProvider"> <arguments> <argument name="methodCodes" xsi:type="array"> <item name="Extension" xsi:type="const">Vendor\Extension\Model\Payment::METHOD_CODE</item> </argument> </arguments> </type> </config>
Step 7: Create a model file to define payment method app\code\Vendor\Extension\Model\Payment.php
<?php namespace Vendor\Extension\Model; class Payment extends \Magento\Payment\Model\Method\Cc { const METHOD_CODE = 'Extension'; protected $_code = self::METHOD_CODE; protected $_Extension; protected $_isGateway = true; protected $_canCapture = true; protected $_canCapturePartial = true; protected $_canRefund = true; protected $_minOrderTotal = 0; protected $_supportedCurrencyCodes = array('USD','GBP','EUR'); 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, \Extension\Extension $Extension, array $data = array() ) { parent::__construct( $context, $registry, $extensionFactory, $customAttributeFactory, $paymentData, $scopeConfig, $logger, $moduleList, $localeDate, null, null, $data ); $this->_code = 'Extension'; $this->_Extension = $Extension; $this->_Extension->setApiKey($this->getConfigData('api_key')); $this->_minOrderTotal = $this->getConfigData('min_order_total'); } public function canUseForCurrency($currencyCode) { if (!in_array($currencyCode, $this->_supportedCurrencyCodes)) { return false; } return true; } public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount) { $order = $payment->getOrder(); $billing = $order->getBillingAddress(); try{ $charge = \Extension\Charge::create(array( 'amount' => $amount*100, 'currency' => strtolower($order->getBaseCurrencyCode()), 'card' => array( 'number' => $payment->getCcNumber(), 'exp_month' => sprintf('%02d',$payment->getCcExpMonth()), 'exp_year' => $payment->getCcExpYear(), 'cvc' => $payment->getCcCid(), 'name' => $billing->getName(), 'address_line1' => $billing->getStreet(1), 'address_line2' => $billing->getStreet(2), 'address_zip' => $billing->getPostcode(), 'address_state' => $billing->getRegion(), 'address_country' => $billing->getCountry(), ), 'description' => sprintf('#%s, %s', $order->getIncrementId(), $order->getCustomerEmail()) )); $payment->setTransactionId($charge->id)->setIsTransactionClosed(0); return $this; }catch (\Exception $e){ $this->debugData(['exception' => $e->getMessage()]); throw new \Magento\Framework\Validator\Exception(__('Payment capturing error.')); } } public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount) { $transactionId = $payment->getParentTransactionId(); try { \Extension\Charge::retrieve($transactionId)->refund(); } catch (\Exception $e) { $this->debugData(['exception' => $e->getMessage()]); throw new \Magento\Framework\Validator\Exception(__('Payment refunding error.')); } $payment ->setTransactionId($transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND) ->setParentTransactionId($transactionId) ->setIsTransactionClosed(1) ->setShouldCloseParentTransaction(1); return $this; } public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null){ $this->_minOrderTotal = $this->getConfigData('min_order_total'); if($quote && $quote->getBaseGrandTotal() < $this->_minOrderTotal) { return false; } return $this->getConfigData('api_key', ($quote ? $quote->getStoreId() : null)) && parent::isAvailable($quote); } }
Step 8: Create a model file to define Allowed CC type app\code\Vendor\Extension\Model\Source\Cctype.php
<?php namespace Vendor\Extension\Model\Source; class Cctype extends \Magento\Payment\Model\Source\Cctype{ public function getAllowedTypes() { return array('VI', 'MC', 'AE', 'DI', 'JCB', 'OT'); } }
Step 9: Create app\code\Vendor\Extension\view\frontend\web\js\view\payment\Extensionpayments.js to register our template or renderer file.
define( [ 'uiComponent', 'Magento_Checkout/js/model/payment/renderer-list' ], function ( Component, rendererList ) { 'use strict'; rendererList.push( { type: 'Extension', component: 'Vendor_Extension/js/view/payment/method-renderer/Extensionmethod' } ); /** Add view logic here if needed */ return Component.extend({}); } );
Step 10: Create app\code\Vendor\Extension\view\frontend\web\js\view\payment\method-renderer\Extensionmethod.js
define( [ 'Magento_Payment/js/view/payment/cc-form', 'jquery', 'Magento_Checkout/js/action/place-order', 'Magento_Checkout/js/model/full-screen-loader', 'Magento_Checkout/js/model/payment/additional-validators', 'Magento_Payment/js/model/credit-card-validation/validator' ], function (Component, $) { 'use strict'; return Component.extend({ defaults: { template: 'Vendor_Extension/payment/Extension' }, getCode: function() { return 'Extension'; }, isActive: function() { return true; }, validate: function() { var $form = $('#' + this.getCode() + '-form'); return $form.validation() && $form.validation('isValid'); } }); } );
Step 11: Create app\code\Vendor\Extension\view\frontend\web\template\payment\Extension.html template file.
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"> <div class="payment-method-title field choice"> <input type="radio" name="payment[method]" class="radio" data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label> </div> <div class="payment-method-content"> <!-- ko foreach: getRegion('messages') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> <div class="payment-method-billing-address"> <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> </div> <form class="form" data-bind="attr: {'id': getCode() + '-form'}"> <!-- ko template: 'Magento_Payment/payment/cc-form' --><!-- /ko --> </form> <div class="checkout-agreements-block"> <!-- ko foreach: $parent.getRegion('before-place-order') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> </div> <div class="actions-toolbar"> <div class="primary"> <button class="action primary checkout" type="submit" data-bind=" click: placeOrder, attr: {title: $t('Place Order')}, css: {disabled: !isPlaceOrderActionAllowed()}, enable: (getCode() == isChecked()) " disabled> <span data-bind="text: $t('Place Order')"></span> </button> </div> </div> </div> </div
Step 12: Create app\code\Vendor\Extension\view\frontend\layout\checkout_index_index.xml to define payment method at checkout page.
<?xml version="1.0"?> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> <argument name="jsLayout" xsi:type="array"> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> <item name="billing-step" xsi:type="array"> <item name="component" xsi:type="string">uiComponent</item> <item name="children" xsi:type="array"> <item name="payment" xsi:type="array"> <item name="children" xsi:type="array"> <item name="renders" xsi:type="array"> <!-- merge payment method renders here --> <item name="children" xsi:type="array"> <item name="Extension-payments" xsi:type="array"> <item name="component" xsi:type="string">Vendor_Extension/js/view/payment/Extensionpayments</item> <item name="methods" xsi:type="array"> <item name="Extension" xsi:type="array"> <item name="isBillingAddressRequired" xsi:type="boolean">true</item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </item> </argument> </arguments> </referenceBlock> </body> </page>
Run the below commands to install the above extension:
Composer require Extension/Extension-php:3.11.0 and add as below sequence
php bin/magento setup:upgrade php bin/magento setup:di:compile php bin/magento setup:static-content:deploy -f php bin/magento cache:clean php bin/magento cache:flush
Utilize our custom payment method service and integrate various payment methods with your Magento 2 store effortlessly.
If you have followed the steps in a perfect manner, you can see your custom payment method on the checkout page. I hope this guide was helpful to serve your purpose. Comments and queries are always welcomed.
Happy Coding
Hello Magento Friends, In today’s blog, I will explain How to Add Tooltip in Checkout…
MongoDB is a popular NoSQL database that offers flexibility and scalability when handling modern web…
In NodeJS, callbacks empower developers to execute asynchronous operations like reading files, handling requests, and…
Hello Magento Friends, In today’s blog, we will learn How to Show SKU in Order…
The "Buy Now" and "Add to Cart" buttons serve as the primary call-to-action (CTA) elements…
Hello Magento Friends, In Magento 2, the checkout process allows customers to choose multiple shipping…
View Comments
The above code will give a compilation error.
Class Extension\Extension does not exist
I'm getting below error while at the time of di:compile.
impossible to process constructor argument Parameter #9 [ Extension\Extension $Extension ] of Vendor\Extension\Model\Payment c
lass
yes correct
after running your code i have a error in my cmd like "Constant name is expected."
while using upgrade command, Do you have a any solution?
Hello,
Thank you for posting this blog it is very helpful for me.
The major stuck for me is that card holder name field is missing, so can you please let me know where to add card holder field in custom payment gateway.
Hie, I am working on Magento 2.2 and I want to make two payment methods in single module, I followed your steps and some articles on StackExchange, I successfully able to create module and it is visible in config. But however The second payment method is not showing on checkout page. I tried with several things, but i am not able to show both the payment methods at a time. Can you please guide me on this???
Please email us at support@Magecomp.com
This module doesn't load the method in admin checkout.
Does this module shows the form to enter credit card details in checkout page?
Hi
Appreciated.
But in case I need a sample payment module to do cards payments using bank API with magento version 1.9 (1.9.1.0).
This Bank API is based on php-javaBridge. I do not know the difficulties in this extension. Can you suggest a way to do this
I would appreciate if you share any sample module for this
Don't you have php-javaBridge installed on your server.
Please contact us at support@magecomp.com for further help.
does this module store CC info into the database? what if I want to get this information and process those CC manually, instead of running them through payment gateway?
This method don't store card detail into the database,
For the manual payment, you need to store card info like saved cc payment method in magento1.
tout d'abord, merci pour le cours ;)
qd j'arrive sur ce ligne de code
=> php bin/magento setup:upgrade
il m'envoye des erreurs ....
**********************CMD***********************************
C:\wamp64\www\magento>php bin/magento setup:upgrade
Parse error: syntax error, unexpected '.' in C:\wamp64\www\magento\vendor\magento\framework\ObjectManager\Factory\AbstractFactory.php on line 93
Call Stack:
0.0003 126688 1. {main}() C:\wamp64\www\magento\bin\magento:0
0.0512 924032 2. Magento\Framework\Console\Cli->__construct() C:\wamp64\www\magento\bin\magento:22
1.3110 13318024 3. Symfony\Component\Console\Application->__construct() C:\wamp64\www\magento\vendor\magento\framework\Console\Cli.php:83
1.3196 13779456 4. Magento\Framework\Console\Cli->getDefaultCommands() C:\wamp64\www\magento\vendor\symfony\console\Symfony\Component\Console\Application.php:91
1.3209 13831960 5. Magento\Framework\Console\Cli->getApplicationCommands() C:\wamp64\www\magento\vendor\magento\framework\Console\Cli.php:112
1.3243 13898632 6. Magento\Framework\App\Bootstrap->getObjectManager() C:\wamp64\www\magento\vendor\magento\framework\Console\Cli.php:128
1.3243 13898704 7. Magento\Framework\App\Bootstrap->initObjectManager() C:\wamp64\www\magento\vendor\magento\framework\App\Bootstrap.php:362
1.3243 13899184 8. Magento\Framework\App\ObjectManagerFactory->create() C:\wamp64\www\magento\vendor\magento\framework\App\Bootstrap.php:385
1.4149 15151288 9. Magento\Framework\App\ObjectManager\Environment\AbstractEnvironment->getObjectManagerFactory() C:\wamp64\www\magento\vendor\magento\framework\App\ObjectManagerFactory.php:177
1.4149 15151480 10. Magento\Framework\App\ObjectManager\Environment\AbstractEnvironment->createFactory() C:\wamp64\www\magento\vendor\magento\framework\App\ObjectManager\Environment\AbstractEnvironment.php:61
1.4149 15151808 11. spl_autoload_call() C:\wamp64\www\magento\vendor\magento\framework\App\ObjectManager\Environment\AbstractEnvironment.php:103
1.4149 15151880 12. Composer\Autoload\ClassLoader->loadClass() C:\wamp64\www\magento\vendor\magento\framework\App\ObjectManager\Environment\AbstractEnvironment.php:0
1.4153 15152016 13. Composer\Autoload\includeFile() C:\wamp64\www\magento\vendor\composer\ClassLoader.php:301
1.4157 15166064 14. include('C:\wamp64\www\magento\vendor\magento\framework\ObjectManager\Factory\Dynamic\Developer.php') C:\wamp64\www\magento\vendor\composer\ClassLoader.php:412
1.4157 15166320 15. spl_autoload_call() C:\wamp64\www\magento\vendor\composer\ClassLoader.php:9
1.4157 15166384 16. Composer\Autoload\ClassLoader->loadClass() C:\wamp64\www\magento\vendor\composer\ClassLoader.php:0
1.4160 15166520 17. Composer\Autoload\includeFile() C:\wamp64\www\magento\vendor\composer\ClassLoader.php:301
********************************** fin **************************************
Pouvez vous m'aider s'il vous plaît!
Cordialement,
This doesn't seems to be the issue of our extension
Please contact us for the help.