Example Form
<!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 hashlibimport base64from datetime import datetimefrom flask import Flask, requestimport 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
Section titled “Test Environment”You can use the following test page to test your integration: