ASP.NET ile yapılmış bir web sitesinde Garanti bankasının sanal pos uygulamasını kullanmak isterseniz öncelikle aşağıdaki bağlantıdan Garanti bankasının sağlamış olduğu örnekleri indirebilirsiniz. Bu yazıda ASP.NET ve C# kullanılarak, Garanti bankası tarafından sağlanan dosyalar dışında hiç bir ek dosya kullanılmadan nasıl sanal pos entegrasyonu yapılabileceğini inceleyeceğiz.
Garanti Bankası Sanal Pos Dosyaları
Öncelikle kart bilgilerinin girileceği yapıyı oluşturalım.
<table> <tr> <td>İsminiz</td> <td> <asp:TextBox ID="txtCardName" runat="server" autocomplete="off" required></asp:TextBox> </td> </tr> <tr> <td>Kart Numarası</td> <td> <asp:TextBox ID="txtCardNumber" runat="server" autocomplete="off" required></asp:TextBox> </td> </tr> <tr> <td>Son Kullanım Tarihi</td> <td> <asp:DropDownList ID="ddlMonth" runat="server" Style="min-width: 65px; width: 45px;" required></asp:DropDownList> / <asp:DropDownList ID="ddlYear" runat="server" Style="min-width: 65px; width: 45px;" required></asp:DropDownList> </td> </tr> <tr> <td>Güvenlik Kodu</td> <td> <asp:TextBox ID="txtCCV" runat="server" Style="min-width: 65px; width: 70px; float: left;" autocomplete="off" required></asp:TextBox> </td> </tr> </table> <asp:Button ID="btnCheckout" runat="server" Text="Ödemeyi Tamamla" OnClick="btnCheckout_Click" UseSubmitBehavior="false" />
Sayfanın tamamının post-back olmaması için button’un UseSubmitBehavior=”false” özelliğini kapatmayı tercih edebiliriz. Çok pratik bir yöntem olmasa da ay ve gün için FormLoad() event’i içinde aşağıdaki kodları kullanarak DropDownList içerisinde ay ve yılları gösterebiliriz.
if (IsPostBack) return; List<string> months = new List<string>(); for (int i = 1; i < 13; i++) months.Add(i.ToString()); ddlMonth.DataSource = months; ddlMonth.DataBind(); List<string> years = new List<string>(); for (int i = 0; i < 15; i++) years.Add(DateTime.Now.AddYears(i).Year.ToString()); ddlYear.DataSource = years; ddlYear.DataBind();
Ek olarak, oluşturulan elemanların HTML5 ile gelen yeni özelliklerden olan otomatik tanımlama özelliğini autocomplete=”off” parametresi ile kapatalım ve required parametresi ile gerekli hale getirelim. Bu kontroller dışında ASP.NET veya jQuery kontrolleri de ekleyebiliriz. Örneğin isim bölümüne sayı ve özel karakter girilememesi için aşağıdaki asp:RegularExpressionValidator kodunu kullanabiliriz.
<asp:RegularExpressionValidator ID="txtCardNameRegularExpressionValidator" runat="server" ControlToValidate="txtCardName" ErrorMessage="İsim bilgilerinizde geçersiz karakter var.<br />" ValidationExpression="[a-zA-Z. çÇüÜıİğĞöÖşŞ]+" Display="Dynamic"></asp:RegularExpressionValidator>
Ödemeyi tamamla button’una tıklandığında olacak işlemler için button’un Click() event’ine değişkenleri tanımlayarak başlayalım.
Garanti bankası sanal pos hizmeti aldığınızda size aşağıdaki bilgiler verilecektir. Bu bilgiler kullanılarak https://gtsweb.garanti.com.tr adresine giriş yapabiliyor ve gerekli izinlere sahip olmanız gerekmektedir. Aşağıdaki kodda değiştirilmesi gereken bölümler, yanında yorum satırları ile verilmiştir. Satış işlemleri sırasında varsayılan olarak tanımlı olan PROVAUT kullanıcısı kullanılabilir.
string strMode = "PROD"; string strVersion = "v0.01"; string strTerminalID = "12345678"; //8 Haneli TerminalID yazılmalı. string _strTerminalID = "0" + strTerminalID; string strProvUserID = "PROVAUT"; //TerminalProvUserID kullanıcısı string strProvisionPassword = "password"; //TerminalProvUserID şifresi string strUserID = "userID"; // Kullanıcı ID'si string strMerchantID = "1234567"; //Üye İşyeri Numarası
Bankacılık işlemleri sırasında kullanıcının IP adresi de öğrenilmelidir. Bu bilgiye aşağıdaki kod ile ulaşılır.
string strIPAddress = Request.UserHostAddress;
Sırada kullanıcının bilgilerinin tutulacağı değişkenleri tanımlayalım. Burada kart bilgilerinin dışında müşterinin e-postasına, sipariş için bir ID numarasına ve toplam ödenecek tutar bilgilerine ihtiyacımız var.
string strEmailAddress = customer.EMail; // Müşterinin e-postası string strOrderID = order.OrderID.ToString().Replace('-', '_'); // Sipariş ID'si string strNumber = txtCardNumber.Text; // Kredi kartı numarası string selectedMonth = ddlMonth.Text.Length < 2 ? "0" + ddlMonth.Text : ddlMonth.Text; string selectedYear = ddlYear.Text.Substring(2, 2); string strExpireDate = selectedMonth + selectedYear; //Kart son kullanma tarihi. Mart 2016 için 0316 şeklinde yazmalı string strCVV2 = txtCCV.Text; string strAmount = (order.TotalAmount * 100).ToString().Substring(0, (cardPayment.TotalAmount * 100).ToString().IndexOf(seperator)); //İşlem Tutarı 1.00 TL için 100 gönderilmeli
Satışta kullanılan döviz türünü ve diğer gerekli bilgileri aşağıdaki değişkenlerde tutuyoruz.
string strType = "sales"; string strCurrencyCode = "949"; // 949 = Türk Lirası string strCardholderPresentCode = "0"; string strMotoInd = "N"; string strInstallmentCount = ""; string strHostAddress = "https://sanalposprov.garanti.com.tr/VPServlet";
Garanti bankasının örneklerinde deneme için farklı bir host adresi de verilmektedir ancak yaşadığım tecrübeler sonucu size deneme sunucusunu kullanmamanızı şiddetle öneriyorum :) Bunun yerine 1 kuruşluk satışlar ile deneme yapabilirsiniz. Hatalı bir miktar girerseniz Garanti bankasının sanalpos sitesi aracılığıyla bir yönetici hesabı ile ödemeleri iptal edebilirsiniz.
Son olarak Garanti bankasının şifreleme algoritmasına göre şifrelenmesi gereken bir şifre oluşturmalıyız. Bu şifre oluştururken Garanti bankasının vermiş olduğu, aşağıda methodları kullanabiliriz.
using System.Security.Cryptography; using System.Text; public string GetSHA1(string SHA1Data) { SHA1 sha = new SHA1CryptoServiceProvider(); string HashedPassword = SHA1Data; byte[] hashbytes = Encoding.GetEncoding("ISO-8859-9").GetBytes(HashedPassword); byte[] inputbytes = sha.ComputeHash(hashbytes); return GetHexaDecimal(inputbytes); } public string GetHexaDecimal(byte[] bytes) { StringBuilder s = new StringBuilder(); int length = bytes.Length; for (int n = 0; n <= length - 1; n++) { s.Append(String.Format("{0,2:x}", bytes[n]).Replace(" ", "0")); } return s.ToString(); }
Tanımlanması gereken son değişkenler ise aşağıdaki gibidir.
string SecurityData = GetSHA1(strProvisionPassword + _strTerminalID).ToUpper(); string HashData = GetSHA1(strOrderID + strTerminalID + strNumber + strAmount + SecurityData).ToUpper();
Artık bankaya gönderilecek XML verisini aşağıdaki kodla oluşturabiliriz. Bankanın önerdiği değişkenleri kullandığımız için bu kısımda bir değişiklik yapmamız çok gerekli değildir. Ancak burada girilen bilgiler minimum gerekli bilgilere karşılık gelmektedir. Satış sonrasında bilgilerin daha iyi arşivlenmesi için elinizdeki bilgilere göre aşağıdaki yapıyı geliştirebilirsiniz. Bu yapıdaki verilerin özellikleri ile ilgili daha detaylı dökümanlar Garanti bankasının sağlamış olduğu dosyalarda mevcuttur.
string strXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<GVPSRequest>" + "<Mode>" + strMode + "</Mode>" + "<Version>" + strVersion + "</Version>" + "<Terminal><ProvUserID>" + strProvUserID + "</ProvUserID><HashData>" + HashData + "</HashData><UserID>" + strUserID + "</UserID><ID>" + strTerminalID + "</ID><MerchantID>" + strMerchantID + "</MerchantID></Terminal>" + "<Customer><IPAddress>" + strIPAddress + "</IPAddress><EmailAddress>" + strEmailAddress + "</EmailAddress></Customer>" + "<Card><Number>" + strNumber + "</Number><ExpireDate>" + strExpireDate + "</ExpireDate><CVV2>" + strCVV2 + "</CVV2></Card>" + "<Order><OrderID>" + strOrderID + "</OrderID><GroupID></GroupID><AddressList><Address><Type>S</Type><Name></Name><LastName></LastName><Company></Company><Text></Text><District></District><City></City><PostalCode></PostalCode><Country></Country><PhoneNumber></PhoneNumber></Address></AddressList></Order>" + "<Transaction>" + "<Type>" + strType + "</Type><InstallmentCnt>" + strInstallmentCount + "</InstallmentCnt><Amount>" + strAmount + "</Amount><CurrencyCode>" + strCurrencyCode + "</CurrencyCode><CardholderPresentCode>" + strCardholderPresentCode + "</CardholderPresentCode><MotoInd>" + strMotoInd + "</MotoInd>" + "</Transaction>" + "</GVPSRequest>";
Artık banka sistemi ile iletişim kurmak için hazırız. Bankaya oluşturduğumuz XML verisini göndermek için aşağıdaki kodları kullanabiliriz.
using System.Net; using System.Xml; using System.IO; try { string data = "data=" + strXML; WebRequest _WebRequest = WebRequest.Create(strHostAddress); _WebRequest.Method = "POST"; byte[] byteArray = Encoding.UTF8.GetBytes(data); _WebRequest.ContentType = "application/x-www-form-urlencoded"; _WebRequest.ContentLength = byteArray.Length; Stream dataStream = _WebRequest.GetRequestStream(); dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); WebResponse _WebResponse = _WebRequest.GetResponse(); //Console.WriteLine(((HttpWebResponse)_WebResponse).StatusDescription); dataStream = _WebResponse.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseFromServer = reader.ReadToEnd(); //Müşteriye gösterilebilir ama Fraud riski açısından bu değerleri göstermeyelim. //Console.WriteLine(responseFromServer); //GVPSResponse XML'in değerlerini okuyoruz. İstediğiniz geri dönüş değerlerini gösterebilirsiniz. string XML = responseFromServer; XmlDocument xDoc = new XmlDocument(); xDoc.LoadXml(XML); //ReasonCode XmlElement xElement1 = xDoc.SelectSingleNode("//GVPSResponse/Transaction/Response/ReasonCode") as XmlElement; //lblResult2.Text = xElement1.InnerText; //Message //XmlElement xElement2 = xDoc.SelectSingleNode("//GVPSResponse/Transaction/Response/Message") as XmlElement; //lblResult2.Text = xElement2.InnerText; //ErrorMsg XmlElement xElement3 = xDoc.SelectSingleNode("//GVPSResponse/Transaction/Response/ErrorMsg") as XmlElement; //00 ReasonCode döndüğünde işlem başarılıdır. Müşteriye başarılı veya başarısız şeklinde göstermeniz tavsiye edilir. (Fraud riski) cardPayment.Result = xElement1.InnerText; if (xElement1.InnerText == "00") { lblResult.Text = "Ödemeniz başarıyla gerçekleşti. Siparişiniz derhal hazırlanıp gönderilecektir.<br />"; } else { lblResult.Text = cardPayment.ErrorDetails + "<br />"; } } catch (Exception ex) { lblResult.Text = ex.Message + "<br />"; }
Bütün işlemler bu kadar. Müşteriye gösterilen mesaj üzerinde sunumunuza yönelik çeşitli tasarımlar yapmanız ve sonucu başarılı / başarısız olarak göstermenizi öneririm. Eğer console’a yazılan hata mesajlarını okumak isterseniz yorum satırı haline getirilmiş kodları açıp inceleyebilirsiniz.