Taksit Bilgisi Size Ait
Kart bilgileriyle tek istekte tahsilat: /Vpos/v1/Payment ucuna use3D=false ile imzalı isteği gönderir, sonucu aynı yanıtın içinde JSON olarak işlersiniz.
Uç Nokta
Test
POST https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment
Canlı
POST https://paynkolay.nkolayislem.com.tr/Vpos/v1/Payment
Gövde
multipart/form-data
Canlı ortama geçerken: canlı uç yalnızca sunucu tarafından yapılan istekleri kabul eder — localhost üzerinden gönderilen istekler güvenlik hatasıyla reddedilir. Bağlantı için en az TLS 1.2 gerekir.
İstek İmzası (hashDatav2)
Alanlar | ile birleştirilir, SHA-512 ile özetlenip Base64'e çevrilir. İmza her zaman sunucu tarafında üretilir:
// customerKey kart saklanmıyorsa boş string olarak hash'e girer
$hashstr = $sx."|".$clientRefCode."|".$amount."|".$successUrl."|".$failUrl."|".$rnd."|".$customerKey."|".$merchantSecretKey;
$hashDatav2 = base64_encode(hash("sha512", $hashstr, true));const crypto = require('crypto');
// customerKey kart saklanmıyorsa boş string girer — borusu yine de korunur
function hashDatav2(sx, clientRefCode, amount, successUrl, failUrl, rnd, customerKey, merchantSecretKey) {
const raw = [sx, clientRefCode, amount, successUrl, failUrl, rnd, customerKey, merchantSecretKey].join('|');
return crypto.createHash('sha512').update(raw, 'utf8').digest('base64');
}Parametreler
| Parametre | Tip | Zorunlu | Açıklama |
|---|---|---|---|
| sx | string | ✅ | Size verilen satış (sx) değeriniz |
| clientRefCode | string | ✅ | Sizin ürettiğiniz referans numarası — her işlem için benzersiz olmalı; Türkçe karakter içermemeli, en fazla 1024 karakter |
| amount | decimal | ✅ | Tutar — kuruş ayıracı nokta (ör. 249.90) |
| successUrl | string | ✅ | Başarılı sonucun POST edileceği SSL'li adres |
| failUrl | string | ✅ | Başarısız sonucun POST edileceği SSL'li adres |
| use3D | boolean | ✅ | true = 3DS akışı, false = Non-3DS akışı |
| cardNumber | string | ✅ | Kart numarası |
| cardHolderName | string | ✅ | Kart üzerindeki isim |
| month / year | string | ✅ | Son kullanma ayı (12) ve yılı (2026) |
| cvv | string | ✅ | Kartın güvenlik kodu |
| installmentNo | integer | — | Taksit sayısı; tek çekim için 1 |
| transactionType | string | ✅ | SALES (satış) veya PRESALES (ön provizyon) |
| environment | string | ✅ | API gönderilmelidir |
| currencyNumber | string | ✅ | Para birimi — TL için 949 |
| cardHolderIP | string | ✅ | Müşterinin çıkış IP adresi (IPv4/IPv6) |
| rnd | string | ✅ | İşlem zamanı, Türkiye saatiyle (UTC+3) — ör. 03-09-2026 14:25:11 |
| hashDatav2 | string | ✅ | SHA-512 + Base64 istek imzası (yukarıda) |
| MerchantCustomerNo | string | — | Temsilci veya alt üye işyeri numaranız |
| csCustomerKey | string | — | Kart saklanacaksa müşteri anahtarı (TCKN/telefon) |
| csAutoSave | boolean | — | true ise ve yetki varsa kart kaydedilir |
Örnek İstek
İstek sunucunuzdan tek bir POST ile gider ve sonuç aynı HTTP yanıtında JSON olarak döner. Aşağıdaki form-data isteğinin yanıtı, Yanıt bölümündeki örnektir:
# POST https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment (form-data)
sx=118591467|W8a1JLU8A5Cw…FbOO5A==
clientRefCode=SIP-2026-000123
amount=249.90
successUrl=https://magaza.com/odeme/basarili
failUrl=https://magaza.com/odeme/hata
use3D=false
cardNumber=4546711234567894
cardHolderName=Ayşe Yılmaz
month=12 year=2026 cvv=000
installmentNo=1
transactionType=SALES environment=API currencyNumber=949
cardHolderIP=85.100.20.15
rnd=03-09-2026 14:25:11
hashDatav2=lunnRyNfDu6pdpNjjlFrlATE4Pj…Aynı non-3D ödemenin dört dilde çalışır örneği. use3D=false olduğu için sonuç bu yanıtın içinde döner; 3D formu, banka ekranı ve callback yoktur. SX_DEGERINIZ ve SECRET_KEY_DEGERINIZ yerine kendi değerlerinizi yazın.
<?php
// === NON-3D FLOW — Paynkolay V1 ===
// Çalıştırma: php -S localhost:8000 example.php → http://localhost:8000
// Not: Canlı uç (https://paynkolay.nkolayislem.com.tr/Vpos/v1/Payment) localhost'tan gelen istekleri reddeder.
date_default_timezone_set('Europe/Istanbul'); // rnd Türkiye saatiyle üretilmeli
$merchantSecretKey = "SECRET_KEY_DEGERINIZ";
$sx = "SX_DEGERINIZ";
$clientRefCode = "789456|AB76"; // her işlemde benzersiz olmalı (ör. "ORDER-" . uniqid())
$amount = "6.00";
$successUrl = "https://siteniz.com/payment/success"; // non-3D'de çağrılmaz ama zorunludur ve hash'e girer
$failUrl = "https://siteniz.com/payment/fail";
$rnd = date("d-m-Y H:i:s");
$customerKey = ""; // kart saklanmıyorsa boş
// Müşteri IP'si: önce proxy başlıkları, yoksa bağlantı adresi
function getClientIp(): string
{
foreach (['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP'] as $header) {
if (!empty($_SERVER[$header])) {
$ip = trim(explode(',', $_SERVER[$header])[0]);
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
return $_SERVER['REMOTE_ADDR'] ?? '127.0.0.1';
}
// Hash: sx|clientRefCode|amount|successUrl|failUrl|rnd|customerKey|secretKey → SHA512 (ham bayt) → Base64
$hashstr = "$sx|$clientRefCode|$amount|$successUrl|$failUrl|$rnd|$customerKey|$merchantSecretKey";
$hashDataV2 = base64_encode(hash("sha512", $hashstr, true));
$postData = [
'sx' => $sx,
'clientRefCode' => $clientRefCode,
'successUrl' => $successUrl,
'failUrl' => $failUrl,
'amount' => $amount,
'installmentNo' => '1',
'cardHolderName' => 'Tuna Çınar',
'month' => '12',
'year' => '2026',
'cvv' => '001',
'cardNumber' => '4546711234567894',
'use3D' => 'false', // ← non-3D'yi belirleyen tek satır
'transactionType' => 'SALES',
'cardHolderIP' => getClientIp(),
'hashDatav2' => $hashDataV2,
'rnd' => $rnd,
'environment' => 'API',
'currencyNumber' => '949',
'MerchantCustomerNo' => '', // opsiyonel: temsilci / alt üye işyeri no
];
// POSTFIELDS dizi olarak verilince istek multipart/form-data gider
$curl = curl_init('https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment');
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($curl);
$error = curl_error($curl);
curl_close($curl);
header('Content-Type: text/plain; charset=utf-8');
if ($response === false) {
exit("Bağlantı hatası: " . $error);
}
// === Non-3D'ye özgü kısım: sonuç bu response'ta, form/callback yok ===
$data = json_decode($response, true);
if (isset($data['RESPONSE_CODE']) && $data['RESPONSE_CODE'] == '2') {
echo "Ödeme başarılı. Referans: " . ($data['REFERENCE_CODE'] ?? '-');
// Siparişi burada COMPLETED yap — callback bekleme
} else {
echo "Ödeme başarısız: " . ($data['RESPONSE_DATA'] ?? $response);
}// Paynkolay Sanal POS V1 — NON-3D ödeme örneği (.NET minimal API)
// Kurulum: dotnet new web -n PaynkolayNon3D → bu dosyayı Program.cs ile değiştirin → dotnet run
// Test: tarayıcıda http://localhost:<port>/odeme (port konsolda yazar)
// Not: Canlı uç localhost'tan gelen istekleri reddeder; canlıda sunucunuzdan çalıştırın.
using System.Globalization;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient();
var app = builder.Build();
// Kimlik bilgileri (size verilen değerler)
const string Sx = "SX_DEGERINIZ";
const string MerchantSecretKey = "SECRET_KEY_DEGERINIZ";
// Test ucu — canlı: https://paynkolay.nkolayislem.com.tr/Vpos/v1/Payment
const string ApiUrl = "https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment";
app.MapGet("/odeme", async (HttpContext ctx, IHttpClientFactory httpFactory) =>
{
// Sipariş ve kart bilgileri (gerçekte ödeme formunuzdan gelir)
var clientRefCode = "789456|AB76"; // her işlemde benzersiz olmalı (ör. "ORDER-" + Guid)
var amount = "6.00";
var successUrl = "https://siteniz.com/payment/success"; // non-3D'de çağrılmaz ama zorunludur ve hash'e girer
var failUrl = "https://siteniz.com/payment/fail";
var customerKey = ""; // kart saklanmıyorsa boş
// rnd: Türkiye saatiyle (UTC+3) dd-MM-yyyy HH:mm:ss
var rnd = DateTime.UtcNow.AddHours(3).ToString("dd-MM-yyyy HH:mm:ss", CultureInfo.InvariantCulture);
// hashDatav2: alanlar | ile birleşir → SHA512 (ham bayt) → Base64
var hashStr = string.Join("|", Sx, clientRefCode, amount, successUrl, failUrl, rnd, customerKey, MerchantSecretKey);
var hashDatav2 = Convert.ToBase64String(SHA512.HashData(Encoding.UTF8.GetBytes(hashStr)));
var fields = new Dictionary<string, string>
{
["sx"] = Sx,
["clientRefCode"] = clientRefCode,
["successUrl"] = successUrl,
["failUrl"] = failUrl,
["amount"] = amount,
["installmentNo"] = "1",
["cardHolderName"] = "Tuna Çınar",
["month"] = "12",
["year"] = "2026",
["cvv"] = "001",
["cardNumber"] = "4546711234567894",
["use3D"] = "false", // ← non-3D'yi belirleyen tek satır
["transactionType"] = "SALES",
["cardHolderIP"] = GetClientIp(ctx),
["rnd"] = rnd,
["hashDatav2"] = hashDatav2,
["environment"] = "API",
["currencyNumber"] = "949",
["MerchantCustomerNo"] = "", // opsiyonel: temsilci / alt üye işyeri no
};
// Body: multipart/form-data
using var form = new MultipartFormDataContent();
foreach (var (key, value) in fields)
{
form.Add(new StringContent(value), key);
}
var http = httpFactory.CreateClient();
http.Timeout = TimeSpan.FromSeconds(30);
string body;
try
{
using var response = await http.PostAsync(ApiUrl, form);
body = await response.Content.ReadAsStringAsync();
}
catch (Exception ex) when (ex is HttpRequestException or TaskCanceledException)
{
return Results.Text($"Bağlantı hatası: {ex.Message}", "text/plain; charset=utf-8", statusCode: 502);
}
// Non-3D'ye özgü kısım: sonuç bu yanıtta, form/callback yok
try
{
using var json = JsonDocument.Parse(body);
var root = json.RootElement;
if (root.TryGetProperty("RESPONSE_CODE", out var code) && code.ToString() == "2")
{
// Siparişi burada COMPLETED yap — callback bekleme
var reference = root.TryGetProperty("REFERENCE_CODE", out var refCode) ? refCode.ToString() : "-";
return Results.Text($"Ödeme başarılı. Referans: {reference}", "text/plain; charset=utf-8");
}
var message = root.TryGetProperty("RESPONSE_DATA", out var data) ? data.ToString() : body;
return Results.Text($"Ödeme başarısız: {message}", "text/plain; charset=utf-8", statusCode: 400);
}
catch (JsonException)
{
return Results.Text($"Ödeme başarısız: {body}", "text/plain; charset=utf-8", statusCode: 400);
}
});
app.Run();
// Müşteri IP'si: önce proxy başlıkları, yoksa bağlantı adresi
static string GetClientIp(HttpContext ctx)
{
foreach (var header in new[] { "CF-Connecting-IP", "X-Forwarded-For", "X-Real-IP" })
{
var value = ctx.Request.Headers[header].ToString();
if (string.IsNullOrWhiteSpace(value)) continue;
var ip = value.Split(',')[0].Trim();
if (IPAddress.TryParse(ip, out _)) return ip;
}
var remote = ctx.Connection.RemoteIpAddress;
if (remote is null) return "127.0.0.1";
return (remote.IsIPv4MappedToIPv6 ? remote.MapToIPv4() : remote).ToString();
}# Paynkolay Sanal POS V1 — NON-3D ödeme örneği (Python + requests)
# Kurulum: pip install requests
# Çalıştırma: python3 example.py → http://localhost:8000/odeme
# Not: Canlı uç localhost'tan gelen istekleri reddeder; canlıda sunucunuzdan çalıştırın.
import base64
import hashlib
import ipaddress
from datetime import datetime, timedelta, timezone
from http.server import BaseHTTPRequestHandler, HTTPServer
import requests
# Kimlik bilgileri (size verilen değerler)
SX = "SX_DEGERINIZ"
MERCHANT_SECRET_KEY = "SECRET_KEY_DEGERINIZ"
# Test ucu — canlı: https://paynkolay.nkolayislem.com.tr/Vpos/v1/Payment
API_URL = "https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment"
def client_ip(handler):
"""Müşteri IP'si: önce proxy başlıkları, yoksa bağlantı adresi."""
for header in ("CF-Connecting-IP", "X-Forwarded-For", "X-Real-IP"):
value = handler.headers.get(header)
if value:
ip = value.split(",")[0].strip()
try:
ipaddress.ip_address(ip)
return ip
except ValueError:
pass
return handler.client_address[0]
def pay(card_holder_ip):
# Sipariş ve kart bilgileri (gerçekte ödeme formunuzdan gelir)
client_ref_code = "789456|AB76" # her işlemde benzersiz olmalı (ör. "ORDER-" + uuid)
amount = "6.00"
success_url = "https://siteniz.com/payment/success" # non-3D'de çağrılmaz ama zorunludur ve hash'e girer
fail_url = "https://siteniz.com/payment/fail"
customer_key = "" # kart saklanmıyorsa boş
# rnd: Türkiye saatiyle (UTC+3) dd-MM-yyyy HH:mm:ss
rnd = datetime.now(timezone(timedelta(hours=3))).strftime("%d-%m-%Y %H:%M:%S")
# hashDatav2: alanlar | ile birleşir → SHA512 (ham bayt) → Base64
hash_str = "|".join([SX, client_ref_code, amount, success_url, fail_url, rnd, customer_key, MERCHANT_SECRET_KEY])
hash_datav2 = base64.b64encode(hashlib.sha512(hash_str.encode("utf-8")).digest()).decode("ascii")
fields = {
"sx": SX,
"clientRefCode": client_ref_code,
"successUrl": success_url,
"failUrl": fail_url,
"amount": amount,
"installmentNo": "1",
"cardHolderName": "Tuna Çınar",
"month": "12",
"year": "2026",
"cvv": "001",
"cardNumber": "4546711234567894",
"use3D": "false", # ← non-3D'yi belirleyen tek satır
"transactionType": "SALES",
"cardHolderIP": card_holder_ip,
"rnd": rnd,
"hashDatav2": hash_datav2,
"environment": "API",
"currencyNumber": "949",
"MerchantCustomerNo": "", # opsiyonel: temsilci / alt üye işyeri no
}
# files=(None, değer) biçimi isteği multipart/form-data gönderir
response = requests.post(API_URL, files={k: (None, v) for k, v in fields.items()}, timeout=30)
# Non-3D'ye özgü kısım: sonuç bu yanıtta, form/callback yok
try:
data = response.json()
except ValueError:
return False, "Ödeme başarısız: " + response.text
if str(data.get("RESPONSE_CODE")) == "2":
# Siparişi burada COMPLETED yap — callback bekleme
return True, "Ödeme başarılı. Referans: {}".format(data.get("REFERENCE_CODE", "-"))
return False, "Ödeme başarısız: {}".format(data.get("RESPONSE_DATA") or response.text)
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path != "/odeme":
return self.reply(404, "Ödeme için /odeme adresini açın.")
try:
ok, message = pay(client_ip(self))
self.reply(200 if ok else 400, message)
except requests.RequestException as exc:
self.reply(502, "Bağlantı hatası: {}".format(exc))
def reply(self, status, text):
body = text.encode("utf-8")
self.send_response(status)
self.send_header("Content-Type", "text/plain; charset=utf-8")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
if __name__ == "__main__":
print("http://localhost:8000/odeme")
HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()// Paynkolay Sanal POS V1 — NON-3D ödeme örneği (Node.js + axios + form-data)
// Kurulum: npm install axios form-data
// Çalıştırma: node example.js → http://localhost:8000/odeme
// Not: Canlı uç localhost'tan gelen istekleri reddeder; canlıda sunucunuzdan çalıştırın.
const http = require('http');
const net = require('net');
const crypto = require('crypto');
const axios = require('axios');
const FormData = require('form-data');
// Kimlik bilgileri (size verilen değerler)
const SX = 'SX_DEGERINIZ';
const MERCHANT_SECRET_KEY = 'SECRET_KEY_DEGERINIZ';
// Test ucu — canlı: https://paynkolay.nkolayislem.com.tr/Vpos/v1/Payment
const API_URL = 'https://paynkolaytest.nkolayislem.com.tr/Vpos/v1/Payment';
// Müşteri IP'si: önce proxy başlıkları, yoksa bağlantı adresi
function clientIp(req) {
for (const header of ['cf-connecting-ip', 'x-forwarded-for', 'x-real-ip']) {
const value = req.headers[header];
if (value) {
const ip = String(value).split(',')[0].trim();
if (net.isIP(ip)) return ip;
}
}
return (req.socket.remoteAddress || '127.0.0.1').replace(/^::ffff:/, '');
}
// rnd: Türkiye saatiyle (UTC+3) dd-MM-yyyy HH:mm:ss
function turkeyTime() {
const d = new Date(Date.now() + 3 * 60 * 60 * 1000);
const p = (n) => String(n).padStart(2, '0');
return `${p(d.getUTCDate())}-${p(d.getUTCMonth() + 1)}-${d.getUTCFullYear()} ` +
`${p(d.getUTCHours())}:${p(d.getUTCMinutes())}:${p(d.getUTCSeconds())}`;
}
async function pay(cardHolderIP) {
// Sipariş ve kart bilgileri (gerçekte ödeme formunuzdan gelir)
const clientRefCode = '789456|AB76'; // her işlemde benzersiz olmalı (ör. 'ORDER-' + Date.now())
const amount = '6.00';
const successUrl = 'https://siteniz.com/payment/success'; // non-3D'de çağrılmaz ama zorunludur ve hash'e girer
const failUrl = 'https://siteniz.com/payment/fail';
const customerKey = ''; // kart saklanmıyorsa boş
const rnd = turkeyTime();
// hashDatav2: alanlar | ile birleşir → SHA512 (ham bayt) → Base64
const hashStr = [SX, clientRefCode, amount, successUrl, failUrl, rnd, customerKey, MERCHANT_SECRET_KEY].join('|');
const hashDatav2 = crypto.createHash('sha512').update(hashStr, 'utf8').digest('base64');
const fields = {
sx: SX,
clientRefCode,
successUrl,
failUrl,
amount,
installmentNo: '1',
cardHolderName: 'Tuna Çınar',
month: '12',
year: '2026',
cvv: '001',
cardNumber: '4546711234567894',
use3D: 'false', // ← non-3D'yi belirleyen tek satır
transactionType: 'SALES',
cardHolderIP,
rnd,
hashDatav2,
environment: 'API',
currencyNumber: '949',
MerchantCustomerNo: '', // opsiyonel: temsilci / alt üye işyeri no
};
// Body: multipart/form-data
const form = new FormData();
for (const [key, value] of Object.entries(fields)) form.append(key, value);
const response = await axios.post(API_URL, form, {
headers: form.getHeaders(),
timeout: 30000,
responseType: 'text',
validateStatus: () => true, // HTTP durum kodundan bağımsız gövdeyi okuyalım
});
const body = response.data;
// Non-3D'ye özgü kısım: sonuç bu yanıtta, form/callback yok
let data;
try {
data = JSON.parse(body);
} catch {
return { ok: false, message: `Ödeme başarısız: ${body}` };
}
if (String(data.RESPONSE_CODE) === '2') {
// Siparişi burada COMPLETED yap — callback bekleme
return { ok: true, message: `Ödeme başarılı. Referans: ${data.REFERENCE_CODE ?? '-'}` };
}
return { ok: false, message: `Ödeme başarısız: ${data.RESPONSE_DATA || body}` };
}
http.createServer(async (req, res) => {
const reply = (status, text) => {
res.writeHead(status, { 'Content-Type': 'text/plain; charset=utf-8' });
res.end(text);
};
if (req.url !== '/odeme') return reply(404, 'Ödeme için /odeme adresini açın.');
try {
const { ok, message } = await pay(clientIp(req));
reply(ok ? 200 : 400, message);
} catch (err) {
reply(502, `Bağlantı hatası: ${err.message}`);
}
}).listen(8000, () => console.log('http://localhost:8000/odeme'));Yanıt
Yanıttaki hashDataV2 imzasını doğrulamadan siparişi onaylamayın; başarı kuralları için Altın Kural'a bakın.
{
"RESPONSE_CODE": 2,
"RESPONSE_DATA": "İşlem Başarılı.",
"REFERENCE_CODE": "IKSIRPF142277040",
"CLIENT_REFERENCE_CODE": "SIP-2026-000123",
"AUTH_CODE": "345344",
"USE_3D": false,
"TRANSACTION_AMOUNT": 249.90,
"INSTALLMENT": 1,
"RND": "1645700316156",
"hashDataV2": "lunnRyNfDu6pdpNjjlFrlATE…"
}{
"RESPONSE_CODE": 0,
"RESPONSE_DATA": "Girdiğiniz bilgileri kontrol ediniz."
}Son güncelleme: 15 Eylül 2026