
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 (örneğin, “Kapıda Ödeme” gibi) mantığıyla hazırlanmıştır. Gerçek bir Sanal POS (redirect veya direct API) entegrasyonu, API çağrıları, güvenlik (PCI DSS) uyumluluğu, 3D Secure yönetimi ve karmaşık hata senaryolarının ele alınmasını gerektirir. Bu tür karmaşık ve kritik entegrasyonlar için profesyonel destek almanız şiddetle tavsiye edilir. Ekip olarak, bu konuda uçtan uca güvenli ve stabil çözümler sunmaktayız.
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ıyı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 Bu dosya, modülümüzün adını ve varsa bağımlılıklarını (dependencies) tanımlar. Ödeme modülleri genellikle Magento_Payment ve Magento_Checkout modüllerine bağımlıdır.
<?xml version="1.0"?>
<config xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](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)
Şimdi, ödeme yöntemimizi Mağazalar > Yapılandırma > Satış > Ödeme Yöntemleri altında görünür hale getirecek ve ayarlarını ekleyeceğiz.
Dosya: app/code/Inovasyon/CustomPayment/etc/adminhtml/system.xml Bu dosya, admin panelindeki konfigürasyon alanlarını oluşturur.
<?xml version="1.0"?>
<config xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](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="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 Bu dosya, system.xml‘de tanımladığımız alanlar için varsayılan (default) değerleri belirler.
<?xml version="1.0"?>
<config xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](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>
Önemli: <model> etiketi, bu ödeme yönteminin mantığını hangi PHP sınıfının yöneteceğini belirtir. Bu, en 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 Bu dosya, ödeme yöntemimizin kodunu (code) ve yeteneklerini (capabilities) Magento’nun ödeme sistemine bildirir.
<?xml version="1.0"?>
<config xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](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>
<method name="custompayment">: Buradaki custompayment adı, config.xml ve system.xml‘deki group ID (<group id="custompayment">) ile aynı olmalıdır.
4. Adım: Çekirdek Ödeme Mantığı (Model)
Bu, ödeme yöntemimizin “beynidir”. config.xml dosyasında <model> olarak belirttiğimiz sınıfı oluşturacağız.
Dosya: app/code/Inovasyon/CustomPayment/Model/Payment.php Bu sınıf, Magento’nun temel ödeme metodundan (AbstractMethod) miras alır ve tüm çekirdek fonksiyonları içerir.
<?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
{
/**
* Ödeme yöntemimizin benzersiz kodu.
* Bu, config.xml, system.xml ve payment.xml'deki adla eşleşmelidir.
*/
const PAYMENT_METHOD_CODE = 'custompayment';
/**
* @var string
*/
protected $_code = self::PAYMENT_METHOD_CODE;
/**
* Bu ödeme yöntemi checkout'ta kullanılabilir mi?
* @var bool
*/
protected $_canUseCheckout = true;
/**
* Müşteri sipariş verdiğinde para çekme (capture) işlemi otomatik yapılsın mı?
* @var bool
*/
protected $_isInitializeNeeded = true;
/**
* Talimatları almak için
*/
public function getInstructions()
{
return $this->getConfigData('instructions');
}
/**
* Sipariş verildikten sonra ödeme işlemini başlatır.
* Genellikle 'capture' veya 'authorize' işlemi burada tetiklenir.
*
* @param InfoInterface $payment
* @param float $amount
* @return $this
* @throws LocalizedException
*/
public function initialize($paymentAction, $stateObject)
{
/**
* Basit bir offline metot için, sipariş durumunu "Yeni Sipariş Durumu"
* (system.xml'de belirlediğimiz) olarak ayarlarız.
*/
$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;
}
/**
* Bu ödeme yöntemi sepet için geçerli mi?
* Örneğin, sadece belirli bir tutar üzerinde veya belirli ülkeler için
* aktif hale getirebilirsiniz.
*
* @param CartInterface|null $quote
* @return bool
*/
public function isAvailable(CartInterface $quote = null)
{
if (parent::isAvailable($quote) === false) {
return false;
}
// Buraya özel kurallar ekleyebilirsiniz.
// Örneğin: Sepet tutarı 100 TL'den azsa gösterme
/*
if ($quote && $quote->getBaseGrandTotal() < 100) {
return false;
}
*/
return true;
}
/**
* Gerçek bir API entegrasyonunda 'Capture' (Ödemeyi Çekme) işlemi burada yapılır.
* API'ye istek gönderilir, cevap alınır ve transaction oluşturulur.
*/
public function capture(InfoInterface $payment, $amount)
{
// Basit bir offline metot olduğumuz için sadece log atıp geçiyoruz.
// Gerçek senaryoda:
// 1. API'ye istek at.
// 2. Başarılıysa:
// $payment->setTransactionId('API_TRANSACTION_ID');
// $payment->setIsTransactionClosed(true); // true = capture, false = authorize
// 3. Başarısızsa:
// throw new LocalizedException(__('Ödeme alınamadı.'));
$this->_logger->info('Inovasyon CustomPayment Capture işlemi tetiklendi.');
return $this;
}
/**
* 'Authorize' (Provizyon Alma) işlemi burada yapılır.
*/
public function authorize(InfoInterface $payment, $amount)
{
// Benzer şekilde, API'den provizyon alınır.
$this->_logger->info('Inovasyon CustomPayment Authorize işlemi tetiklendi.');
// $payment->setTransactionId('API_TRANSACTION_ID');
// $payment->setIsTransactionClosed(false);
return $this;
}
// refund, void gibi diğer önemli metodlar da burada override edilebilir.
}
5. Adım: Checkout (Ödeme Sayfası) Entegrasyonu
Son adım, bu ödeme yöntemini ödeme sayfasında (checkout) göstermektir. Magento 2 checkout, Knockout.js tabanlıdır.
Dosya: app/code/Inovasyon/CustomPayment/etc/frontend/di.xml Ödeme yöntemimizin Model sınıfını ve frontend Component‘ini Magento’nun Composite listesine ekleriz.
<?xml version="1.0"?>
<config xmlns:xsi="[http://www.w3.org/2001/XMLSchema-instance](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 (Admin Panel) 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 Bu sınıf, backend’deki yapılandırmayı (başlık, talimatlar vb.) frontend’deki Knockout.js bileşenine JSON olarak aktarır.
<?php
namespace Inovasyon\CustomPayment\Model\Ui;
use Magento\Checkout\Model\ConfigProviderInterface;
use Inovasyon\CustomPayment\Model\Payment;
class ConfigProvider implements ConfigProviderInterface
{
/**
* @var Payment
*/
protected $method;
public function __construct(
\Magento\Payment\Helper\Data $paymentHelper
) {
$this->method = $paymentHelper->getMethodInstance(Payment::PAYMENT_METHOD_CODE);
}
/**
* Checkout config'e eklenecek verileri hazırlar
*
* @return array
*/
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 Bu, Knockout.js “view-model” dosyasıdır. Ödeme yöntemimizin frontend’deki mantığını (tıklama, veri bağlama) yönetir.
define(
[
'Magento_Checkout/js/view/payment/default',
'Inovasyon_CustomPayment/js/action/set-payment-method-action', // Gerçek senaryoda bu dosyayı da oluşturmak gerekir
'ko',
'Magento_Checkout/js/model/quote'
],
function (Component, setPaymentMethodAction, ko, quote) {
'use strict';
return Component.extend({
defaults: {
template: 'Inovasyon_CustomPayment/payment/custompayment'
},
// Ödeme metodumuzun kodunu döndürür
getCode: function () {
return 'custompayment';
},
// Aktif olup olmadığını kontrol eder
isActive: function () {
return true;
},
// ConfigProvider'dan gelen talimatları alır
getInstructions: function () {
var instructions = window.checkoutConfig.payment.instructions[this.getCode()];
return instructions;
},
// ConfigProvider'dan gelen başlığı alır
getTitle: function() {
return window.checkoutConfig.payment.custompayment.title;
}
/**
* Gerçek bir 'redirect' (yönlendirmeli) senaryoda,
* 'placeOrder' fonksiyonunu override edip
* müşteriyi bankanın 3D Secure sayfasına yönlendirirsiniz.
* * placeOrder: function (data, event) {
* // ...
* // Müşteriyi yönlendirme işlemleri
* // ...
* }
*/
});
}
);
Dosya: app/code/Inovasyon/CustomPayment/view/frontend/web/template/payment/custompayment.html Bu, ödeme yöntemimizin checkout’ta görünecek HTML şablonudur.
<!--
/**
* 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">
<!-- Başlığı ConfigProvider'dan alıyoruz -->
<span data-bind="text: getTitle()"></span>
</label>
</div>
<div class="payment-method-content">
<!-- 'Place Order' butonuna tıklandığında gösterilecek içerik -->
<div class="payment-method-billing-address">
<!-- Ödeme metodu seçildiğinde talimatları göster -->
<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 Magento 2 Ödeme Yöntemi Geliştirme Hizmetleri
Yukarıdaki adımlar, basit bir ödeme yönteminin temel yapısını göstermektedir. Ancak gerçek dünyada, özellikle Türkiye pazarındaki banka Sanal POS’ları (Iyzico, PayTR, Garanti, Akbank vb.) için bir entegrasyon çok daha karmaşıktır:
- Güvenlik ve PCI DSS Uyumluluğu: Müşteri kredi kartı bilgilerinin güvenliği en yüksek önceliktir. API (Direct) yöntemlerinde sunucunuzun PCI uyumlu olması gerekir. Yönlendirmeli (Redirect/3D Secure) yöntemlerde ise geri dönen verinin (callback/response) doğrulanması (hash kontrolü) hayati önem taşır.
- API Entegrasyonu (Direct/Redirect): Çoğu ödeme sağlayıcısı, ödemeyi başlatmak, doğrulamak ve sonucu almak için karmaşık API’ler (SOAP veya REST) kullanır. Bu API’lere GuzzleHttp gibi kütüphanelerle güvenli istekler yapılmalı, XML/JSON cevapları doğru yorumlanmalıdır.
- 3D Secure Yönetimi: 3D Secure (veya 3D Secure 2.0) akışı, müşterinin banka sayfasına yönlendirilmesini, doğrulama yapmasını ve sitenize geri dönmesini içerir. Bu ‘callback’ işlemini yönetecek özel Controller’lar (Success, Fail, Callback) yazılmalıdır.
- Transaction (İşlem) Yönetimi: Ödeme “Authorize” (Provizyon) mı, yoksa “Capture” (Çekim) mi yapılacak? Başarılı işlemler için Magento’da “Transaction” ve “Invoice” (Fatura) otomatik oluşturulmalı, başarısız işlemlerde sipariş iptal edilmeli veya ‘pending’ durumunda bırakılmalıdır.
- İptal ve İade (Void/Refund): Gerçek bir entegrasyon, Magento admin paneli üzerinden (fatura sayfasından) doğrudan Sanal POS’a bağlanarak iade veya iptal işlemi yapabilmelidir (
can_void,can_refund). - Sürüm Uyumluluğu ve Bakım: Magento sürekli güncellenir. Geliştirilen ödeme modülünün yeni Magento sürümleriyle (örn. Magento 2.4.x) ve PHP sürümleriyle (PHP 8.x) uyumlu çalışmaya devam etmesi için bakım gereklidir.
Neden Profesyonel Hizmet Almalısınız?
Bir ödeme ağ geçidi, e-ticaret sitenizin kalbidir. Bu sistemdeki küçük bir hata veya güvenlik açığı, sadece satış kaybetmenize değil, aynı zamanda müşteri güvenini kaybetmenize ve yasal yaptırımlarla karşılaşmanıza neden olabilir.
Ekip olarak, Magento 2 için A’dan Z’ye özel ödeme ağ geçidi geliştirme, Sanal POS entegrasyonu ve mevcut modüllerinizin güvenlik denetimi konularında profesyonel hizmet sunmaktayız. Sitenizin güvenli, stabil ve hızlı bir ödeme altyapısına sahip olması için bizimle iletişime geçebilirsiniz.
Sonuç
Magento 2’de özel ödeme yöntemi geliştirmek, platformun derinliklerine inmeyi gerektiren zorlu bir görevdir. Bu rehber, gerekli olan temel dosya yapısını ve konseptleri anlamanız için bir başlangıç noktasıdır. Başarılı ve güvenli bir entegrasyon için her adımı dikkatle planlamak ve test etmek şarttır.

