Asp.Net Sanal pos entegrasyonu (Epayment)

Tarih 23 Ocak 2010 Cumartesi | Etiket(ler) Asp.Net, Visual Basic, E-Ticaret | Yorumlar 17 yorum

İnternette bu konu ile ilgili birçok kaynak bulusa da Asp.Net ile ilgili çok az kaynağa rastlanıyor. Epayment.dll kullanacağımız bu uygulamada çok fazla teknik konuya girmeden sanal pos'un asp.net üzerinde nasıl uygulandığına değinmeye çalışacağım. Yaptığımız örnek epayment.dll kullandığı için birçok bankayla uyumlu çalışmaktadır. Garanti bankası, Akbank, Citibank, Finansbank, HSBC ve İş Bankası bu sistemi kullandığından hepsinde sorunsuz olarak çalışıyor. Bankanızın dökümanlarında epayment.dll i bulabilir ya da projenin çalışan halini download ederek içindeki dll i kullanabilirsiniz. İlk olarak epayment.dll ilimizi projemize referans olarak ekleyerek işe başlayalım.

Daha sonra gerekli bilgileri alacağımız form tasarımımızı yaparak uygulamamıza giriş yapalım.
    <form id="form1" runat="server">
    <label id="lblSonuc" runat="server"></label>
    <h2>Kredi kartı ödeme bilgileri</h2>
    <p>
        <label>Ödenecek miktar</label>
        <asp:TextBox ID="kkmiktar" MaxLength="4" Columns="5" runat="server"></asp:TextBox>
        <asp:DropDownList ID="kkcekim" runat="server">
            <asp:ListItem Text="Tek çekim" Value="1"></asp:ListItem>
            <asp:ListItem Text="6 taksit" Value="6"></asp:ListItem>
            <asp:ListItem Text="12 taksit" Value="12"></asp:ListItem>
        </asp:DropDownList>
    </p>
    <p>
        <label>Kart sahibi</label>
        <asp:TextBox ID="kksahip" Columns="50" runat="server"></asp:TextBox>
    </p>
    <p>
        <label>Kart no / CVC no</label>
        <asp:TextBox ID="kknum" MaxLength="16" Columns="20" runat="server"></asp:TextBox>
        /
        <asp:TextBox ID="kkcvc" MaxLength="3" Columns="4" runat="server"></asp:TextBox>
    </p>
    <p>
        <label>Son kullanma tarihi>/label>
        <asp:DropDownList ID="kkay" runat="server">
            <asp:ListItem Text="1" Value="1"></asp:ListItem>
            <asp:ListItem Text="2" Value="2"></asp:ListItem>
            <asp:ListItem Text="3" Value="3"></asp:ListItem>
            <asp:ListItem Text="4" Value="4"></asp:ListItem>
            <asp:ListItem Text="5" Value="5"></asp:ListItem>
            <asp:ListItem Text="6" Value="6"></asp:ListItem>
            <asp:ListItem Text="7" Value="7"></asp:ListItem>
            <asp:ListItem Text="8" Value="8"></asp:ListItem>
            <asp:ListItem Text="9" Value="9"></asp:ListItem>
            <asp:ListItem Text="10" Value="10"></asp:ListItem>
            <asp:ListItem Text="11" Value="11"></asp:ListItem>
            <asp:ListItem Text="12" Value="12"></asp:ListItem>
        </asp:DropDownList>
        /
        <asp:DropDownList ID="kkyil" runat="server">
            <asp:ListItem Text="2010" Value="2010"></asp:ListItem>
            <asp:ListItem Text="2011" Value="2011"></asp:ListItem>
            <asp:ListItem Text="2012" Value="2012"></asp:ListItem>
            <asp:ListItem Text="2013" Value="2013"></asp:ListItem>
            <asp:ListItem Text="2014" Value="2014"></asp:ListItem>
            <asp:ListItem Text="2015" Value="2015"></asp:ListItem>
            <asp:ListItem Text="2016" Value="2016"></asp:ListItem>
            <asp:ListItem Text="2017" Value="2017"></asp:ListItem>
        </asp:DropDownList>
    </p>
    <p>
        <label>&nbsp;</label>
        <asp:Button ID="kksubmit" Text="Ödeme yap" runat="server" />
    </p>
    </form>
Formumuzun görünümü şu şekilde oldu :

SanalPos

Bilgileri alacak kodlarımızı yazmaya başlayalım. Bu formdan gelecek bilgileri kontrol ettirmek vs. gibi işlemleri yapmadan basitçe anlatmaya çalışıyorum. Siz gelen bilgileri uygun formatta mutlaka kontrol edin.
    Protected Sub kksubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles kksubmit.Click
        Try
            Dim mycc5pay As New ePayment.cc5payment()
            mycc5pay.host = "ADRES" ' Verileri göndereceğimiz adres
            mycc5pay.name = "KULLANICIADI" ' Bankadan verilen kullanıcı adı
            mycc5pay.password = "PAROLA" ' Bankadan verilen parola
            mycc5pay.clientid = "MAGAZAID" ' Bankadan verilen mağaza id

            mycc5pay.orderresult = "0" ' 0 Gerçek işlem, 1 Test işlemi
            mycc5pay.cardnumber = kknum.Text ' Kredi kartı numarası
            mycc5pay.expmonth = kkay.Text ' Kredi kartı son kullanım ay
            mycc5pay.expyear = kkyil.Text ' Kredi kartı son kullanım yıl
            mycc5pay.cv2 = kkcvc.Text ' Kredi kartı CVC numarası
            mycc5pay.currency = 949 ' TL için 949
            mycc5pay.chargetype = "Auth"
            mycc5pay.ip = Request.ServerVariables("REMOTE_ADDR") ' IP adresi

            mycc5pay.subtotal = kkmiktar.Text ' Çekilecek tutar

            If kkcekim.SelectedItem.Value = 6 Then ' 6 taksit seçilmişse
                mycc5pay.taksit = "6"
            ElseIf kkcekim.SelectedItem.Value = 12 Then ' 12 taksit seçilmişse
                mycc5pay.taksit = "12"
            End If

            Dim bankaSonuc As String = mycc5pay.processorder() ' Fonksiyonumuzu çağırıyoruz
            Dim bankaHata As String = mycc5pay.errmsg ' Geri dönen hata mesajı
            Dim bankaOid As String = mycc5pay.oid ' Geri dönen order id
            Dim bankaAppr As String = mycc5pay.appr ' Geri dönen işlem sonucu
            Dim bankaProv As String = mycc5pay.code ' Geri dönen provizyon numarası

            ' Bankadan gelen sonuçları lblSonuc labelına yazdırıyoruz.
            If bankaSonuc = "1" Then
                If bankaAppr = "Approved" Then ' Ödeme işlemi tamam
                    lblSonuc.Text = "Ödeme işlemi başarıyla gerçekleşti"
                ElseIf bankaAppr = "Declined" Then ' Ödeme işlemi reddedildi
                    lblSonuc.Text = "Ödeme işlemi banka tarafından reddedildi! : " & bankaHata & ""
                Else
                    lblSonuc.Text = "Bir hata oluştu : " & bankaHata & ""
                End If
            Else
                lblSonuc.Text = "Bankayla irtibat kurulamadı!"
            End If
        Catch ex As Exception
            lblSonuc.Text = ex.Message
        End Try
    End Sub
Önemli notlar :
Kullanıcıdan alınan bilgileri mutlaka ama mutlaka kontrol edip gönderin.
Taksit parametresi bankayla anlaşma yaptıysanız çalışır aksi halde hata döndürür.
Test yaparken orderresult parametresini "1" olarak değiştirin.
Satış yapacağınız para birimine uygun kodu currency parametresine eşitleyin.

Form tasarımını basit tuttum ve ne yaptıysam yanlarına açıklamalarını yazdım. Formdaki bilgileri siz ister veritabanınızdan alın ister döngülerle çoğaltın. Başlangıç seviyesinde bilmeniz gereken şeyleri çok kafa karıştırmadan anlatmaya çalıştım. Sonraki yazılarımda gönderilen ekstra parametreleri ve diğer özellikleri anlatmaya çalışacağım.

Projenin çalışan halini buradan indirebilirsiniz
Son kaydın ID değerini alalım SCOPE_IDENTITY()

Tarih 19 Ocak 2010 Salı | Etiket(ler) Asp.Net, Sql ve Veritabanları, Visual Basic | Yorumlar 2 yorum

Herhangi bir kayıt işleminde 2 tabloya triggersız kayıt girmek veya henüz girdiğimiz ID değerini kullanmak istediğimizde pek çoğumuz 2 ayrı sql cümlesi kullanırız. Aslında bu işlem için iki ayrı sql cümlesi yazıp işlem yapmak hem gereksiz kaynak tüketmeye hemde gereksiz kod kalabalığına neden olur. Böyle bir durumda SCOPE_IDENTITY() biçilmiş kaftan olarak karşımıza çıkar. Senaryo olarak tbl_sorular ve tbl_cevaplar adlarında iki tablomuzun olduğunu varsayalım. Adlarından anlaşılacağı gibi tbl_sorular tablomuza soruları, tbl_cevaplar tablomuza cevapları girmek istiyoruz. tbl_cevaplar tablosundaki cevapları, tbl_sorular tablosundaki soruyla eşleştirmek için SORUID değerine ihtiyacımız var ve her yeni kayıtta 3 sql cümlesine ihtiyacımız olacak (bu yazıdan sonra olmayacak) :

1) sorular tablosuna kayıt girmek için INSERT cümlesi
2) sorular tablosundaki son ID değeri için SELECT cümlesi
3) cevaplar tablosuna cevap girmek için INSERT cümlesi

Şimdi bu üç sorgu yerine çok daha az kodla ve kaynakla bu işlemleri yapmaya çalışacağız.

SQL Server tablo yapımız şu şekilde :
tbl_sorular tablomuz :

tbl_sorular

tbl_cevaplar tablomuz :

tbl_cevaplar

böyle bir durumda 3 sorgu yerine, 2 sorgu kullanıp kodumuzu optimize hale getiriyoruz. Bunun için aşağıdaki gibi bir kod bloğu kullanabilirsiniz.
' Veritabanı bağlantı satırımız
Dim Veritabani As New SqlConnection("SQL_BAGLANTI_SATIRIMIZ;")
' Birinci Sql cümlemizi yazacağımız SqlCommand ve parametreleri
Dim Sql1 As New SqlCommand
Sql1.CommandType = CommandType.Text
' Veritabanımızı SqlCommand'ımız ile ilişkilendirelim
Sql1.Connection = Veritabani
' Son ID değerimizi alabilmek için gerekli parametrelerimiz
Dim insertPrm As New SqlParameter
insertPrm.Direction = ParameterDirection.Output
' ID değerini istediğimiz alan
insertPrm.ParameterName = "SORUID"
insertPrm.Size = 10
Sql1.Parameters.Add(insertPrm)
' INSERT cümlemizi tanımlayalım, sihirli kelime SCOPE_IDENTITY() AS SORUID bize istediğimizi verecek
Sql1.CommandText = "INSERT INTO tbl_sorular (SORU) VALUES ('Sorumuz buraya gelsin'); SELECT SCOPE_IDENTITY() AS SORUID"
' Geri dönen değeri almak için tabiiki ExecuteScalar kullanmalıyız
Dim sonId As String = Sql1.ExecuteScalar

' Ve cevaplar tablomuza cevabımızı girelim
Dim Sql2 As New SqlCommand("INSERT INTO tbl_cevaplar (SORUID,CEVAP) VALUES (" & sonId & ",'Cevabım buraya gelsin');", Veritabani)
If Veritabani.State = ConnectionState.Closed Then Veritabani.Open()
Sql2.ExecuteNonQuery()
Veritabani.Close()
Dikkat ettiyseniz ilk tabloya eklediğimiz ID değerini ikinci bir sql cümlesi ve kaynağı kullanmadan ExecuteScalar ile geri döndürdük ve cevaplar tablomuza istediğimiz değeri yazdırdık. Son eklenen değeri ikinci bir cümleyle almak hatalara neden olabilirdi. O sırada başka bir kayıdın girilmesi yanlış ID değerine ulaşmamıza neden olabilir ve yukarıda anlattığım gibi gereksiz yük ve zaman kaybı olarak başımızı ağrıtabilirdi. Sihirli kelimemiz SCOPE_IDENTITY() son eklediğimiz kaydın ID değerini başarıyla geri döndürdü.

Yeri gelmişken @@IDENTITY veya IDENT_CURRENT() kelimeleri de aynı işi farklı yöntemlerle yapmamızı sağlayabilirdi. Yalnız unutmamalıyız ki @@IDENTITY tablomuzda trigger çalışıyorsa yanlış ID değerini geri döndürebilir. Aslında bu kadar basit. Yeni bir yazıda görüşmek üzere...
ExecuteScalar, ExecuteNonQuery ve ExecuteReader

Tarih 18 Ocak 2010 Pazartesi | Etiket(ler) Asp.Net, Visual Basic, Sql ve Veritabanları | Yorumlar 2 yorum

En çok sorulan sorulardan biri ExecuteScalar, ExecuteNonQuery ve ExecuteReader metodlarının ne işe yaradıkları ve birbirlerinden ne farklarının olduğudur. Asp.Net e yeni başlayanların kafasını kurcalayan bu konuyu sade ve yalın olarak, çok fazla teknik cümleler kurmadan basit bir şekilde anlatmaya çalışacağım. Herbirinin kullanım alanlarının farklı olduğunu söylemekle başlayalım.

ExecuteScalar :

Geriye object tipinde değer döndüren bu alan, aynı zamanda geriye tek bir değer döndürür. Gönderilen SQL sorgusunda geriye ne kadar satır veya sütun dönerse dönsün sadece ilk satırın ilk sütunu sonuç olarak alınabilir. Genelde SUM, COUNT, AVG, MAX, MIN vs. gibi tek veri istenilen sorgularda kullanılır. Ya da veritabanında kayıtlı olan bir kaydın kontrol edilebilmesi için uyarlanabilir. Örneğimize geçelim.
Dim Veritabani As New SqlConnection("server=SERVER;database=ORNEKDB;user=USER;password=PASS;")
Dim Sql As New SqlCommand("SELECT COUNT(ID) FROM tablo_adi;", Veritabani)
    Try
        Veritabani.Open()
        ' lblSonuc isimli label a tablo_adi tablosunda kaç kayıt olduğunu yazdırıyoruz
        lblSonuc.Text = Sql.ExecuteScalar.ToString
    Catch ex As Exception
        Response.Write(ex.Message)
    Finally
        Veritabani.Close()
    End Try
ExecuteNonQuery :

Geriye Integer olarak DELETE, INSERT, UPDATE komutları sonucu kaç kayıdın etkilendiği döndürüyor. Diğer bir deyişle DELETE sql komutunu kullandığınızda kaç kayıt silindiğini, INSERT komutunu kullandığınızda kaç kayıt eklendiğini, UPDATE komutunu kullandığınızda kaç kayıdın güncellendiğini söylüyor. Veritabanı üzerinde kayıtlar ile ilgili değişiklik yapacağımız zaman bu metodu kullanıyoruz. Örnek verirsek.
Dim Veritabani As New SqlConnection("server=SERVER;database=ORNEKDB;user=USER;password=PASS;")
Dim Sql As New SqlCommand("UPDATE tablo_adi SET SAYI = 1;", Veritabani)
    Try
        Veritabani.Open()
        ' lblSonuc isimli label a tablo_adi tablosunda kaç kayıt değiştiğini yazıyoruz
        Dim sonuc As Integer = Sql.ExecuteNonQuery
        If sonuc > 0 Then
            lblSonuc.Text = sonuc.ToString
        Else
            lblSonuc.Text = "Hiçbir kayıt düzenlenmedi"
        End If
    Catch ex As Exception
        Response.Write(ex.Message)
    Finally
        Veritabani.Close()
    End Try
ExecuteReader :

Bir veritabanından SELECT sorgusu ile çektiğimiz kayıtların veri akışını sağlar. SELECT sql sorgusu sonucunda dönen kayıtların hepsini satır ve sütun bazında herhangi bir veri kaynağına aktarmamızı ya da direkt olarak basmamızı kolaylaştırır. Dönen sonuçlar SqlDataReader nesnesi üzerinden aktarılır.
Dim Veritabani As New SqlConnection("server=SERVER;database=ORNEKDB;user=USER;password=PASS;")
Dim Sql As New SqlCommand("SELECT * FROM tablo_adi;", Veritabani)
    Try
        Veritabani.Open()
        Dim sonuclar As SqlDataReader = Sql.ExecuteReader
        ' Geri dönen tüm sonuçları ekrana bastırıyoruz.
        While sonuclar.Read
            Response.Write(sonuclar.Item("ADI"))
            Response.Write(sonuclar.Item("SOYADI"))
        End While
        sonuclar.Close()
    Catch ex As Exception
        Response.Write(ex.Message)
    Finally
        Veritabani.Close()
   End Try
Genel kullanım alanları basit olarak bu şekilde anlatılabilir. Umarım kafanızda soru işareti kalmamıştır. Tüm sorularınız için benimle iletişime geçebilirsiniz.
BackgroundWorker ve MultiThreading

Tarih 16 Ekim 2009 Cuma | Etiket(ler) Visual Basic | Yorumlar 2 yorum


BackgroundWorker; kısaca hazırladığınız bir Windows formunda, adından da anlaşılabileceği gibi arka planda işlem yapmak için kullanılır. Aslında işi tamamen MultiThreading ve yaptığı işi raporlamadır. Ekleyeceğiniz her BackgroundWorker birbirinden bağımsız kanallarda çalışarak, ana kanalınızı tıkamadan çalışmanıza olanak verir. Kullanımı çok kolay olmasına rağmen işlevi büyük ve önemlidir. Örnekleyecek olursak. Windows formu içerisinde uzun sürecek bir işlem (çok kayıt döndürecek bir SQL sorgusu, Web adresi çağırma vs..) kullanıyorsak Form donacak ve işlem tamamlanana kadar yanıt vermeyecektir. Tamamen istemediğimiz bir durum. Bu sırada bir progress bar, animated gif gibi görseller kullanacak olursak, bunların görevlerini yerine getirmediğini, donduklarını göreceksiniz. İşte tam bu sırada BackgroundWorker imdada yetişiyor ve bizi bu durumdan sonsuza kadar kurtarıyor. Nasıl kullanıldığına gelirsek.

1) Form üzerine bir BackgroundWorker sürükleyip bırakıyoruz.
2) BackgroundWorker'ın arka planda çalıştıracağı kodu DoWork eventine yazıyor veya çağırıyoruz.
3) BackgroundWorker'ı çalıştırmak için RunWorkerAsync() komutu ile DoWork eventini tetikliyoruz.
4) İşlem sırasında progressbar göstermek istiyorsak BackgroundWorker'ın çalışma durumunu bildiriyoruz.
5) ProgressChanged ile Formumuz üzerindeki bir kontrolü değiştiriyoruz.

4. ve 5. maddeler tamamen opsiyonel olarak kullanılır. Bir kontrol yerine animated GIF göstermeyi tercih edebilirsiniz.

Örnek Kod :
Formda bir adet button olduğunu var sayıyorum
Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button1.Click
backgroundWorker1.RunWorkerAsync() 'butonumuza basıyoruz ve backgroundWorker'ı çalıştırıyoruz
Sub

Private Sub backgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles backgroundWorker1.DoWork
MsgBox("işlem başladı", MsgBoxStyle.Information, "SONUÇ")
System.Threading.Thread.Sleep(3000) ' arka planda işlem yapacak kod
End Sub
  
Private Sub backgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles backgroundWorker1.RunWorkerCompleted
MsgBox("işlem bitti", MsgBoxStyle.Information, "SONUÇ") ' bittiğinde yapılacak işlem
End Sub
Bu işlemler sırasında kullanıcı işlemi iptal etmek isteyebilir. Böyle durumlarda backgroundWorker1.CancelAsync() tetikleyerek işlemi iptal edebilirsiniz.

We're in this together, we share the same skin!