Denizbank Node.js Sanal Pos Entegrasyonu

Fuat Kestane
mobilist_labs
Published in
4 min readOct 12, 2020

Merhabalar,

Bu yazımda sizlere Denizbank sanal pos konusundan bahsedeceğim. Yakın zamanda bir uygulamamıza entegre ettiğimiz Denizbank’ın Sanal Pos servisi kaynak olarak dokümantasyon ve ASP, Java ve PHP özelinde örnek kodlar ile elinize ulaşıyor. Node.js gibi yeni bir dil ile entegre etmek istediğimizde ise maalesef bir kaynak bulamıyorsunuz. Bu nedenle hem yaptığımız basit entegrasyona değinip Node.js ortamında nasıl çağrılır, parametreler nelerdir konularına değineceğim, hem de örnek bir kodu Github üzerinden paylaşacağım.

Sanal POS Nedir?

Kredi Kartı ile yaptığımız alışverişlerde kullandığımız POS cihazlarının (Point of sale / ödeme noktası), internet üzerinden yapılan elektronik ticarete uyarlanmış haline VPOS (Virtual point of sale-sanal ödeme noktası) denir. Bu sistem üzerinden müşteri ile mağaza arasındaki alışverişler Internet üzerinden, elektronik ortamda gerçek zamanlı (online) olarak yapılabilmektedir. Müşterinin yaptığı bu işlemler/ödemeler, Sanal POS hizmeti alınan üye işyerinin anlaşmalı olduğu bankadaki firma hesabına geçmektedir.

Node.js Kurulumu ve Gerekli Araçlar

İlk olarak bilgisayarınızda Node.js sürümlerinden birinin kurulu olması gerekmektedir. Ben Node.js ile Express framework kullanarak uygulamayı geliştirdim. İsterseniz Express Generator Tool kullanarak kolaylıkla proje oluşturabilirsiniz. Link: https://expressjs.com

Örnek projemize başlayalım. Backend ortamında 3 tane servis endpointine ihtiyacımız var.

· payment/create

· payment/3DPayOdemeSuccess

· payment/3DPayOdemeError

create: Dışarıdan alınan ödeme parametreleri burada toplanır. Denizbank’ın Sanal Pos servisine gönderilir.

3DPayOdemeSuccess: create servisinden dönen parametreler eğer ki başarılı ise buraya yönlenir.

3DPayOdemeError: create servisinden dönen parametreler eğer ki başarısız ise buraya yönlenir.

Denizbank Sanal Pos İçin Gerekli Parametreler

Denizbank Sanal Pos Parametreleri

Öncelikle Payment/Create servisini oluşturuyoruz. Ben dışarıdan PurchAmount, Pan, Cvv2, Expiry, CardType parametrelerini alacağım. Geri kalan parametreleri backend tarafında statik olarak vereceğim. MerchantPass ve ShopCode parametreleri hesabınıza özel olarak iletiliyor.

Aşağıdaki örnek kodda data objesinin içeriği görüntülenmektedir. Burada amacımız, verdiğimiz parametrelerle bir hash oluşturmak. Data objesi içine parametreleri doldurduktan sonra str adında bir string değer oluşturuyorum ve bu değer sonuna merchantPass değerini de eklemeyi unutmuyorum. MerchantPass değeri hiçbir zaman açık şekilde gönderilmiyor. O yüzden str değişkenini oluşturduk. Daha sonra oluşan bu değeri encrypt işlemi için b64_sha1 fonksiyonuna gönderiyorum. Hashleme fonksiyonlarını kodun içinde bulabilirsiniz.

Artık elimde içinde hash değeri olan bir data objesi mevcut. Şimdi bu isteğimizi Denizbank’ın test ortamına gönderelim. Dönen response’a göre bir sonra ki adımımıza geçelim.

Payment/Create endpoint

const express = require('express');
const router = express.Router();
const request = require('request');
const uuid = require('uuid/v4');
const f = require('../utils/functions');
const merchantPass = "YourMerchantPass";
router.post('/create', (req, res, next) => {

let data = {
ShopCode: "YOURSHOPCODE",
OrderId: uuid(),
PurchAmount: req.body.purchAmount,
Currency: 949,
OkUrl: "http://localhost:3000/payment/3DPayOdemeSuccess",
FailUrl: "http://localhost:3000/payment/3DPayOdemeError",
Rnd: new Date(Date.now()).toLocaleString(),
InstallmentCount: 1,
TxnType: "Auth",
Pan: req.body.cardNumber,
Cvv2: req.body.cvv2,
Expiry: req.body.expiry,
CardType: req.body.cardType,
SecureType: "3DPay"
};

let str = data.ShopCode + data.OrderId + data.PurchAmount + data.OkUrl + data.FailUrl + data.TxnType + data.InstallmentCount + data.Rnd + merchantPass;
data.Hash = f.b64_sha1(str);

let options = {
method: 'POST',
url: "https://sanaltest.denizbank.com/mpi/Default.aspx",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
form: data
};

request(options, (error, response, body) => {
if (error) {
res.status(500).json({ errorCode: error.errCode, errorMessage: error.message, data: null });
} else {
res.status(200).json({ successCode: 200, successMessage: 'Ödeme parametreleri alındı.', data: body });
}
});
});

Payment/Create isteğini yaptıktan sonra bir Http Response dönecektir. Eğer bu Http Response içinde bir hata mesajı barınmıyorsa, süreç başarılı ise 3DPayOdemeSuccess endpointine gidecektir.

Payment/3DPayOdemeSuccess endpointini inceleyelim.

router.post('/3DPayOdemeSuccess', (req, res, next) => {
let parameters = req.body;
let hashparams = parameters["HASHPARAMS"];
let hashparamsval = parameters["HASHPARAMSVAL"];
let hashparam = parameters["HASH"];
let paramsval = "";
let hashparamsArray = hashparams.split(':');
for (let i = 0; i < hashparamsArray.length; i++) {
if (parameters[hashparamsArray[i]] != null) {
paramsval += parameters[hashparamsArray[i]];
}
}

hashval = paramsval + merchantPass;
let hash = f.b64_sha1(hashval);
if (paramsval != hashparamsval || hashparam != hash) {
res.status(500).json({ errorCode: 500, errorMessage: 'Güvenlik Sayısal imza geçerli değil.' });
}

let status = parameters["3DStatus"];

if (status == 1 || status == 2 || status == 3 || status == 4) {
let response = parameters["ProcReturnCode"];

if (response == "00") {
res.status(200).json({ successCode: 200, successMessage: parameters.TxnResult });
} else {
res.status(500).json({ errorCode: 500, errorMessage: parameters.TxnResult });
}
} else {
res.status(500).json({ errorCode: 500, errorMessage: "3D işlemi başarısız." });
}
});

Http response kodu başarılı ise bu endpointe gelecektir. Burada çözümlenen hash değeriyle kıyaslama yapılır. Eğer değerler birbirine eşitse banka tarafından ProcReturnCode adında bir alan üretilir. Bu alan 00 değeriyle geldiği zaman işlem başarılı olup ödeme alınmış olur.

Bir diğer senaryo ise hatalı durum. Http response kodu hatalı ise 3DPayOdemeError endpointine gidecektir. Aşağıdaki kodda sadece hata durumunda geriye json result dönülmektedir.

router.post('/3DPayOdemeError', (req, res, next) => {
res.status(500).json({ errorCode: req.body.ErrorCode, errorMessage: req.body.ErrorMessage });
});

Backend’e ek olarak örnek test uygulamasını da testlerinizi gerçekleştirmeniz için paylaşıyorum.

Github Repo: https://github.com/mobilistlabs/DenizbankSanalPos-node.js

Bir sonra ki yazıda görüşmek dileğiyle :)

--

--

Fuat Kestane
mobilist_labs

Software Developer, DevOps, Flutter @mobilist_labs