Magento 2 Özel Ödeme Ağ Geçidi (Payment Gateway) Geliştirme: Kapsamlı Rehber
Magento 2'de özel bir ödeme ağ geçidi (payment gateway) modülü geliştirme adımları: modül yapısı, sistem ayarları, model, frontend entegrasyonu ve güvenlik notları.
Magento 2, dünyanın en esnek e‑ticaret platformlarından biridir. Bu esnekliğin en önemli parçası, yerel banka sanal POS’ları, özel ödeme servisleri veya pazar yeri çözümleri gibi her türlü ödeme sistemini platforma entegre edebilme yeteneğidir.
Ancak, bir ödeme ağ geçidi (payment gateway) modülü geliştirmek, basit bir “Merhaba Dünya” modülünden çok daha karmaşıktır. Bu süreç, Magento’nun mimarisini, ödeme akışlarını, güvenlik standartlarını ve hem backend hem de frontend (Knockout.js) bilgisini gerektirir.
Bu rehberde, sıfırdan basit bir özel ödeme yönteminin nasıl oluşturulacağına dair temel adımları ve kod örneklerini bulacaksınız.
Önemli Not: Bu rehber, temel yapıyı göstermek amacıyla “çevrimdışı” (offline) bir ödeme metodu mantığıyla hazırlanmıştır. Gerçek bir Sanal POS entegrasyonu, API çağrıları, güvenlik (PCI DSS) uyumluluğu, 3D Secure yönetimi ve hata senaryolarının ele alınmasını gerektirir. Kritik entegrasyonlar için profesyonel destek almanız tavsiye edilir.
1. Adım: Modülün Temel Yapısını Oluşturma
Her şeyden önce, Magento 2 standartlarına uygun bir modül oluşturmalısınız. Modülümüzün adı Inovasyon_CustomPayment olsun.
Dosya: app/code/Inovasyon/CustomPayment/registration.php — Bu dosya, modülümüzü Magento’ya kaydeder.
<?php
/**
* Copyright © Inovasyon, Inc. All rights reserved.
*/
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'Inovasyon_CustomPayment',
__DIR__
);
Dosya: app/code/Inovasyon/CustomPayment/etc/module.xml — Modül adını ve bağımlılıkları tanımlar.
<?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="Inovasyon_CustomPayment" setup_version="1.0.0">
<sequence>
<module name="Magento_Payment"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
Bu iki dosyayı oluşturduktan sonra, modülü etkinleştirmek için terminalden şu komutları çalıştırın:
php bin/magento setup:upgrade
php bin/magento cache:flush
2. Adım: Ödeme Yöntemini Yapılandırma (Configuration)
Ödeme yöntemimizi Mağazalar > Yapılandırma > Satış > Ödeme Yöntemleri altında görünür hale getirecek ve ayarlarını tanımlayacağız.
Dosya: app/code/Inovasyon/CustomPayment/etc/adminhtml/system.xml — Admin panelindeki konfigürasyon alanlarını oluşturur.
<?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="custompayment" translate="label" type="text" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Özel Ödeme Yöntemi</label>
<field id="active" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Etkin</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="title" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Başlık</label>
<comment>Ödeme sayfasında görünecek başlık.</comment>
</field>
<field id="order_status" translate="label" type="select" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="0" canRestore="1">
<label>Yeni Sipariş Durumu</label>
<source_model>Magento\Sales\Model\Config\Source\Order\Status\NewStatus</source_model>
</field>
<field id="instructions" translate="label" type="textarea" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Talimatlar</label>
<comment>Ödeme yöntemi seçildiğinde görünecek açıklama.</comment>
</field>
<field id="sort_order" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Sıralama</label>
</field>
</group>
</section>
</system>
</config>
Dosya: app/code/Inovasyon/CustomPayment/etc/config.xml — system.xml’de tanımlanan alanlar için varsayılan değerleri belirler.
<?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>
<custompayment>
<active>0</active>
<model>Inovasyon\CustomPayment\Model\Payment</model>
<title>Özel Ödeme</title>
<order_status>pending</order_status>
<can_authorize>1</can_authorize>
<can_capture>1</can_capture>
<can_void>1</can_void>
<can_refund>1</can_refund>
<can_use_checkout>1</can_use_checkout>
<can_use_internal>1</can_use_internal>
</custompayment>
</payment>
</default>
</config>
<model> etiketi, ödeme yönteminin mantığını hangi PHP sınıfının yöneteceğini belirtir — bu kritik bağlantıdır.
3. Adım: Ödeme Yöntemini Magento’ya Tanıtma
Magento’ya bunun bir ödeme yöntemi olduğunu ve checkout’ta nasıl görüneceğini söylememiz gerekiyor.
Dosya: app/code/Inovasyon/CustomPayment/etc/payment.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Payment:etc/payment.xsd">
<methods>
<method name="custompayment">
<allow_multiple_address>1</allow_multiple_address>
</method>
</methods>
</config>
4. Adım: Çekirdek Ödeme Mantığı (Model)
Ödeme yönteminin “beynini” oluşturan sınıf app/code/Inovasyon/CustomPayment/Model/Payment.php olacaktır. Bu sınıf, Magento’nun AbstractMethod sınıfından türetilir ve capture, authorize gibi metodları override eder.
<?php
namespace Inovasyon\CustomPayment\Model;
use Magento\Payment\Model\Method\AbstractMethod;
use Magento\Framework\Exception\LocalizedException;
use Magento\Quote\Api\Data\CartInterface;
use Magento\Payment\Model\InfoInterface;
use Magento\Sales\Model\Order\Payment\Transaction;
class Payment extends AbstractMethod
{
const PAYMENT_METHOD_CODE = 'custompayment';
protected $_code = self::PAYMENT_METHOD_CODE;
protected $_canUseCheckout = true;
protected $_isInitializeNeeded = true;
public function getInstructions()
{
return $this->getConfigData('instructions');
}
public function initialize($paymentAction, $stateObject)
{
$payment = $this->getInfoInstance();
$order = $payment->getOrder();
$order->setCanSendNewEmailFlag(true);
$state = $this->getConfigData('order_status');
$stateObject->setState($state);
$stateObject->setStatus($state);
$stateObject->setIsNotified(true);
return $this;
}
public function isAvailable(CartInterface $quote = null)
{
if (parent::isAvailable($quote) === false) {
return false;
}
return true;
}
public function capture(InfoInterface $payment, $amount)
{
$this->_logger->info('Inovasyon CustomPayment Capture işlemi tetiklendi.');
return $this;
}
public function authorize(InfoInterface $payment, $amount)
{
$this->_logger->info('Inovasyon CustomPayment Authorize işlemi tetiklendi.');
return $this;
}
}
5. Adım: Checkout (Ödeme Sayfası) Entegrasyonu
Bu adımda frontend Knockout.js ve layout yapılarını ekleyerek ödeme sayfasında metodumuzu görüntüleriz.
Dosya: app/code/Inovasyon/CustomPayment/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<!-- Frontend (Checkout) için ödeme metodu bileşenlerini ekleme -->
<type name="Magento\Checkout\Model\CompositeConfigProvider">
<arguments>
<argument name="configProviders" xsi:type="array">
<item name="inovasyon_custompayment_config_provider" xsi:type="object">Inovasyon\CustomPayment\Model\Ui\ConfigProvider</item>
</argument>
</arguments>
</type>
<!-- Backend'de görünecek talimatlar için -->
<type name="Inovasyon\CustomPayment\Block\Info">
<arguments>
<argument name="data" xsi:type="array">
<item name="is_secure_mode" xsi:type="boolean">false</item>
</argument>
</arguments>
</type>
</config>
Dosya: app/code/Inovasyon/CustomPayment/Model/Ui/ConfigProvider.php
<?php
namespace Inovasyon\CustomPayment\Model\Ui;
use Magento\Checkout\Model\ConfigProviderInterface;
use Inovasyon\CustomPayment\Model\Payment;
class ConfigProvider implements ConfigProviderInterface
{
protected $method;
public function __construct(
\Magento\Payment\Helper\Data $paymentHelper
) {
$this->method = $paymentHelper->getMethodInstance(Payment::PAYMENT_METHOD_CODE);
}
public function getConfig()
{
$config = [];
if ($this->method->isAvailable()) {
$config['payment']['instructions'][Payment::PAYMENT_METHOD_CODE] = $this->method->getInstructions();
$config['payment']['custompayment']['title'] = $this->method->getTitle();
}
return $config;
}
}
Dosya: app/code/Inovasyon/CustomPayment/view/frontend/web/js/view/payment/method-renderer/custompayment-method.js
define([
'Magento_Checkout/js/view/payment/default',
'Inovasyon_CustomPayment/js/action/set-payment-method-action', // Gerçek senaryoda bu dosya da oluşturulmalıdır
'ko',
'Magento_Checkout/js/model/quote',
], function (Component, setPaymentMethodAction, ko, quote) {
'use strict';
return Component.extend({
defaults: {
template: 'Inovasyon_CustomPayment/payment/custompayment',
},
getCode: function () {
return 'custompayment';
},
isActive: function () {
return true;
},
getInstructions: function () {
var instructions = window.checkoutConfig.payment.instructions[this.getCode()];
return instructions;
},
getTitle: function () {
return window.checkoutConfig.payment.custompayment.title;
},
});
});
Dosya: app/code/Inovasyon/CustomPayment/view/frontend/web/template/payment/custompayment.html
<!--
/**
* Copyright © Inovasyon, Inc. All rights reserved.
*/
-->
<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">
<div class="payment-method-billing-address">
<div class="checkout-payment-method-custom-instructions">
<span data-bind="text: getInstructions()"></span>
</div>
</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: isPlaceOrderActionAllowed()"
disabled
>
<span data-bind="i18n: 'Place Order'"></span>
</button>
</div>
</div>
</div>
</div>
Profesyonel İpuçları
- Gerçek bir entegrasyon için PCI DSS, 3D Secure ve hata yönetimi gibi kritik konuları uzman ekibinizle planlayın.
- API istemcisi olarak
GuzzleHttpgibi kütüphaneler kullanılabilir; HTTP istekleri, zaman aşımı, yeniden deneme ve güvenlik için dikkatlice yapılandırılmalıdır. - Her API çağrısını ve geri dönüşünü loglayın, ancak hassas verileri (kredi kartı gibi) loglamaktan kaçının.
- Testler: Unit ve integration testlerini yazın; sahte (mock) API sunucuları ile testler oluşturun.
Sonuç
Magento 2’de özel bir ödeme yöntemi geliştirmek zordur ancak modüler yapıyı doğru kurguladığınızda yönetilebilir ve sürdürülebilir çözümler üretebilirsiniz. Bu rehber, başlangıç için gerekli temel yapı ve örnekleri verdi. Gerçek bir entegrasyon için daha derin test ve güvenlik kontrolleri gereklidir.
Etiketler:
Yılmaz Soft
Yılmaz Soft olarak web geliştirme, mobil uygulama ve dijital pazarlama alanlarında profesyonel çözümler sunuyoruz. Müşterilerimizin dijital dönüşüm süreçlerinde yanlarında olmaktan gurur duyuyoruz.
İletişime Geçin