Esc
Start typing to search...

Example Form Usage

example.php
<!doctype html>
<html>
<head>
<title>Sanal POS entegrasyonu örnek PHP sayfamız</title>
<meta charset="utf-8">
</head>
<body>

<?php
// sx değeriniz size verilecektir
$sx="118591467|bScbGDYCtPf7SS1N6PQ6/+58rFhW1WpsWINqvkJFaJlu6bMH2tgPKDQtjeA5vClpzJP24uA0vx7OX53cP3SgUspa4EvYix+1C3aXe++8glUvu9Oyyj3v300p5NP7ro/9K57Zcw==";
$merchantSecretKey="_YckdxUbv4vrnMUZ6VQsr"; // size özel - special to you
$successUrl="https://paynkolay.com.tr/test/success";
$failUrl="https://paynkolay.com.tr/test/fail";
$amount="1.00";
$clientRefCode="2352345";
$use3D="true";
$rnd = date("d.m.Y H:i:s");
$agentCode="1236";
$detail="false";
$transactionType="SALES";
$customerKey = "";
$hashstr = $sx . "|" . $clientRefCode . "|" . $amount . "|" . $successUrl . "|" . $failUrl . "|" . $rnd . "|" . $customerKey . "|" . $merchantSecretKey;

$hash = mb_convert_encoding($hashstr, 'UTF-8');
$hashedBytes = hash("sha512", $hash, true);
$hashDataV2 = base64_encode($hashedBytes);

function getClientIpAddress(): string
{
    // A list of headers to check in order of priority
    $headers = [
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_X_CLUSTER_CLIENT_IP',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR'
    ];

    foreach ($headers as $header) {
        if (isset($_SERVER[$header])) {
            // HTTP_X_FORWARDED_FOR can contain a comma-separated list of IPs.
            // The first one is the original client IP.
            $ipList = explode(',', $_SERVER[$header]);
            $ip = trim($ipList[0]);

            // Validate the IP address
            if (filter_var($ip, FILTER_VALIDATE_IP)) {
                return $ip;
            }
        }
    }

    return 'UNKNOWN';
}

// How to use the function
$cardHolderIP = getClientIpAddress();

?>

<form method="post" action="https://paynkolaytest.nkolayislem.com.tr/Vpos">
  <input type="hidden" name="sx" value="<?= $sx ?>">
  <input type="hidden" name="successUrl" value="<?= $successUrl ?>">
  <input type="hidden" name="failUrl" value="<?= $failUrl ?>">
  <input type="hidden" name="amount" value="<?= $amount ?>">
  <input type="hidden" name="clientRefCode" value="<?= $clientRefCode ?>">
  <input type="hidden" name="use3D" value="<?= $use3D ?>">
  <input type="hidden" name="rnd" value="<?= $rnd ?>">
  <input type="hidden" name="agentCode" value="<?= $agentCode ?>">
  <input type="hidden" name="transactionType" value="<?= $transactionType ?>">
  <input type="hidden" name="hashDataV2" value="<?= $hashDataV2 ?>">
  <input type="hidden" name="cardHolderIP" value="<?= $cardHolderIP ?>">
  <input type="submit" value="Gönder" />
</form>

</body>
</html>
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Cryptography;
using System.Text;
using System.Globalization;
using System.Linq;
using System.Net;

namespace MyApi.Pages
{
    public class SanalPosModel : PageModel
    {
        private readonly IConfiguration _config;
        public SanalPosModel(IConfiguration config) => _config = config;

        // Updated Sx value
        public string Sx { get; private set; } =
            "118591467|bScbGDYCtPf7SS1N6PQ6/+58rFhW1WpsWINqvkJFaJlu6bMH2tgPKDQtjeA5vClpzJP24uA0vx7OX53cP3SgUspa4EvYix+1C3aXe++8glUvu9Oyyj3v300p5NP7ro/9K57Zcw==";
        public string SuccessUrl { get; private set; } = "https://paynkolay.com.tr/test/success";
        public string FailUrl    { get; private set; } = "https://paynkolay.com.tr/test/fail";
        public string Amount     { get; private set; } = "1";
        public string ClientRefCode { get; private set; } = "2352345";
        public string Use3D      { get; private set; } = "true";
        public string AgentCode  { get; private set; } = "1236";
        public string Detail     { get; private set; } = "false";
        public string TransactionType { get; private set; } = "SALES";
        public string CustomerKey { get; private set; } = "";
        public string Rnd { get; private set; } = "";
        public string HashDataV2 { get; private set; } = "";

        // Renamed property for the client's IP address
        public string cardHolderIP { get; private set; } = "";

        /// <summary>
        /// Gets the client's IP address by checking various headers, similar to the PHP example.
        /// This is more reliable when the application is behind a proxy or load balancer.
        /// </summary>
        /// <returns>The client's IP address as a string, or "UNKNOWN".</returns>
        private string GetClientIpAddress()
        {
            // A list of headers to check in order of priority.
            // These correspond to the $_SERVER variables in the PHP example.
            var headers = new[]
            {
                "Client-IP",
                "X-Forwarded-For",
                "X-Forwarded",
                "X-Cluster-Client-IP",
                "Forwarded-For",
                "Forwarded"
            };

            foreach (var header in headers)
            {
                // Try to get the value of the header
                var ipHeaderValue = HttpContext.Request.Headers[header].FirstOrDefault();

                if (!string.IsNullOrEmpty(ipHeaderValue))
                {
                    // The "X-Forwarded-For" header can contain a comma-separated list of IPs.
                    // The first IP in the list is the original client's IP.
                    var ipList = ipHeaderValue.Split(',').Select(ip => ip.Trim());
                    var firstIp = ipList.FirstOrDefault();

                    // Validate that the first IP in the list is a valid IP address
                    if (firstIp != null && IPAddress.TryParse(firstIp, out _))
                    {
                        return firstIp;
                    }
                }
            }

            // If no valid IP is found in the headers, fall back to the remote IP address of the connection
            var remoteIp = HttpContext.Connection.RemoteIpAddress;
            if (remoteIp != null)
            {
                // Map to IPv4 if possible to ensure a consistent format, then convert to string
                return remoteIp.MapToIPv4().ToString();
            }

            return "UNKNOWN";
        }


        public void OnGet()
        {
            // optional: override from env/appsettings (safer)
            Sx              = _config["PaynKolay:Sx"] ?? Sx;
            SuccessUrl      = _config["PaynKolay:SuccessUrl"] ?? SuccessUrl;
            FailUrl         = _config["PaynKolay:FailUrl"] ?? FailUrl;
            Amount          = _config["PaynKolay:Amount"] ?? Amount;
            ClientRefCode   = _config["PaynKolay:ClientRefCode"] ?? ClientRefCode;
            Use3D           = _config["PaynKolay:Use3D"] ?? Use3D;
            AgentCode       = _config["PaynKolay:AgentCode"] ?? AgentCode;
            Detail          = _config["PaynKolay:Detail"] ?? Detail;
            TransactionType = _config["PaynKolay:TransactionType"] ?? TransactionType;
            CustomerKey     = _config["PaynKolay:CustomerKey"] ?? CustomerKey;

            // Updated MerchantSecretKey value
            var merchantSecretKey = _config["PaynKolay:MerchantSecretKey"] ?? "_YckdxUbv4vrnMUZ6VQsr";

            // Call the new, more robust method to get the client's IP address
            cardHolderIP = GetClientIpAddress();

            Rnd = DateTime.Now.ToString("dd.MM.yyyy H:mm:ss", CultureInfo.InvariantCulture);

            var raw = $"{Sx}|{ClientRefCode}|{Amount}|{SuccessUrl}|{FailUrl}|{Rnd}|{CustomerKey}|{merchantSecretKey}";
            using var sha512 = SHA512.Create();
            HashDataV2 = Convert.ToBase64String(sha512.ComputeHash(Encoding.UTF8.GetBytes(raw)));
        }
    }
}

@page "/sanalpos"
@model MyApi.Pages.SanalPosModel
<!doctype html>
<html lang="tr">
<head><meta charset="utf-8" /><title>Sanal POS Örnek</title></head>
<body>
    <form method="post" action="https://paynkolaytest.nkolayislem.com.tr/Vpos">
        <input type="hidden" name="sx"              value="@Model.Sx" />
        <input type="hidden" name="successUrl"      value="@Model.SuccessUrl" />
        <input type="hidden" name="failUrl"         value="@Model.FailUrl" />
        <input type="hidden" name="amount"          value="@Model.Amount" />
        <input type="hidden" name="clientRefCode"   value="@Model.ClientRefCode" />
        <input type="hidden" name="use3D"           value="@Model.Use3D" />
        <input type="hidden" name="rnd"             value="@Model.Rnd" />
        <input type="hidden" name="agentCode"       value="@Model.AgentCode" />
        <input type="hidden" name="detail"          value="@Model.Detail" />
        <input type="hidden" name="transactionType" value="@Model.TransactionType" />
        <input type="hidden" name="hashDataV2"      value="@Model.HashDataV2" />
        <input type="hidden" name="cardHolderIP"    value="@Model.cardHolderIP" />
        <button type="submit">Gönder</button>
    </form>
</body>
</html>
import hashlib
import base64
from datetime import datetime
from flask import Flask, request
import ipaddress

app = Flask(__name__)

def get_client_ip():
    """
    Gets the client's IP address by checking various headers,
    replicating the logic from the provided PHP example.
    """
    # A list of headers to check in order of priority.
    # In Flask, these are in the `request.environ` dictionary.
    headers = [
        'HTTP_CLIENT_IP',
        'HTTP_X_FORWARDED_FOR',
        'HTTP_X_FORWARDED',
        'HTTP_X_CLUSTER_CLIENT_IP',
        'HTTP_FORWARDED_FOR',
        'HTTP_FORWARDED',
        'REMOTE_ADDR'
    ]

    for header in headers:
        if header in request.environ:
            # Some headers can contain a comma-separated list of IPs.
            # The client's IP is typically the first one.
            ip_list = request.environ.get(header).split(',')
            ip = ip_list[0].strip()

            # Validate the IP address
            try:
                ipaddress.ip_address(ip)
                return ip
            except ValueError:
                # Not a valid IP, so we continue to the next header
                pass

    return 'UNKNOWN'

@app.route('/')
def generate_payment_form():
    """
    Generates an HTML form for the payment gateway with a calculated hash.
    This function replicates the logic from the original PHP script.
    """
    # Get client IP address using the robust function
    card_holder_ip = get_client_ip()

    # 1. Define your payment parameters
    # This value will be provided to you by the payment gateway
    sx = "118591467|bScbGDYCtPf7SS1N6PQ6/+58rFhW1WpsWINqvkJFaJlu6bMH2tgPKDQtjeA5vClpzJP24uA0vx7OX53cP3SgUspa4EvYix+1C3aXe++8glUvu9Oyyj3v300p5NP7ro/9K57Zcw=="
    merchant_secret_key = "_YckdxUbv4vrnMUZ6VQsr"  # Your unique secret key
    success_url = "https://paynkolay.com.tr/test/success"
    fail_url = "https://paynkolay.com.tr/test/fail"
    amount = "1.00"
    client_ref_code = "2352345"
    use_3d = "true"
    agent_code = "1236"
    transaction_type = "SALES"
    customer_key = ""

    # Get the current timestamp in the required format
    rnd = datetime.now().strftime("%d.%m.%Y %H:%M:%S")

    # 2. Create the hash string by concatenating the values
    # The order of concatenation is crucial and must match the payment gateway's documentation.
    hash_str_parts = [
        sx,
        client_ref_code,
        amount,
        success_url,
        fail_url,
        rnd,
        customer_key,
        merchant_secret_key
    ]
    hash_str = "|".join(hash_str_parts)

    # 3. Calculate the SHA-512 hash and then Base64 encode it
    # First, encode the string to bytes using UTF-8
    hash_bytes = hash_str.encode('utf-8')

    # Calculate the SHA-512 hash, getting the raw binary output (digest)
    sha512_hash_digest = hashlib.sha512(hash_bytes).digest()

    # Base64 encode the raw hash digest
    hash_data_v2_bytes = base64.b64encode(sha512_hash_digest)

    # Decode the Base64 bytes into a string to use in the HTML form
    hash_data_v2 = hash_data_v2_bytes.decode('utf-8')

    # 4. Generate the HTML content using an f-string
    html_content = f"""
<!doctype html>
<html>
<head>
<title>Sanal POS entegrasyonu örnek Python sayfamız</title>
<meta charset="utf-8">
</head>
<body>

<h2>Payment Form (Generated by Python)</h2>
<p>Click the button below to proceed to the payment page.</p>

<form method="post" action="https://paynkolaytest.nkolayislem.com.tr/Vpos">
  <input type="hidden" name="sx" value="{sx}">
  <input type="hidden" name="successUrl" value="{success_url}">
  <input type="hidden" name="failUrl" value="{fail_url}">
  <input type="hidden" name="amount" value="{amount}">
  <input type="hidden" name="clientRefCode" value="{client_ref_code}">
  <input type="hidden" name="use3D" value="{use_3d}">
  <input type="hidden" name="rnd" value="{rnd}">
  <input type="hidden" name="agentCode" value="{agent_code}">
  <input type="hidden" name="transactionType" value="{transaction_type}">
  <input type="hidden" name="hashDataV2" value="{hash_data_v2}">
  <input type="hidden" name="cardHolderIP" value="{card_holder_ip}">
  <input type="submit" value="Gönder" style="padding: 10px 20px; font-size: 16px; cursor: pointer;" />
</form>

</body>
</html>
"""

    # 5. Return the generated HTML content
    return html_content


if __name__ == "__main__":
    # To run this application, you first need to install Flask:
    # pip install Flask
    #
    # After installation, run this script:
    # python sanalpos.py
    #
    # It will start a local web server. You can access the payment form by opening
    # http://127.0.0.1:5000 in your web browser.
    app.run(debug=True)
const express = require('express');
const crypto = require('crypto');
const net = require('net');

const app = express();
const port = 3000;

function getClientIp(req) {
    const headers = [
        'x-client-ip',
        'x-forwarded-for',
        'x-forwarded',
        'x-cluster-client-ip',
        'forwarded-for',
        'forwarded',
    ];

    for (const header of headers) {
        if (req.headers[header]) {
            const ipList = req.headers[header].split(',');
            const ip = ipList[0].trim();
            if (net.isIP(ip)) {
                return ip;
            }
        }
    }

    if (req.socket && req.socket.remoteAddress) {
        const remoteAddress = req.socket.remoteAddress;
        // Handle IPv6-mapped IPv4 addresses
        if (remoteAddress.substr(0, 7) == "::ffff:") {
            const ipv4 = remoteAddress.substr(7)
            if (net.isIP(ipv4)) {
                return ipv4;
            }
        }
        if (net.isIP(remoteAddress)) {
            return remoteAddress;
        }
    }

    return 'UNKNOWN';
}

function generatePaymentForm(cardHolderIP) {
    // 1. Define your payment parameters using the new values
    const sx = "118591467|bScbGDYCtPf7SS1N6PQ6/+58rFhW1WpsWINqvkJFaJlu6bMH2tgPKDQtjeA5vClpzJP24uA0vx7OX53cP3SgUspa4EvYix+1C3aXe++8glUvu9Oyyj3v300p5NP7ro/9K57Zcw==";
    const merchantSecretKey = "_YckdxUbv4vrnMUZ6VQsr"; // Your unique secret key
    const successUrl = "https://paynkolay.com.tr/test/success";
    const failUrl = "https://paynkolay.com.tr/test/fail";
    const amount = "1.00";
    const clientRefCode = "2352345";
    const use3D = "true";
    const agentCode = "1236";
    const transactionType = "SALES";
    const customerKey = "";

    // Helper function to format the date as "dd.mm.yyyy HH:MM:SS"
    const getFormattedDate = () => {
        const now = new Date();
        const pad = (num) => num.toString().padStart(2, '0');

        const day = pad(now.getDate());
        const month = pad(now.getMonth() + 1); // Months are 0-indexed
        const year = now.getFullYear();

        const hours = pad(now.getHours());
        const minutes = pad(now.getMinutes());
        const seconds = pad(now.getSeconds());

        return `${day}.${month}.${year} ${hours}:${minutes}:${seconds}`;
    };

    const rnd = getFormattedDate();

    // 2. Create the hash string by concatenating the values
    // The order of concatenation is crucial.
    const hashStrParts = [
        sx,
        clientRefCode,
        amount,
        successUrl,
        failUrl,
        rnd,
        customerKey,
        cardHolderIP, // Added IP here
        merchantSecretKey
    ];
    const hashStr = hashStrParts.join("|");

    // 3. Calculate the SHA-512 hash and then Base64 encode it
    const hash = crypto.createHash('sha512');
    hash.update(hashStr, 'utf-8');
    const hashDataV2 = hash.digest('base64');

    // 4. Generate the HTML content using a template literal
    const htmlContent = `
<!doctype html>
<html>
<head>
<title>Sanal POS entegrasyonu örnek Node.js sayfamız</title>
<meta charset="utf-8">
</head>
<body>

<h2>Payment Form (Generated by Node.js)</h2>
<p>Your IP address is: ${cardHolderIP}</p>
<p>Click the button below to proceed to the payment page.</p>

<form method="post" action="https://paynkolaytest.nkolayislem.com.tr/Vpos">
  <input type="hidden" name="sx" value="${sx}">
  <input type="hidden" name="successUrl" value="${successUrl}">
  <input type="hidden" name="failUrl" value="${failUrl}">
  <input type="hidden" name="amount" value="${amount}">
  <input type="hidden" name="clientRefCode" value="${clientRefCode}">
  <input type="hidden" name="use3D" value="${use3D}">
  <input type="hidden" name="rnd" value="${rnd}">
  <input type="hidden" name="agentCode" value="${agentCode}">
  <input type="hidden" name="transactionType" value="${transactionType}">
  <input type="hidden" name="cardHolderIP" value="${cardHolderIP}">
  <input type="hidden" name="hashDataV2" value="${hashDataV2}">
  <input type="submit" value="Gönder" style="padding: 10px 20px; font-size: 16px; cursor: pointer;" />
</form>

</body>
</html>
`;

    return htmlContent;
}

app.get('/payment', (req, res) => {
  const ip = getClientIp(req);
  const htmlForm = generatePaymentForm(ip);
  res.send(htmlForm);
});

app.listen(port, () => {
  console.log(`Server running on port ${port}`);
  console.log(`Access the payment form at http://localhost:${port}/payment`);
});

Test Environment #

You can use the following test page to test your integration: