Ödeme Modülü Geliştirme
Ödeme yöntemi, ModuleBase'i genişleten ve
$isPayment = true ile kayıt olan bir modüldür.
Genel modül kuralları için Yeni Modül Oluştur
ve kancalar için Kanca Listesi sayfalarına bakın.
Zorunlu özellikler
| Özellik | Açıklama |
|---|---|
$isPayment |
true — ödeme adımında yöntem olarak kaydeder |
$paymentMethodId |
orders.payment_method içinde saklanan benzersiz kimlik
(radyo value ile aynı olmalı) |
$paymentMethodLabel |
Vitrinde görünen etiket (ör. Havale / EFT) |
$paysBeforeOrder |
true — sipariş oluşturulmadan önce yönlendirmeli PSP / sanal POS |
Görüntüleme kancaları
order_payment— ödeme yöntemi seçimi (radyo + açıklama)order_confirmation— sipariş sonrası talimat / banka bilgisi-
Yönlendirmeli sağlayıcılar için
$paysBeforeOrder = trueve gerekirse özel front route (ör.sanalpos/ PayTR / ParamPOS tarzı)
processPayment(array $order): array
Ödeme işlendikten sonra tipik dönüş:
return [
'success' => true,
'redirect' => '', // PSP URL'si (gerekirse)
'message' => '',
];
Referanslar:
basit havale için
bankwire;
yönlendirme / 3D dönüş için paytr, parampos veya
sanalpos tarzı modüllere bakın.
Callback / bildirim uçları
Sağlayıcı dönüşlerini $apiActions içinde kaydedin ve
/api/module.php?m={name}&action=... veya
api/callback.php kalıbı üzerinden karşılayın.
CSRF muaf tutulan tipik aksiyon adları:
callbacknotifywebhookipnreturn3d-return
Önemli: CSRF muafiyeti, imza / hash doğrulamasını kaldırmaz.
Sağlayıcı imzasını her zaman sunucu tarafında doğrulayın.
Güvenlik kontrol listesi
- İstemciden gelen tutara asla güvenmeyin — sipariş / sepet tutarını sunucudan doğrulayın
- PSP imzasını, merchant key / hash'i ve sipariş kimliğini doğrulayın
- Başarılı ödemeyi yalnızca doğrulanmış callback / IPN sonrası işaretleyin
- PHP 7.4 uyumlu kod yazın (
match, birleşik tipler, adlandırılmış argüman yok) - SQL için hazırlanmış ifadeler; çıktıda escape
İlgili sayfalar
PHP
<?php
if (!defined('IN_SCRIPT') && !defined('IN_ADMIN')) {
exit;
}
class DemoPayModule extends ModuleBase
{
public string $name = 'demo-pay';
public string $version = '1.0.0';
public string $displayName = 'Demo Pay';
public string $description = 'Sample payment module';
public bool $isPayment = true;
public string $paymentMethodId = 'demo_pay';
public string $paymentMethodLabel = 'Demo Pay';
public bool $paysBeforeOrder = false;
public array $displayHooks = [
'order_payment' => 'Checkout payment option',
'order_confirmation' => 'Thank-you page instructions',
];
public array $defaultDisplayHooks = [
'order_payment',
'order_confirmation',
];
public array $apiActions = [
'callback' => 'api/callback.php',
];
public function processPayment(array $order): array
{
// Post-order flow (bankwire-style). Redirect only if needed.
return [
'success' => true,
'redirect' => '',
'message' => '',
];
}
public function renderDisplayHook(string $hook, array $context = [])
{
if ($hook === 'order_payment') {
return $this->renderFrontTemplate('order_payment', [
'paymentMethodId' => $this->paymentMethodId,
'label' => $this->paymentMethodLabel,
'formData' => isset($context['formData']) ? $context['formData'] : [],
]);
}
if ($hook === 'order_confirmation') {
return $this->renderFrontTemplate('order_confirmation', [
'order' => isset($context['order']) ? $context['order'] : [],
]);
}
return null;
}
}
callback.php — imza doğrulama taslağı
<?php
// modules/demo-pay/api/callback.php — verify PSP signature sketch
if (!defined('IN_SCRIPT')) {
exit;
}
header('Content-Type: application/json; charset=utf-8');
$merchantKey = (string) Settings::get('DEMO_PAY_MERCHANT_KEY');
$payload = file_get_contents('php://input');
$data = json_decode((string) $payload, true);
if (!is_array($data)) {
$data = $_POST;
}
$provided = isset($data['hash']) ? (string) $data['hash'] : '';
$orderId = isset($data['merchant_oid']) ? (string) $data['merchant_oid'] : '';
$status = isset($data['status']) ? (string) $data['status'] : '';
$total = isset($data['total_amount']) ? (string) $data['total_amount'] : '';
$expected = base64_encode(hash_hmac(
'sha256',
$orderId . $merchantKey . $status . $total,
$merchantKey,
true
));
if ($provided === '' || !hash_equals($expected, $provided)) {
http_response_code(403);
echo json_encode(['success' => false, 'message' => 'Invalid signature']);
exit;
}
// Never trust client amount alone — load order and compare server-side totals here.
if ($status !== 'success') {
echo json_encode(['success' => false, 'message' => 'Payment not successful']);
exit;
}
echo json_encode(['success' => true]);