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?
- Private key bilginizi isteklerin imzalanmasında kullanacağınız için BKM dahil herhangi bir yerle paylaşmamalısınız.
- 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.
- openssl genrsa -out private.pem 2048
- openssl pkcs8 -topk8 -in private.pem -out privatePKCS8.pem -nocrypt
- openssl rsa -in private.pem -outform PEM -pubout -out public.pem
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
- Ödemenin geçeceği sanal pos bilgilerinin her işlemde paylaşılıp paylaşılmamasına göre entegrasyonda az da olsa farklılıklar mevcuttur.
- Normal ve Kuş Tüyü olmak üzere 2 farklı entegrasyon tipi bulunmaktadır.
- Normal entegrasyon'da sanal pos bilgileri sizde kalır. İşlem sırasında işlemin sanal pos’tan kaç taksitle geçeceğine siz karar verirsiniz.
- Kuş Tüyü entegrasyonda sanal pos bilgileri BKM Express üzerinde tutulur. İşlem sırasında sadece taksit bilgisine siz karar verirsiniz. Uygun sanal pos’a BKM Express'te karar verilir.
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.
Preprod: BKM Express'i uygulamanıza entegre etmek için kullanacağınız test ortamı.
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
- Server SDK’yı kendi uygulamanıza entegre etmek için Solution Explorer’da References’a sağ tıklayıp Add Reference’ı seçin.
- Açılan pencereden Browse butonuna basın.
- 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ı
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;
- Daha önce aldığınız Connection Token
- Yapılacak ödeme işleminin tutarı
- BKM Express server'ının sizin uygulamanızdan taksit / sanal pos bilgilerini alabilmesi için hazırladığınız bir endpoint (3. adımda detayları görülebilir.)
- BKM Express server'ının sizin uygulamanızdan siparişin uygunluğu kontrol edebilmesi için hazırladığınız bir endpoint (4.2 adımında detayları görülebilir.)
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("overrideOrderId", "VAKIFbankMyCustomOrderID123");
$vposConfig->setBankIndicator($bankCode);
$vposConfig->setServiceUrl("https://onlineodemetest.vakifbank.com.tr:4443/VposService/v3/Vposreq.aspx");
} 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("QNB_API_KULLANICI_3DPAY");
$vposConfig->setVposPassword("UcBN0");
$vposConfig->addExtra("MbrId", "5");
$vposConfig->addExtra("MerchantId", "085300000009704");
// vposConfig.AddExtra("overrideOrderId", "FINANSBANKMyCustomOrderID123");
$vposConfig->setBankIndicator($bankCode);
$vposConfig->setServiceUrl("https://vpostest.qnbfinansbank.com/Gateway/Default.aspx");
} 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:
Kuştüyü entegrasyonda Taksit bilgisi göndermemeniz durumunda default olarak 1 taksit seçeneği görüntülenir.
Kuştüyü entegrasyonda ‘VposConfig’ alanını null göndermelisiniz.
4.1.3 Ön otorizasyon (Preauth)
BKM Express üzerinden ön otorizasyonlu işlem gönderebilirsiniz.
- Normal entegrasyon modelinde ön otorizasyon özelliğini aktif etmek için vposConfig içerisinde preAuth parametresini true olarak göndermelisiniz.
Örnek:
“vposConfig” : {
“vposUserId” : “bkmtest”,
“vposPassword” : “TEST1691”,
“extra” : {“ClientId”:“190001691”, “storekey”:“TRPS1691”, “orderId”:“9073194”},
“bankIndicator” : “0010”,
“serviceUrl” : “http://srvirt01:7200/ziraat”,
“preAuth” : true
}
- Kuştüyü entegrasyon modelinde ön otorizasyon özelliği BKM tarafından aktif edilmektedir.Bunun için isyerientegrasyon@bkm.com.tr ile iletişime geçebilirsiniz.
Ö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:
- Öncelikle kendi server'ınızda bir endpoint oluşturmalısınız.
- 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. - Server'ınızdaki endpoint'e gelen istekteki veriler
NonceRequest
nesnesi ile temsil edilmektedir. Bu nesnenin içindekisignature
'ı doğruladıktan sonra bu nesne içerisindeki bilgileri de kullanarak kendi tarafınızdaki kontrolleri yapmaya başlayabilirsiniz. - Kendi kontrollerinizi tamamladıktan sonra (stok kontrolü, sepet tutarı kontrolü gibi),
NonceRequest
nesnesindekinonce
bilgisini yollamalısınız. Bunu yapmak için Server SDK'dekiSendNonceResponse
metodunu kullanmalısınız. SendNonceResponse
metoduNonceResultResponse
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 3 - Taksit Seçenekleri / Kuştüyü
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, Kuveyt Türk ve TFKB 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.
- 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>
- Server SDK'nızı canlı ortam moduna almalısınız. Bkz. SDK Kurulumlarını Yapın
- 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 |
Kuveyttürk | https://sanalpos.kuveytturk.com.tr/ServiceGateWay/Home/ThreeDModelGate |
Kuveyttürk Non3D | https://boa.kuveytturk.com.tr/BOA.Integration.WCFService/BOA.Integration.VirtualPos/VirtualPosService.svc/Basic |
Denizbank | https://spos.denizbank.com/mpi/default.aspx |
Denizbank | https://inter-vpos.com.tr/MPI/Default.aspx |
HSBC | https://vpos.qnbfinansbank.com/Gateway/Default.aspx |
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 |
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.
- Tutar içinde nokta(.) bulunmamalıdır.
- Tutarın ondalıklı kısmı virgül(,) ile ayrılmalıdır.
- Küsürat virgülden sonra 2 basamaklı olmalıdır. Örn; 1000,00 veya 1000,52 gibi.
Örnek:
- “1000.52” değil, “1000,52” olmalıdır.
- “1.000,52” değil, “1000,52” olmalıdır.
Bunun için Server SDK'da MoneyUtils
sınıfı bulunmaktadır.
double
veyafloat
tipindeki tutarını “####,##” formatına çevirmek içinMoneyUtils.FormatTurkishLira
metodunu kullanabilirsiniz.- “
####,##
” formatındaki tutarıdouble
veyafloat
tipine çevirmek için iseMoneyUtils.ToDouble
veyaMoneyUtils.ToFloat
metodlarını kullanabilirsiniz, sırasıyla.
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.
List<string> binNo
: Kartın ilk 6 hanesi ve banka kod bilgisini içerir.string totalAmount
: Toplam ödeme tutarı.string ticketId
: Kullanıcının ödeme işlemi için üretilmiş token'ın id'si.string signature
: Güvenlik amaçlı bulundurulan bir field. BKM Express, Server'ınıza taksitler için istekte bulunduğunda, bu request'te bulunanticketId
ile imzalanmış bu imzayı doğrulamalısınız.List<BinAndBank> BinAndBanks()
: Kullanıcının ödeme yapmak istediği kartın bin numarası ve banka kodu listesini döner.
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.
string vposUserId
: Bankanın sanal pos için belirlediği user id.string vposPassword
: Bankanın sanal pos için belirlediği şifre.Dictionary<string, string> extra
: Bankanın sanal pos için belirlediği extra bilgiler.string bankIndicator
: Kartın tanımlı olduğu bankanın kodu.string serviceUrl
: Bankanın sanal pos için belirlediği url.
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.
string numberOfInstallments
: Taksit sayısı.string installmentAmount
: Taksit tutarı.string totalAmount
: Toplam tutar.string vposConfig
: Sanal POS bilgilerinizi VposConfig sınıfı ile temsil ettikten sonra,EncryptWithBex
metodunu kullanarak bu bilgileri şifreleyip göndermelisiniz.
class InstallmentsResponse
BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.
Dictionary<string, List<Installment>> installments
:Installment
yani taksit bilgilerini içeren liste.string status
: Durumun başarılı olup olmadığını belirten alan.string error
: Hata varsa nedenini belirteceğiniz field.
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.
string status
: Durumun başarılı olup olmadığını belirten alan. Paid veya Failed değeri olur.string installmentCount
: Taksit sayısı.string totalAmount
: Toplam tutar.string cardFirst6
: Kartın ilk 6 hanesi.string cardLast4
: Kartın son 4 hanesi.string cardHash
: Kart bilgisinin hash değeri. Her kart için benzersizdir(unique). Güvenlik amaçlı kullanılmaktadır.string bkmTokenId
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.-
PosResult posResult
: Vpos üzerinden dönen cevabı temsil eden sınıf.
class PosResult
Vpos üzerinden dönen cevabı temsil eden sınıf.
string orderId
: Pos üzerindeki işlemin sipariş numarasıstring authCode
: Pos üzerindeki işlem kaydıstring posResponse
: Pos'tan dönen cevapstring posResultCode
: Pos'tan dönen cevabın kodustring posResultMessage
: Pos'tan dönen cevabın mesajı.string referenceNumber
: Pos'tan dönen referans numarası.string posTransactionId
: Pos'tan dönen transaction id.string posBank
: İşlemin geçtiği pos'un banka kodu.
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.
string ticketId
: Başlatılan ödeme işleminin ticket id'si.string orderId
: Sipariş numarası.string signature
: BKM ödemeyi tamamlamadan önceki aşamada nonce endpoint'inize yaptığı request'te, kendi kontrollerinizi yapmadan önce doğrulamanız gereken alan.string nonce
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.string path
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.string totalAmount
: Ödeme işleminin toplam tutarı.string totalAmountWithInstallmentCharge
: Vade farkı ile ödeme tutarının toplamı.string numberOfInstallments
: Taksit sayısı.String hash:
Bool tcknMatch:
Ticket Token'ın oluştururken gönderdiğiniz TCKN bilgisinin kullanıcın BKM Express'teki TCKN'si ile uyuşup uyuşmadığı bilgisi. Uyuşması halinde true döner.Bool msisdnMatch:
Ticket Token'ın oluştururken gönderdiğiniz cep telefonu bilgisinin kullanıcın BKM Express'teki cep telefonu ile uyuşup uyuşmadığı bilgisi. Uyuşması halinde true döner.
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.
string status
: Varsayılan değeri “OK”.
class MerchantNonceResponse
bool result
: Kontrollerinizi yaptıktan sonra herhangi bir problem yoksatrue
, varsafalse
değerini vermeniz gerekir.string nonce
: BKM Express'in endpoint'inize yaptığı istekte,NonceRequest
nesnesinin içindekinonce
verisini vermeniz gereken alan.string message
: Kontrollerinizden sonra bir hata varsa, ilgili hata için bir mesaj belirtebilirsiniz.
class NonceResultResponse
string status
: Durumun başarılı olup olmadığını belirten alan. Paid veya Failed değeri olur.string error
: Bir hata varsa hatanın mesajını belirtir.string installmentCount
: Taksit sayısı.string totalAmount
: Toplam tutar.string cardFirst6
: Kartın ilk 6 hanesi.string cardLast4
: Kartın son 4 hanesi.string cardHash
: Kart bilgisinin hash değeri. Her kart için benzersizdir(unique). Güvenlik amaçlı kullanılmaktadır.string bkmTokenId
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.PosResult posResult
: Vpos üzerinden dönen cevabı temsil eden sınıf.
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.
string id
: Token id'si.string path
: Token path'i.string token
: Token'ın string hali.
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.
Token connection
:Login
olduktan sonra size verilen connection token.string amount
: Ödemenin tutarı.string installmentUrl
: BKM Express'in taksitleri sorgulamak için server'ınızdaki bir endpoint'in url'i.string nonceUrl
: BKM Express'in ödemeyi tamamlamadan önce, server'ınızdaki bir endpoint'e, ödeme bilgilerini doğrulamanız için istek gönderir.
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.
$binNo
: Kartın ilk 6 hanesi.$totalAmount
: Toplam ödeme tutarı.$ticketId
: Kullanıcının ödeme işlemi için üretilmiş token'ın id'si.$signature
: Güvenlik amaçlı bulundurulan bir field. BKM Express, Server'ınıza taksitler için istekte bulunduğunda, bu request'te bulunanticketId
ile imzalanmış bu imzayı doğrulamalısınız.
class VposConfig
Sanal pos konfigürasyon bilgilerini temsil eden sınıftır.
$vposUserId
: Bankanın sanal pos için belirlediği user id.$vposPassword
: Bankanın sanal pos için belirlediği şifre.$extra = array()
: Bankanın sanal pos için belirlediği extra bilgiler.$bankIndicator
: Kartın tanımlı olduğu bankanın kodu.$serviceUrl
: Bankanın sanal pos için belirlediği url.
class Installment
Bir taksiti temsil eden sınıf.
$numberOfInstallment
: Taksit sayısı.$installmentAmount
: Taksit tutarı.$totalAmount
: Toplam tutar.$vposConfig
:VposConfig
sınıfı ile temsil edilen bilgiler.
class InstallmentsResponse
BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.
$installments = array()
:Installment
yani taksit bilgilerini içeren array.$status
: Durumun başarılı olup olmadığını belirten alan.$error
: Hata varsa nedenini belirteceğiniz field.
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.
$status
: Durumun başarılı olup olmadığını belirten alan.$installmentCount
: Taksit sayısı.$totalAmount
: Toplam tutar.$cardFirst6
: Kartın ilk 6 hanesi.$cardLast4
: Kartın son 4 hanesi.$paymentPurchased
: Durumun başarılı olup olmadığını belirten alan. true ise ödeme başarılı ile alınmıştır.$string bkmTokenId
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.$PosResult posResult
: Vpos üzerinden dönen cevabı temsil eden sınıf.
class PosResult
Vpos üzerinden dönen cevabı temsil eden sınıf.
$orderId
: Pos üzerindeki işlemin sipariş numarası$authCode
: Pos üzerindeki işlem kaydı$posResponse
: Pos'tan dönen cevap$posResultCode
: Pos'tan dönen cevabın kodu$referenceNumber
: Pos'tan dönen referans numarası.$posTransactionId
: Pos'tan dönen transaction id.$posBank
: İşlemin geçtiği pos'un banka kodu.
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.
$id
: Sipariş numarası.$path
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.$token
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.$signature
: BKM ödemeyi tamamlamadan önceki aşamada nonce endpoint'inize yaptığı request'te, kendi kontrollerinizi yapmadan önce doğrulamanız gereken alan.$reply
: NonceData sınıfının içeriği.
class NonceData
$ticketId
: Başlatılan ödeme işleminin ticket id'si.$orderId
: Sipariş numarası.$totalAmount
:Ödeme işleminin toplam tutarı$totalAmountWithInstallmentCharge
:Vade farkı ile ödeme tutarının toplamı$numberOfInstallments
: Taksit sayısı.
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.
$status
: Varsayılan değeri “ok”.$result
: Varsayılan değeri “ok”.
class MerchantNonceResponse
$result
: Kontrollerinizi yaptıktan sonra herhangi bir problem yoksatrue
, varsafalse
değerini vermeniz gerekir.$nonce
: BKM Express'in endpoint'inize yaptığı istekte,NonceRequest
nesnesinin içindekinonce
verisini vermeniz gereken alan.$message
: Kontrollerinizden sonra bir hata varsa, ilgili hata için bir mesaj belirtebilirsiniz.
class NonceResultResponse
$status
: Durumun başarılı olup olmadığını belirten alan. Paid veya Failed değeri olur.$error
: Bir hata varsa hatanın mesajını belirtir.$installmentCount
: Taksit sayısı.$totalAmount
: Toplam tutar.$cardFirst6
: Kartın ilk 6 hanesi.$cardLast4
: Kartın son 4 hanesi.$string bkmTokenId
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.$PosResult posResult
: Vpos üzerinden dönen cevabı temsil eden sınıf.
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.
$shortId
: Token short id'si.$path
: Token id'si.$token
: Token'ın string hali.
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.
$connectionToken
:Login
olduktan sonra size verilen connection token.$amount
: Ödemenin tutarı.$installment
: BKM Express'in taksitleri sorgulamak için server'ınızdaki bir endpoint'in url'i.
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.
List<String> binNo
: Kartların ilk 6 hanesi ve bank kod bilgisini içerir.List<BinAndBank> binAndBanks()
: bin() methodu kartın ilk 6 hanesini döner, bankCode() bankanın kodunu bank() ise Banks enum'ındaki değerini döner.String totalAmount
: Toplam ödeme tutarı.String ticketId
: Kullanıcının ödeme işlemi için üretilmiş token'ın id'si.String signature
: Güvenlik amaçlı bulundurulan bir field. BKM Express, Server'ınıza taksitler için istekte bulunduğunda, bu request'te bulunanticketId
ile imzalanmış bu imzayı doğrulamalısınız.
class VposConfig
Sanal pos konfigürasyon bilgilerini temsil eden sınıftır.
String vposUserId
: Bankanın sanal pos için belirlediği user id.String vposPassword
: Bankanın sanal pos için belirlediği şifre.Map<String, String> extra
: Bankanın sanal pos için belirlediği extra bilgiler.String bankIndicator
: Kartın tanımlı olduğu bankanın kodu.String serviceUrl
: Bankanın sanal pos için belirlediği url.
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.
string numberOfInstallments
: Taksit sayısı.string installmentAmount
: Taksit tutarı.string totalAmount
: Toplam tutar.VposConfig vposConfig
:VposConfig
sınıfı ile temsil edilen bilgiler.
class InstallmentsResponse
BKM Express, sizin sunucunuza taksit sorgulamak için istekte bulunduğunda döneceğiniz cevabı temsil eden sınıf.
Map<String, List<Installment>> installments
:Installment
yani taksit bilgilerini içeren liste. Size gelen her bir bin için ayrı bir liste oluşturulmalı.String status
: Durumun başarılı olup olmadığını belirten alan.String error
: Hata varsa nedenini belirteceğiniz field.
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.
String status
: İşlemin başarılı sonlandığını belirtir.String isPaymentPurchased()
: Durumun başarılı olup olmadığını belirten alan. true ise ödeme başarılı ile alınmıştır.String getInstallmentCount()
: Taksit sayısı.String getYotalAmount()
: Toplam tutar.String getCardFirst6()
: Kartın ilk 6 hanesi.String getCardLast4()
: Kartın son 4 hanesi.String getCardHash()
: Kart bilgisinin hash değeri. Her kart için benzersizdir(unique). Güvenlik amaçlı kullanılmaktadır.String getBkmTokenId()
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.PosResult getPosResult()
: Vpos üzerinden dönen cevabı temsil eden sınıf.
class PosResult
Vpos üzerinden dönen cevabı temsil eden sınıf.
String orderId
: Pos üzerindeki işlemin sipariş numarasıString authCode
: Pos üzerindeki işlem kaydıString posResponse
: Pos'tan dönen cevapString posResultCode
: Pos'tan dönen cevabın koduString posResultMessage
: Pos'tan dönen cevabın mesajı.String referenceNumber
: Pos'tan dönen referans numarası.String posTransactionId
: Pos'tan dönen transaction id.String posBank
: İşlemin geçtiği pos'un banka kodu.
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.
String ticketId
: Başlatılan ödeme işleminin ticket id'si.String orderId
: Sipariş numarası.String signature
: BKM ödemeyi tamamlamadan önceki aşamada nonce endpoint'inize yaptığı request'te, kendi kontrollerinizi yapmadan önce doğrulamanız gereken alan.String path
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.String token
: BKM Express, ödemeyi tamamlamadan önceki adımda yaptığı request'te, kendi kontrollerinizi tamamladıktan sonra geri yollayacağınız alan.String totalAmount
: Ödeme işleminin toplam tutarı.String totalAmountWithInstallmentCharge
: Vade farkı ile ödeme tutarının toplamı.String numberOfInstallments
: Taksit sayısı.String hash:
Boolean tcknMatch:
Ticket Token'ın oluştururken gönderdiğiniz TCKN bilgisinin kullanıcın BKM Express'teki TCKN'si ile uyuşup uyuşmadığı bilgisi. Uyuşması halinde true döner.Boolean msisdnMatch:
Ticket Token'ın oluştururken gönderdiğiniz cep telefonu bilgisinin kullanıcın BKM Express'teki cep telefonu ile uyuşup uyuşmadığı bilgisi. Uyuşması halinde true döner.
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.
String status
: Varsayılan değeri “OK”.
class MerchantNonceResponse
boolean result
: Kontrollerinizi yaptıktan sonra herhangi bir problem yoksatrue
, varsafalse
değerini vermeniz gerekir.String nonce
: BKM Express'in endpoint'inize yaptığı istekte,NonceRequest
nesnesinin içindekinonce
verisini vermeniz gereken alan.String message
: Kontrollerinizden sonra bir hata varsa, ilgili hata için bir mesaj belirtebilirsiniz.
class NonceResultResponse
String getStatus()
: İşlemin başarılı sonlandığını belirtir.String getError()
: Bir hata varsa hatanın mesajını belirtir.String isPaymentPurchased()
: Durumun başarılı olup olmadığını belirten alan. true ise ödeme başarılı ile alınmıştır.String getInstallmentCount()
: Taksit sayısı.String getYotalAmount()
: Toplam tutar.String getCardFirst6()
: Kartın ilk 6 hanesi.String getCardLast4()
: Kartın son 4 hanesi.String getCardHash()
: Kart bilgisinin hash değeri. Her kart için benzersizdir(unique). Güvenlik amaçlı kullanılmaktadır.String getBkmTokenId()
: Ödeme işleminden sonraki BKM tarafında kontrol için kullanılan id.PosResult getPosResult()
: Vpos üzerinden dönen cevabı temsil eden sınıf.
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.
String id
: Token id'si.String token
: Token'ın string hali.
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.
Token connection
:login
olduktan sonra size verilen connection token.String amount
: Ödemenin tutarı.String installment
: BKM Express'in taksitleri sorgulamak için server'ınızdaki bir endpoint'in url'i.
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.