Ana içeriğe atla

PAYTR SANAL POS ASP.NET C# Entegrasyonu

merhaba, bu makalede sizlere PAYTR Sanal pos yapısını .NET üzerinde nasıl çalıştıracağımız ile ilgili bilgi aktarmaya çalışacağım. Ücretsiz başlangıç sağlaması ve sabit ödeme almaması sebebiyle düşük bütçeli e-ticaret yapmak isteyen kişilerin tercih ettiği PAYTR Sanal pos entegrasyonu temelde PHP üzerine kurulmuş. Dolayısıyla .net ile e-ticaret yazmaktaysanız bu sizi bir hayli zorluyor zira firma ile birçok görüşme yapmama rağmen sağlıklı bir .net örneklemesi bulamadım. Baktım olacak gibi değil, sonunda oturdum kendi entegrasyonumu kendim yazdım :). aşağıda detaylı olarak bulabilirsiniz.

//using satırlarımızı ekleyelim;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;
//aşağıdaki sabit PAYTR Fonksiyonlarını ekleyelim.(bu fonksiyonları global olarak tanımlayabilirsiniz.
public static string make_user_basket(object[][] user_basket_arr)
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        string user_basket_json = ser.Serialize(user_basket_arr);
        string user_basket = Convert.ToBase64String(Encoding.UTF8.GetBytes(user_basket_json)); return user_basket;
    }
    public static string create_token(string merchant_id, string user_ip, string merchant_oid, string email, string payment_amount, string user_basket, string no_installment, string max_installment, string currency, string merchant_salt, string merchant_key)
    {
        string Birlestir = string.Concat(merchant_id, user_ip, merchant_oid, email, payment_amount, user_basket, no_installment, max_installment, currency, merchant_salt);
        HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(merchant_key));
        byte[] b = hmac.ComputeHash(Encoding.UTF8.GetBytes(Birlestir));
        return Convert.ToBase64String(b);
    }
    public static string siparisnumarasiuret(int length)
    {
        string ts = DateTime.Now.ToString("hhmmss");
        string chars = "ST123456789ABCDEFGHJKLMNOPRSTUIVYZWX";
        var random = new Random();
        return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()) + ts;
    }

   protected void Page_Load(object sender, EventArgs e)
    {
        string merchant_id = "xxx"; //PAYTR tarafından veriliyor.
        string merchant_key = "xxx";//PAYTR tarafından veriliyor.
        string merchant_salt = "xx"; //PAYTR tarafından veriliyor.
        string emailstr = "cancevikoglu@gmail.com"; //Müşteri e-posta adresi
        int payment_amountstr = 1537; // Ödeme tutarı  15,37 için 1537 yazmanız gerekiyor. Tutar * 100 yapıp strin'e convert edebilirsiniz
        string merchant_oid = siparisnumarasiuret(8); //paytr için sipariş numarası üretiliyor. kendi oluşturduğunuz siparişlerde ödeme sipariş numarası şeklinde tutarsanız inceleme için faydalı olur
        string user_namestr = "can çevikoğlu"; // müşteri adı soyadı
        string user_addressstr = "test adres bilgileri";
        string user_phonestr = "5305555555"; //Müşteri telefon numarası
        string merchant_ok_url = "http://www.siteniz.com/basariliadres"; //ödeme başarılı olduğunda yönlenecek sayfa
        string merchant_fail_url = "http://www.siteniz.com/basarisizadres"; //ödeme başarısız olduğunda yönlenecek sayfa
        string user_basketstr = "";
        string user_ip = ""; //müşteri ip adresi
        string timeout_limit = "15"; //dakika işlem yapmazsa işlem iptal olur
        string debug_on = "1"; //test modu olup olmadığını belirtir. 1 test modu, 0 canlı mod.  (panelden de bu ayarı düzeltmeniz gerekir)
        string no_installment = "1"; //taksit istemiyorsanız 1 istiyorsanız 0 yapın
        string max_installment = "3"; //taksiti açmış iseniz taksit limiti belirtin
        string currency = "TL"; //para birimi
        string lang = "tr"; // arayüz dili
        DataTable qSepet = SepetIslemleri.SepetListe(5); //SepetListe benim yazdığım fonksiyondur. DataTable türünde müşteri sepetini döndürür.
        int qArrayCount = qSepet.Rows.Count;
        object[][] user_basket = new object[qArrayCount][];
        int i = 0;
        foreach (DataRow dr in qSepet.Rows)
        {
            string qStokKodu = dr["StokKodu"].ToString();
            decimal qFiyat = Convert.ToDecimal(dr["Tutar"]);
            int qAdet = Convert.ToInt32(dr["Adet"]);
            user_basket[i] = new object[] { qStokKodu, qFiyat, qAdet };
            i++;
        }
        user_basketstr = make_user_basket(user_basket);
        NameValueCollection data = new NameValueCollection();
        data["merchant_id"] = merchant_id;
        data["user_ip"] = user_ip;
        data["merchant_oid"] = merchant_oid;
        data["email"] = emailstr;
        data["payment_amount"] = payment_amountstr.ToString();
        data["paytr_token"] = create_token(merchant_id, user_ip, merchant_oid, emailstr, payment_amountstr.ToString(), user_basketstr, no_installment, max_installment, currency, merchant_salt, merchant_key);
        data["user_basket"] = user_basketstr;
        data["debug_on"] = debug_on;
        data["no_installment"] = no_installment;
        data["max_installment"] = max_installment;
        data["user_name"] = user_namestr;
        data["user_address"] = user_addressstr;
        data["user_phone"] = user_phonestr;
        data["merchant_ok_url"] = merchant_ok_url;
        data["merchant_fail_url"] = merchant_fail_url;
        data["timeout_limit"] = timeout_limit;
        data["currency"] = currency;
        data["lang"] = lang;
       string qToken = null;
        using (WebClient client = new WebClient())
        {
            client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
            byte[] result = client.UploadValues("https://www.paytr.com/odeme/api/get-token", "POST", data);
            string ResultAuthTicket = Encoding.UTF8.GetString(result);
            dynamic json = JValue.Parse(ResultAuthTicket);
            qToken  = json.token;
            string durum = json.status;
        }
                    if (qToken != null)
                    {
Session["qToken"] = qToken;
Response.Redirect("BildirimURL.aspx") // token alındı ise ödeme işleminin yapılacağı sayfanıza yönlendirme yapabilirsiniz.
                    }

    }
yukarıdaki kodlar ile token alımı gerçekleştirebilirsiniz. daha sonra token alındı ise, ödeme sayfanıza yönlendirme yaparsınız. Session["qToken"] ile aldığınız token'i sayfalar arasında aktarabilmeniz mümkündür.Bildirim URL sayfanızda kullanacağınız bir iframe ile ödeme ekranını kullanıcıya gösterebilirsiniz. Örnek Kullanım şu şekilde olabilir;
if (Session["qToken"] != null)
        {
            string qURL = "https://www.paytr.com/odeme/guvenli/" + Session["qToken"].ToString();
            iframe.Attributes.Add("src", qURL);
        }
bu adımda kullanıcı iframe üzerinde ödeme seçeneğini belirler, işlemi sonlandığında ödeme başarılı ise "işlem başarılı" sayfasına, değilse "başarısız url" sayfanıza yönlenir.burada belirtmek isterim; işlem başarılı sayfasına ulaşmadan önce sizin sipariş oluşturacağınız bir ara sayfa daha vardır. PAYTR iframe üzerinden kullanıcı bilgilerini aldığında işlem başarılı ise önce oluşturacağınız onay sayfasına gider, sizden ekrana "OK" yazdırmanızı ister. daha sonra başarılı sayfasına yönlendirme sağlanır. Oluşturacağınız bu onay sayfasında hiçbir HTML elemanı olmamalıdır. Kodları aşağıdaki şekilde olabilir;
string merchant_key = "xxx"; //siz ayarlayacaksınız ...
    string merchant_salt = "xxx"; // siz ayarlayacaksınız ...
   protected void Page_Load(object sender, EventArgs e)
    {
        string merchant_oid = Request.Form["merchant_oid"];
        string status = Request.Form["status"];
        string total_amount = Request.Form["total_amount"];
        string hash = Request.Form["hash"];
        string installment_count = Request.Form["installment_count"];
        string Birlestir = string.Concat(merchant_oid, merchant_salt, status, total_amount);
        HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(merchant_key));
        byte[] b = hmac.ComputeHash(Encoding.UTF8.GetBytes(Birlestir));
        string token = null;
        token = Convert.ToBase64String(b);
        //if (hash != token)
        //{
        //    Response.Write("PAYTR notification failed: bad hash");
        //    return;
        //}
        if (status == "success")
        {
            Response.Write("OK");
        //siparişinizi bu adımda oluşturabilirsiniz.
        }

}
biraz zor bir anlatım olmuş olabilir, takıldığınız yerler olursa yardımcı olmaya çalışabilirim. Sistem biraz karmaşık olduğundan anlatması da bir hayli zor oluyor maalesef. Umarım faydalı olmuştur. Aşağıdaki linkten örnek dosyaları indirebilirsiniz;

 https://drive.google.com/file/d/14QQFln84UNmEHLTceOqAeXEalywzNayL/view?usp=sharing

Yorumlar

  1. Merhabalar, ben bu işlemi controllerda yapmaya çalışıyorum, Bildirim URL den gelen yönlendirmede aşağıdaki verileri alamıyorum, ve hata veriyor, bunun çözümü için yardımcı olmanız mümkün müdür?



    string merchant_oid = Request.Form["merchant_oid"];
    string status = Request.Form["status"];
    string total_amount = Request.Form["total_amount"];
    string hash = Request.Form["hash"];


    saygılarımla

    YanıtlaSil
    Yanıtlar
    1. Merhaba,

      tabii ki yardımcı olmaya calısırım fakat biraz daha detay bilgiye ihtiyacım bulunmakta.

      Sil
    2. ilginiz için çok teşekkürler,

      öde işleminde ödeme başarılı sayfasına kadar geliyorum, buradan sitemde bulunan ödeme tamamlandı sayfasına yönlendirme sırasında aşağıdaki hatayı alıyorum,

      Object reference not set to an instance of an object.
      Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

      Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

      Stack Trace:


      [NullReferenceException: Object reference not set to an instance of an object.]
      NYSWeb.Controllers.HomeController.tamamlandi() in C:\Project\*******\*******\*****\Controllers\HomeController.cs:65
      65. satır kodu aşağıdaki gibidir.

      if (hash.ToString() != token)
      {
      Response.Write("PAYTR notification failed: bad hash");
      //return;
      }

      daha önceki mesajımda vermiş olduğum kodlar form parametreleri fakat bunları nasıl alacağımı çözemedim, siteden bir parametre dönmüyor,

      Sil
    3. Merhaba,

      sanırım hash null geliyor. sayfa geçişi esnasında, yeni sayfada hangi request form değişkenlerinin geldiğini kontrol edin. aşağıdaki döngü işinize yarayabilir.

      foreach (string key in Request.Form.AllKeys)
      {
      Response.Write(key + "
      ");
      }

      Sil
    4. Bu yorum yazar tarafından silindi.

      Sil
  2. hocam sanırım ben bir yerde hata yapıyorum, methodu aşağıdaki şekilde tanımladığım zaman paytr sayfasından gelen veri buraya hiç uğramıyor, buradan kaynaklı bir sıkıntı olma olasılığı var mıdır?

    [HttpPost]
    public ActionResult tamamlandi()
    {
    }

    YanıtlaSil
    Yanıtlar
    1. Merhaba,

      o zaman PAYTR panelindeki parametreleri kontrol etmeniz gerekir. Oradaki sayfa ayarlarına bir bakın, PAYTR nin sayfa parametrelerinde hata mevcut olabilir.

      Sil
  3. hocam ben bu paytr deki kişilerle bir türlü anlaşamadım, paytr den bildirim url im geldi controller bu şekilde Request.Form'daki değişkenlere veri atayabilmem için bir parametre gelmesi gerektiğini düşünüyorum ve bu şekilde izah ediyorum ama bana dönüş parametresi ile ilgili bilgi vermiyorlar, burada benim eksikliğimde olabilir, ne yapabilirim parametreleri nasıl alabilirim, yardımcı olabilirseniz çok sevinirim.

    public ActionResult Index()
    {
    string merchant_key = "*******************";
    string merchant_salt = "****************";

    // ####### Bu kısımda herhangi bir değişiklik yapmanıza gerek yoktur. #######
    //
    // POST değerleri ile hash oluştur.
    string merchant_oid = Request.Form["merchant_oid"];
    string status = Request.Form["status"];
    string total_amount = Request.Form["total_amount"];
    string hash = Request.Form["hash"];
    }

    YanıtlaSil
  4. anlıyorum bende benzer sorunları yaşamıştım. İlk olarak, paytr panelden test modunda olup olmadığınızı kontrol edin. test modunda olmalısınız. Daha sonra bildirim url kontrolünü yapın, bildirim url, request form değişkenlerini alacağın sayfadır dolayısıyla ismi aynı olmalı. bunların 2 side doğruysa yukarıdaki for döngüsü ile request form parametrelerini alabiliyor olmanız gerekir.

    YanıtlaSil
  5. Can Bey selamlar. Token aldıktan sonra ödeme işleminin yapılacağı sayfaya gidiyorum. Test olduğu için parametreler dolu halde geliyor. Ödeme yap dediğimde {"status":"failed","reason":"Zorunlu alan degeri gecersiz veya gonderilmedi (odeme): payment_type"} hatası alıyorum. Bu konu da yardımcı olabilir misiniz?

    YanıtlaSil
    Yanıtlar
    1. Merhaba,

      tam olarak hangi değerleri nasıl set ettiniz bilemiyorum fakat aşağıdaki yorumum yardımcı olabilir;

      parametreleri aşağıdaki şekilde ayarlayın ve tekrar deneyin,
      mağazanızı test moduna alın,
      parametreler şu şekilde;
      test_mode=1
      debug_on=1
      no_installment =1 (taksitsiz)
      max_installment parametrelerde yer almasın,

      bunun haricinde diğer base parametreleri (merchant_id ,user_ip) gibi doğru set ettiğinizden emin olun. ayrıca hem sitede, hemde kod tarafında fail ve success URL lerin doğru olduğundan lütfen emin olun

      Sil
  6. Merhaba, anlatım için teşekkürler.
    Biz bir sayfa oluşturduk Odeme.aspx şeklinde. Bu sayfanın Page_Load metodunu doldurduk. Ancak,

    byte[] result = client.UploadValues("https://www.paytr.com/odeme/api/get-token", "POST", data);

    satırında hata alıyoruz.

    Hata şu şekilde;

    System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a send. ---> System.IO.IOException: Authentication failed because the remote party has closed the transport stream. (Devamı da var.)

    Nerede hata yapıyor olabiliriz ?

    Teşekkürler.

    YanıtlaSil
  7. Eğer controllerinizde [Authorize] varsa; PAYTR ile ilgili actionların başına:

    [AllowAnonymous]
    public async Task PayOk()
    {

    string merchant_oid = Request.Form["merchant_oid"];
    string status = Request.Form["status"];
    string total_amount = Request.Form["total_amount"];
    string hash = Request.Form["hash"];


    }

    şeklinde [AllowAnonymous] attribute ü koymalısınız. Aynı attribute PayTROK ve PayTRFail actionlarının başında da olmalıdır.

    YanıtlaSil
    Yanıtlar
    1. Merhaba,

      public partial class Odeme : System.Web.UI.Page
      {
      protected void Page_Load(object sender, EventArgs e)
      {
      ...
      }
      }


      bu kod bloğunda [AllowAnonymous] gibi bir ifade kabul görmüyor.

      Sil
  8. Hocam ViewBag 'de hata alıyorum yardımcı olurmusunuz?

    YanıtlaSil
    Yanıtlar
    1. Merhaba, nasıl bir hata alıyorsunuz detay paylaşırsanız yardımcı olayım?

      Sil
  9. Merhaba kolay gelsin, Asp.net mvc ile entegrasyonu yaptım success olduğunda post yakalıyorum. Ama bakiye yetersiz dediğinde ne success sayfasında nede merchant_fail_url sayfasında yakalayamıyorum. Hatayı alıp sql basmak istiyorum.

    Yardımcı olursanız sevinirim.
    Teşekkürler

    YanıtlaSil
    Yanıtlar
    1. Merhaba, iki sayfaya da bir dönüş gerçekleşmiyorsa, paytr panel parametrelerinizi kontrol etmenizi öneririm. Benzer entegrasyonlarda ben bakiye yetersiz şeklinde http request alıyordum. fail url sayfanızda IsPostback gibi bir tanımlama varsa kaldırmalısınız. Hiçbir hatayı mı yakalayamıyorsunuz yoksa sadece bakiye yetersizliği hatasını mı?

      Sil
    2. Paytr bir türlü anlatamadık. Şimdi şöyle özetleyeyim. Ödeme başarılı ise bildiri sayfasına post olur. Yakalıyoruz ve işlemi bitiriyoruz. Ama bakiye yetersiz hatalı bir işlemi fail url hiç uğramıyor. Çözemedim. :(

      Sil
    3. paytr panele girdiğiniz fail url ile request i kontrol ettiğiniz url aynı mı? http / s noktasına dikkat edin. hiç fail alamıyorsanız request yanlış URL ye gidiyordur muhtemelen, birde hata kodunun success url ye düşüp düşmediğini de kontrol edin, birde fail ve success url yi aynı url 'ye set edin o şekilde bir deneme sağlayın derim.

      Sil
    4. Paytr bildirim panelinde tek bildirim url var. if(post.sucsess) else döngüsü de var. Paytr/hata sayfasına hiç gelmiyor. Bildirime de hiç uğramıyor. Paytr panelinde fail ayarları nerede tarif eder mısınız? Birtane bildirim url var.

      Sil
    5. merchant_ok_url ve merchant_fail_url değişkenlerini aynı sayfayı gösterecek şekilde set edip denediniz mi? örnekte dataların post edildiği bir NameValueCollection nesnesi var, bu nesneye ait data["merchant_ok_url"] ve data["merchant_fail_url"] property lerine aynı sayfayı set edin, ayrıca data["debug_on"] property sini de kontrol edin, 1 yapıp deneme sağlayabilirsiniz, olmazsa 0 deneyin

      Sil
    6. Hocam hepsini yaptım hata kodunu başka yere yönlendirdim bildirim yerine yönlendirdim. Birtürlü yakalayamadım.

      Sil
    7. Merhabalar asp net mvc için kod örneği atabilir misiniz rica etsem?

      Sil
  10. Hocam merhaba örneğinizi uyguladım ancak iframe de işlemi alıyor 200 OK olarak ta görünyorum F12 de ancak localhostta göremiyorum. Bir de anlamadığım bir konu daha var yardımcı olursanız çok sevinirim ben iframe de gördükten sonra SiparisSonuc sayfasına yönlenip OK mesajını göndermesi ile ilgili bir kod göremedim biraz kafam karıştı açıkçası

    YanıtlaSil
  11. Merhabalar .net core ile paytr entegrasyonu yapmam gerekiyor. Konu hakkında yardımcı olabilir misiniz ?

    YanıtlaSil
  12. Merhabalar bildirim url kısmında hata alıyorum aşağıdaki koda uğramıyor bile 404 dönüyor ve url i bulamıyor bildirim urli nasıl oluşturmalıyım

    [HttpPost]
    public IActionResult GeriDonusPayTR(string status)
    {
    string merchant_key = "key";
    string merchant_salt = "id";

    string merchant_oid = Request.Form["merchant_oid"];
    string total_amount = Request.Form["total_amount"];
    string hash = Request.Form["hash"];

    string Birlestir = string.Concat(merchant_oid, merchant_salt, status, total_amount);
    HMACSHA256 hmac = new HMACSHA256(Encoding.UTF8.GetBytes(merchant_key));
    byte[] b = hmac.ComputeHash(Encoding.UTF8.GetBytes(Birlestir));
    string token = Convert.ToBase64String(b);

    if (hash.ToString() != token)
    {
    TempData["gelen"] = "PAYTR notification failed: bad hash";
    }

    if (status == "success")
    {
    TempData["gelen"] = "OK";
    }
    else
    {
    TempData["gelen"] = "OK";
    }

    return View();
    }

    YanıtlaSil
    Yanıtlar
    1. sipariş detaylarında siteden bu şekilde hata dönüyor

      HTTP Hata Kodu: 404

      Sil

Yorum Gönder

Bu blogdaki popüler yayınlar

ASP.NET Sayfalar arası veri taşıma işlemleri

merhaba; bu yazımda sizlere asp.net üzerinde sayfalar arasında veri taşıma işlemlerinden bahsetmek istiyorum.hepimizin bildiği gibi uygulamarımızda sayfalarımız arası haberleşmeler büyük önem arzetmektedir.bazı sayfalarda bazı işlemlerin yerine getirilebilmesi için diğer sayfalardan gelecek verilere ihtiyaç duyulabilir(GET).ASP.NET üzerinde veri taşıma işlemleri aşağıdaki şekillerde yapılabilir. 1-)QueryString : en yaygın ve basit kullanıma sahip olanıdır.istenilen verileri sayfayı post ettiğiniz zaman yönlendirildiğiniz sayfaya URL üzerinden taşır. Kullanımı : a sayfasından b sayfasına isim taşıyalım. a sayfasında linkinizi şu şekilde değiştirirseniz: Response.Redirect("gidileceksayfa.aspx?isim=can"); Tarayıcınızın URL kısmına baktığınızda: www.siteadi.com/b.aspx?isim=can olarak görürsünüz.a sayfasından veri aktarımı tamamlanmıştır.bundan sonraki adım b sayfasından gelen veriyi almaktan ibarettir.o da şu şekilde yapılır: b sayfasında "isim" adında b

ASP.NET - Aynı anahtara sahip bir girdi zaten var.

Eğer ASP.NET ile uğraşırken böyle bir hata aldıysanız aşağıdaki paragraf tam size göre; " Aynı anahtara sahip bir girdi zaten var."  hatasının sebebi sayfanızdaki birden çok nesne için  ClientIDMode Özelliğini " Static " olarak ayarlamanızdan kaynaklanmaktadır.Normal şartlarda sayfa içerisindeki her kontrolün ID si birbirinden farklı olmalıdır.bu tanımı düzelttiğinizde sorununda çözüldüğünü göreceksiniz.Burdaki problem şu ki visual studio hatayı farklı satırlarda veriyor.buda özellikle ilk defa böyle bir hata ile karşılaşıyorsanız çözümü inanılmaz zorlaştırıyor.