• Sanal Pos

Virtual POS Transactions General Concepts

Garanti Virtual POS is a secure payment solution created to receive credit card payments for online sales.

Merchants can open an online branch in their stores and turn it into a sales platform that never closes with Garanti Virtual POS. This contributes to increasing both the number of customers and turnover.

The following transactions are generally performed under Garanti Virtual POS:

  • Sales Transactions
  • Common Payment Page Operations
  • Cancellation Procedures
  • Refund Procedures
  • Closing Operations
  • Inquiry Procedures

In this document, the steps required for member merchants to be able to provide non 3Ds Sales transactions under Garanti Virtual POS, the operations to be performed within each step, and the structures of the transaction requests sent and response messages received are explained.

Virtual POS Sales Transactions

The sub transaction types under Virtual POS Sales transactions are generally as follows:

  • Installment Sales: It is the transaction type that enables installment transactions.
  • Pre-Authorization: Preauth - Preauthorization process ensures that the amount to be taken from the card is blocked between 7 and 9 days by blocking an amount on the card. In this way, it is guaranteed that the card will not receive a limit error when the authorization is closed. During this period, pre-authorization closing process must be performed in order for the amount to be recognized. At the end of the pre-authorization blocking period, the amount block on the card is removed. In the pre-authorization closing requests sent after the end of this period, the transaction result is returned according to whether the card has a limit or not.
  • Point Sale: It is the transaction type that allows you to make a purchase with bonus. Total transaction amount is sent in the Amount field. In UsedAmount field, the bonus rate to be used is sent. Debit is passed to the card side as much as amount - usedbonus amount. Used bonus is deducted from card bonuses. Bonus utilization is reflected in the workplace accounting the next day regardless of the workplace working conditions.
  • Repeat Sales: The sales transaction is realized at regular intervals and goes to provisioning.
  • DCC: DCC (dynamic currency conversion) is a system that ensures that the amount to be reflected on the card side in transactions made to foreign bank cards is made at the exchange rate of the card. In this system, the transaction amount is reflected to the merchant side in TL. The card side is reflected with the selected exchange rate. In this way, the cardholder clearly knows the amount to be reflected on the statement. For this transaction, the merchant and the bank side earn commission. Before the DCC transaction, DCC query is performed to obtain the supported exchange rates and exchange rate values. These values are reflected on the screen and the customer is asked to select one of the TL or incoming exchange rate values. The transaction is realized at the selected exchange rate.
  • Multi Currency: Transactions in foreign currencies other than Turkish lira.
  • Common Card: The Common Card is a card payment system that regulates the cash and document flow that occurs in the sales made by companies to their customers and allows term shopping.
  • Term Sale: Receipt of the sales price on a specified date.

3D Concept

3D Secure is a version of the application on VirtualPoS where cardholders are verified with a password on PoS. The cardholder is directed to the verification screens of the card bank to use a password in the transaction. The cardholder enters the information requested by his/her bank on these screens and shows that the card actually used is his/her own card.

After verification, the verification status is returned to the merchant bank (merchant). Then, depending on the status of the 3D information, the authorization process is carried out or the transaction is terminated.

3D Secure is supported by Master, Visa and American Express (Amex) cards. Merchants using 3D model (information about merchant models is given below) are required to come directly to provisioning without performing 3D verification for cards other than Mastercard, Visa and Amex. Since 3D secure is not supported, the responsibility for Fraud in such transactions belongs to the merchant. The merchant must take measures to protect itself.

Virtual POS Transactions Non 3ds

This is when the transaction is concluded without touching any 3D secure stage during the authorization flow. In this type of transaction, the customer's "I didn't do it" objections turn into a chargeback request. The chargeback process is evaluated by requesting evidence from the merchant that the transaction was made by the customer. In 3D transactions with successful verification, "I did not do it" claims are terminated by the bank.

Sanal POS İşlemleri Genel Kavramlar 

Garanti Sanal POS, internet üzerinden yapılan satışlarda kredi kartı ile ödeme alınabilmesi için oluşturulan güvenli bir ödeme çözümüdür.

Üye işyerleri, mağazalarında internet üzerinde bir şube açıp, Garanti Sanal POS ile, onu hiç kapanmayan bir satış platformu haline gelebilir. Böylece hem müşteri sayıları, hem de cironun artırılmasına katkı sağlanır.

Garanti Sanal POS altında genel olarak aşağıdaki işlemler gerçekleştirilmektedir:

  • Satış İşlemleri
  • Ortak Ödeme Sayfası İşlemleri
  • İptal İşlemleri
  • İade İşlemleri
  • Kapama İşlemleri
  • Sorgulama İşlemleri

Bu doküman içerisinde, üye işyerlerinin Garanti Sanal POS altında 3D’li Peşin Satış işlemlerinin sağlanabilmesi için gerekli olan adımlar, her bir adım içerisinde yapılması gereken işlemler ve gönderilen işlem istekleri ve alınan cevap mesajlarının yapıları anlatılmaktadır. 

Sanal POS İptal İşlemleri

İptal, yapılan bir işlemin gün içerisinde geçersiz olması için yapılan işlemdir.

İşlemler aynı gün içerisinde iptal edilebilir. Takip eden günler için işlemin iptal edilmesi gerekiyorsa yapılması gereken işlem iadedir.

İptal işleminin iptali yoktur. Bu sebeple yanlışlıkla bir iptal yapılırsa bu durumda ipal edilen işlemin tekrar yaptırılması gerekmektedir.

İptal işlemleri kart üzerinden iz oluşturmaz. Kart ekstrelerinde ya da dönemi içi işlemlerde gözükmez.

3D Kavramı

3D Secure , PoS üzerinde kart sahiplerinin şifre ile doğrulandığı uygulamanın, SanalPoS üzerinde yapılan halidir. Kart sahibi, işlemde şifre kullanması için kart bankasına ait doğrulama ekranlarına yönlendirilir. Kart sahibi bu ekranlar üzerinden bankasının istediği bilgileri girerek, gerçekten kullanılan kartın kendisine ait bir kart olduğunu gösterir.

Doğrulama sonucunda, doğrulama durumu işyeri bankaya (işyerine) döndürülür. Daha sonra 3D bilgilerinin durumuna göre provizyon işleminin gerçekleştirilmesi ya da işlemin sonlandırılması gerçekleştirilir.

3D Secure Master, Visa ve American Express(Amex) kartların desteklediği bir uygulamadır. 3D model (aşağıda işyeri modelleri hakkında bilgi verilmektedir) kullanan işyerlerinin Mastercard, Visa ve Amex dışındaki kartlar için 3D doğrulaması gerçekleştirmeden direk provizyona gelmeleri gerekmektedir. 3D secure desteklenmediği için bu tür işlemlerde Fraud sorumluluğu işyerine aittir. İşyeri kendisini koruyacak önlemleri almalıdır.  

Sanal POS 3D'siz İşlemler

Gerçekleşen işlemin provizyon akışı sırasında herhangi bir 3D secure aşamasına değmeden sonuçlanmasıdır. Bu işlem tipinde müşterinin “ben yapmadım” itirazları chargeback talebine dönüşür. İşyerinden işlemin müşteri tarafından yapıldığına yönelik kanıtlar talep edilerek chargeback süreci değerlendirilir. 3D’li işlemlerde başarılı doğrulaması yapılan işlemlerde işlemi “ben yapmadım” talepleri banka tarafında sonlandırılır.

Test / Prod Ortam Seçimleri: 

Sanal POS Satış işlemleri için, üye işyeri tarafından 2 farklı yöntem ile ilerlenmesi mümkündür. Üye işyeri dilerse yapacağı tüm geliştirmeleri Test ortamında yapabilir. Alternatif olarak doğrudan yayın ortamında da bu işlemler için gerekli geliştirmeler yapılabilir.

Üye işyeri tarafından seçilecek yönteme göre, Sanal POS satış işlemlerine başlamadan önce aşağıdaki başlıklardan uygun olana göre ilk işlemlerin yapılması gerekmektedir:

Yapılacak çalışmaların test ortamında yürütülmesi durumunda, aşağıda belirtilen ön tanımlı değerler oldugu gibi kullanılabilir:

Parametre Değer
MerchantID 7000679
ProvUserID PROVAUT / PROVRFN / PROVOOS
ProvisionPassword 123qweASD/
TerminalID 30691297
StoreKey 12345678

Test ortamında yapılacak çalışmalarda "https://sanalposprovtest.garanti.com.tr/VPServlet" url'i kullanılacaktır.

Test ortamında yapılan işlemlerin takip edilebileceği ve görüntülenebileceği panele bu adresten erişebilirsiniz.

Değişken Değer
Kullanıcı Adı 99999999999
Parola Destek.3
Şifre 147852

Not: Parola işlemlerinde hata alınması durumunda 2.kez deneme yapılmadan önce lütfen Bize Soru Gönderin formu ile bilgi veriniz.

Test ortamında kullanılabilecek tüm test kartlarının listesine bu sayfadan ulaşabilirsiniz.

Bu yöntem ile ilerlendiğinde, üye işyeri tarafından ilk adım olarak kurulumda kullanılacak olan şifreler (“PROVAUT”,“PROVOOS”, “PROVRFN” ve “3D” (storekey) şifreleri) Sanal POS İlk Adımlar dokümanı içerisinde belirtildiği şekilde sanal pos yönetim panelinden oluşturmalıdır.

Sonraki adımlarda, bu şekilde oluşturulan şifre ve hesaplar kullanılacaktır. 

PROD ortamında yapılacak çalışmalarda "https://sanalposprov.garanti.com.tr/VPServlet" url'i kullanılacaktır.

Hash Algoritması

Bu doküman içerisinde, birçok işlem tipi altında kullanılan ve istek mesajı içerisinde <HashData> şeklinde yer alan etiket için gerekli olan verinin nasıl oluşturulacağını adım adım anlatılmaktadır.

İstek mesajları içerisinde yer alan <HashData> etiketi; kullanıcıya ait şifre doğrulamasının yapılmasını sağlayan alandır. Hash oluşturma detayları aşağıda ayrıca anlatılmaktadır.

Yeni SanalPoS uygulamasında, terminale ait şifrenin açık şekilde dolaşmasının engellenmesi için HASH yapısı kullanılmaktadır.

Hash hesabı:

  • Hashedpassword bilgisinin hesaplanmasında SHA1
  • Hashvalue değerinin hesaplanmasında SHA512 algoritması kullanılmaktadır.

Hash hesaplamasında, İki parçalı HASH yapısı kullanılmaktadır. İlk aşamada provizyon şifresinin, terminal numarası ile yanyana getirilmesi ile SHA1 algoritması kullanılarak hashedpassword değerinin elde edilmesi sağlanacaktır.

Hash oluşturmak için gerekli olan işlemler, aşağıda farklı programlama dilleri için sunulmuştur:

public static string Sha1(string text) {\n var provider = CodePagesEncodingProvider.Instance;\n Encoding.RegisterProvider(provider);\n\n var cryptoServiceProvider = new SHA1CryptoServiceProvider();\n var inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text));\n\n var builder = new StringBuilder();\n for (int i = 0; i < inputbytes.Length; i++) {\n builder.Append(string.Format(\"{0,2:x}\", inputbytes[i]).Replace(\" \", \"0\"));\n }\n\n return builder.ToString().ToUpper();\n}\n\npublic static string Sha512(string text) {\n var provider = CodePagesEncodingProvider.Instance;\n Encoding.RegisterProvider(provider);\n\n var cryptoServiceProvider = new SHA512CryptoServiceProvider();\n var inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text));\n\n var builder = new StringBuilder();\n for (int i = 0; i < inputbytes.Length; i++) {\n builder.Append(string.Format(\"{0,2:x}\", inputbytes[i]).Replace(\" \", \"0\"));\n }\n\n return builder.ToString().ToUpper();\n}\n\npublic static string GetHashData(string userPassword, string terminalId, string orderId, string cardNumber, ulong amount, int currencyCode) {\n var hashedPassword = Sha1(userPassword + terminalId);\n return Sha512(orderId + terminalId + cardNumber + amount + currencyCode + hashedPassword).ToUpper();\n}
Public Shared Function Sha1(ByVal text As String) As String\n Dim provider = CodePagesEncodingProvider.Instance\n Encoding.RegisterProvider(provider)\n Dim cryptoServiceProvider = New SHA1CryptoServiceProvider()\n Dim inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text))\n Dim builder = New StringBuilder()\n\n For i As Integer = 0 To inputbytes.Length - 1\n builder.Append(String.Format(\"{0,2:x}\", inputbytes(i)).Replace(\" \", \"0\"))\n Next\n\n Return builder.ToString().ToUpper()\nEnd Function\n\nPublic Shared Function Sha512(ByVal text As String) As String\n Dim provider = CodePagesEncodingProvider.Instance\n Encoding.RegisterProvider(provider)\n Dim cryptoServiceProvider = New SHA512CryptoServiceProvider()\n Dim inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text))\n Dim builder = New StringBuilder()\n\n For i As Integer = 0 To inputbytes.Length - 1\n builder.Append(String.Format(\"{0,2:x}\", inputbytes(i)).Replace(\" \", \"0\"))\n Next\n\n Return builder.ToString().ToUpper()\nEnd Function\n\nPublic Shared Function GetHashData(ByVal userPassword As String, ByVal terminalId As String, ByVal orderId As String, ByVal cardNumber As String, ByVal amount As ULong, ByVal currencyCode As Integer) As String\n Dim hashedPassword = Sha1(userPassword & terminalId)\n Return Sha512(orderId & terminalId & cardNumber & amount & currencyCode & hashedPassword).ToUpper()\nEnd Function
public static String calculateHash(String data, String algorithm, String charset) throws UnsupportedEncodingException, NoSuchAlgorithmException {\n\tMessageDigest md = MessageDigest.getInstance(algorithm);\n\tbyte[] databytes = data.getBytes(charset);\n\t\n\tmd.update(databytes);\n byte[] hashBytes = md.digest();\n \n return byteArray2HexaDecimal(hashBytes);\n}\n\npublic static String sha1(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException { \n return calculateHash(data, \"SHA-1\", \"ISO-8859-9\").toUpperCase();\n}\n\npublic static String sha512(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException { \n return calculateHash(data, \"SHA-512\", \"ISO-8859-9\").toUpperCase();\n}\n\npublic static String getHashData(String userPassword, String terminalId, String orderId, String cardNumber, Long amount, int currencyCode) {\n var hashedPassword = sha1(userPassword + terminalId);\n return sha512(orderId + terminalId + cardNumber + amount + currencyCode + hashedPassword);\n}
private function GenerateSecurityData($terminalId)\n {\n $password = \"password\";\n\n $data = [\n $password,\n str_pad((int)$terminalId, 9, 0, STR_PAD_LEFT)\n ];\n\n $shaData = sha1(implode('', $data));\n\n return strtoupper($shaData);\n }\n\n public function GenerateHashData()\n {\n $orderId = \"order_id\"; //must be uniqe\n $terminalId = \"terminal_id\"; //must be integer\n $cardNumber = \"1234123412341234\"; //card number\n $amount = \"100\"; //amount\n $currencyCode = \"currency_code\"; //must be int\n\n $hashedPassword = GenerateSecurityData($terminalId);\n\n $data = [\n $orderId, $terminalId, $cardNumber, $amount, $currencyCode, $hashedPassword\n ];\n \n $shaData = strtoupper(hash(\"sha512\", implode('', $data)));\n\n return strtoupper($shaData);\n }

Hash Algorithm

This document explains step by step how to create the data required for the <HashData> tag in the request message, which is used under many transaction types.

The <HashData> tag in the request messages is the field that allows the password verification of the user. Hash creation details are explained separately below.

In the new VirtualPoS application, the HASH structure is used to prevent the password of the terminal from circulating openly.

Hash account:

1. SHA1 in the calculation of hashedpassword information

2. SHA512 algorithm is used to calculate the hashvalue.

In the hash calculation, a two-part HASH structure is used. In the first stage, the hashedpassword value will be obtained using the SHA1 algorithm by juxtaposing the provisioning password with the terminal number.

The operations required to generate hash are presented below for different programming languages:

public static string Sha1(string text) {\n var provider = CodePagesEncodingProvider.Instance;\n Encoding.RegisterProvider(provider);\n\n var cryptoServiceProvider = new SHA1CryptoServiceProvider();\n var inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text));\n\n var builder = new StringBuilder();\n for (int i = 0; i < inputbytes.Length; i++) {\n builder.Append(string.Format(\"{0,2:x}\", inputbytes[i]).Replace(\" \", \"0\"));\n }\n\n return builder.ToString().ToUpper();\n}\n\npublic static string Sha512(string text) {\n var provider = CodePagesEncodingProvider.Instance;\n Encoding.RegisterProvider(provider);\n\n var cryptoServiceProvider = new SHA512CryptoServiceProvider();\n var inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text));\n\n var builder = new StringBuilder();\n for (int i = 0; i < inputbytes.Length; i++) {\n builder.Append(string.Format(\"{0,2:x}\", inputbytes[i]).Replace(\" \", \"0\"));\n }\n\n return builder.ToString().ToUpper();\n}\n\npublic static string GetHashData(string provisionPassword, string terminalId, string orderId, int installmentCount, string storeKey, ulong amount, int currencyCode, string successUrl, string type, string errorUrl) {\n var hashedPassword = Sha1(provisionPassword + \"0\" + terminalId);\n return Sha512(terminalId + orderId + amount + currencyCode + successUrl + errorUrl + type + installmentCount + storeKey + hashedPassword).ToUpper();\n}
Public Shared Function Sha1(ByVal text As String) As String\n Dim provider = CodePagesEncodingProvider.Instance\n Encoding.RegisterProvider(provider)\n Dim cryptoServiceProvider = New SHA1CryptoServiceProvider()\n Dim inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text))\n Dim builder = New StringBuilder()\n\n For i As Integer = 0 To inputbytes.Length - 1\n builder.Append(String.Format(\"{0,2:x}\", inputbytes(i)).Replace(\" \", \"0\"))\n Next\n\n Return builder.ToString().ToUpper()\nEnd Function\n\nPublic Shared Function Sha512(ByVal text As String) As String\n Dim provider = CodePagesEncodingProvider.Instance\n Encoding.RegisterProvider(provider)\n Dim cryptoServiceProvider = New SHA512CryptoServiceProvider()\n Dim inputbytes = cryptoServiceProvider.ComputeHash(Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(text))\n Dim builder = New StringBuilder()\n\n For i As Integer = 0 To inputbytes.Length - 1\n builder.Append(String.Format(\"{0,2:x}\", inputbytes(i)).Replace(\" \", \"0\"))\n Next\n\n Return builder.ToString().ToUpper()\nEnd Function\n\nPublic Shared Function GetHashData(provisionPassword As String, terminalId As String, orderId As String, installmentCount As Integer, storeKey As String, amount As ULong, currencyCode As Integer, successUrl As String, type As String, errorUrl As String) As String\n Dim hashedPassword As String = Sha1(provisionPassword & \"0\" & terminalId)\n Return Sha512(terminalId & orderId & amount & currencyCode & successUrl & errorUrl & type & installmentCount & storeKey & hashedPassword).ToUpper()\nEnd Function
public static String calculateHash(String data, String algorithm, String charset) throws UnsupportedEncodingException, NoSuchAlgorithmException {\n\tMessageDigest md = MessageDigest.getInstance(algorithm);\n\tbyte[] databytes = data.getBytes(charset);\n\t\n\tmd.update(databytes);\n byte[] hashBytes = md.digest();\n \n return byteArray2HexaDecimal(hashBytes);\n}\n\npublic static String sha1(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException { \n return calculateHash(data, \"SHA-1\", \"ISO-8859-9\").toUpperCase();\n}\n\npublic static String sha512(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException { \n return calculateHash(data, \"SHA-512\", \"ISO-8859-9\").toUpperCase();\n}\n\npublic static String getHashData(String provisionPassword, String terminalId, String orderId, int installmentCount, String storeKey, long amount, int currencyCode, String successUrl, String type, String errorUrl) throws NoSuchAlgorithmException {\n String hashedPassword = sha1(provisionPassword + \"0\" + terminalId);\n return sha512(terminalId + orderId + amount + currencyCode + successUrl + errorUrl + type + installmentCount + storeKey + hashedPassword).toUpperCase();\n}
private function GenerateSecurityData($terminalId)\n {\n $password = \"password\";\n $data = [\n $password,\n str_pad((int)$terminalId, 9, 0, STR_PAD_LEFT)\n ];\n $shaData = sha1(implode('', $data));\n return strtoupper($shaData);\n }\n\n public function GenerateHashData()\n {\n $orderId = \"order_id\"; //must be uniqe\n $terminalId = \"terminal_id\"; //must be integer\n $amount = \"100\"; //amount\n $currencyCode = \"currency_code\"; //must be int\n $storeKey = \"\";\n $installmentCount = 0;\n $successUrl = \"https://localhost/success\";\n $errorUrl = \"https://localhost/error\";\n $type = \"\",\n $hashedPassword = GenerateSecurityData($terminalId); \n return strtoupper(hash('sha512', $terminalId . $orderId . $amount . $currencyCode . $successUrl . $errorUrl . $type . $installmentCount . $storeKey . $hashedPassword));\n }

Virtual POS Sales General Form Structure for All Transaction Types with 3D

<form method=\"post\" role=\"form\" action=\"https://sanalposprovtest.garantibbva.com.tr/servlet/gt3dengine\">\n\t<!--Value for field test environment: For TEST production environment: PROD olmalıdır.-->\n\t<input type=\"hidden\" name=\"mode\" id=\"mode\" value=\"TEST\" />\n\t<!--API Sürümü-->\n\t<input type=\"hidden\" name=\"apiversion\" id=\"apiversion\" value=\"512\" />\n\t<!-- Safety Level (Value values: \"CUSTOM_PAY\", \"3D_PAY\", \"3D_FULL\", \"3D_HALF\" should be one of the options.)-->\n\t<input type=\"hidden\" name=\"secure3dsecuritylevel\" id=\"secure3dsecuritylevel\" value=\"3D_PAY\" />\n\t<!--Terminal Provision User ID-->\n\t<input type=\"hidden\" name=\"terminalprovuserid\" id=\"terminalprovuserid\" value=\"PROVAUT\" />\n\t<!--Terminal User ID-->\n\t<input type=\"hidden\" name=\"terminaluserid\" id=\"terminaluserid\" value=\"GARANTI\" />\n\t<!--Terimal Merchant ID-->\n\t<input type=\"hidden\" name=\"terminalmerchantid\" id=\"terminalmerchantid\" value=\"7000679\" />\n\t<!--Terminal ID-->\n\t<input type=\"hidden\" name=\"terminalid\" id=\"terminalid\" value=\"30691297\" />\n\t<!--Order ID (It must be a unique transaction number.)-->\n <input type=\"hidden\" name=\"orderid\" id=\"orderid\" value=\"ef43ef579b97484d9f67d445e4b15b93\" />\n\t<!-- Successful Process Return Link -->\n\t<input type=\"hidden\" name=\"successurl\" id=\"successurl\" value=\"oospayment/result\" />\n\t<!-- Failed Transaction Return Link -->\n\t<input type=\"hidden\" name=\"errorurl\" id=\"errorurl\" value=\"oospayment/result\" />\n\t<!-- Customer E-Mail Address -->\n\t<input type=\"hidden\" name=\"customeremailaddress\" id=\"customeremailaddress\" value=\"eticaret@garanti.com.tr\" />\n\t<!-- Customer IP Address -->\n\t<input type=\"hidden\" name=\"customeripaddress\" id=\"customeripaddress\" value=\"192.168.0.1\" />\n\t<!-- Company Name -->\n\t<input type=\"hidden\" name=\"companyname\" id=\"companyname\" Value=\"GARANTI TEST\" />\n\t<!-- Language Information -->\n\t<input type=\"hidden\" name=\"lang\" id=\"lang\" Value=\"tr\" />\n\t<!-- Process Time (UTC)-->\n\t<input type=\"hidden\" name=\"txntimestamp\" id=\"txntimestamp\" value=\"2023-04-30T11:31:53Z\" />\n\t<!-- Renewal Period -->\n\t<input type=\"hidden\" name=\"refreshtime\" id=\"refreshtime\" value=\"1\" />\n\t<!-- Secure Hash Key (The value from the hash algorithm must be entered in this field.)-->\n\t<input type=\"hidden\" name=\"secure3dhash\" id=\"secure3dhash\" value=\" The calculated hash value must be added.\" />\n\t<!-- Amount Transacted -->\n\t<input type=\"hidden\" name=\"txnamount\" id=\"txnamount\" value=\"100\" />\n <!-- Transaction Type -->\n\t<!--Value of the pre-authorization operation type: \"preauth\"-->\n\t<!--Value value in transaction type when using a bonus: \"preauth\"-->\n\t<!--Value value in repeat sale transaction type: \"preauth\"-->\n\t<!--DCC transaction type value: \"dccinq\"-->\n\t<!--Common Card transaction type value: \"commercialcard\"-->\n\t<!--The value of the Futures Sale transaction type: \"extendedcredit\"-->\n\t<input type=\"hidden\" name=\"txntype\" id=\"txntype\" value=\"sales\" />\n\t<!--Currency value values: TR: \"949\" | USD: \"840\" | EURO: \"978\" | GBP: \"826\" | JPY: \"392\"-->\t<input type=\"hidden\" name=\"txncurrencycode\" id=\"txncurrencycode\" value=\"949\" />\n\t<!--Number of Installments (For transactions that do not require installments: \"0\" must be entered.)-->\n\t<input type=\"hidden\" name=\"txninstallmentcount\" id=\"txninstallmentcount\" value=\"0\" />\n\n\t<!-- Additional Parameters Can Be Added to This Field Startup _____________________________ -->\n\t\n\t<!-- Bonus Redemption Parameters Start -->\n\t<input type=\"text\" name=\"txnrewardcount\" value=\"1\"><br>\n\t<input type=\"text\" name=\"txnrewardtype1\" value=\"BNS\"><br>\n\t<input type=\"text\" name=\"txnrewardusedamount1\" value=\"100\"><br>\n\t<!--Bonus Usage Parameters End-->\n\n\t<!--Company Bonus Usage Parameters Start-->\n\t<input type=\"text\" name=\"txnrewardcount\" value=\"1\"><br>\n\t<input type=\"text\" name=\"txnrewardtype1\" value=\"FBB\"><br>\n\t<input type=\"text\" name=\"txnrewardusedamount1\" value=\"100\"><br>\n <!--Company Bonus Usage Parameters End-->\n\n\t<!--Bonus and Company Bonus Usage Parameters Start-->\t<input type=\"text\" name=\"txnrewardcount\" value=\"2\"><br>\n\t<input type=\"text\" name=\"txnrewardtype1\" value=\"BNS\"><br>\n\t<input type=\"text\" name=\"txnrewardusedamount1\" value=\"100\"><br>\n\t<input type=\"text\" name=\"txnrewardtype2\" value=\"FBB\"><br>\n\t<input type=\"text\" name=\"txnrewardusedamount2\" value=\"100\"><br>\n\t<!--Bonus and Company Bonus Usage Parameters End-->\n\n\t<!--Fixed Repeat Sales Start-->\t<input type=\"hidden\" name=\"recurringtype\" value=\"R\" />\n\t<input type=\"hidden\" name=\"totalpaymentnum\" value=\"5\" /> <!-- Number of Repetitions -->\n\t<input type=\"hidden\" name=\"frequencytype\" value=\"M\" /> <!-- Month: (M), Day: (D), Week: (W)-->\n\t<input type=\"hidden\" name=\"frequencyinterval\" value=\"1\" /> <!--1 Repeat Frequency (M/D/W)-->\n\t<input type=\"hidden\" name=\"startdate\" value=\"20221213\" /> <!--YYYYMMDD-->\n\t<!--Fixed Repeat Sale End-->\n\n\t<!--Variable Repeat Sales Start-->\n\t<input type=\"hidden\" name=\"recurringamount1\" value=\"\" />\t<!-- 1. Variable amount -->\n\t<input type=\"hidden\" name=\"recurringamount2\" value=\"\" /> <!-- 2nd variable amount -->\n\t<!-- + additional amounts can be added as recurringamount3 4 5 ... if desired.-->\n\t<!--Variable Repeat Sale End-->\n <!--Add Additional Parameters Can Be Added In This Field End _____________________________ -->\n\n\t<!--Customer Name on Card-->\n\t<input name=\"cardholdername\" value=\"Test User\" />\n\t<!--Customer Card Number-->\n\t<input name=\"cardnumber\" value=\"5406697543211173\" />\n\t<!--Customer Card Expiration Month-->\n\t<input name=\"cardexpiredatemonth\" value=\"03\"/>\n\t<!--Customer Card Expiration Year-->\n\t<input name=\"cardexpiredateyear\" value=\"23\" />\n\t<!--Customer Card CVC Security Number-->\n\t<input name=\"cardcvv2\" value=\"465\" /></form>

The form structure in html format below contains both common and differentiated tags for all 3D transaction types under Virtual POS Sales.

The changes that need to be made on this common structure are explained in detail in the relevant description page for the transaction type.

Special Form Structure Arrangements for Virtual POS Sales 3D Fixed Amount Repeat Transaction

On the common html structure given above; the form structure required for the transaction type can be obtained by providing the following operations:

Delete the code block starting with the description "Additional Parameters can be added to this field" and ending with the description "Additional Parameters can be added to this field".

Specific to the transaction type, the following code block should be edited as specified:

<input type=\"hidden\" name=\"txntype\" id=\"txntype\" value=\"sales\" />

The following code block should be added to the form to make transactions in the form of fixed recurring sales:

<!--Fixed Repeat Sales Start-->\n<input type=\"hidden\" name=\"recurringtype\" value=\"R\" />\n<input type=\"hidden\" name=\"totalpaymentnum\" value=\"5\" /> <!--Repeat Count-->\n<input type=\"hidden\" name=\"frequencytype\" value=\"M\" /> <!--Month: (M), Day: (D), Week: (W)-->\n<input type=\"hidden\" name=\"frequencyinterval\" value=\"1\" /> <!--1 Repeat Frequency (M/D/W)-->\n<input type=\"hidden\" name=\"startdate\" value=\"20221213\" /> <!--YYYYYMMDD-->\n<!--Fixed Repeat Sale End-->

If the transaction is successful, the merchant should write the page url where the parameters of the successful transaction return will be met in the following code block:

<!--Successful Transaction Return Link-->\n<input type=\"hidden\" name=\"successurl\" id=\"successurl\" value=\"oospayment/result\" />

In case the transaction fails, the merchant writes the page url where the parameters of the successful transaction return will be met in the following code block:

<!--Failed Transaction Return Link-->\n<input type=\"hidden\" name=\"errorurl\" id=\"errorurl\" value=\"oospayment/result\" />

After the addition and subtraction operations specific to the transaction type mentioned above, the form block is ready and placed in the relevant html page.

After the form is filled and submitted by the visitors, the transaction continues on the Garanti BBVA Sales page.

Sales Page Transaction Reply

After the transaction is completed on the sales page, the system will post a form to the address specified in the previous steps (Successful transaction url or failed transaction url)

In the page at the relevant address, this form data coming from the system must be parse as described here.

In the table below; there are descriptions of the data coming from the system. The data obtained after the parse process should be interpreted according to this table:

Domain Name Description
mdstatus Field where the 3D answer is given numerically
mderrormessage Textual description of the 3D response transaction status
errmsg 3D response error message in case of incorrect transactions
clientid Terminal id information of the merchant
oid Order number sent during the transaction
response Field indicating whether the operation was successful or not
procreturncode Provision response
successurl The url information to be returned in case of a successful transaction
txninstallmentcount Number of installments sent during the transaction
refreshtime Renewal time sent when processing
orderid Order number sent during the transaction
cardholdername Customer name sent during the transaction
txntype Transaction type specified during the transaction
terminalmerchantid Merchant number during the transaction
txnamount Total amount information sent during the transaction
txntimestamp Process time
terminaluserid Merchant username
mode Processed media information
txncurrencycode The currency specified at the time of the transaction
secure3dhash The hash information calculated during the transaction
apiversion API version information sent during the transaction
companyname Merchant name
errorurl The url information where the erroneous transactions sent during the transaction will be returned
secure3dsecuritylevel 3D model information specified during the transaction
customeremailaddress Customer email information sent during the transaction
customeripaddress Customer IP address information sent during the transaction
terminalid Terminal number
terminalprovuserid Provision user information sent during the transaction
lang Service response language preference information sent during the process
hash The hash data generated after the operation
hashparams Hash formula information to be used after the transaction
hashparamsval Hash details to be used after the operation

Important Reminder : Before checking the provision results in the transaction returns after the installation;

You need to make sure that the returned data comes from the bank. There are several methods to do this. The hash value in the returned values must be the same as the hash value to be created by creating from the returned values, (hashparams value should be calculated from the returned values and hashparamsval should not be used. )Continuing the process according to the result of the query by querying with xml using the orderinq transaction type after each transaction,Checking each order from the virtual pos management screens before shipping,The amount value posted from the site to the virtual pos should be used instead of the amount that the customer sees on the site or the basket amount on the previous page, the amount to be withdrawn from the database should be used,You can check the original transaction amount with the amount returned as a result of the transaction, You can switch to the encrypted response structure, In this structure, the amount will not be changed because the amount will come in encrypted fields. The user can check the transaction amount returned in the answer and the amount in the transaction and catch whether there is any tampering in the transaction more securely in this way. The company can check the transaction status after the query by using the orderinq or orderhisinq functions after the sale and compare the incoming amount with the basket amount.

The return should only be checked for 00. There is no need for other cases and no calculation can be made.

string responseHash = Request.Form.Get(\"hash\"); \nchar[] separator = new char[] { ':' };\n// He's going to use it for a separator. hashparams \nstring responseHashparams = Request.Form.Get(\"hashparams\");\n// This field retrieves the individual values of the returned parameters according to their names.\nstring[] paramList = responseHashparams.Split(separator); \n\nforeach (string param in paramList)\n{\n digestData += Request.Form.Get(param) == null ? \"\" : Request.Form.Get(param);\n}\n//Sonuna store key is added\ndigestData += strStoreKey;\n\n// Encryption is applied as follows.\nSystem.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider();\nbyte[] hashbytes = System.Text.Encoding.GetEncoding(\"ISO-8859-9\").GetBytes(digestData);\nbyte[] inputbytes = sha.ComputeHash(hashbytes);\nString hashCalculated = Convert.ToBase64String(inputbytes);\nif (responseHash.Equals(hashCalculated))\n{\n\tResponse.Write(\"!!!!!MESAJ BANKADAN GELİYOR!!!!!\");\n\tisValidHash = true;\n\t// Yes, it comes from the bank\n}

• Expected order number?

• Request.Form.Get("procreturncode") is 00?

• Request.Form.Get("hashparams"); should not be null or ""

After the above checks, if the result is successful, the transaction should be confirmed.

'hashparams' => 'clientid:oid:authcode:procreturncode:response:mdstatus:cavv:eci:md:rnd:',r.

Hashparams are created sequentially as above. It is then encrypted with Cryptography sha1 by adding 3d Key at the end. If the result and Request.Form.Get("hash"); are the same, the result is successful. Otherwise the process should be checked.

Code Examples

Below are the github repo links for custom code examples written in different programming languages, including this transaction type. You can examine the codes written with predefined values through the link of your preferred programming language.

Error Codes

Error codes from this page you can reach.

Test Cards

List of test cards from this page you can reach.

We would love to hear from you. Do you have problems/questions about services ? Send us detailed email about it ?

Send Us a Question Send Us a Question