NAV Navbar
Logo
.NET PHP JAVA

BKM Express Entegrasyonu Genel Bilgiler

Bu adımda BKM Express entegrasyonuna ilişkin genel bilgileri bulabilirsiniz.

Bunun yanı sıra BKM Express API'lerini kullanmak istiyorsanız aşağıdaki linkten de API'lere ilişkin dokümana ulaşabilirsiniz:

https://test-api.bkmexpress.com.tr/docs/tr/bkmExpressApi.html/

Server SDK Nedir?

Kendi server'ınıza entegre edeceğiniz SDK (Software Development Kit)‘dır. İçerisinde kendi server'ınız ile BKM Express Server'ı arasında iletişimi sağlayacak request ve response objeleri bulunur.

Client SDK Nedir?

Ödeme sayfanıza entegre edeceğiniz SDK'dır. Client SDK'yı kullanarak BKM Express uygulamasını başlatabilirsiniz. Son kullanıcılar başlatılan BKM Express uygulaması üzerinden ödeme işlemini tamamlar.

Hangi Yazılım Dillerinde Entegre Olabilirsiniz?

Kullandığınız yazılım diline uygun Server SDK’yi kullanmalısınız.

Şimdilik .Net, Java ve PHP Server SDK’larımız bulunmaktadır.

BKM Express’i Hangi Platformlarda Kullanabilirsiniz?

BKM Express'e Web ve Mobile Web platformlarında entegre olabilirsiniz.

Başlangıç

Entegrasyona başlamadan önce ihtiyacınız olan bilgileri bu adımda oluşturmalısınız.

1 MID Bilginizi Alın

Merchant indicator (MID), BKM'de sizin için açılan hesabın id'sidir.

BKM üzerinden merchant indicator (MID) bilginizi almalısınız.

(!) MID bilginizi bir yere kaydedin, entegrasyon sırasında kullanacaksınız.

2 Private Key ve Public Key Bilgilerinizi Oluşturun

Private Key ve Public Key Nedir / Ne İşe Yarar?

Private Key ve Public Key bilgilerini BKM'ye yaptığınız server to server isteklerin imzalarında kullanacaksınız. Gönderdiğiniz istekleri Private Key'inizle imzalıyorsunuz. BKM'de yer alan Public Key ile imzanızın doğruluğunu kontrol ediyoruz. Böylece isteğin sizden gelip gelmediğini anlıyoruz.

(!) Private Key'inizi 4.1 Taksit İsteğini Karşılayın ve 4.2 Siparişin Uygunluğunu Kontrol Edin (Nonce) adımlarında kullanacaksınız.

Private Key ve Public Key'i Kiminle Paylaşmalıyım?

  1. Private key bilginizi isteklerin imzalanmasında kullanacağınız için BKM dahil herhangi bir yerle paylaşmamalısınız.
  2. Public key bilginiz BKM'de hesabınıza tanımlanmalı. Bu nedenle Public Key'inizi BKM ile paylaşmalısınız.

Private Key ve Public Key'i Nasıl Oluşturabilirim?

Windows için

RSA Key Generator Download linkinden işletim sisteminize uygun RSA Key Generator'ı indirmelisiniz.

RSA Key Generator, PEM dosyasını çalıştırdığınız klasöre oluşturacaktır. PEM dosyası içerisinde private key ve public key bilgilerini görebilirsiniz.

OSX & Linux için

Terminal'i açıp aşağıdaki komutları çalıştırın.

Oluşan privatePKCS8.pem içerisinde Private-Key'iniz bulunmaktadır.

Oluşan public.pem içerisinde Public-Key'iniz bulunmaktadır.

(!) Public Key bilginizi BKM ile paylaşmayı unutmayın. Private Key bilginizi bir yere kaydedin.

Openssl özelliğin açık olduğunu aşağıdaki adımlar ile kontrolünüzü sağlayabilirsiniz;

1- Php info sayfanızda Loaded configuration file kısmında php.ini konumunu bulabilirsiniz.

2- Ya da sorun yaşarsanız info sayfası oluşturmak için aşağıdaki adımları izleyebilirsiniz:

• php root dizininde phpinfopage.php şeklide boş bir dosya oluşturun.

• içerisine <?php phpinfo(); ?> yazıp kaydedin.

• tarayıcınızdan “localhost/ phpinfopage.php” adresine gidin.

• Loaded configuration file satırında php.ini konumunu görebilirsiniz.

3- Openssl'in açık olduğunu belirtmek için Php.ini dosyanız içerisinde aşağıdaki satır olmalıdır.

extension=php_openssl.dll

3 Kullanacağınız Entegrasyon Tipine Karar Verin

Bu konuya karar vermek için desteğe ihtiyacınız varsa isyerientegrasyon@bkm.com.tr adresine ulaşabilirsiniz.

SDK'ların Kurulumunu Yapın

Entegrasyona başlamadan önce Server SDK ve Client SDK'yı uygulamanıza entegre etmelisiniz.

Server SDK’yı Uygulamanıza Entegre Edin

(!) Server SDK'de BKM Express ile konuşabilmeniz için 2 farklı `Environment’ bulunmaktadır.

  1. Preprod: BKM Express'i uygulamanıza entegre etmek için kullanacağınız test ortamı.

  2. Production: BKM Express'i uygulamanıza entegre edip testlerini tamamladıktan sonra, müşterilerinizin sizin ödeme sayfanızdan BKM Express uygulamasını kullanabilecekleri ortam.

(!) Server'larınızda herhangi bir IP kısıtı bulunuyorsa BKM server'larına erişim yetkisi vermelisiniz.

  • Preprod için: 31.145.171.22

  • Production için: 62.244.244.65 & 213.14.215.65

.NET

.NET için Server SDK'yı buradan indirin

  1. Server SDK’yı kendi uygulamanıza entegre etmek için Solution Explorer’da References’a sağ tıklayıp Add Reference’ı seçin.
  2. Açılan pencereden Browse butonuna basın.
  3. Server SDK’nın bulunduğu klasörden dll’i seçin ve OK butonuna basın.

Önemli Not: Server SDK DLL'inin kullanabilmesi için RestSharp ve BouncyCastle referansları tanımlı olmalı. RestSharp BKM server'ı ile iletişime geçmeyi sağlarken, BouncyCastle şifreleme ile ilgili işlemleri yapıyor. Her iki referansı da nuget'tan indirebilirsiniz.

PHP

PHP için Server SDK'yı buradan indirin (PHP VERSION 5.5 USTU)

PHP için Server SDK'yı buradan indirin (PHP VERSION 5.5 ALTI)

Server SDK’yı kendi uygulamanıza entegre etmek için size verilmiş olan PHP SDK'yı projenize eklemelisiniz.

JAVA

Java için Server SDK'yı buradan indirin

Client SDK’yı Uygulamanıza Entegre Edin

Önyüz tarafında Client SDK entegrasyonu için ödeme sayfanıza yapılacak eklemeler aşağıda koyu renkte belirtildiği gibidir.

<html>
<body> …..

<!– BKMExpress butonuna tıklandığında sayfa üzerinde bir iframe açılabilmesi için ödeme sayfasında uygun bir yere aşağıdaki şekilde bir div eklenmelidir –>

<div id=“payment-dropin”></div>
….
….

<!– Butona tıklandığında açılacak BKMExpress iframei ve üzerindeki işlemler için aşağıdaki şekide js library si eklenmelidir.–>
<script src=“https://preprod-js.bkmexpress.com.tr/v1/javascripts/bex.js”></script>

</body>
</html>

Entegrasyon Adımları

Entegrasyon Diyagramı

1. Connection Token İsteği: Server SDK'yı kullanarak BKM Express Server'ına yapacağınız istek ile Connection Token oluşturursunuz.

2. Ticket Token İsteği: Server SDK'yı kullanarak Connection Token ile birlikte BKM Express Server'ına yapacağınız istek ile Ticket Token oluşturursunuz.

3. Ticket Token'ın Client SDK'ya İletilmesi: Oluşturduğunuz Ticket Token'ı Client SDK'ya ileterek BKM Express uygulamasını başlatırsınız.

4. Taksit ve Nonce İstekleri: Kullanıcı ödeme sayfanızda açılan BKM Express uygulamasına giriş yaptıktan sonra, uygulama BKM Express server’ı ile konuşur.

4.1. Taksit İsteği: BKM Express Server’ı kullandığınız entegrasyon tipine (Normal veya Kuştüyü) göre taksit ile pos veya sadece taksit bilgileri için sizin server'ınıza istekte bulunur. Server'larınızda Server SDK’dan faydalanarak gerekli bilgileri BKM Express server’ına dönersiniz.

4.2. Nonce İsteği: BKM Express Server'ı ödeme işlemini tamamlamadan önce güvenlik, stok ve sepet kontrolü amacıyla sizin server'ınızdaki bir endpoint'e istek gönderir. Bu istekteki imzayı doğruladıktan sonra gerekli stok kontrollerinizi ve sepet güvenlik kontrollerinizi yaptıktan sonra ödeme gerçekleştirilsin/gerçekleştirilmesi gibi geri dönüşler yapabilirsiniz.

1. Connection Token'ı Üretin

// Connection Token'ın Alınabilmesi için Gerekli Konfigürasyonun Yapılması

BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = "SİZİN MERCHANT ID'NİZ",
                     privateKey = "SİZİN PRIVATE KEY'İNİZ"
                 };
// Connection Token'ın Alınması

Token connection = bex.GetMerchantService().Login();
<?php
//Verilmiş olan SDK'yı zip formatından çıkartıp projemize ekliyoruz.
//Dikkat edilmesi gereken SDK'nın pathinin doğru verilmiş olması.

require_once "bex2-sdk-php/src/main/Bex/Bex.php";

$config=BexPayment::startBexPayment("ENVIROMENT TÜRÜ","SİZİN MERCHANT ID'NİZ","SİZİN PRIVATE KEY'İNİZ");

<?php
// Connection Token'ın Alınması

$merchantService = new MerchantService($config);

$merchantResponse = $merchantService->login();



// Connection Token'ın Alınabilmesi için Gerekli Konfigürasyonun Yapılması

BexPayment bex = new BexPayment(Environment.PREPROD, "YOUR-MERCHANT-ID", "PRIVATE-KEY");





// Connection Token'ın Alınması


Token connection = bex.merchantService().login();


2. Ticket Token'ı Üretin

// Ticket Token'ı Üretilmesi

Token ticket = bex.GetMerchantService().OneTimeTicket(connection, "ÖDEME TUTARI", "SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL","SIPARISIN UYGUNLUGUNUN KONTROL EDILMESI ICIN URL")
<?php

//TicketToken Üretilmesi
$ticketResponse=$merchantService->oneTimeTicketWithNonce($merchantResponse->getToken(),"ÖDEME TUTARI","SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL","SIPARISIN UYGUNLUGUNUN KONTROL EDILMESI ICIN URL");


//Builder kullarak TicketToken Üretilmesi

$builder = Builder::newPayment("payment");

$builder->amount("1000,56");  // zorunlu (Ödeme Tutarı)

$builder->installmentUrl("https://isyeri.com/installments");  // zorunlu ("SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL")

$builder->nonceUrl("https://isyeri.com/nonce"); // zorunlu ("SIPARISIN UYGUNLUGUNUN KONTROL EDILMESI ICIN URL")

$ticketResponse = $merchantService->oneTimeTicketWithBuilder($merchantResponse->getToken(), $builder);

// Ticket Token'ı Üretilmesi


Token ticket = bex.merchantService().oneTimeTicket(connection, "ÖDEME TUTARI", "SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL","SIPARISIN UYGUNLUGUNUN KONTROL EDILMESI ICIN URL")


Ödeme işlemi başlatabilmek için ise Ticket Token'ı kullanacaksınız. Ticket Token'ı üretirken aşağıdaki bilgileri kullanmalısınız;

BKM Express Server'indan aldiginiz Ticket token'ı Client SDK'da veya Mobil SDK'da işlemi başlatabilmek için kullanacaksınız. Bu nedenle bu objeyi ödeme sayfanıza iletmeniz gerekir.

Ticket token objesi içerisinde “id”, “path” ve “token” parametreleri bulunmaktadır.

2.1 Builder Kullanılarak Ticket Token Üretilmesi (Sipariş Numarası, Kampanya Kodu, TCKN, Email Entegrasyonu Kullanımı Bilgilerinin Gönderilmesi)


<?php

use Bex\merchant\request\Builder;

//Builder kullarak TicketToken Üretilmesi

$builder = Builder::newPayment("payment");

$builder->amount("1000,56");  // zorunlu (Ödeme Tutarı)

$builder->installmentUrl("https://isyeri.com/installments");  // zorunlu ("SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL")

$builder->nonceUrl("https://isyeri.com/nonce"); // zorunlu ("SIPARISIN UYGUNLUGUNUN KONTROL EDILMESI ICIN URL")

$builder->campaignCode("BKM1234"); // opsiyonel (Kampanya Kodu)

$builder->orderId("123456"); // opsiyonel. ( Sipariş Numarası - Her Ticket isteği için farklı bir değer içermeli)

$builder->tckn("10000000146", true); // opsiyonel (number => "TC Kimlik Numarası", check => "BKM Express içerisinde kontrol edilsin mi")

$builder->msisdn("5051234567", true); // opsiyonel ('no' => "cep telefonu numarası", 'check' => "BKM Express içerisinde kontrol edilsin mi")

?>


  request = TicketRequest.Builder.newPayment()
                            .amount("1000,56")
                            .orderId("123456")
                            .campaignCode("my campaign")
                            .installmentUrl("https://isyeri.com/installments")
                            .nonceUrl("https://isyeri.com/nonce")
                            .tckn("10000000146", true)
                            .msisdn("5051234567", true)
                            .build();


Token ticket = bex.merchantService().createOneTimeTicket(connection, tr); (edited)

ticketRequest = new TicketRequest.Builder()
                        .newPayment()
                        .orderId("123456") // sipariş numarası
                        .amount("1000,56") // sipariş toplam tutarı
                        .campaignCode("my campaign") // kampanya kodu
                        .installmentUrl("https://isyeri.com/installment")
                        .nonceUrl("https://isyeri.com/nonce")
                        .tckn("10000000146", true)) // kullanıcının tck kimlik numarası ve BKM Express içerisinde kontrol edilsin mi bilgisi
                        .msisdn("5051234567", true)) // kullanıcının tck kimlik numarası ve BKM Express içerisinde kontrol edilsin mi bilgisi
                        .build();

Token ticket = bex.GetMerchantService().OneTimeTicket(connection, tr);

Tikcet Token'ı üretirken sipariş numarası, kampanya kodu, kullanıcının TC Kimlik Numarası ve email bigilerini gönderebilmek için Ticket Token'ı builder kullanarak üretmelisiniz.

1. Sipariş numarası (orderId): corderId banka tarafına iletilen sipariş numarasıdır. Her Ticket oluşturma isteği için farklı bir orderId değeri göndermelisiniz. OrderId göndermediğiniz durumda sipariş numarası olarak bankaya sistemde üretilen bir değer gönderilir. İşlem sonucunda bu değer size iletilir.

2. Kampanya Numarası (campaignCode): BKM Express ile bir kampanya anlaşmanız bulunması halinde sipariş için oluşturduğunuz kampanya kodunu bu alanda göndermelisiniz.

3. Kullanıcının TC Kimlik Numarası (tckn): Kullanıcının elinizdeki TCKN bilgisini BKM Express'e iletebilir ve TCKN kontrolü yapılmasını isteyebilirsiniz. Kullanımı için bkz. 4.2 Siparişin Uygunluğunu Kontrol Edin (Nonce)

4. Kullanıcının Telefon Numarası (msisdn): Kullanıcının elinizdeki cep telefonu numarası bilgisini BKM Express'e iletebilir ve cep telefonu kontrolü yapılmasını isteyebilirsiniz. Kullanımı için bkz. 4.2 Siparişin Uygunluğunu Kontrol Edin (Nonce)

3. Ticket Token Alın ve Ödeme İşlemini Başlatın

// MVC için Ticket Token'ın Ön Yüze İletilmesi 

ViewBag.Amount = "ODEME TUTARI";
ViewBag.Ticket = ticket.Json();

// Client SDK url'ini kendiniz manuel girebilirsiniz
// ama bu sekilde de yaparsaniz, her ortam degisiklikligi 
// yaptiginizda(Preprod, Production) url'i degistirmenize gerek kalmadan ortam icin dogru url'i verir. 

ViewBag.BkmJsUrl = bex.BaseJsUrl();

// Web Forms için Ticket Token'ın Ön Yüze İletilmesi
// Web Forms için kullanicilarin ödeme yaptigi sayfanin "Checkout" sayfasi oldugunu varsayalim. `Checkout.aspx.cs` dosyasi

... 
public string Ticket { get; set; }
public string Amount { get; set; }
public string BkmJsUrl { get; set; }
protected void Page_Load()
{
    ...

    Amount = "ODEME TUTARI";
    Ticket = ticket.Json();
    BkmJsUrl = bex.BaseJsUrl();
    ...
}
...
// Ticket Token'ın Ön Yüze İletilmesi

modelAndView.addObject("ticket", ticket.json());





// Client SDK url'ini kendiniz manuel girebilirsiniz


// ama bu sekilde de yaparsaniz, her ortam degisiklikligi 


// yaptiginizda(Preprod, Production) url'i degistirmenize gerek kalmadan ortam icin dogru url'i verir. 


modelAndView.addObject("bkmJsUrl", bex.baseJsUrl());





BKM Express ile Öde butonun ödeme sayfanızda görünmesi ve butona tıklandığında sayfa üzerinde iframe açılmasını sağlamanız için Client SDK’yı Uygulamanıza Entegre Edin detayından ulaşabilirsiniz.

3.1 BKM Express Öde Butonunun Kullanımı

// Butonun Kullanımı MVC için

var ticketAsString = '@Html.Raw(ViewBag.ticket)';
var ticket = JSON.parse(ticketAsString);
Bex.init(ticket, "modal", {
    container: "payment-dropin",
    buttonSize: [135, 70],
    skipButton: true,
    onCancel: function(){},
    onComplete: function(status){}

});

// Butonun Kullanımı Web Forms için `Checkout.aspx` dosyasi

var ticket = <%= this.Ticket %>;
Bex.init(ticket, "modal", {
    container: "payment-dropin",
    buttonSize: [135, 70],
    skipButton: true,
    onCancel: function(){},
    onComplete: function(status){}
});

<?php
//Butonu kullanmak için Client SDK'yı oluştururken parametreler arasına skipButton parametresini "true" olarak eklemeniz gerekmektedir. 
?>
<html>
<script type="text/javascript" src = <?php echo "'".$config->getBexApiConfiguration()->getBaseUrl()."'" ;?> ></script>
<script type="text/javascript">
var ticketIdForInit = <?php echo "'".$ticketShortId."'" ;?>;

var ticketPathForInit = <?php echo "'".$ticketPath."'" ;?>;

var ticketTokenForInit = <?php echo "'".$ticketToken."'" ;?>;

Bex.init({"id":ticketIdForInit,"path":ticketPathForInit,"token":ticketTokenForInit}, "modal", {
    container: "payment-dropin",
    buttonSize: [135, 70],
    skipButton: true,
    onCancel: function(){},
    onComplete: function(status){}

});
</script>
</html>

// Butonun Kullanımı 

th:src="${bkmJsUrl}"


 th:inline="javascript"

var ticketAsString = [[${ticket}]];

var ticket = JSON.parse(ticketAsString);

Bex.init(ticket, "modal", {
    container: "payment-dropin",
    buttonSize: [135, 70],
    skipButton: true,
    onCancel: function(){},
    onComplete: function(status){}
});

Ödeme sayfanızda buton gösterimini sağladıktan sonra BKM Express ile öde butonuna tıklandığında ticket token’ı ödeme sayfanıza eklediğiniz “bex.js” javascript dosyasında “Bex.init” metodu ile ödeme işlemini başlatabilirsiniz.

4.0 BKM Express Uygulamasına Sağlanacak Servisler

Bu aşamada BKM Express uygulamasının çağıracağı 2 REST servisi açmanız beklenmektedir. İlki kullanıcının kartına sağlanabilecek taksit seçenekleri dönen servis, ikincisi de sanal posunuzdan işlemin geçmesini sağlayacak servis. İlk servis detayları (installments) 4.1 de, ikinci servis detayları da 4.2 adımlarında anlatılmaktadır.

4.1 BKM Express Uygulamasından Gelecek Taksit İsteğini Karşılayın

Kullanıcı BKM Express uygulamasına giriş yaptıktan sonra, BKM Express server'ı, kullanıcının her bir kartına ilişkin taksit seçeneklerini almak için sizin belirlediğiniz bir endpoint'e request gönderir. Bunun için kendi uygulamanızda bu request'leri karşılayacak bir endpoint oluşturmanız gerekir. Her bir taksit request'i bir bin içindir.

Server'ınıza taksit isteği geldiğinde vereceğiniz yanıtta sanal pos bilgileri olacağından bu bilgilerin gizliliği önem kazanmaktadır. Bu bilgilerin gerekli otoriteler haricinde başkaları tarafından görülmemesi için, request'teki imzayı Server SDK'daki EncryptionUtil.VerifyBexSignature metodu ile doğrulamalısınız.

Not: Tüm kartlara tek taksit yapıyorsanız ve kuş tüyü entegrasyonu kullanıyorsanız, herhangi bir endpoint oluşturmanıza gerek kalmayacaktır. 2. Ticket Token'ı Üretin adımında da “SIZIN SERVER'INIZDA TAKSITLERI SORGULAMAK ICIN BIR URL” alanını göndermemelisiniz. Gelen her ödeme işlemi BKM Express'te tanımlı pos'larınızda tek taksit olarak çekilecektir. Bu durumda bu adımı atlayabilirsiniz.

Endpoint'in Oluşturulması

// .NET'te olusturdugumuz endpoint'lerin url'lerinde kolaylik olsun diye C#'in `attribute`'larini kullanıldı. Dilerseniz başka şekilde de ilerleyebilirsiniz. 


// MVC için Endpoint'in Oluşturulması

// ASP.NET Web Forms'ta endpoint olusturmak icin ASP.NET Web API kullanabilirsiniz. Bunu yapmak aşağdaki 2 adım izlenmeli;
// 1. Projenize sag tiklayip **Add** ve sonra **New Item** dedikten sonra, karsiniza cikan dialog box'tan **Web Api Controller Class**'i secip, bu Controller'in adini verdikten sonra **Add** butonuna tiklayin.
// 2. **Application_Start** fonksiyonuna, bu yaratacaginiz endpoint'in route'unu ekleyin.

...
[HttpPost]
public JsonResult Installments(InstallmentRequest request)

{
    InstallmentsResponse response = new InstallmentsResponse();
    if (!EncryptionUtil.VerifyBexSignature(request.ticketId, request.signature))
    {
        response.error = "signature verification failed";
    }
    else
    {
        ...
    }
}

// Web Forms için Endpoint'in Oluşturulması `Checkout.aspx` dosyasi


...


public class BKMController : ApiController
{
    ...
    [Route("Installments")]
    [HttpPost]
    public InstallmentsResponse Installments(InstallmentRequest request)
    {
        InstallmentsResponse response = new InstallmentsResponse();
        if (!EncryptionUtil.VerifyBexSignature(request.ticketId, request.signature))
        {
            response.error = "signature verification failed";
        }
        else
        {
            ...
        }
    }
}

// `Application_Start` metoduna olusturdugunuz endpoint'lerin route'larini koymak icin `WebApiConfig` adinda bir sinif yaratalim. Icinde de `Register` adli static bir metod belirleyelim.

public class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.MapHttpAttributeRoutes();
    }
}

// `Application_Start` metodunda `register` edelim.

...

protected void Application_Start(object sender, EventArgs e)

{

    GlobalConfiguration.Configure(WebApiConfig.Register);

    ...

}

<?php
use Bex\merchant\request\InstallmentRequest;


//Örnek installment url
//Ticket oluştururken verilen url
const installmentUrl="http://www.sizinsiteniz.com/installmentların-bulunduğu-sayfa.php?installment=checkout";

// Endpoint'in Oluşturulması
if(isset($_REQUEST['installment']) && $_REQUEST['installment'] == 'checkout'){ //Mikroservisden gelen isteğin karşılandığı yer.

     header('Content-type: application/json'); //Dönen response application/json formatında olmalıdır.

     $data = json_decode(file_get_contents('php://input'),TRUE); //Requestten gelen datayı alınışı.
     if(!empty($data)){ //Gelen datanın kontrolü
         //installment Requestinin oluşturulması.
         $installmentRequest = new InstallmentRequest($data['bin'],$data['totalAmount'],$data['ticketId'],$data['signature']);
         //Requestte gelen signature değerinin kontrolu , eğer dışarıdan müdahale edildi ise hata dönülür.
         //Güvenlik kontrolleri EncryptionUtil sınıfında yapılmaktadır.
         if(!EncryptionUtil::verifyBexSign($installmentRequest->getTicketId(),$installmentRequest->getSignature())){
             //Örnek hata responsu
             exit(json_encode(array("data" =>null,'status' => "fail" , 'error' => 'Signature verification failed.')));

         }else{
            ......
         }
     }
}

// Endpoint'in Oluşturulması


...


@RequestMapping(value = "/installments", method = RequestMethod.POST, consumes = "application/json")

@ResponseBody

public InstallmentsResponse installments(InstallmentRequest request)

{

    InstallmentsResponse response = new InstallmentsResponse();
    if (!EncryptionUtil.verifyBexSign(request.getTicketId(), request.getSignature()))

    {
        response.setError("signature verification failed");
    }

    else

    {

        ...

}


4.1.1 Normal Entegrasyon

// MVC Normal Entegrasyon Kod Örneği 

public class InstallmentController : Controller
{
    [HttpPost]
    public JsonResult Index(InstallmentRequest installmentRequest)
    {        
        InstallmentsResponse installmentsResponse = new InstallmentsResponse();
        if (installmentRequest?.binNo == null || installmentRequest.ticketId == null || installmentRequest.totalAmount == null || !EncryptionUtil.VerifyBexSignature(installmentRequest.ticketId, installmentRequest.signature))
        {
            installmentsResponse.error = "RequestBody fields cannot be null or signature verification failed";
            return Json(installmentsResponse);
        }
        return Json(GetInstallmentResponse(installmentRequest, installmentsResponse));
    }
    private InstallmentsResponse GetInstallmentResponse(InstallmentRequest installmentRequest, InstallmentsResponse installmentsResponse)
    {
        Dictionary<string, List<Installment>> installments = GetInstallments(installmentRequest);
        installmentsResponse.installments = installments;
        installmentsResponse.status = "ok";
        installmentsResponse.error = "";
        return installmentsResponse;
    }
    private Dictionary<string, List<Installment>> GetInstallments(InstallmentRequest installmentRequest)
    {
        Dictionary<string, List<Installment>> all = new Dictionary<string, List<Installment>>();
        double totalAmount = MoneyUtils.ToDouble(installmentRequest.totalAmount);
        foreach (BinAndBank binAndBank in installmentRequest.BinAndBanks())
        {
            string bankCode = binAndBank.bankCode;
            int count = Convert.ToInt32(bankCode.Substring(3)) + 2;
            List<Installment> installments = new List<Installment>();
            for (int i = 1; i <= count; i++)
            {
                Installment installment = new Installment
                {
                    numberOfInstallment = Convert.ToString(i),
                    installmentAmount = MoneyUtils.FormatTurkishLira(totalAmount / (ulong)i),
                    totalAmount = MoneyUtils.FormatTurkishLira(totalAmount),
                    vposConfig = prepareVposConfig(bankCode)
                };
                installments.Add(installment);
            }
            all.Add(binAndBank.bin, installments);
        }
        return all;
    }

// Order id’lerini kendileri vermek isteyen merchant’lar vpos configlerinin extra field’ına overrideOrderId alanı ekleyerek order id’lerini kendileri kontrol edebilecekler. 

// Bu field girilmediği takdirde sistem varsayılan ayarlarla çalışmaya devam edecekler. 


    private string prepareVposConfig(string bankCode)
    {
        var bankList = new Banks();
        VposConfig vposConfig = new VposConfig {bankIndicator = bankCode};    
        if (bankList[bankCode].Equals("AKBANK"))
        {
            vposConfig.vposUserId = "akapi";
            vposConfig.vposPassword = "TEST1234";
            vposConfig.AddExtra("ClientId", "100111222");
            vposConfig.AddExtra("storekey", "TEST1234");
            // vposConfig.AddExtra("overrideOrderId", "AkbankMyCustomOrderID123");
            vposConfig.serviceUrl = "http://srvirt01:7200/akbank";
        }
        else if (bankList[bankCode].Equals("TEBBANK"))
        {
            vposConfig.vposUserId = "bkmapi";
            vposConfig.vposPassword = "KUTU8520";
            vposConfig.AddExtra("ClientId", "401562930");
            vposConfig.AddExtra("storekey", "KUTU8520");
            // vposConfig.AddExtra("overrideOrderId", "TEBMyCustomOrderID123");
            vposConfig.serviceUrl = "http://srvirt01:7200/teb";
        }
        else if (...)
        {
            ...
        }
        else { // Default POS
            // Sanal POS’u olmayan bir kart kullanıldığında hangi sanal pos’a yönlenmesi isteniyorsa o banka bilgileri yazılmalıdır.                
        }
        ... // baska bankalar icin vpos hazirlama
        // VPOS bilgilerinizi yollamadan önce şifrelemelisiniz.
        return EncryptionUtil.EncryptWithBex(vposConfig);
    }
}

// Web Forms Normal Entegrasyon Kod Örneği

public class InstallmentController : ApiController
{
    [Route("Installments")]
    [HttpPost]
    public InstallmentsResponse Index(InstallmentRequest installmentRequest)
    {        
        InstallmentsResponse installmentsResponse = new InstallmentsResponse();
        if (installmentRequest?.binNo == null || installmentRequest.ticketId == null || installmentRequest.totalAmount == null || !EncryptionUtil.VerifyBexSignature(installmentRequest.ticketId, installmentRequest.signature))
        {
            installmentsResponse.error = "RequestBody fields cannot be null or signature verification failed";
            return installmentsResponse;
        }
        return GetInstallmentResponse(installmentRequest, installmentsResponse);
    }
    private InstallmentsResponse GetInstallmentResponse(InstallmentRequest installmentRequest, InstallmentsResponse installmentsResponse)
    {
        List<Installment> installments = GetInstallments(installmentRequest);
        installmentsResponse.installments = installments;
        installmentsResponse.status = "ok";
        installmentsResponse.error = "";
        return installmentsResponse;
    }
private Dictionary<string, List<Installment>> GetInstallments(InstallmentRequest installmentRequest)
    {
        Dictionary<string, List<Installment>> all = new Dictionary<string, List<Installment>>();
        double totalAmount = MoneyUtils.ToDouble(installmentRequest.totalAmount);
        foreach (BinAndBank binAndBank in installmentRequest.BinAndBanks())
        {
            string bankCode = binAndBank.bankCode;
            int count = Convert.ToInt32(bankCode.Substring(3)) + 2;
            List<Installment> installments = new List<Installment>();
            for (int i = 1; i <= count; i++)
            {
                Installment installment = new Installment
                {
                    numberOfInstallment = Convert.ToString(i),
                    installmentAmount = MoneyUtils.FormatTurkishLira(totalAmount / (ulong)i),
                    totalAmount = MoneyUtils.FormatTurkishLira(totalAmount),
                    vposConfig = prepareVposConfig(bankCode)
                };
                installments.Add(installment);
            }
            all.Add(binAndBank.bin, installments);
        }
        return all;
    }
    private string prepareVposConfig(string bankCode)
    {
        var bankList = new Banks();
        VposConfig vposConfig = new VposConfig {bankIndicator = bankCode};  
        if (bankList[bankCode].Equals("AKBANK"))
        {
            vposConfig.vposUserId = "akapi";
            vposConfig.vposPassword = "TEST1234";
            vposConfig.AddExtra("ClientId", "100111222");
            vposConfig.AddExtra("storekey", "TEST1234");
            vposConfig.serviceUrl = "http://srvirt01:7200/akbank";
        }
        else if (bankList[bankCode].Equals("TEBBANK"))
        {
            vposConfig.vposUserId = "bkmapi";
            vposConfig.vposPassword = "KUTU8520";
            vposConfig.AddExtra("ClientId", "401562930");
            vposConfig.AddExtra("storekey", "KUTU8520");
            vposConfig.serviceUrl = "http://srvirt01:7200/teb";
        }
        else if (...)
        {
            ...
        }
        ... // baska bankalar icin vpos hazirlama
        // VPOS bilgilerinizi yollamadan önce şifrelemelisiniz.

        return EncryptionUtil.EncryptWithBex(vposConfig);
    }

}
<?php
// Normal Entegrasyon Kod Örneği

if(isset($_REQUEST['installment']) && $_REQUEST['installment'] == 'checkout'){ //Mikroservisden gelen isteğin karşılandığı yer.

     header('Content-type: application/json'); //Dönen response application/json formatında olmalıdır.

     $data = json_decode(file_get_contents('php://input'),TRUE); //Requestten gelen datayı alınışı.
     if(!empty($data)){ //Gelen datanın kontrolü
         //installment Requestinin oluşturulması.
         $installmentRequest = new InstallmentRequest($data['bin'],$data['totalAmount'],$data['ticketId'],$data['signature']);
         //Requestte gelen signature değerinin kontrolu , eğer dışarıdan müdahale edildi ise hata dönülür.
         //Güvenlik kontrolleri EncryptionUtil sınıfında yapılmaktadır.
         if(!EncryptionUtil::verifyBexSign($installmentRequest->getTicketId(),$installmentRequest->getSignature())){
             //Örnek hata responsu
             exit(json_encode(array("data" =>null,'status' => "fail" , 'error' => 'Signature verification failed.')));
         }
         //Taksit array i 
         $installments = array();
         //Requestten gelen bin numarasının 0. elementinde bin and bank değerine atıyoruz.
         $binAndBank = $installmentRequest->getBinNo()[0];
         //banka kodunu explodedArr değişkenine atıyoruz.
         $explodedArr = explode("@",$binAndBank);
         //Taksit sayılarının belirlendiği yer.
         //Burası ÖRNEKTİR. Siz taksit sayılarınızı kendi firmanızın ürün politikasına göre ayarlayabilirsiniz.
         $count = substr($explodedArr[1],3);
         $count = (int) $count +2;

         for ($i = 1 ; $i < $count ; $i++){
             //Taksitlerin tutarları MoneyUtils sınıfında  bulunan formata uygun olmalıdır.
             //Gelen tutarı doğru formata çeviriyoruz.
             $installmentAmount = \Bex\util\MoneyUtils::toFloat($installmentRequest->getTotalAmount()) / floatval($i);
             $installmentAmount = \Bex\util\MoneyUtils::formatTurkishLira($installmentAmount);
             //Herbir taksitin içerisinde o taksite ait vpos bilgileri bulunmaktadır.
             //prepareVposConfig methodu vpos bilgilerini ayarlamaktadır.
             $vposConfig = prepareVposConfig($explodedArr[1]);
             //Taksitlerin oluşturulması
             $installment = new \Bex\merchant\response\Installment($i,$installmentAmount,"",$installmentRequest->getTotalAmount(),$vposConfig);
             //Oluşturulan taksitler uygun response formatına çevirilmesi.
             $output = array('numberOfInstallment' => $installment->getNumberOfInstallment(),'installmentAmount' => $installment->getInstallmentAmount() , 'totalAmount' => $installment->getTotalAmount() ,
                 'vposConfig' => $installment->getVposConfig()
             );
             //array_push methodu ile yukarıda oluşturulan $installmens arrayinin içerisi doldurulmaktadır.
             array_push($installments,$output);
         }

         //Dönülecek genel response tipi aşağıdaki gibi olmalıdır.
         $binAndInstallments = new \Bex\merchant\response\BinAndInstallments();
         $installmentResponse->setInstallments($installments);
         $installmentResponse->setStatus("ok");
         $installmentResponse->setBin($explodedArr[0]);
         $returnArray = array();

         $returnArray[$installmentResponse->getBin()] = $installmentResponse->getInstallments();
         $binAndInstallments->setInstallments($returnArray);

         if(isset($binAndInstallments)){
            //Başarılı dönüş tipi.
             exit(json_encode(array("data" => $binAndInstallments,'status' => "ok" , 'error' => '')));
          }else{
           //Başarısız dönüş tipi.
             exit(json_encode(array("data" => null,'status' => "fail" , 'error' => 'Can not get Installments')));
          }
     }else{
           throw new \Bex\exceptions\BexException("Request body can not get !");
     }
}


function prepareVposConfig($bankCode)
{
    //VPOSLARI DONERKEN VPOS CONFIG OBJESINI OLUSTURARAK DONUYORUZ.
    // Order id’lerini kendileri vermek isteyen merchant’lar vpos configlerinin extra field’ına overrideOrderId alanı ekleyerek order id’lerini kendileri kontrol edebilecekler.
    // Bu field girilmediği takdirde sistem varsayılan ayarlarla çalışmaya devam edecekler.

    $vposConfig = new VposConfig();
    //BANKA KODLARININ KONTROLU
    //BANKS SINIFINDA HEPSI TANIMLIDIR.
    if (Banks::AKBANK == $bankCode) {
        //ORNEK VPOS CONFIG AYARLANMASI.
        $vposConfig->setVposUserId("akapi");
        $vposConfig->setVposPassword("TEST1234");
        $vposConfig->addExtra("ClientId", "100111222");
        $vposConfig->addExtra("storekey", "TEST1234");
        // vposConfig.AddExtra("overrideOrderId", "AkbankMyCustomOrderID123");

        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/akbank");

    } else if(Banks::TEBBANK == $bankCode) {

        $vposConfig->setVposUserId("bkmapi");
        $vposConfig->setVposPassword("KUTU8520");
        $vposConfig->addExtra("ClientId", "401562930");
        $vposConfig->addExtra("storekey", "KUTU8520");
        // vposConfig.AddExtra("overrideOrderId", "TEBABANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/teb");

    } else if(Banks::VAKIFBANK == $bankCode) {

        $vposConfig->setVposUserId("000000000011429");
        $vposConfig->setVposPassword("BKMexpress");
        $vposConfig->addExtra("posno", "vp000263");
        $vposConfig->addExtra("uyeno", "000000000011429");
        $vposConfig->addExtra("islemyeri", "I");
        $vposConfig->addExtra("uyeref", "917250515");
        // vposConfig.AddExtra("overrideOrderId", "VAKIFbankMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/vpos724v3/");

    } else if(Banks::ALBARAKA == $bankCode) {

        $vposConfig->setVposUserId("600218");
        $vposConfig->setVposPassword("123qweASD");
        $vposConfig->addExtra("terminalprovuserid", "PROVAUT");
        $vposConfig->addExtra("terminalmerchantid", "7000679");
        $vposConfig->addExtra("storekey", "12345678");
        $vposConfig->addExtra("terminalid", "30690168");
        // vposConfig.AddExtra("overrideOrderId", "ALBARAKAMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/VPServlet");

    } else if(Banks::BANKASYA == $bankCode) {

        $vposConfig->setVposUserId("");
        $vposConfig->setVposPassword("");
        $vposConfig->addExtra("MerchantId", "006100200140200");
        $vposConfig->addExtra("MerchantPassword", "12345678");
        // vposConfig.AddExtra("overrideOrderId", "BANKASYAMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/iposnet/sposnet.aspx");

    } else if(Banks::DENIZBANK == $bankCode) {

        $vposConfig->setVposUserId("1");
        $vposConfig->setVposPassword("12345");
        $vposConfig->addExtra("ShopCode", "3123");
        $vposConfig->addExtra("UserCode", "InterTestApi");
        $vposConfig->addExtra("storeKey", "gDg1N");
        // vposConfig.AddExtra("overrideOrderId", "DENIZBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/mpi/Default.aspx");

    } else if(Banks::FINANSBANK == $bankCode) {

        $vposConfig->setVposUserId("bkmapi");
        $vposConfig->setVposPassword("TEST1234");
        $vposConfig->addExtra("ClientId", "600000120");
        $vposConfig->addExtra("storekey", "TEST1234");
        // vposConfig.AddExtra("overrideOrderId", "FINANSBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/finans");

    } else if(Banks::GARANTI == $bankCode) {

        $vposConfig->setVposUserId("600218");
        $vposConfig->setVposPassword("123qweASD");
        $vposConfig->addExtra("terminalprovuserid", "PROVAUT");
        $vposConfig->addExtra("terminalmerchantid", "7000679");
        $vposConfig->addExtra("storekey", "12345678");
        $vposConfig->addExtra("terminalid", "30690168");
        // vposConfig.AddExtra("overrideOrderId", "GARANTIMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/VPServlet");

    } else if(Banks::HALKBANK == $bankCode) {

        $vposConfig->setVposUserId("testapi");
        $vposConfig->setVposPassword("TEST1234");
        $vposConfig->addExtra("ClientId", "500020009");
        $vposConfig->addExtra("storekey", "Ab123456");
        // vposConfig.AddExtra("overrideOrderId", "HALKBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/halkbank");

    } else if(Banks::HSBC == $bankCode) {

        $vposConfig->setVposUserId("a");
        $vposConfig->setVposPassword("Test1234");
        $vposConfig->addExtra("ClientId", "0004220");
        // vposConfig.AddExtra("overrideOrderId", "HSBCMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("https://vpostest.advantage.com.tr/servlet/cc5ApiServer");

    } else if(Banks::ING == $bankCode) {

        $vposConfig->setVposUserId("600218");
        $vposConfig->setVposPassword("123qweASD");
        $vposConfig->addExtra("terminalprovuserid", "PROVAUT");
        $vposConfig->addExtra("terminalmerchantid", "7000679");
        $vposConfig->addExtra("storekey", "12345678");
        $vposConfig->addExtra("terminalid", "30690168");
        // vposConfig.AddExtra("overrideOrderId", "INGMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/VPServlet");

    } else if(Banks::ISBANK == $bankCode) {

        $vposConfig->setVposUserId("bkmapi");
        $vposConfig->setVposPassword("KUTU8900");
        $vposConfig->addExtra("ClientId", "700655047520");
        $vposConfig->addExtra("storekey", "TEST123456");
        // vposConfig.AddExtra("overrideOrderId", "ISBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/isbank");

    } else if(Banks::KUVEYTTURK == $bankCode) {

        $vposConfig->setVposUserId("apiuser");
        $vposConfig->setVposPassword("Api123");
        $vposConfig->addExtra("MerchantId", "2");
        $vposConfig->addExtra("CustomerId", "8736633");
        $vposConfig->addExtra("orderId", "852507088");
        // vposConfig.AddExtra("overrideOrderId", "KUVEYTTURKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("https://boatest.kuveytturk.com.tr/boa.virtualpos.services/Home/ThreeDModelGate");

    } else if(Banks::ODEABANK == $bankCode) {

        $vposConfig->setVposUserId("600218");
        $vposConfig->setVposPassword("123qweASD");
        $vposConfig->addExtra("terminalprovuserid", "PROVAUT");
        $vposConfig->addExtra("terminalmerchantid", "7000679");
        $vposConfig->addExtra("storekey", "12345678");
        $vposConfig->addExtra("terminalid", "30690168");
        // vposConfig.AddExtra("overrideOrderId", "ODEABANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/VPServlet");

    } else if(Banks::SEKERBANK == $bankCode) {

        $vposConfig->setVposUserId("600218");
        $vposConfig->setVposPassword("123qweASD");
        $vposConfig->addExtra("terminalprovuserid", "PROVAUT");
        $vposConfig->addExtra("terminalmerchantid", "7000679");
        $vposConfig->addExtra("storekey", "12345678");
        $vposConfig->addExtra("terminalid", "30690168");
        // vposConfig.AddExtra("overrideOrderId", "SEKERBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/VPServlet");

    } else if(Banks::TFKB == $bankCode) {

        $vposConfig->setVposUserId("");
        $vposConfig->setVposPassword("");
        $vposConfig->addExtra("orgNo", "006");
        $vposConfig->addExtra("firmNo", "9470335");
        $vposConfig->addExtra("termNo", "955434");
        $vposConfig->addExtra("merchantKey", "HngvXM22");
        $vposConfig->addExtra("orderId", "674451441");
        // vposConfig.AddExtra("overrideOrderId", "TFKBMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("https://testserver1:15443/BKMExpressServices.asmx");

    } else if(Banks::ZIRAATBANK == $bankCode) {

        $vposConfig->setVposUserId("bkmtest");
        $vposConfig->setVposPassword("TEST1691");
        $vposConfig->addExtra("ClientId", "190001691");
        $vposConfig->addExtra("storekey", "TRPS1691");
        $vposConfig->addExtra("orderId", "9073194");
        // vposConfig.AddExtra("overrideOrderId", "ZIRAATBANKMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/ziraat");

    } else if(Banks::YKB == $bankCode) {

        $vposConfig->setVposUserId("bkm3d1");
        $vposConfig->setVposPassword("12345");
        $vposConfig->addExtra("mid", "6706598320");
        $vposConfig->addExtra("tid", "67245089");
        $vposConfig->addExtra("posnetID", "4280");
        // vposConfig.AddExtra("overrideOrderId", "YKBMyCustomOrderID123");
        $vposConfig->setBankIndicator($bankCode);
        $vposConfig->setServiceUrl("http://srvirt01:7200/PosnetWebService/XML");

    } else { // Default POS
        // Sanal POS’u olmayan bir kart kullanıldığında hangi sanal pos’a yönlenmesi isteniyorsa o banka bilgileri yazılmalıdır.
    }
    //Ayarlanan değerler json_encode edilip EncryptionUtil sınıfı yardımıyla şifrelenmektedir.
    $vps_jsn = array('vposUserId' => $vposConfig->getVposUserId() , 'vposPassword' => $vposConfig->getVposPassword() , 'extra' => $vposConfig->getExtra() , 'bankIndicator' => $vposConfig->getBankIndicator() , 'serviceUrl' => $vposConfig->getServiceUrl());
    return EncryptionUtil::encryptWithBex(json_encode($vps_jsn));

}
// Normal Entegrasyon Kod Örneği

@Controller


public class InstallmentController

{
    @RequestMapping(value = "/installments", method = RequestMethod.POST, consumes = "application/json")

    @ResponseBody

    public InstallmentsResponse installments(@RequestBody InstallmentRequest installmentRequest)

    {        
        InstallmentsResponse installmentsResponse = new InstallmentsResponse();

        if (installmentRequest.getBinNo() == null || installmentRequest.getTicketId() == null || installmentRequest.getTotalAmount() == null || !EncryptionUtil.verifyBexSign(installmentRequest.getTicketId(), installmentRequest.getSignature()))


        {
            installmentsResponse.setError("RequestBody fields cannot be null or signature verification failed");

            return installmentsResponse;
        }

        return getInstallmentResponse(installmentRequest, installmentsResponse);

    }

    private InstallmentsResponse getInstallmentResponse(@RequestBody InstallmentRequest installmentRequest, InstallmentsResponse installmentsResponse) {

        Map<String, List<Installment>> installments = getInstallments(installmentRequest);

        installmentsResponse.setInstallments(installments);

        installmentsResponse.setStatus("ok");

        installmentsResponse.setError("");

        return installmentsResponse;
    }

    private Map<String, List<Installment>> getInstallments(@RequestBody InstallmentRequest installmentRequest) {

        BigDecimal totalAmount = MoneyUtils.toBigDecimal(installmentRequest.getTotalAmount());

        Map<String, List<Installment>> all = new HashMap<>();

        for (BinAndBank binAndBank : installmentRequest.binAndBanks()) {

            String bankCode = binAndBank.bankCode();

            int count = Integer.parseInt(bankCode.substring(3, 4)) + 2;

            List<Installment> installments = new ArrayList<>();

            for (int i = 1; i <= count; i++) {

                Installment installment = new Installment();

                installment.setNumberOfInstallment(String.valueOf(i));

                installment.setInstallmentAmount(MoneyUtils.formatTurkishLira(totalAmount.divide(BigDecimal.valueOf(i), 2, BigDecimal.ROUND_HALF_UP)));

                installment.setTotalAmount(MoneyUtils.formatTurkishLira(totalAmount));

                installment.setVposConfig(prepareVposConfig(bankCode));

                installments.add(installment);

            }


            all.put(binAndBank.bin(), installments);


        }

        return all;
    }

    // Order id’lerini kendileri vermek isteyen merchant’lar vpos configlerinin extra field’ına overrideOrderId alanı ekleyerek order id’lerini kendileri kontrol edebilecekler. 

    // Bu field girilmediği takdirde sistem varsayılan ayarlarla çalışmaya devam edecekler.

    private String prepareVposConfig(String bankCode)

    {

        VposConfig vposConfig = new VposConfig()

        vposConfig.setBankIndicator(bankCode);

        if (Banks.AKBANK.getId().equals(bankCode))

        {

            vposConfig.setVposUserId("akapi");

            vposConfig.setVposPassword("TEST1234");

            vposConfig.addExtra("ClientId", "100111222");

            vposConfig.addExtra("storekey", "TEST1234");

            // vposConfig.AddExtra("overrideOrderId", "AkbankMyCustomOrderID123");

            vposConfig.setServiceUrl("http://srvirt01:7200/akbank");
        }

        else if (Banks.TEBBANK.getId().equals(bankCode))

        {
            vposConfig.setVposUserId("bkmapi");

            vposConfig.setVposPassword("KUTU8520");

            vposConfig.addExtra("ClientId", "401562930");

            vposConfig.addExtra("storekey", "KUTU8520");

            // vposConfig.AddExtra("overrideOrderId", "TEBMyCustomOrderID123");

            vposConfig.setServiceUrl("http://srvirt01:7200/teb");

        }

        else if (...)
        {
            ...
        }
        else { // Default POS
            // Sanal POS’u olmayan bir kart kullanıldığında hangi sanal pos’a yönlenmesi isteniyorsa o banka bilgileri yazılmalıdır.
        }

        ... // baska bankalar icin vpos hazirlama

        return EncryptionUtil.encryptWithBex(vposConfig);


    }

}

Normal entegrasyon tipini seçtiyseniz request'te size gönderilen bin için her taksite ilişkin bankanın sanal pos bilgilerini response'ta yollamalısınız. Preprod ortamları için BKM'de geçerli sanal pos bilgilerine Test bölümünden erişebilirsiniz. Her bir taksit request'i bir bin içindir.

Önemli Not: Normal entegrasyonda taksit cevabında ‘VposConfig’ alanını mutlaka dolu göndermelisiniz.

Sizde sanal POS’u olmayan kartlar için, işlemlerin geçmesini istediğiniz POS bilgilerini Default POS alanına yazınız.

4.1.2 Kuştüyü Entegrasyonu

// Kuştüyü Entegrasyon Kod Örneği:


[HttpPost]
public JsonResult Installments(InstallmentRequest request)
{
    InstallmentsResponse response = new InstallmentsResponse { status = "success" };
    var all = new Dictionary<string, List<Installment>>();
    foreach(var binAndBank in request.BinAndBanks())
    {
        string bankCode = binAndBank.bankCode;
        int count = Convert.ToInt32(bankCode.Substring(3)) + 2;
        var installments = new List<Installment>();

        // ornek olarak taksit sayisini 5 yapalim

        for (var i = 0; i < count; i++)
        {
            Installment installment = new Installment();
            float amount = MoneyUtils.ToFloat(request.totalAmount);

            // her bir taksit icin tutari hesaplamak.

            installment.installmentAmount = MoneyUtils.FormatTurkishLira(amount / 5);

            // tum taksitlerin toplam tutari

            installment.totalAmount = MoneyUtils.FormatTurkishLira(amount);

            // taksit sayisi

            installment.numberOfInstallment = Convert.ToString(5);

            // kustuyu entegrasyonunu kullandigimiz icin 

            // sanal pos bilgisini null gonderebiliriz

            VposConfig vposConfig = null;
            installment.vposConfig = vposConfig;
            installments.Add(installment);
        }
        all.add(binAndBank.bin, all);
    }
    response.installments = all;
    return Json(response);
}

// Web Forms Kuştüyü Entegrasyon Kod Örneği


[Route("Installments")]
[HttpPost]
public InstallmentsResponse Installments(InstallmentRequest request)
{
    InstallmentsResponse response = new InstallmentsResponse { status = "success" };
    var all = new Dictionary<string, List<Installment>>();
    foreach(var binAndBank in request.BinAndBanks())
    {
        string bankCode = binAndBank.bankCode;
        int count = Convert.ToInt32(bankCode.Substring(3)) + 2;
        var installments = new List<Installment>();

        // ornek olarak taksit sayisini 5 yapalim
        for (var i = 0; i < count; i++)
        {
            Installment installment = new Installment();
            float amount = MoneyUtils.ToFloat(request.totalAmount);

            // her bir taksit icin tutari hesaplamak.
            installment.installmentAmount = MoneyUtils.FormatTurkishLira(amount / 5);

            // tum taksitlerin toplam tutari
            installment.totalAmount = MoneyUtils.FormatTurkishLira(amount);

            // taksit sayisi
            installment.numberOfInstallment = Convert.ToString(5);

            // kustuyu entegrasyonunu kullandigimiz icin 
            // sanal pos bilgisini null gonderebiliriz
            VposConfig vposConfig = null;
            installment.vposConfig = vposConfig;

            installments.Add(installment);
        }
        all.add(binAndBank.bin, all);
    }
    response.installments = all;
    return response;
}
<?php
// Kuştüyü Entegrasyon Kod Örneği

if(isset($_REQUEST['installment']) && $_REQUEST['installment'] == 'checkout'){ //Mikroservisden gelen isteğin karşılandığı yer.

     header('Content-type: application/json'); //Dönen response application/json formatında olmalıdır.

     $data = json_decode(file_get_contents('php://input'),TRUE); //Requestten gelen datayı alınışı.
     if(!empty($data)){ //Gelen datanın kontrolü
         //Taksit Requestinin oluşturulması.
         $installmentRequest = new InstallmentRequest($data['bin'],$data['totalAmount'],$data['ticketId'],$data['signature']);
         //Requestte gelen signature değerinin kontrolu , eğer dışarıdan müdahale edildi ise hata dönülür.
         //Güvenlik kontrolleri EncryptionUtil sınıfında yapılmaktadır.
         if(!EncryptionUtil::verifyBexSign($installmentRequest->getTicketId(),$installmentRequest->getSignature())){
             //Örnek hata responsu
             exit(json_encode(array("data" =>null,'status' => "fail" , 'error' => 'Signature verification failed.')));
         }
         //Taksit array i 
         $installments = array();
         //Requestten gelen bin numarasının 0. elementinde bin and bank değerine atıyoruz.
         $binAndBank = $installmentRequest->getBinNo()[0];
         //banka kodunu explodedArr değişkenine atıyoruz.
         $explodedArr = explode("@",$binAndBank);
         //Taksit sayılarının belirlendiği yer.
         //Burası ÖRNEKTİR. Siz taksit sayılarınızı kendi firmanızın ürün politikasına göre ayarlayabilirsiniz.
         $count = substr($explodedArr[1],3);
         $count = (int) $count +2;

         for ($i = 1 ; $i < $count ; $i++){
             //Taksitlerin tutarları MoneyUtils sınıfında  bulunan formata uygun olmalıdır.
             //Gelen tutarı doğru formata çeviriyoruz.
             $installmentAmount = \Bex\util\MoneyUtils::toFloat($installmentRequest->getTotalAmount()) / floatval($i);
             $installmentAmount = \Bex\util\MoneyUtils::formatTurkishLira($installmentAmount);
             //Taksitlerin oluşturulması
             $installment = new \Bex\merchant\response\Installment($i,$installmentAmount,"",$installmentRequest->getTotalAmount(),$vposConfig);
             //Oluşturulan taksitler uygun response formatına çevirilmesi.
             $output = array('numberOfInstallment' => $installment->getNumberOfInstallment(),'installmentAmount' => $installment->getInstallmentAmount() , 'totalAmount' => $installment->getTotalAmount() ,
                 'vposConfig' => null
             );
             //array_push methodu ile yukarıda oluşturulan $installmens arrayinin içerisi doldurulmaktadır.
             array_push($installments,$output);
         }

         //Dönülecek genel response tipi aşağıdaki gibi olmalıdır.
         $binAndInstallments = new \Bex\merchant\response\BinAndInstallments();
         $installmentResponse->setInstallments($installments);
         $installmentResponse->setStatus("ok");
         $installmentResponse->setBin($explodedArr[0]);
         $returnArray = array();

         $returnArray[$installmentResponse->getBin()] = $installmentResponse->getInstallments();
         $binAndInstallments->setInstallments($returnArray);

         if(isset($binAndInstallments)){
            //Başarılı dönüş tipi.
             exit(json_encode(array("data" => $binAndInstallments,'status' => "ok" , 'error' => '')));
          }else{
           //Başarısız dönüş tipi.
             exit(json_encode(array("data" => null,'status' => "fail" , 'error' => 'Can not get Installments')));
          }
     }else{
           throw new \Bex\exceptions\BexException("Request body can not get !");
     }
}

// Kuştüyü Entegrasyon Kod Örneği

@RequestMapping(value = "/installments", method = RequestMethod.POST, consumes = "application/json")

@ResponseBody

public InstallmentsResponse installments(@RequestBody InstallmentRequest request)

{

    InstallmentsResponse response = new InstallmentsResponse();

    response.setStatus("success");

    Map<String, List<Installment>> installmentMap = new HashMap<>();

    for (BinAndBank binAndBank : installmentRequest.binAndBanks()) {

        String bankCode = binAndBank.bankCode();

        int count = Integer.parseInt(bankCode.substring(3, 4)) + 2;

        List<Installment> installments = new ArrayList<>();

        for (int i = 1; i <= count; i++) {

            Installment installment = new Installment();

            installment.setNumberOfInstallment(String.valueOf(i));

            installment.setInstallmentAmount(MoneyUtils.formatTurkishLira(totalAmount.divide(BigDecimal.valueOf(i), 2, BigDecimal.ROUND_HALF_UP)));

            installment.setTotalAmount(MoneyUtils.formatTurkishLira(totalAmount));

            installment.setVposConfig(null);

            installments.add(installment);

        }
        installmentMap.put(binAndBank.bin(), installments);

    }
    response.setInstallments(installmentMap)

    return response;


}


Kuştüyü entegrasyon tipini seçtiyseniz request'te size gönderilen bin'e ilişkin sadece taksit bilgilerini dönmeniz yeterli olacaktır. Sanal pos bilgilerini göndermemelisiniz.

Önemli Not:

4.1.3 Ön otorizasyon (Preauth)

BKM Express üzerinden ön otorizasyonlu işlem gönderebilirsiniz.

Örnek:

“vposConfig” : {

“vposUserId” : “bkmtest”,

“vposPassword” : “TEST1691”,

“extra” : {“ClientId”:“190001691”, “storekey”:“TRPS1691”, “orderId”:“9073194”},

“bankIndicator” : “0010”,

“serviceUrl” : “http://srvirt01:7200/ziraat”,

“preAuth” : true

}

ÖNEMLİ: BKM Express üzerinden gerçekleşmiş ön otorizasyonlu işlemin , ön otorizasyon kapamasını yapabilirsiniz. BKM Ön Otorizasyon Kapama servisin detayına ulaşabilirsiniz.

4.2. Siparişin Uygunluğunu Kontrol Edin (Nonce)

(!) Bu adıma başlamadan önce siparişin uygunluğunun kontrol edebilmesi için hazırladığınız endpoint url'ini ticket token'ı ürettiğinizde göndermiş olduğunuzdan emin olun.

(!) Burada paylaşılan kod örneği sadece signature kontrolünü yapacak şekildedir. Sepet - tutar, stok gibi kontrollerinizi bu kod örneğine göre siz yapmalısınız.

// MVC için Kod Örneği 

[HttpPost]
public JsonResult Nonce(NonceRequest request)
{
    Task.Factory.StartNew(() => {
        var ticketId = request.ticketId;
        var path = request.path;
        var nonce = request.token;
        var orderId = request.orderId;
        var signature = request.signature;
        var response = new MerchantNonceResponse();
        BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = "SİZİN MERCHANT ID'NİZ",
                     privateKey = "SİZİN PRIVATE KEY'İNİZ"
                 };

       var connectionToken = bex.GetMerchantService().Login();

        if (EncryptionUtil.VerifyBexSignature(ticketId, signature))
        {
            response.nonce = nonce;
            response.result = true;
            response.id = path;
            var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
        }
        else
        {
            response.nonce = nonce;
            response.result = false;
            response.id = path;
            response.message = "Signature verification failed";

            // ödemenin sonucunu temsil eder.
            // burada ödemenin sonucu ile ilgili gerekli işlemleri yapabilirsiniz
            // veritabanına kaydetmek gibi vs
            var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
        }
    });
    return Json(new NonceReceivedResponse());
}
// Web Forms için Kod Örneği 

[Route("Nonce")]
[HttpPost]
public NonceReceivedResponse Nonce(NonceRequest request)
{
    Task.Factory.StartNew(() => {
        var ticketId = request.ticketId;
        var path = request.path;
        var nonce = request.token;
        var orderId = request.orderId;
        var signature = request.signature;
        var response = new MerchantNonceResponse();
        BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = "SİZİN MERCHANT ID'NİZ",
                     privateKey = "SİZİN PRIVATE KEY'İNİZ"
                 };

        var connectionToken = bex.GetMerchantService().Login();

        if (EncryptionUtil.VerifyBexSignature(ticketId, signature))
        {
            response.nonce = nonce;
            response.result = true;
            response.id = path;
            var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
        }
        else
        {
            response.nonce = nonce;
            response.result = false;
            response.id = path;
            response.message = "Signature verification failed";

            // ödemenin sonucunu temsil eder.
            // burada ödemenin sonucu ile ilgili gerekli işlemleri yapabilirsiniz
            // veritabanına kaydetmek gibi vs
            var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
        }
    });
    return new NonceReceivedResponse();
}
<?php
//NONCE KOD ORNEGI
// Nonce onaylama fonksiyonu.

require_once "../../src/main/Bex/Bex.php";
//VERILMIS OLAN SDK YI ZIP FORMATINDAN CIKARTIP PROJEMIZE EKLIYORUZ.
//SDKNIN PROJEYE YUKLENMESI
//DIKKAT EDILMESI GEREKEN SDK NIN PATHININ DOGRU VERILMESI.

use Bex\config\BexPayment;
use Bex\exceptions\BexException;
use Bex\exceptions\ConfigurationException;
use Bex\merchant\response\nonce\MerchantNonceResponse;
use Bex\merchant\response\TicketRefresh;
use Bex\merchant\security\EncryptionUtil;
use Bex\merchant\service\MerchantService;

function getValue($array, $key)
{
    if (array_key_exists($key, $array)) {
        return $array[$key];
    }
    return null;
}


class Bex
{
    private $config;
    private $isLoggedIn = false;
    private $merchantService;
    private $merchantLoginResponse;

    private function __construct($environment, $merchantId, $merchantPrivateKey)
    {
        $this->config = Bex::init($environment, $merchantId, $merchantPrivateKey);
    }

    private static function init($environment, $merchantId, $merchantPrivateKey)
    {
        if (!isset($environment)) {
            throw new ConfigurationException("BKM Express Ayar dosyasında environment değeri bulunamadı ! Ipucu: 'environment' değeri 'PREPROD', 'PRODUCTION' ortamlarından birini belirtmelidir !");
        }
        if (!isset($merchantId)) {
            throw new ConfigurationException("BKM Express Ayar dosyasında id değeri bulunamadı ! Ipucu: 'id' değeri BKM Expressden size tahsis edilen tekil belirteçtir.!");
        }
        if (!isset($merchantPrivateKey)) {
            throw new ConfigurationException("BKM Express Ayar dosyasında privateKey değeri bulunamadı ! Ipucu: 'PREPROD', 'PRODUCTION değerlerinden biri olmalıdır !");
        }
        return BexPayment::startBexPayment($environment, $merchantId, $merchantPrivateKey);
    }

    /**
     * @param $environment
     * @param $merchantId
     * @param $merchantPrivateKey
     */
    public static function configure($environment, $merchantId, $merchantPrivateKey)
    {
        return new Bex($environment, $merchantId, $merchantPrivateKey);
    }

    public function refreshTicket($ticketArray)
    {
        $ticketResult = $this->createTicket($ticketArray);
        $ticketRefresh = new TicketRefresh(
            $ticketResult['id'],
            $ticketResult['path'],
            $ticketResult['token']
        );
        return array(
            "id" => $ticketRefresh->getId(),
            "path" => $ticketRefresh->getPath(),
            "token" => $ticketRefresh->getToken()
        );
    }

    private function login()
    {
        if (!$this->isLoggedIn) {
            $this->merchantService = new MerchantService($this->config);
            $this->merchantLoginResponse = $this->merchantService->login();
            $this->isLoggedIn = $this->merchantLoginResponse->getResult();
        }
        if (!$this->isLoggedIn) {
            $message = $this->merchantLoginResponse->getMessage();
            throw new BexException($message);
        }
    }

    public function approve(callable $callback)
    {
        $this->login();
        //NULL CHECK
        $data = $this->takeDataAndRespond();
        if ($data != null) { // Data is ok.
            //ILK RESPONSE U DONDUKDEN SONRA MICRO SERVIS  2. RESPONSU DONECEGIZ.
            //NONCE RESPONSE ORNEGI
            $merchantNonceResponse = new MerchantNonceResponse();
            //MERCHANT SERVICE I AYAGA KALDIRIYORUZ
            //YUKARIDA BEX:STARTPAYMENT TAN GELEN $config DEGISKENI
            // $merchantService = new MerchantService($this$config);

            //SIGNATURE KONTROLUNU YAPIYORUZ.
            //EGER SIGNATURE DOGRU ISE ISTENILEN RESPONSU AYARLIYORUZ.
            //BASARILI RESPONSE ORNEGI
            //SIGNATURE KONTROLUNDE TICKET ID OLARAK NONCE REQUESTTEN GELEN TICKET ID ILE KONTROL ETMEK GEREKMEKTEDIR
            //KONTROL EDILECEK OLAN SIGNATURE DA NONCE DAN GELMEKTEDIR.
            if (EncryptionUtil::verifyBexSign($data["id"], $data["signature"])) {
                //DONULMESI GEREKEN RESPONSE'UN KOD ORNEGI.
                $merchantNonceResponse->setResult($callback($data));
                $merchantNonceResponse->setNonce($data["token"]);
                $merchantNonceResponse->setId($data["path"]);
                //NONCE RESPONSU SETLEDIKDEN SONRA MERCHANT SERVICE DEN SENDNONCERESPONCE SERVISINI CAGIRIYORUZ.
                //PARAMETRELER SIRASIYLA
                //1-)SETLEDIGIMIZ RESPONSE SINIFI
                //2-)MERCHANTLOGINDEN DONEN PATH
                //3-)NONCE REQUESTTEN GELEN PATH
                //4-)MERCHANT LOGINDEN GELEN CONNECTION TOKEN
                //5-)NONCE REQUESTTEN GELEN TOKEN
                return $this->merchantService->sendNonceResponse(
                    $merchantNonceResponse,
                    $this->merchantLoginResponse->getPath(),
                    $data["path"],
                    $this->merchantLoginResponse->getConnectionToken(),
                    $data["token"]
                );
            } else {
                //BASARISIZ RESPONSE ORNEGI
                //BURADA RESULT FALSE OLARAK SETLENIR VE MESSAGE SETLENIR.
                $merchantNonceResponse->setResult(false);
                $merchantNonceResponse->setNonce($data["token"]);
                $merchantNonceResponse->setId($data["path"]);
                $merchantNonceResponse->setMessage("Signature verification failed");
                return $this->merchantService->sendNonceResponse(
                    $merchantNonceResponse,
                    $this->merchantLoginResponse->getPath(),
                    $data["path"],
                    $this->merchantLoginResponse->getConnectionToken(),
                    $data["token"]
                );
            }
        }
    }

    /**
     * respondOK.
     */
    protected function takeDataAndRespond()
    {
        //ISTEKDEN GELEN REQUESTI ALIYORUZ.
        $data = json_decode(file_get_contents('php://input'), TRUE);
        //NULL CHECK
        if ($data != null) {
            //DONULMESI GEREKEN RESPONSE ORNEGI JSON FORMATINDA OLMALIDIR.
            header('Content-type: application/json');
            // NONCE ILK RESPONSE
            //ILK RESPONSE UN FORMATINA DIKKAT EDILMELIDIR.
            ob_start();
            echo json_encode(array(
                "result" => "ok",
                "data" => "ok"
            ));
            $size = ob_get_length();
            // Disable compression (in case content length is compressed).
            header("Content-Encoding: none");
            header($_SERVER["SERVER_PROTOCOL"] . " 202 Accepted");
            header("Status: 202 Accepted");
            header("Content-Length: {$size}");
            header("Connection: close");
            ignore_user_abort(true);
            set_time_limit(0);
            ob_end_flush();
            flush();
            sleep(5);
            // check if fastcgi_finish_request is callable
            if (is_callable('fastcgi_finish_request')) {
                /*
                 * This works in Nginx but the next approach not
                 */
                session_write_close();
                fastcgi_finish_request();
            }
            return $data;
        }
        return null;
    }

    public function getConfig()
    {
        return $this->config;
    }

    public function getBaseJs()
    {
        return $this->config->getBexApiConfiguration()->getBaseJs();
    }

    public function getBaseUrl()
    {
        return $this->config->getBexApiConfiguration()->getBaseUrl();
    }
}

const ENVIRONMENT = \Bex\enums\Environment::PREPROD; // Environments: PREPROD , PRODUCTION
const MERCHANT_ID = "219be6b7-b3ca-4bd1-9886-a16d40b0bfe2";
const PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOLA7InQdCbT8n5Rx8zk8uSCFQ5q4Tyxl0Kr02DoykWxLMBUl1p0YU9hoiocv6Hako5rZssHG0Eb4prh2nmZNpyfhOoOw48Pzg3eB7hKjpXLEPKdK8oemonBcvJ+E9/at4KLg4epyGum1cGdiaYkVF8frG+z53b0ngEq7/CzU8htAgMBAAECgYBNn6OZzf1lKVsy+QX/00R/CzTwGZB/eYABd9bFrwtHbk6WjJ6/fWWuigq8hdjoLG3NSWEIEae30zbwtG5ZACUcNa00Ar9mjsQncZXvLXp9hNb6/TR/mKQvZTjXgoRgn/ltS48GSpqWKbmKVl5JQWgNTb1zHGs2igBb161/ag16tQJBAPzVo2YAVcqXCvuNEWhkqsW1+74GSCrX5QcQwv8qwpt7raumojoFCdeW+xt1Je/bsw01pywkvI3cIO0pdHKwDDcCQQDll7GOPUT/q3Gvmw+kCTnvEH/yYSR2XsPLfEvewxp7SbFI1orLO61A+r5uLDGcfPoxQ7AORzf/OpSfNTD7IGZ7AkAUs5Fbaq+blN5rVlOUjpmE8q+YEX+bMm4oM/EjX2brwCaqJUynH358znnk96SRjRWOAVScwq1FmD6B7KECOvPlAkEA4GaWlXbPFLFGKaP98o9N/5p547YMxGE1L5LqOO0q2euaCp4fBCrs2MD7FYW+a7w/cZ0924bCdYSVNNLxb9IoNwJAJ6PVEsZWT5uGTxqlbTBDFSjHF79OLFWllHsa+2uwf/f6OwNAAMagVbWSdAIlZtaiifDhhXkC4h3ozI1f3xolJg==";

$serverUrl = "http://$_SERVER[HTTP_HOST]";
$bex = Bex::configure(
    ENVIRONMENT,
    MERCHANT_ID,
    PRIVATE_KEY
);

$nonceResult = $bex->approve(function ($data) {
    if ($data["reply"]["totalAmount"] === "1000,5") { // Nonce kontrolü
        return true; // onayla
    }
    return false; // reddet
});

if ($nonceResult->getPaymentPurchased()) { // payment is ok.
    // İşlem tamamlandı. Ödeme yapıldı.
    // Bu durumda kendi sisteminizdeki siparişi güncelleyebilirsiniz.
} else {
    // Ödeme yapılamadı.
}

?>

@RequestMapping(value = "/nonce", method = RequestMethod.POST)

@ResponseBody

public NonceReceivedResponse nonce(@RequestBody NonceRequest request) {

    // işyerinin sağladığı bu servis BKMExpress'in, işyerine yaptığı nonce için hazırız bildirimidir.
    // bu servisin cevabına işyeri tarafından başarılı dönülür.                                                                       
    // DİKKAT !!!!
    // nonce tamamlama işlemi BKMExpress sunucularına yapılacak ayrı bir servis çağrısıdır. (Aşağıdaki asyncTask servisi gibi.)
    // bu servis çağrısını Java 8 öncesinde Thread kullanarak, Java 8 ve sonrasında CompletableFuture sınıfını kullanarak,
    // sağladığınız bu servis içerisinde kullandığınız Java versiyonuna göre aşağıdaki gibi yapabilirsiniz.

    // Java 8 öncesi                     
    new Thread(new Runnable() {
       @Override
       public void run() {

           asyncTask(request);
       }
    }).start();

    // Java 8 ve sonrası      
    CompletableFuture.supplyAsync(() -> {                                                               
        asyncTask(request);
    };                                         


    return new NonceReceivedResponse();
}





public void asyncTask(NonceRequest nonceRequest) {

    // İşlemin hala geçerliliğinin korunup, korumadığı kontrol edilir.


....

    // basarili nonce cevabı

    MerchantNonceResponse response = new MerchantNonceResponse();

    response.setNonce(nonceRequest.getToken());

    response.setId(nonceRequest.getPath());

    response.setResult(true);

    response.setMessage("YOUR-MESSAGE-WILL-BE-STORED-IN-BKM");

    // connection token'i sakladiginizi varsayarak "this.token" verisi kullanildi.
    // eger saklamiyorsaniz yeni connection token alip nonce'i gonderebilirsiniz.

    NonceResultResponse nonceResponse = bex.merchantService().sendNonceResponse(connectionToken, response);

    // nonceResponse ile ödeme sonucu kontrol edilip, işyeri kendi ödeme sonrası aksiyonlarını çağırabilir.


....   


}



public void asyncTask(NonceRequest nonceRequest) {

    // İşlemin hala geçerliliğinin korunup, korumadığı kontrol edilir.

....

    // basarili nonce cevabı

    MerchantNonceResponse response = new MerchantNonceResponse();

    response.setNonce(nonceRequest.getToken());

    response.setId(nonceRequest.getPath());

    response.setResult(false);

    response.setMessage("Out of stock for order id: 12345678910");

    NonceResultResponse nonceResponse = bex.merchantService().sendNonceResponse(connectionToken, response);
....   

}

BKM Express'te kullanıcının OTP gönderip ödemeyi tamamlamaya hazırlandığı aşamada kendi tarafınızda siparişin uygunluğuna dair gerekli kontrolleri yapmalısınız. Sepet tutarı ile ödeme tutarının eşitliği, ürün stoğu yeterliliği gibi.

1. Ödeme Tutarı Kontrolü

Bu kontrolün yapılması Fraud senaryolarını önlemek için zorunludur. Ödemenin son aşamasında bir sepetteki ürünlerin tutarının değiştirilip değiştirilmediğini (farklı bir sekmeden/browser'dan sepetteki ürünlerin değiştirilmesi gibi Fraud denemelerini önlemek için) kontrol etmelisiniz.

2. Stok ve Diğer Kontroller

Stok riski bulunan (bilet, rezarvasyon gibi.) bir iş modeliniz varsa, ödemenin son aşamasında ürünün stoğunun olup olmadığını kontrol etmelisiniz.

3. TC Kimlik Numarası Kontrolü

Ticket Token oluşturulurken kullanıcının TC Kimlik Numarası bilgisini ve TC Kimlik Numarası kontrol edilsin isteğinizi iletmeniz halinde, ilettiğiniz TC Kimlik Numarası kullanıcının BKM Express'teki TC Kimlik numarası ile karşılaştırılacak ve size aynı olup olmadığı bilgisi dönülecektir. Bu kontrolü Fraud tespiti gibi işlemlerde kullanabilirsiniz.

4. Cep Telefonu Kontrolü

Ticket Token oluşturulurken kullanıcının Cep Telefonu numarası bilgisini ve Cep Telefonu numarası kontrol edilsin isteğinizi iletmeniz halinde, ilettiğiniz cep telefonu numarası kullanıcının BKM Express'teki cep telefonu numarası ile karşılaştırılacak ve size aynı olup olmadığı bilgisi dönülecektir. Bu kontrolü Fraud tespiti gibi işlemlerde kullanabilirsiniz.

Bu Kontrolleri Nasıl Uygulayabilirsiniz?

Bu kontrolleri yapmak için izlemeniz gereken adımlar aşağıdaki gibidir:

  1. Öncelikle kendi server'ınızda bir endpoint oluşturmalısınız.
  2. BKM Express Server'ı bu endpoint'inize istekte bulunduğunda, öncelikle isteğin sizin endpoint'inize ulaştığını belirtmek için, Server SDK'in sağladığı NonceReceivedResponse nesnesini yollamalısınız.
  3. Server'ınızdaki endpoint'e gelen istekteki veriler NonceRequest nesnesi ile temsil edilmektedir. Bu nesnenin içindeki signature'ı doğruladıktan sonra bu nesne içerisindeki bilgileri de kullanarak kendi tarafınızdaki kontrolleri yapmaya başlayabilirsiniz.
  4. Kendi kontrollerinizi tamamladıktan sonra (stok kontrolü, sepet tutarı kontrolü gibi), NonceRequest nesnesindeki nonce bilgisini yollamalısınız. Bunu yapmak için Server SDK'deki SendNonceResponse metodunu kullanmalısınız.
  5. SendNonceResponse metodu NonceResultResponse nesnesini döner. Bu nesne içerisinde ödemenin sonucu ile ilgili bilgiler (sipariş numarası, sanal pos cevabı vb.) yer almaktadır.

Böylelikle siparişinize dair gerekli kontrollerinizi yapmış ve ödemeyi tamamlamış olursunuz.

5. Sitenize Geri Dönüşleri Tanımlayın

Client SDK'da, ödeme işleminin iptali ve ödeme işleminin tamamlanması durumunda iki callback method bulunur: onCancel ve onComplete.

onCancel: function(status){/* ödeme tamamlanamadığında yapılacak işlemler için kullanılacak callback */}

});

onComplete: function(status){/* ödeme tamamlandığında yapılacak işlemler için kullanılacak callback */}

});

Örnek Entegrasyon Videoları

Örnek entegrasyon videoları üzerinden de BKM Express ile entegrasyonunuzu gerçekleştirebilirsiniz.

(!) Entegrasyona başlamadan önce Başlangıç'taki adımları tamamlamayı unutmayın.

.NET için Örnek Entegrasyon Videolarına aşağıdan ulaşabilirsiniz.

.NET - 1 Server SDK'yi Uygulamanıza Entegre Edin

.NET - 2 Client SDK'yi Ödeme Sayfanıza Entegre Edin

.NET - 3 Taksitleri Belirleyin

.NET - 4 Kullanıcının Uygulamadan Çıkması ve Ticketı Yenileme

.NET - 5 Ödemenin Uygunluğunu Kontrol Etme

PHP için Örnek Entegrasyon Videolarına aşağıdan ulaşabilirsiniz.

PHP 1 - Ticket Oluşturma

PHP 2 - Arayüz Ayarlamaları

PHP 3 - Taksit Seçenekleri / Kuştüyü

PHP 4 - Normal Entegrasyon

PHP 5 - Ticket Refresh

PHP 6 - Nonce

PHP 7 - Oncomplete

Test Süreci ve Bilgileri

Test yapacağınız kullanıcı bilgileri test sırasında sizinle paylaşılacaktır.

Test OTP Bilgisi

Preprod ortamları için ödeme sayfasında her kart için OTP'yi 123456 şeklinde girebilirsiniz.

Test Kullanıcı Bilgileri

Preprod Ortamı Test Kullanıcı Bilgileri

Tüm kullanıcıların şifreleri 147258'dir.

Kullanıcı Bilgisi Banka
0010@banka.com ZİRAAT BANKASI
0012@banka.com HALK BANKASI
0015@banka.com VAKIFBANK
0032@banka.com TEB
0046@banka.com AKBANK
0062@banka.com GARANTİ
0064@banka.com İŞBANK
0067@banka.com YAPI KREDİ
0111@banka.com FİNANS
0134@banka.com DENİZ
qnbfinans@bkm.com FİNANS YENİ
isyeri@bkm.com KARMA SET

Test Sanal Pos Bilgileri

Banka Bank ID vposUserId vposPassword extra serviceUrl
AKBANK 0046 akapi TEST1234 {“ClientId” : “100111222”,
“storekey”: “TEST1234”}
http://srvirt01:7200/akbank
ZIRAATBANK 0010 bkmtest TEST1691 {“ClientId”:“190001691”,
“storekey”:“TRPS1691”,
“orderId”:“9073194”}
http://srvirt01:7200/ziraat
HALKBANK 0012 testapi TEST1234 {“ClientId”:“500020009”,
“storekey”:“Ab123456”}
http://srvirt01:7200/halkbank
VAKIFBANK 0015 000000000011429 123456 {“posno”:“vp000263”} https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx
TEBBANK 0032 bkmapi KUTU8520 {“ClientId”:“401562930”,
“storekey”:“KUTU8520”}
http://srvirt01:7200/teb
GARANTI 0062 600218 123qweASD {“terminalprovuserid”:“PROVAUT”,
“terminalmerchantid”:“7000679”,
“storekey”:“12345678”,
“terminalid”:“30690168”}
http://srvirt01:7200/VPServlet
ISBANK 0064 bkmapi KUTU8900 {“ClientId”:“700655047520”,
“storekey”:“TEST123456”}
http://srvirt01:7200/isbank
YKB 0067 bkm3d1 12345 {“mid”:“6706598320”,
“tid”: “67245089”,
“posnetID”: “4280”}
 3D orderId 24 karakter olmalı, 3D sizde 20 karakter
http://srvirt01:7200/PosnetWebService/XML
FINANSBANK 0111 bkmapi TEST1234 {“ClientId”:“600000120”,
“storekey”:“TEST1234”}
http://srvirt01:7200/finans
QNBFINANSBANK yeni 0111 QNB_API_KULLANICI_3DPAY UcBN0 {“MbrId”:“5”,“MerchantId”:“085300000009704”} https://vpostest.qnbfinansbank.com/Gateway/Default.aspx
DENIZBANK 0134 1 12345 {“ShopCode”:“3123”,
“UserCode”:“InterTestApi”,
“UserPass”:“3”,
“storeKey”:“gDg1N”}
http://srvirt01:7200/mpi/Default.aspx

Not: ING, HSBC, Odea, Albaraka, Kuveyt Türk, TFKB ve Şekerbank'ın bilgileri için lütfen iletişime geçiniz.

Sanal Pos Özel Alan Gönderimi

SubMerchant Kullanımı:

PF(Payment Facilitator) olan ödeme aracı kuruluşları SubMerchant bilgisini sanal pos bazında gönderebilir.

Installment aşamasında vposconfig içerisinde sanal pos bilgisini gönderirken extra alanında SubMerchant'ı iletebilirsiniz.

Vakıfbank:

Vakıfbank posu için Ana bayi veya Alt bayi durumuna göre aşağıdaki gibi gönderim sağlayabilirsiniz.

“subMerchantType”:“1” -> ANA BAYİ

“subMerchantType”:“2”,“subMerchantId”:“000100000014728” -> ALT BAYİ

// Anabayi Kullanımı

"vposConfig": {
     "vposUserId": "000100000014678",
     "vposPassword": "y3HKw41E",
     "extra": {
     "posno":"VP000660","subMerchantType":"1"},
     "bankIndicator": "0015",
     "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
              }


// Altbayi Kullanımı

"vposConfig": {
    "vposUserId": "000100000014678",
    "vposPassword": "y3HKw41E",
    "extra": {
    "posno":"VP000664","subMerchantType":"2","subMerchantId":"000100000014728"},
    "bankIndicator": "0015",
    "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
             }


// Anabayi Kullanımı

"vposConfig": {
     "vposUserId": "000100000014678",
     "vposPassword": "y3HKw41E",
     "extra": {
     "posno":"VP000660","subMerchantType":"1"},
     "bankIndicator": "0015",
     "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
              }


// Altbayi Kullanımı

"vposConfig": {
    "vposUserId": "000100000014678",
    "vposPassword": "y3HKw41E",
    "extra": {
    "posno":"VP000664","subMerchantType":"2","subMerchantId":"000100000014728"},
    "bankIndicator": "0015",
    "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
             }


// Anabayi Kullanımı

"vposConfig": {
     "vposUserId": "000100000014678",
     "vposPassword": "y3HKw41E",
     "extra": {
     "posno":"VP000660","subMerchantType":"1"},
     "bankIndicator": "0015",
     "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
              }



// Altbayi Kullanımı

"vposConfig": {
    "vposUserId": "000100000014678",
    "vposPassword": "y3HKw41E",
    "extra": {
    "posno":"VP000664","subMerchantType":"2","subMerchantId":"000100000014728"},
    "bankIndicator": "0015",
    "serviceUrl": "https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx"
             }



Canlı Ortama Geçiş

Geliştirmelerinizden sonra Test bölümünde verilen detaylarda uygulamayı test etmelisiniz.

Testlerinizi tamamladıktan sonra isyerientegrasyon@bkm.com.tr adresine bilgi vermelisiniz.

  1. Canlı ortama geçişte Client SDK url'ini sağdaki url ile değiştirmelisiniz. <script src=“https://js.bkmexpress.com.tr/v1/javascripts/bex.js”></script>
  2. Server SDK'nızı canlı ortam moduna almalısınız. Bkz. SDK Kurulumlarını Yapın
  3. Normal entegrasyon modelini kullanıyorsanız installment urlde vposconfig içerisinde gerçek sanal pos bilgilerinizi güncellemelisiniz,kuştüyü modelini kullanıyor iseniz BKM ye gerçek sanal pos bilgilerinizi ileterek tanımlatmanız gerekir.

Not: Preprod ortamındayken kullandığınız merchant id, private key ve public key bilgilerini Canlı ortamda kullanabilirsiniz.

Production ortamı Sanal Pos url Adresleri:

Banka Adı Sanal Pos URL
Garanti BBVA https://sanalposprov.garanti.com.tr/VPServlet
QNB Finansbank https://www.fbwebpos.com/servlet/cc5ApiServer
QNB Finansbank https://www.fbwebpos.com/fim/api
QNB Finansbank Yeni https://vpos.qnbfinansbank.com/Gateway/Default.aspx
Akbank https://www.sanalakpos.com/servlet/cc5ApiServer
Akbank https://www.sanalakpos.com/fim/api
İşbankası https://sanalpos.isbank.com.tr/fim/api
İşbankası https://spos.isbank.com.tr/servlet/cc5ApiServer
İşbankası https://spos.isbank.com.tr/fim/api
İşbankası https://sanalpos.isbank.com.tr/servlet/cc5ApiServer
İşbankası Innova https://trx.vpos.isbank.com.tr/TransactionServices.asmx
ING https://sanalpos.ing.com.tr/fim/api
YKB https://posnet.yapikredi.com.tr/PosnetWebService/XML
Vakıfbank https://onlineodeme.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx
Halkbank https://sanalpos.halkbank.com.tr/fim/api
Halkbank https://sanalpos.halkbank.com.tr/servlet/cc5ApiServer
Teb https://sanalpos.teb.com.tr/fim/api
Teb https://sanalpos.teb.com.tr/servlet/cc5ApiServer
Odeabank https://vpos.odeabank.com.tr/MPI/Default.aspx
Kuveyttürk https://boa.kuveytturk.com.tr/sanalposservice/Home/ThreeDModelGate
Denizbank https://spos.denizbank.com/mpi/default.aspx
Denizbank https://inter-vpos.com.tr/MPI/Default.aspx
HSBC https://www.fbwebpos.com/servlet/cc5ApiServer
Ziraat https://sanalpos2.ziraatbank.com.tr/fim/api
Ziraat Innova https://sanalpos.ziraatbank.com.tr/v4/TransactionServices.asmx
Türkiye Finans Katılım Bankası https://sanalpos.turkiyefinans.com.tr/fim/api
Türkiye Finans Katılım Bankası https://sanalpos.turkiyefinans.com.tr/fim/est3Dgate

Ek 1 Tutar Formatları

// Ödemeyi başlatmak için Ticket Token alırken belirtmeniz gereken tutar bu formatta olmalıdır.

Token ticket = bex.GetMerchantService.OneTimeTicket(connection, "1000,52", "taksitleri almak için server'ınızdaki endpoint");
// MoneyUtils sınıfı kullanılarak aynı örneğin gerçekleştirilmesi 

var amount = MoneyUtils.FormatTurkishLira(1000.52); // tutar "1000,52"'ye çevrildi
Token ticket = bex.GetMerchantService.OneTimeTicket(connection, amount, "taksitleri almak için server'ınızdaki endpoint");

<?php
// Ödemeyi başlatmak için Ticket Token alırken belirtmeniz gereken tutar bu formatta olmalıdır.

$ticketResponse = $merchantService->oneTimeTicket("Merchant Login Response Token", "1000,52", "Taksit Url i");

<?php
// MoneyUtils sınıfı kullanılarak aynı örneğin gerçekleştirilmesi 

$amount = MoneyUtils::formatTurkishLira(1000.52); // tutar "1000,52"'ye çevrildi

$ticketResponse = $merchantService->oneTimeTicket("Merchant Login Response Token", $amount, "Taksit Url i");

// Ödemeyi başlatmak için Ticket Token alırken belirtmeniz gereken tutar bu formatta olmalıdır.


Token ticket = bex.merchantService.oneTimeTicket(connection, "1000,52", "taksitleri almak için server'ınızdaki endpoint");


// MoneyUtils sınıfı kullanılarak aynı örneğin gerçekleştirilmesi 


var amount = MoneyUtils.formatTurkishLira(1000.52); // tutar "1000,52"'ye çevrildi


Token ticket = bex.merchantService.oneTimeTicket(connection, amount, "taksitleri almak için server'ınızdaki endpoint");


Tutar gönderimlerinin formatında aşağıdaki kurallara dikkate edilmelidir.

Örnek:

Bunun için Server SDK'da MoneyUtils sınıfı bulunmaktadır.

Ek 2 Örnek Kodun Tam Hali

Client SDK

// MVC için 

...


        var ticketAsString = '@Html.Raw(ViewBag.ticket)';
        var ticket = JSON.parse(ticketAsString);
        Bex.init(ticket, "modal", {
            container: "payment-dropin",
            buttonSize: [135, 70],
            onCancel: function(){
                $.ajax({
                    type : "GET",
                    url: "/ReInitTicket",
                    timeout : 100000,
                    success: function (data) {
                        ticket = JSON.parse(data);
                        Bex.refresh(ticket);
                    },
                    error: function(result) { console.log("errorr ", result)}
                });
                console.info("User canceled the payment");
            },
            onComplete: function(status){
              // ödeme tamamlandığında aldığınız aksiyon
            }
        });


...
// Web Forms için 
...
       var ticket = <%= this.Ticket %>;
        Bex.init(ticket, "modal", {
            container: "payment-dropin",
            buttonSize: [135, 70],
            onCancel: function(){
                $.ajax({
                    type : "GET",
                    url: "/ReInitTicket",
                    timeout : 100000,
                    success: function (data) {
                        ticket = JSON.parse(data);
                        Bex.refresh(ticket);
                    },
                    error: function(result) { console.log("errorr ", result)}
                });
                console.info("User canceled the payment");
            },
            onComplete: function(status){

               // ödeme tamamlandığında aldığınız aksiyon
            }
        });

...
<?php
// Örnek kodun tam halini sdk projesi içerisinde bulunan sample klasorünün içerisinde bulabilirsiniz.

...

  th:if="${success}">


{

   th:src="${bkmJsUrl}"


        var ticketAsString = [[${ticket}]];
        var ticket = JSON.parse(ticketAsString);

        Bex.init(ticket, "modal", {

            container: "payment-dropin",
            buttonSize: [135, 70],

            onCancel: function(){

                $.ajax({

                    type : "GET",
                    url: "/reInitTicket",
                    timeout : 100000,
                    success: function (data) {

                        ticket = JSON.parse(data);

                        Bex.refresh(ticket[0]);

                    },

                    error: function(result) { console.log("errorr ", result)}

                });

                console.info("User canceled the payment");

            },

            onComplete: function(status){

                // ödeme tamamlandığında aldığınız aksiyon

            }

        });


} else {

        "An error occurred"

}

...


Server SDK

<?php
// Örnek kodun tam halini sdk projesi içerisinde bulunan sample klasorünün içerisinde bulabilirsiniz.
// Örnek kod içerisinde Environment PREPROD ortamı olarak ayarlanmıştır.PRODUCTION ortamında çalışmak için  sample->src->main klasörü içerisinde bulunan SampleSetup.php sınıfında environment='PRODUCTION' yapmalısınız.
// Ayrıca index.php ve custom.php sınıflarında bulunan scriptlerin url'i  https://preprod-js.bkmexpress.com.tr/v1/javascripts/bex.js olmalıdır.

//MVC için

namespace BexCSharpSample.Controllers
{
    public class CheckoutController : Controller
    {
        private static string InstallmentUrl = "https://my-merchant.com/net/installment";
        private static string NonceUrl = "https://my-merchant.com/net/checkout/nonce";
        private static Dictionary<string, NonceResultResponse> orders = new Dictionary<string, NonceResultResponse>();
        private BexCsharpSDK.Environment environment = BexCsharpSDK.Environment.PREPROD;

        public ActionResult Index()
        {
            BexPayment bex = new BexPayment(environment, ConfigurationManager.AppSettings["MerchantId"], ConfigurationManager.AppSettings["MerchantPrivateKey"]);

            Token connection = bex.GetMerchantService().Login();

            float amount = 1000.56f;
            Token ticket = bex.GetMerchantService().OneTimeTicket(connection, MoneyUtils.FormatTurkishLira(amount), InstallmentUrl, NonceUrl);

            ViewBag.Success = true;
            ViewBag.Amount = "1000 TL";
            ViewBag.BkmJsUrl = bex.BaseJsUrl();
            ViewBag.Ticket = ticket.Json();
            return View();

        }

        public ActionResult CheckoutSkipButton()
        {
            Configuration config = new Configuration(environment, ConfigurationManager.AppSettings["MerchantId"],
                ConfigurationManager.AppSettings["MerchantPrivateKey"]);

            BexPayment bex = new BexPayment(config);

            Token connection = bex.GetMerchantService().Login();
            var request = new TicketRequest.Builder().newPayment().amount("1000").installmentUrl(InstallmentUrl).build();

            Token ticket = bex.GetMerchantService().OneTimeTicket(connection, request);

            ViewBag.Success = true;
            ViewBag.Amount = "1000 TL";
            ViewBag.BkmJsUrl = bex.BaseJsUrl();
            ViewBag.Ticket = ticket.Json();
            return View();
        }

        [HttpPost]
        public String Result(string ticketId)
        {
            Configuration config = new Configuration(environment, ConfigurationManager.AppSettings["MerchantId"],
                ConfigurationManager.AppSettings["MerchantPrivateKey"]);

            BexPayment bex = new BexPayment(config);

            Token connection = bex.GetMerchantService().Login();

            var result = orders[ticketId];

            var pageResult = new PageResult();
            pageResult.Status = result.paymentPurchased;

            return JsonConvert.SerializeObject(pageResult);
        }

        [HttpGet]
        public ActionResult Success()
        {
            return View();
        }

        [HttpGet]
        public ActionResult Fail()
        {
            return View();
        }

        [HttpGet]
        public string ReInitTicket()
        {
            Configuration config = new Configuration(environment, ConfigurationManager.AppSettings["MerchantId"],
                ConfigurationManager.AppSettings["MerchantPrivateKey"]);

            BexPayment bex = new BexPayment(config);
            Token connection = bex.GetMerchantService().Login();
            Token ticket = bex.GetMerchantService().OneTimeTicket(connection, "1000", InstallmentUrl);
            return JsonConvert.SerializeObject(ticket.Json());
        }

        public ActionResult MerchantLoginFail()
        {
            Configuration config = new Configuration(environment, "1005", null);

            BexPayment bex = new BexPayment(config);
            try
            {
                bex.GetMerchantService().Login();
            } catch (BexException e)
            {
                ViewBag.errorMessage = e.Message;
            }
            ViewBag.success = false;
            return View();

        }

        [HttpPost]
        public string Nonce(NonceRequest request)
        {

            var ticketId = request.ticketId;

            Task.Factory.StartNew(() =>
            {
                var path = request.path;
                var nonce = request.token;
                var orderId = request.orderId;
                var signature = request.signature;

                var response = new MerchantNonceResponse();

                Configuration config = new Configuration(environment, ConfigurationManager.AppSettings["MerchantId"],
                ConfigurationManager.AppSettings["MerchantPrivateKey"]);

                BexPayment bex = new BexPayment(config);

                var token = bex.GetMerchantService().Login();

                if (EncryptionUtil.VerifyBexSignature(ticketId, signature) && IsOrderSafe(request))
                {
                    response.nonce = nonce;
                    response.result = true;
                    response.id = path;
                    var nonceResult = bex.GetMerchantService().SendNonceResponse(token, response);
                    orders.Add(request.ticketId, nonceResult);
                }
                else
                {
                    response.nonce = nonce;
                    response.result = false;
                    response.id = path;
                    response.message = "Signature verification failed";
                    var nonceResult = bex.GetMerchantService().SendNonceResponse(token, response);
                }
            });

            return JsonConvert.SerializeObject(new NonceReceivedResponse());
        }

        private bool IsOrderSafe(NonceRequest request)
        {
            // check if order is safe
            return true;
        }
    }

    class PageResult
    {
        public bool Status { get; set; }
    }
}
// Web Forms için 

namespace BexCSharpSample.Controllers
{
    public class CheckoutController : ApiController
    {
        [Route("RedirectToSuccessPage")]
        [HttpPost]
        public PaymentResultResponse Result([FromBody]string ticketPath)
        {
            Configuration config = new Configuration(environment, ConfigurationManager.AppSettings["MerchantId"],
            ConfigurationManager.AppSettings["MerchantPrivateKey"]);

            BexPayment bex = new BexPayment(config);

            Token connection = bex.GetMerchantService().Login();

            var result = orders[ticketId];

            var pageResult = new PageResult();
            pageResult.Status = result.paymentPurchased;

            return JsonConvert.SerializeObject(pageResult);
        }
        [Route("ReInitTicket")]
        [HttpGet]
        public string ReInitTicket()
        {
            BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = ConfigurationManager.AppSettings["MerchantId"]),
                     privateKey = ConfigurationManager.AppSettings["MerchantPrivateKey"])
                 };
            Token connection = bex.GetMerchantService().Login();
            Token ticket = bex.GetMerchantService().OneTimeTicket(connection, "1000,52", InstallmentUrl);
            return ticket.Json();
        }
        /*
        kustuyu entegrasyonu icin taksit sorgulama endpoint'i.
        normal entegrasyon icin yukarda verilen InstallmentController ornegine bakin
        */
        [Route("Installments")]
        [HttpPost]
        public InstallmentsResponse Installments(InstallmentRequest request)
        {
            InstallmentsResponse response = new InstallmentsResponse { status = "success" };
            var all = new Dictionary<string, List<Installment>>();
            foreach(var binAndBank in request.BinAndBanks())
            {
                string bankCode = binAndBank.bankCode;
                int count = Convert.ToInt32(bankCode.Substring(3)) + 2;
                var installments = new List<Installment>();
                // ornek olarak taksit sayisini 5 yapalim
                for (var i = 0; i < count; i++)
                {
                    Installment installment = new Installment();
                    float amount = MoneyUtils.ToFloat(request.totalAmount);
                    // her bir taksit icin tutari hesaplamak.
                    installment.installmentAmount = MoneyUtils.FormatTurkishLira(amount / 5);
                    // tum taksitlerin toplam tutari
                    installment.totalAmount = MoneyUtils.FormatTurkishLira(amount);
                    // taksit sayisi
                    installment.numberOfInstallment = Convert.ToString(5);
                    // kustuyu entegrasyonunu kullandigimiz icin 
                    // sanal pos bilgisini null gonderebiliriz
                    VposConfig vposConfig = null;
                    installment.vposConfig = vposConfig;
                    installments.Add(installment);
                }
                all.add(binAndBank.bin, all);
            }
            response.installments = all;
            return response;
        }
        [Route("Nonce")]
        [HttpPost]
        public NonceReceivedResponse Nonce(NonceRequest request)
        {
            Task.Factory.StartNew(() => {
                var ticketId = request.ticketId;
                var path = request.path;
                var nonce = request.token;
                var orderId = request.orderId;
                var signature = request.signature;
                var response = new MerchantNonceResponse();

                BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = "SİZİN MERCHANT ID'NİZ",
                     privateKey = "SİZİN PRIVATE KEY'İNİZ"
                 };

                var connectionToken = bex.GetMerchantService().Login();

                if (EncryptionUtil.VerifyBexSignature(ticketId, signature))
                {
                    response.nonce = nonce;
                    response.result = true;
                    response.id = path;
                    var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
                }
                else
                {
                    response.nonce = nonce;
                    response.result = false;
                    response.id = path;
                    response.message = "Signature verification failed";
                    // ödemenin sonucunu temsil eder.
                    // burada ödemenin sonucu ile ilgili gerekli işlemleri yapabilirsiniz
                    // veritabanına kaydetmek gibi vs
                    var nonceResult = bex.GetMerchantService().SendNonceResponse(connectionToken, response);
                }
            });
            return new NonceReceivedResponse();
        }
    }
}
@Controller
public class CheckoutController
{
    // bu ornekte endpoint olarak bu koddaki 
    // Installments metodunu kullanacagiz
    // url olarak vermeniz gerekir.
    // ornegin: "https://sizin-serveriniz.com/Checkout/Installments"
    private static String INSTALLMENT_URL = "taksitleri sorgulamak için server'ınızdaki bir endpoint";
    @RequestMapping("/checkout")
    public ModelAndView index(){
        BexPayment bex = new BexPayment(env, bkmConfiguration.merchantId(), bkmConfiguration.merchantPrivateKey());
        Token connection = bex.merchantService().login();
        Token ticket = bex.merchantService().oneTimeTicket(connection, "1000,52", INSTALLMENT_URL);
        ModelAndView modelAndView = new ModelAndView("checkout/index");
        modelAndView.addObject("amount", "1000,52 TL");
        modelAndView.addObject("ticketJson", ticket.json());
        modelAndView.addObject("success", true);
        modelAndView.addObject("bkmJsUrl", bex.baseJsUrl());
        return modelAndView;
    }
    @RequestMapping("/checkoutSkipButton")
    public ModelAndView checkoutSkipButton(){
        BexPayment bex = new BexPayment(env, bkmConfiguration.merchantId(), bkmConfiguration.merchantPrivateKey());
        Token connection = bex.merchantService().login();
        Token ticket = bex.merchantService().oneTimeTicket(connection, "1000,52", INSTALLMENT_URL);
        ModelAndView modelAndView = new ModelAndView("checkout/checkoutSkipButton");
        modelAndView.addObject("amount", "1000,55 TL");
        modelAndView.addObject("ticketJson", ticket.json());
        modelAndView.addObject("success", true);
        modelAndView.addObject("bkmJsUrl", bex.baseJsUrl());
        return modelAndView;
    }
    @RequestMapping("/result")
    @ResponseBody
    public PaymentResultResponse result(@RequestParam String ticketPath){
        BexPayment bex = new BexPayment(env, bkmConfiguration.merchantId(), bkmConfiguration.merchantPrivateKey());
        Token connection = bex.merchantService().login();
        return bex.merchantService().result(connection, ticketPath);
    }
    @RequestMapping("/reInitTicket")
    @ResponseBody
    public String reInitTicket(){
        BexPayment bex = new BexPayment(env, bkmConfiguration.merchantId(), bkmConfiguration.merchantPrivateKey());
        Token connection = bex.merchantService().login();
        Token ticket = bex.merchantService().oneTimeTicket(connection, "1000,52", INSTALLMENT_URL);
        return ticket.array();
    }
    /*
    kustuyu entegrasyonu icin taksit sorgulama endpoint'i.
    normal entegrasyon icin yukarda verilen InstallmentController ornegine bakin
    */
    @RequestMapping(value = "/installments", method = RequestMethod.POST, consumes="application/json")
    @ResponseBody
    public InstallmentsResponse installments(@RequestBody InstallmentRequest request)
    {
        InstallmentsResponse response = new InstallmentsResponse();
        response.setStatus("success");
        BigDecimal totalAmount = MoneyUtils.toBigDecimal(installmentRequest.getTotalAmount());
        Map<String, List<Installment>> all = new HashMap<>();
        for (BinAndBank binAndBank : installmentRequest.binAndBanks()) {
            String bankCode = binAndBank.bankCode();
            int count = Integer.parseInt(bankCode.substring(3, 4)) + 2;
            List<Installment> installments = new ArrayList<>();
            for (int i = 1; i <= count; i++) {
                Installment installment = new Installment();
                installment.setNumberOfInstallment(String.valueOf(i));
                installment.setInstallmentAmount(MoneyUtils.formatTurkishLira(totalAmount.divide(BigDecimal.valueOf(i), 2, BigDecimal.ROUND_HALF_UP)));
                installment.setTotalAmount(MoneyUtils.formatTurkishLira(totalAmount));
                installment.setVposConfig(prepareVposConfig(bankCode));
                installments.add(installment);
            }
            all.put(binAndBank.bin(), installments);
        }
        response.setInstallments(all);
        return response;
    }
    @RequestMapping(value = "/nonce", method = RequestMethod.POST, consumes = "application/json")
    public NonceReceivedResponse nonce(NonceRequest request)
    {
        // asenkron bir işlem ile işlem kontrolleri yapılmalıdır. 
        asyncTask(request)
        // asenkron işlemden önce Nonce isteğinin başarılı olarak alındığı iletilmelidir.
        return new NonceReceivedResponse();
    }
    public void asyncTask(NonceRequest nonceRequest)
    {
        // İşlemin hala geçerliliğinin korunup, korumadığı kontrol edilir.
        ....
        // basarili nonce cevabı
        MerchantNonceResponse response = new MerchantNonceResponse();
        response.setNonce(nonceRequest.getToken());
        response.setId(nonceRequest.getPath());
        response.setResult(true);
        // connection token'i sakladiginizi varsayarak "this.token" verisi kullanildi.
        // eger saklamiyorsaniz yeni connection token alip nonce'i gonderebilirsiniz.
        NonceResultResponse nonceResponse = bex.merchantService().sendNonceResponse(this.token, response);
        // nonceResponse ile ödeme sonucu kontrol edilip, işyeri kendi ödeme sonrası aksiyonlarını çağırabilir.
        ....   
    }
}

Ek 3 .NET SDK Dokümantasyonu

class BexPayment


public BexPayment(BexCsharpSDK::Configuration configuration)


public BexPayment(BexCsharpSDK::Environment environment, string merchantId, string privateKey)

BexPayment sınıfı, uygulamanız üzerinden BKM Express işlemlerini yapmanızı sağlayan sınıftır.

// BexPayment sınıfının iki `constructor`'ı var; 1.si

BexPayment bex = new BexPayment
                 {
                     environment = Environment.Preprod,
                     merchantId = ConfigurationManager.AppSettings["MerchantId"]),
                     privateKey = ConfigurationManager.AppSettings["MerchantPrivateKey"])
                 };

// BexPayment sınıfının iki `constructor`'ı var; 2.si

using BexCsharpSDK.Environment;
using Configuration = BexCsharpSDK.Configuration;
var config = new Configuration(Environment.Preprod, "Merchant Id'niz", "Merchant Private Key'iniz");
BexPayment bex = new BexPayment(config);

BaseJsUrl




public string BaseJsUrl()

Belirttiğiniz Environment(Preprod,Production) değerine göre ödeme sayfanızın önyüzünde kullanılacak javascript dosyasının linkini döner.

// Dönen Client SDK url'ini ödeme sayfanıza elle girmek yerine bu metodu kullanabilirsiniz.

...

ViewBag.BkmJsUrl = bex.BaseJsUrl()

...

GetMerchantService




public MerchantService GetMerchantService()

BKM Express Server'ı ile konuşmanızı sağlayan sınıf, MerchantService nesnesini döner.

class Configuration



public Configuration(Environment environment, string merchantId, string privateKey)

BKM Express ile konuşabilmek için gerekli konfigürasyonu temsil eden sınıf.

class Environment



public enum Environment

{

    Preprod,

    Production

}

Entegrasyon sırasında kendi testlerinizi yapmak için Preprod ortamını kullanın. Her şeyin düzgün çalıştığından emin olduktan sonra, BKM Express'i kullanarak kullanıcılarınızdan ödemeye başladığınızda, ortamınızı Production'a çevirin.

class Banks

Bankalara göre taksit işlemlerini yapmak için banka adlarına ve id'lerine ulaşabileceğiniz sınıftır. Yukarda bankalarla ilgili bilgiler içeren tabloya bakabilirsiniz.

FindById



public string FindById(string id)

id parametresini kullanarak bankanın ismini verir. Eğer öyle bir id yoksa, mesajı Bank not found olan bir exception fırlatır.

class InstallmentRequest

BKM Express, taksitleri sorgulamak için sizin server'ınıza yaptığı request'i temsil eden sınıftır.

class BinAndBank

bin ve banka kodunu temsil eder.

Bank

// Banka koduna göre bankanın adını döner.

public string Bank()

class VposConfig

Sanal pos konfigürasyon bilgilerini temsil eden sınıftır.

AddExtra



public void AddExtra(string key, string value)

Sanal pos extra bilgileri. Her bir bankanın extra bilgilerini eklemek için bu metodu kullanın.

class Installment

Bir taksiti temsil eden sınıf.

class InstallmentsResponse

BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.

class PaymentResultResponse

Ödeme işleminin sonucu için kendi server'ınızdan BKM Express Server'ına yapacağınız request'te, BKM Express'in size döneceği yanıtı temsil eden sınıf.

class PosResult

Vpos üzerinden dönen cevabı temsil eden sınıf.

class NonceRequest

BKM Express, ödemeyi tamamlamadan önce, sepet ve stok gibi kontrollerinizi yapmanız için, server'ınızdaki bir endpoint request yaptığında, gönderdiği verileri temsil eden bir sınıf.

class NonceReceivedResponse

BKM Express, ödemeden bir önceki adımda kontrollerinizi yapmanız için endpoint'inize istek yaptığında ilk yapmanız gereken şey, bu sınıfın örneğini göndermek olmalıdır.

class MerchantNonceResponse

class NonceResultResponse

class EcryptionUtil

VerifyBexSignature




public static bool VerifyBexSignature(string data, string signature)

BKM Express, taksitleri sorgulamak için server'ınıza request yaptığında, bu request nesnesi, InstallmentRequest, güvenlik amaçlı signature parametresini de yollar. Herhangi bir güvenlik ihlali olmadığından emin olmak için bu signature'ı doğrulamanız gerekir.

Taksit sorgulama isteği geldiğinde, her şeyden önce signature'ı doğrulamanız gerekir. Bu metodu kullanarak doğrulamalısınız.


...
public JsonResult Installments(InstallmentRequest request)
{
    ...
    InstallmentsResponse response = new InstallmentsResponse();
    if (!EncryptionUtil.VerifyBexSignature(request.ticketId, request.signature))
    {
        response.error = "signature verification failed";
    }
    ...
    else
    {
        response.status = "ok";
        response.error = "";
        ...
    }
    ...
}
...

EncryptWithBex


public static string EncryptWithBex(VposConfig vposConfig)

Normal entegrasyon tipini seçtiyseniz, ödemeler için BKM Server'ına Sanal POS bilgilerinizi yollamalısınız. Bu bilgileri BKM Server'ına güvenli bir şekilde iletmeniz için bu metodu kullanarak Sanal POS bilgilerinizi şifrelemelesiniz.

class Token

MerchantService nesnesini kullanarak BKM Express'e Login olduğunuzda ya da ödeme işlemi için OneTimeTicket kullandığınızda BKM Express size connection token ve ticket token yollar, sırasıyla. Bu sınıf, bu token'ları temsil eder.

IdDecoded


public string IdDecoded()

Token id'yi Base32 formatına encode eder.

Array


public string Array()

Token nesnesinin id, path ve token'ını JSON Array nesnesinin string halini döner.

Json



public string Json()

Token nesnesinin id, path ve token'ını JSON Object nesnesinin string halini döner.

class MerchantService

BKM Express ile konuşmanızı sağlayan sınıftır. Bu sınıfı doğrudan kendinizin yaratması tavsiye edilmemektedir. Bu nesneyi oluşturmak için new BexPayment(config).GetMerchantService() metodunu kullanın.

Login



public Token Login()

Ödeme işlemini başlatmak için ilk önce giriş yapmanız gerekmektedir. Giriş başarılı geçtikten sonra, size connection token üretir.

OneTimeTicket

public Token OneTimeTicket(Token connection, string amount)

public Token OneTimeTicket(Token connection, string amount, string installmentUrl)

public Token OneTimeTicket(Token connection, string amount, string installmentUrl, string nonceUrl)

Bir ödeme işlemi için ticket token'a sahip olmanız gerekmektedir. Login olduktan sonra size verilen connection token'ı kullanarak ticket token almalısınız.

Kuştüyü entegrasyon tipini seçtiyseniz, kendi server'ınızda taksitlerin sorgulanması için bir endpoint oluşturma zorunluluğunuz yok. Bu durumda connection token ve ödeme tutarını vermeniz yeterli.

Ödeme yapılmadan önce ödeme bilgilerini doğrulamak istiyorsanız, nonceUrl parametresini de girmelisiniz.

Result



public PaymentResultResponse Result(Token connection, string ticketPath)

Ödeme işleminin sonucunu sorgulamak için kullanılan metod. PaymentResultResponse nesnesi verir.

SendNonceResponse


public NonceResultResponse Nonce(Token connection, MerchantNonceResponse response)

MoneyUtils

FormatTurkishLira

double veya float tipindeki tutarı, ondalıklı kısmı virgül(,) ile ayrılmış hale çevirir.


public static string FormatTurkishLira(double amount)
public static string FormatTurkishLira(float amount)

ToDouble

####,## string formatındaki tutarı double türüne(####.##) çevirir.


public static double ToDouble(string amount)

ToFloat

####,## string formatındaki tutarı float türüne(####.##) çevirir.

public static float ToFloat(string amount)

Ek 4 PHP SDK Dokümantasyonu

class BexPayment

BexPayment sınıfı, uygulamanız üzerinden BKM Express işlemlerini yapmanızı sağlayan sınıftır.

<?php


public BexPayment


<?php
// BexPayment sınıfının static methodu `startBexPayment`'ın çağırılması :

$config = BexPayment::startBexPayment("Environment Türü","Merchant Id niz","Merchant Private Key iniz");





BaseJsUrl

Belirttiğiniz Environment(PREPROD, PRODUCTION) değerine göre ödeme sayfanızın önyüzünde kullanılacak javascript dosyasının linkini döner.

<?php


public string BaseJsUrl()


<?php


...
// Dönen Client SDK url'ini ödeme sayfanıza elle girmek yerine bu metodu kullanabilirsiniz.


 $baseJsUrl = $config->getBexApiConfiguration()->getBaseJs();





...


MerchantService Class ı

BexPayment class'ının startBexPayment methodundan dönen $config objesinin MerchantService class'ının constructor ına verilerek servis aktif hale getirilir. BKM Express Server'ı ile konuşmanızı sağlayan sınıf, MerchantService nesnesini döner.

<?php

...





$merchantService = new MerchantService($config);


...





class Configuration

BKM Express ile konuşabilmek için gerekli konfigürasyonu temsil eden sınıf.

<?php

public  Configuration(Environment environment, string merchantId, string privateKey)


class Environment

Entegrasyon sırasında kendi testlerinizi yapmak için Preprod ortamını kullanın. Her şeyin düzgün çalıştığından emin olduktan sonra, BKM Express'i kullanarak kullanıcılarınızdan ödemeye başladığınızda, ortamınızı Production'a çevirin.

<?php


class Environment


{

      const PREPROD = "PREPROD";


      const PRODUCTION = "PRODUCTION";

}





class Banks

Bankalara göre taksit işlemlerini yapmak için banka adlarına ve id'lerine ulaşabileceğiniz sınıftır. Yukarda bankalarla ilgili bilgiler içeren tabloya bakabilirsiniz.

class InstallmentRequest

BKM Express, taksitleri sorgulamak için sizin server'ınıza yaptığı request'i temsil eden sınıftır.

class VposConfig

Sanal pos konfigürasyon bilgilerini temsil eden sınıftır.

class Installment

Bir taksiti temsil eden sınıf.

class InstallmentsResponse

BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.

class PaymentResultResponse

Ödeme işleminin sonucu için kendi server'ınızdan BKM Express Server'ına yapacağınız request'te, BKM Express'in size döneceği yanıtı temsil eden sınıf.

class PosResult

Vpos üzerinden dönen cevabı temsil eden sınıf.

class NonceRequest

BKM Express, ödemeyi tamamlamadan önce, sepet ve stok gibi kontrollerinizi yapmanız için, server'ınızdaki bir endpoint request yaptığında, gönderdiği verileri temsil eden bir sınıf.

class NonceData

class NonceReceivedResponse

BKM Express, ödemeden bir önceki adımda kontrollerinizi yapmanız için endpoint'inize istek yaptığında ilk yapmanız gereken şey, bu sınıfın örneğini göndermek olmalıdır.

class MerchantNonceResponse

class NonceResultResponse

class EcryptionUtil

verifyBexSign

BKM Express, taksitleri sorgulamak için server'ınıza request yaptığında, bu request nesnesi, InstallmentRequest, güvenlik amaçlı $signature parametresini de yollar. Herhangi bir güvenlik ihlali olmadığından emin olmak için bu signature'ı doğrulamanız gerekir.

<?php

public static function verifyBexSign($ticketId,$signature);





<?php
// Taksit sorgulama isteği geldiğinde, her şeyden önce `signature`'ı doğrulamanız gerekir. Bu metodu kullanarak doğrulamalısınız.


...


private function  initInstallment(InstallmentRequest $installmentRequest , InstallmentsResponse $installmentResponse)





{
<?php




    if(!isset($installmentRequest))





    { 



  $installmentResponse->setError("Request Body can not be null !");


    return $installmentResponse;


  }else if (empty($installmentRequest->getBinNo()) || empty($installmentRequest->getBankCode()) || empty($installmentRequest->getTotalAmount()) || empty($installmentRequest->getTicketId())) {


 $installmentResponse->setError("Request Body variables can not be null !");


  return $installmentResponse;


     }else if (!EncryptionUtil::verifyBexSign($installmentRequest->getTicketId(),$installmentRequest->getSignature())){


    $installmentResponse->setError("Signature verification failed");


return $installmentResponse;

    }


...





class Token

MerchantService nesnesini kullanarak BKM Express'e login olduğunuzda ya da ödeme işlemi için oneTimeTicket kullandığınızda BKM Express size connection token ve ticket token yollar, sırasıyla. Bu sınıf, bu token'ları temsil eder.

Login

Ödeme işlemini başlatmak için ilk önce giriş yapmanız gerekmektedir. Giriş başarılı geçtikten sonra, size MerchantLoginResponse sınıfını döner. Buradan $connectionToken üretir.

<?php

public function login()


OneTimeTicket

<?php


public function oneTimeTicket(Token $connection, $amount, $installmentUrl)


Bir ödeme işlemi için ticket token'a sahip olmanız gerekmektedir. Login olduktan sonra size verilen connection token'ı kullanarak ticket token almalısınız.

Result

Ödeme işleminin sonucunu sorgulamak için kullanılan metod. PaymentResultResponse nesnesi verir.

<?php

public function result($token,$connectionId, $ticketId)





SendNonceResponse

MerchantService class ı içerisinde nonce isteği yapan method.

<?php

public function  sendNonceResponse(Token $token, MerchantNonceResponse $response)


MoneyUtils

FormatTurkishLira

$amount tipindeki tutarı, ondalıklı kısmı virgül(,) ile ayrılmış hale çevirir.

<?php

public static function formatTurkishLira($amount)


toDouble

toFloat methodunu çağırır.

<?php

public static function toDouble($amount)


toFloat

####,## string formatındaki tutarı float türüne(####.##) çevirir.

<?php

public static function toFloat($amount)


Ek 5 JAVA SDK Dokümantasyonu

class BexPayment



public BexPayment(Configuration configuration)




public BexPayment(Environment environment, string merchantId, string privateKey)


BexPayment sınıfı, uygulamanız üzerinden BKM Express işlemlerini yapmanızı sağlayan sınıftır.

// BexPayment sınıfının iki `constructor`'ı var: 1.si;


BexPayment bex = new BexPayment(Environment.PREPROD, "MERCHANT ID'NIZ", "PRIVATE KEY'INIZ");


Ya da

//2.si;


Configuration config = new Configuration(Environment.Preprod, "Merchant Id'niz", "Merchant Private Key'iniz");





BexPayment bex = new BexPayment(config);


baseJsUrl



public String baseJsUrl()


Belirttiğiniz Environment(PREPROD, PRODUCTION) değerine göre ödeme sayfanızın önyüzünde kullanılacak javascript dosyasının linkini döner.

Dönen Client SDK url'ini ödeme sayfanıza elle girmek yerine bu metodu kullanabilirsiniz.



...


modelAndView.addObject("bkmJsUrl", bex.baseJsUrl);


...


merchantService



public MerchantService merchantService()


BKM Express Server'ı ile konuşmanızı sağlayan sınıf, MerchantService nesnesini döner.

class Configuration



public Configuration(Environment environment, string merchantId, string privateKey)


BKM Express ile konuşabilmek için gerekli konfigürasyonu temsil eden sınıf.

class Environment



public enum Environment


{

    PREPROD,

    PRODUCTION


}


Entegrasyon sırasında kendi testlerinizi yapmak için Preprod ortamını kullanın.Her şeyin düzgün çalıştığından emin olduktan sonra, BKM Express'i kullanarak kullanıcılarınızdan ödemeye başladığınızda, ortamınızı Production'a çevirin.

class Banks

Bankalara göre taksit işlemlerini yapmak için banka adlarına ve id'lerine ulaşabileceğiniz sınıftır. Yukarda bankalarla ilgili bilgiler içeren tabloya bakabilirsiniz.

findById



public string findById(String id)


id parametresini kullanarak bankanın ismini verir. Eğer öyle bir id yoksa, mesajı Bank not found olan bir exception fırlatır.

class InstallmentRequest

BKM Express, taksitleri sorgulamak için sizin server'ınıza yaptığı request'i temsil eden sınıftır.

class VposConfig

Sanal pos konfigürasyon bilgilerini temsil eden sınıftır.

addExtra



public void addExtra(string key, string value)


Sanal pos extra bilgileri. Her bir bankanın extra bilgilerini eklemek için bu metodu kullanın.

class Installment

Bir taksiti temsil eden sınıf.

class InstallmentsResponse

BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.

class PaymentResultResponse

Ödeme işleminin sonucu için kendi server'ınızdan BKM Express Server'ına yapacağınız request'te, BKM Express'in size döneceği yanıtı temsil eden sınıf.

class PosResult

Vpos üzerinden dönen cevabı temsil eden sınıf.

class NonceRequest

BKM Express, ödemeyi tamamlamadan önce, sepet ve stok gibi kontrollerinizi yapmanız için, server'ınızdaki bir endpoint request yaptığında, gönderdiği verileri temsil eden bir sınıf.

class NonceReceivedResponse

BKM Express, ödemeden bir önceki adımda kontrollerinizi yapmanız için endpoint'inize istek yaptığında ilk yapmanız gereken şey, bu sınıfın örneğini göndermek olmalıdır.

class MerchantNonceResponse

class NonceResultResponse

class EncryptionUtil

verifyBexSign



public static bool verifyBexSign(string data, string signature)


BKM Express, taksitleri sorgulamak için server'ınıza request yaptığında, bu request nesnesi, InstallmentRequest, güvenlik amaçlı signature parametresini de yollar. Herhangi bir güvenlik ihlali olmadığından emin olmak için bu signature'ı doğrulamanız gerekir.

Taksit sorgulama isteği geldiğinde, her şeyden önce signature'ı doğrulamanız gerekir. Bu metodu kullanarak doğrulamalısınız.



...


public InstallmentsResponse Installments(InstallmentRequest request)


{


    ...

    InstallmentsResponse response = new InstallmentsResponse();

    if (!EncryptionUtil.verifyBexSign(request.getTicketId(), request.signature))


    {


        response.error = "signature verification failed";


    }

    ...

    else


    {


        response.status = "ok";

        response.error = "";


        ...

    }

    ...

}

...


class Token

MerchantService nesnesini kullanarak BKM Express'e login olduğunuzda ya da ödeme işlemi için oneTimeTicket kullandığınızda BKM Express size connection token ve ticket token yollar, sırasıyla. Bu sınıf, bu token'ları temsil eder.

idDecoded



public String idDecoded()


Token id'yi Base32 formatına encode eder.

array



public String array()


Token nesnesinin id, path ve token'ını JSON Array nesnesinin String halini döner.

json



public String json()


Token nesnesinin id, path ve token'ını JSON Object nesnesinin String halini döner.

class MerchantService

BKM Express ile konuşmanızı sağlayan sınıftır. Bu sınıfı doğrudan kendinizin yaratması tavsiye edilmemektedir. Bu nesneyi oluşturmak için BexPayment(config).merchantService() metodunu kullanın.

login



public Token login()


Ödeme işlemini başlatmak için ilk önce giriş yapmanız gerekmektedir. Giriş başarılı geçtikten sonra, size connection token üretir.

oneTimeTicket



public Token oneTimeTicket(Token connection, String amount, String installmentUrl)


Bir ödeme işlemi için ticket token'a sahip olmanız gerekmektedir. login olduktan sonra size verilen connection token'ı kullanarak ticket token almalısınız.

result



public PaymentResultResponse result(Token connection, String ticketId)


Ödeme işleminin sonucunu sorgulamak için kullanılan metod. PaymentResultResponse nesnesi verir.

sendNonceResponse



public NonceResultResponse sendNonceResponse(String connectionToken, String connectionId, MerchantNonceResponse response)


class MoneyUtils

formatTurkishLira



public static String formatTurkishLira(double amount)





public static String formatTurkishLira(float amount)


double veya float tipindeki tutarı, ondalıklı kısmı virgül(,) ile ayrılmış hale çevirir.

toDouble



public static double toDouble(String amount)


####,## string formatındaki tutarı double türüne(####.##) çevirir.

toFloat



public static float toFloat(String amount)


####,## string formatındaki tutarı float türüne(####.##) çevirir.