NAV Navbar
Logo
.NET PHP JAVA

BKM Express API Listesi

İş yeri olarak BKM Express API'lerini kullanarak aşağıdaki işlemleri gerçekleştirebilirsiniz;

Ortamlar

BKM Express API'leri iki ortam üzerinde bulunur. Geliştirme yaparken test edebilmeniz için PREPROD ortamını kullanabilirsiniz. Gerçek ortamda yapılan işlemler için PRODUCTION ortamı kullanılmalıdır.

API'ler için dokümanda belirtilen endpoint adreslerine iki ortam üzerinden erişim sağlayabilirsiniz.

Genel Değişkenler

Değişken Açıklama
MERCHANT-ID BKM tarafından size verilen ID değerini belirtir
PRIVATE-KEY Imzalama işlemleri için tarafınızda üretilen şifreleme değerini belirtir.
SIGNATURE {MERCHANT-ID} verisi ile {PRIVATE-KEY} kullanılarak RSA-SHA256 algoritmasına göre yapılan imzalama işleminin sonucudur.
TICKET-ID BKM aracılığıyla yapılmış ödeme işlemi id bilgisini içerir.
ORDER-ID BKM aracılığıyla yapılmış ödeme'de oluşan sipariş numarasını belirtir.
POS-USER-ID RSA ile şifrelenmiş sanal pos kullanıcı id değerini belirtir. Kuş tüyü müşteriler için gerekli değildir.
POS-PASSWORD RSA ile şifrelenmiş sanal pos şifre değerini belirtir. Kuş tüyü müşteriler için gerekli değildir.
POS-SERVICE-URL Pos servis url bilgisini belirtir. Kuş tüyü müşteriler için gerekli değildir.
POS-BANK-CODE Sanal POS kullanılacak banka kodunu belirtir. Kuş tüyü müşteriler için gerekli değildir.
POS-EXTRA Pos bilgilerini belirtir. Kuş tüyü müşteriler için gerekli değildir.
TOTAL-AMOUNT Toplam tutar bilgisini belirtir.
POS-TRANSACTION-ID Ön otorizasyon kapama işlemi yapılacak tutar bilgisini belirtir.
POS-RESPONSE Pos sonucunu belirtir (“APPROVED” veya “FAILED”).
POS-RAW-RESPONSE Pos işleminde bankadan dönen ham sonucu belirtir.

1. İşlem Listesi Sorgulama

Üye iş yerleri üzerinden BKM Express aracılığla yapılan işlemlerin sonuçlarını alabilmeniz için geliştirilmiştir. Başarılı/başarısız işlemleri belli bir tarih aralığında ya da ticketId veya orderId üzerinden tekil sorgulamanıza yardımcı olur.

İşlem Listesi Sorgulama API'si üzerinden tekil işlem sorgulama ve toplu işlem sorgulama yapılabilir.

İşlem Listesi Sorgulama API'sini kullanmak için BKM'den MerchantID'niz için yetki almalısınız. Bunun için isyerientegrasyon@bkm.com.tr ile iletişime geçebilirsiniz.

İş yerinin yapacağı istek

Yapılması gereken isteği yandaki kod bloğunda görebilirsiniz.

Aşağıda da istekteki alanların detaylarını görebilirsiniz.

// Örnek bir toplu işlem sorgulama curl isteği:
curl -X POST 'https://api.bkmexpress.com.tr/v1/merchant/merchantTransactionList'\
  -H 'content-type: application/json' \
  -d '{
   "id":"YOUR-MERCHANT-ID",
   "signature":"Signature",
   "startDate": {TRANSACTION-START-DATE}, // "2017-04-02 01:00",
   "endDate": {TRANSACTION-END-DATE}, // "2017-05-02 23:00",
   "paymentResult": {PAYMENT-RESULT}, // "1"
   "page":"",
   "orderType":null
  }'
// Örnek bir tek işlem sorgulama curl isteği:
curl -X POST 'https://api.bkmexpress.com.tr/v1/merchant/merchantTransactionList' \
  -H 'content-type: application/json' \
  -d '{
   "id":"YOUR-MERCHANT-ID",
   "signature":"Signature",
   "ticketId": {TICKET-ID},
   "orderId": {ORDER-ID},
  }'
İstek
Bağlantı Adresi Prod: https://api.bkmexpress.com.tr/v1/merchant/merchantTransactionList
Bağlantı Adresi Preprod: https://preprod-api.bkmexpress.com.tr/v1/merchant/merchantTransactionList
Bağlantı Metodu POST
İstek Content-Type Başlığı application/json
İstek içeriği Toplu işlem sorgulama örneği:{“id”:“Your-Merchant-ID”, “signature”:“Signature”, startDate":“2017-04-02 01:00”, “endDate”:“2017-05-02 23:00”, “paymentResult”:“1”, “page”:“”, “orderType”:null} Tek işlem sorgulama örneği:{“id”:“Your-Merchant-ID”, “signature”:“Signature”, ticketId: “TICKET_ID” or “orderId”: “ORDER_ID”
İstek içerisindeki parametrelerin açıklamaları
id alanı BKM tarafından size iletilen ‘id’ bilgisi
signature alanı 'id’ alanına yazılan değerin BKM tarafına public kısmını ilettiğiniz private key ile şifrelenmiş hali. “SHA-256 with RSA” şifreleme yöntemi ile şifrelenmeli. Örnek şifreleme kodu için tıklayın
startDate alanı 'yy-MM-dd HH:mm’ formatında iletilen işlem sorgu başlangıç tarih değeri. Tek işlem sorgulamada geçersiz olacaktır
endDate alanı 'yy-MM-dd HH:mm’ formatında iletilen işlem sorgu bitiş tarih değeri. Tek işlem sorgulamada geçersiz olacaktır.
paymentResult alanı “0” ya da “1” olarak yollanır. 0:başarısız işlemler 1:başarılı işlemler. Tek işlem sorgulamada geçersiz olacaktır.
page alanı “” ya da istenilen sayfa değeri yollanır. İşlem listesi ilk sorgusu size toplam satır sayısını döner. 50'şer olarak sayfalayarak sorgulama yapabilirsiniz. Tek işlem sorgulamada geçersiz olacaktır.
orderType alanı true ya da false olarak yollanır ve tarihe göre sıralamayı seçmenize yarar. null ve false değerleri artan olarak sıralama yapar. Tek işlem sorgulamada geçersiz olacaktır.
ticketId alanı Sorgulanmak istenen ödeme işlemine ait ticketId değeri yollanır. Toplu işlem sorgulamada geçersiz olacaktır.
orderId alanı Sorgulanmak istenen ödeme işlemine ait daha önce BKM Express'e gönderilmiş sipariş numarası(orderId) değeri yollanır. Toplu işlem sorgulamada geçersiz olacaktır.

BKM Express'ten iş yerine dönülecek cevap

BKM Express'ten size dönecek cevabı yandaki kod bloğunda görebilirsiniz.

Aşağıda da cevaptaki alanların detaylarını görebilirsiniz.

// Örnek bir başarılı toplu işlem sorgulama cevabı:
{
  "code": "OK-COM-001",
  "call": "merchant/{id}/command",
  "description": "Başarıyla tamamlandı.",
  "message": "Completed successfully.",
  "result": "ok",
  "parameters": {},
  "data": {
    "status": "ok",
    "transactionCount": "179",
    "page": "1",
    "merchantTransactions": [
      {
         "ticket": "fac1ee27-6132-45d6-99c9-160f91e421a3",
         "amount": "6000,52",
         "paymentAmount": "6000,52",
         "paymentDate": "2017-11-01 01:16:41.292",
         "bankCode": "0010",
         "vposBankCode": "0010",
         "installment": "1",
         "paymentResult": "0",
         "posResponse": "{\"orderId\":\"\",\"groupId\":\"\",\"response\":\"Error\",\"authCode\":\"\",\"hostRefNum\":\"\",\"procReturnCode\":\"99\",\"transId\":\"15177OSDD00100673\",\"errMsg\":\"HP SV - 4200 TL üzeri işlem kabul edilmedi.\",\"extra\":{\"settleId\":\"\",\"trxDate\":\"20171101 01:17:26\",\"errorCode\":\"CORE-2507\",\"hostDate\":null,\"numCode\":\"992507\"}}",
         "failResultReason": "Sanal POS'tan hata alındı.",
         "failResultCode": "04",
         "isPreAuth": "false",
         "tcknHash": "d10a5af1bb4a62e47911002232b2229022137b4f6cbe9d7fbaa8db6976615f72",
         "first6digits": "454360",
         "last4digits": "3655"
      },
      ...
    ]
  }
}
// Örnek bir başarılı tek işlem sorgulama cevabı:
{
    "code": "OK-COM-001",
    "call": "merchant/merchantTransactionList",
    "description": "Başarıyla tamamlandı.",
    "message": "Completed successfully.",
    "result": "ok",
    "parameters": {},
    "data": {
        "status": "ok",
               "merchantTransactions": [
            {
                "ticket": "7ea9305d-5855-418d-ab67-4f34dbfe4a01",
                "orderId": "fdc212f1-4ee8-4789-b01a-e726b3ca5633",
                "amount": "14,44",
                "paymentAmount": "14,44",
                "paymentDate": "2019-09-16 09:28:27.38",
                "bankCode": "0010",
                "vposBankCode": "0046",
                "installment": "1",
                "paymentResult": "1",
                "authorizationCode": "662480",
                "posResponse": "{\"orderId\":\"fdc212f1-4ee8-4789-b01a-e726b3ca5633\",\"groupId\":\"fdc212f1-4ee8-4789-b01a-e726b3ca5633\",\"response\":\"Approved\",\"authCode\":\"662480\",\"hostRefNum\":\"509614421347\",\"procReturnCode\":\"00\",\"transId\":\"15096OrKA00120108\",\"errMsg\":\"\",\"extra\":{\"settleId\":\"854\",\"trxDate\":\"20150406 14:43:09\",\"errorCode\":\"\",\"hostDate\":null,\"numCode\":\"00\",\"hostMsg\":\"000 ONAY KODU XXXXXX\",\"cevapAltKoduAciklama\":null,\"cevapAltKodu\":null}}",
                "referenceNumber": "509614421347",
                "failResultCode": "00",
                "isPreAuth": "false",
                "tcknHash": "59b1875e1f86ff80bdfa7bfbd65dab880e0ddb91dce45bd82da016a7a63dca4b",
                "first6digits": "540130",
                "last4digits": "4456"
            }

        ]
    }
}
Cevap İçeriği
Content-Type Başlığı application/json
result alanı Bu alan içerisinde istek sonucu döner. 'ok’ ise işlem başarılı olmuştur.
code alanı Bu alan içerisinde istek sonuç kodu döner. İşlem listesi isteği hata kodları için tıklayın.
data alanı Bu alan işlemleriniz ile ilgili bilgileri içerir.
data İçeriği
transactionCount alanı Yapılan istekte dönen toplam işlem sayısını içerir.
page alanı İstek yapılan sayfa numarasını içerir.
merchantTransactions alanı İstek sonucunda dönen işlem özetlerini içerir.
data.merchantTransactions İçeriği
orderId alanı İşlemin sipariş numarası bilgisini içerir.
amount alanı İşlemin başında belirtilen tutar bilgisini içerir.
paymentAmount alanı İşlemin sonunda pos'a yollanan tutar bilgisini içerir.
Vade farklı işlemlerde amount alanından farklı olabilir.
paymentDate alanı İşlemin zaman bilgisini içerir.
bankCode alanı İşlemde kullanılan kartın banka bilgisini içerir.
vposBankCode alanı İşlemde kullanılan vpos'un banka bilgisini içerir.
installment alanı İşlemin taksit bilgisini içerir.
paymentResult alanı İşlemin başarılı olup olmadığını gösterir. 1 başarılı, 0 başarısız.
failResultReason alanı Başarısız işlemlerde işlemin neden başarısız olduğu bilgisini içerir.
Başarılı işlemlerde bu alan boş dönülecektir.
Alabileceği değerler; “Gönderilen parametrelere göre sistemde herhangi bir kayıt bulunamadı.”,“Kullanıcı ödeme işlemini tamamlamadı.”,“Sanal POS'tan hata alındı”, “OTP'de hata alındı”
authorizationCode alanı İşlemin authorizationCode bilgisini içerir.
posResponse alanı İşlemin vpos üzerinden aldığı cevap bilgilerini içerir.
referenceNumber alanı İşlemin referenceNumber bilgisini içerir.
isPreAuth alanı İşlemin ön otorizasyona ya da ödemeye ait olduğunu gösterir. Ödeme işlemi için bu değer “false”, ön otorizasyon için “true"dir.
tcknHash alanı Kullanıcıya ait tckn bilgisini hash değerinde döner.
first6digits alanı İşleme ait kartın ilk 6 hane bin bilgisini döner.
last4digits alanı İşleme ait kartın son 4 hane bin bilgisini döner.

İşlem listesi sorgulama isteği hata kodlari

İşlem listesi isteğine dönen hata kodları

KOD AÇIKLAMA
OK-FE-CON-001 Başarıyla tamamlandı.
EX-FE-CON-009 id ya da signature parametresi eksik.
EX-MS-MRC-002 İş yeri id bilgisi yanlış.
EX-MS-MRC-004 İş yeri imzalama hatası.
EX-COM-001 İş yeri imzalama formatı hatalı.
EX-COM-002 Yapılan istekteki parametreler kontrol edilmeli.
EX-COM-004 Yapılan istekteki parametreler kontrol edilmeli.
EX-FE-CON-004 Bağlantı bilgilerinin kullanım süresi doldu.
EX-MS-MRC-005 İş yerinin işlem listesini çağırmaya yetkisi yok.
EX-MS-MRC-006 En fazla hata mesajında belirtilen ay kadar öncesine sorgulama yapılabilir.
EX-MS-MRC-007 Maksimum hata mesajında belirtilen gün sayısı kadar sorgulama yapılabilir.
EX-MS-MRC-008 Maksimum hata mesajında belirtilen sayfa sayısı kadar istek yapılabilir.
EX-MER-COM-001 Tarih formatı 'yyyy-MM-dd HH:mm’ olmalı.
EX-MER-COM-002 Başlangıç ve bitiş tarihi birbirinden farklı olmalı.
EX-MER-COM-003 Başlangıç ve bitiş tarihi şu an ki zamandan önce olmalı.
EX-MER-COM-004 Bitiş tarihi, başlangıç tarihinden sonra olmalı.
EX-MER-COM-005 orderId ve ticketId parametreleri birlikte kullanılamaz.
EX-MER-COM-006 orderId veya ticketId ile paymentResult parametresi kullanılamaz.
EX-MER-COM-007 orderId veya ticketId ile startDate parametresi kullanılamaz.
EX-MER-COM-008 orderId veya ticketId ile endDate parametresi kullanılamaz.
EX-MER-COM-009 orderId veya ticketId ile page parametresi kullanılamaz.
EX-MER-COM-010 orderId veya ticketId ile orderType parametresi kullanılamaz.
EX-MER-COM-011 İşlem listesi sorgulama için yeterli parametre yok.

2. Ön Otorizasyon Kapama

BKM Express üzerinden daha önce ön otorizasyonlu yaptığınız bir işlemin, ön otorizasyon kapamasını yapabilirsiniz.

Önemli: BKM Ön provizyon kapama servisinde sadece işbankası ve garanti sanal pos desteklenmektedir.

İş yerinin yapacağı istek

Yapılması gereken isteği yandaki kod bloğunda görebilirsiniz.

Aşağıda da istekteki alanların detaylarını görebilirsiniz.


curl -X POST https://api.bkmexpress.com.tr/v1/merchant/postAuth\
-H 'content-type: application/json' \
-d '{
    "id":"YOUR-MERCHANT-ID",
    "signature":"Signature",
    "ticketId": {TICKET-ID},
    "orderId": {ORDER-ID}, //(optional)
    "totalAmount": {TOTAL-AMOUNT},
    "posUserId": {POS-USER-ID}, // (RSA şifreleme, Kuş tüyü olmayanlar için zorunlu)
    "posPassword": {POS-PASSWORD},// (RSA şifreleme, Kuş tüyü olmayanlar için zorunlu)
    "serviceUrl": {POS-SERVICE-URL}, // (RSA şifreleme, Kuş tüyü olmayanlar için zorunlu)
    "vposBankCode": {POS-BANK-CODE}, // (Kuş tüyü olmayanlar için zorunlu),
    "extra":{POS-EXTRA} // (seçimli)
}'
İstek
Bağlantı Adresi Prod: https://api.bkmexpress.com.tr/v1/merchant/postAuth
Bağlantı Adresi Preprod: https://preprod-api.bkmexpress.com.tr/v1/merchant/postAuth
Bağlantı Metodu POST
Content-Type application/json
İstek içeriği {
"id”: {Your-Merchant-ID},
“signature”: {SIGNATURE},
“ticketId”: {TICKET-ID},
“orderId”: {ORDER-ID},
“totalAmount”: {TOTAL-AMOUNT},
“posUserId”: {POS-USER-ID},
“posPassword”: {POS-PASSWORD},
“serviceUrl”: {POS-SERVICE-URL},
“bankIndicator”: {BANK-CODE},
“extra”:{POS-EXTRA}
}
İstek içerisindeki parametrelerin açıklamaları:
id alanı BKM tarafından size iletilen 'id’ bilgisi
signature alanı 'id’ alanına yazılan değerin BKM tarafına public kısmını ilettiğiniz private key ile şifrelenmiş hali. “SHA-256 with RSA” şifreleme yöntemi ile şifrelenmeli. Örnek şifreleme kodu için tıklayın
ticketId alanı Ödeme işlemine ait ticketId bilgisi
orderId alanı Sipariş numara bilgisi
totalAmount alanı Toplam tutar bilgisi
posUserId alanı Pos kullanıcı bilgisi. “SHA-256 with RSA” şifreleme yöntemi ile şifrelenmeli. Şifrelenmiş sonuç Base64.encode edilmeli.
posPassword alanı Pos şifre bilgisi. “SHA-256 with RSA” şifreleme yöntemi ile şifrelenmeli. Şifrelenmiş sonuç Base64.encode edilmeli.
serviceUrl alanı Pos servis bağlantı bilgisi. “SHA-256 with RSA” şifreleme yöntemi ile şifrelenmeli. Şifrelenmiş sonuç Base64.encode edilmeli.
vposBankCode alanı Pos Banka kodu bilgisi
extra alanı Pos ek bilgiler.

BKM Express'ten iş yerine dönülecek cevap

BKM Express'ten size dönecek cevabı yandaki kod bloğunda görebilirsiniz.

Aşağıda da cevaptaki alanların detaylarını görebilirsiniz.

// Otorizasyon kapama sonucunda aşağıdaki şekilde response döner. 
{   headers: {
      "content-type":"application/json"
    }
    response: {
      "code": "OK-COM-001",
      "call": "merchant/postAuth",
      "description": "Başarıyla tamamlandı.",
      "message": "Completed successfully",
      "result": "ok",
      "parameters": {},
      "data": {
        "bkmTokenId": {TICKET_ID},
        "totalAmount": {TOTAL-AMOUNT},
        "posResult": {
          "posResponse": "APPROVED",
          "posResultCode": "00",
          "orderId": {ORDER-ID},
          "posTransactionId": {POS-TRANSACTION-ID},
          "rawResponse": {POS-RAW-RESPONSE}
        },
        "paymentPurchased": true
      }
    }
}
Cevap İçeriği
Content-Type Başlığı application/json
result alanı Bu alan içerisinde istek sonucu döner. 'ok’ ise işlem başarılı olmuştur.
code alanı Bu alan içerisinde istek sonuç kodu döner. İşlem listesi isteği hata kodları için tıklayın.
data alanı Bu alan postAuth cevabını içerir.
data İçeriği
bkmTokenId alanı Bu alan {TICKET-ID} değerini içerir
totalAmount alanı Bu alan gönderilen toplam tutar değerini içerir
posResult alanı Pos'dan alınan sonuç bilgisini içerir
paymentPurchased alanı Posta yapılan işlemin durumunu içerir. true işlem başarıyla tamamlandı. false Pos'tan hata alındı.
data.posResult İçeriği
posResponse alanı Pos sonuç bilginisini APPROVED, FAILED içerir.
posResultCode alanı Pos cevap kodunu içerir.
orderId alanı Ödeme sipariş bilgisini içerir.
posTransactionId alanı transaction id bilgisini içerir.
rawResponse alanı Bankadan gelen ham cevabı içerir.

Hata Kodları

KOD AÇIKLAMA
OK-COM-001 Başarıyla Tamamlandı.
EX-FE-CON-009 id ya da signature parametresi eksik.
EX-MS-MRC-002 İş yeri id bilgisi yanlış.
EX-MS-MRC-004 İş yeri imzalama hatası.
EX-COM-001 İş yeri imzalama formatı hatalı.
EX-COM-002 Yapılan istekteki parametreler kontrol edilmeli.
EX-MER-COM-021 Ticket ( ticketId ) parametresi eksik.
EX-MER-COM-022 Toplam tutar ( totalAmount ) gönderimi zorunludur.
EX-MER-COM-023 Gönderilen toplam tutar ( totalAmount ) formatı geçerli değil.
EX-MER-COM-024 Pos kullanıcı bilgisi ( posUserId ) gönderimi zorunludur.
EX-MER-COM-025 Pos şifre bilgisi ( posPassword ) gönderimi zorunludur.
EX-MER-COM-026 Pos servis bağlantı bilgisi ( serviceUrl ) gönderimi zorunludur.
EX-MER-COM-027 Pos banka kodu bilgisi ( vposBankCode ) gönderimi zorunludur.
EX-MER-COM-028 Ön otorizasyon kapama işlemi için yetkiniz bulunmamaktadır.
EX-MER-COM-029 Ön otorizasyon kapama işlemi için yeterli parametre bulunamadı.
EX-MS-POS-003 Gönderilen ticket ( ticketId ) parametresi sistemde bulunamadı.
EX-MS-POS-004 Gönderilen sipariş numarası ( orderId ) ile sistemde bir eşleşme bulunamadı !
EX-MS-POS-005 Gönderilen sipariş numarası ( orderId ) ile sistemde birden fazla eşleşme bulundu !
EX-MS-POS-006 Ön otorizasyon kapama işlemi gönderilen banka kodu ve servis url için uygulanamaz.
EX-MS-POS-008 Gönderilen parametrelerle sanal pos bulunamadı.

Normal Entegrasyon Kullananlar için Test Sanal POS Bilgileri

Taksit entegrasyonu olarak normal entegrasyonu kullanmakta olan iş yerleri ön otorizasyon kapama API isteğinde POS bilgilerini göndermeliler. Preprod ortamında testler sırasında aşağıdaki POS bilgileri kullanılabilir.

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 BKMexpress {“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
DENIZBANK 0134 1 12345 {“ShopCode”:“3123”,
“UserCode”:“InterTestApi”,
“UserPass”:“3”,
“storeKey”:“gDg1N”}
http://srvirt01:7200/mpi/Default.aspx

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

İmzalama ve Şifreleme

İmza oluşturulurken “SHA-256 with RSA” şifreleme yöntemi kullanılmalı ve BKM tarafına ilettiğiniz public key ile eşleşen private key kullanılmalı.

İmzalama ve Şifreleme için Kullanılacak Class

İmzalama ve şifreleme işlemleri için EncryptionUtil class'ını kullanın.

// Java EncryptionUtil sınıfı

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.LinkedHashMap;
import java.util.Map;

public final class EncryptionUtil {
    private static final PublicKey PUBLIC_KEY;

    static {
        PUBLIC_KEY = getPublicKeyFromString(
                "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuZj/TQ9ZRY5KnsA3HMPq" +
                        "bNwI32J+Bisyv7KX7IRJh5rN5LW3g7t6pulArLIEU3sn28ZQEQ+GCb9yvk6zIUoq" +
                        "KBqH0H+gvxOtsklOUkFRgh+/FghNDoe0OzkXTLjQKhh6MRMBR9l3cws9nA2cu+M5" +
                        "kw67F8j0+4SogHJ+VS1wA2kfWx58PNDIg9DtAVwmD1JbjAziPONv0wHSa8oNgia9" +
                        "Tx6ia6FS4nfjRNqpVqI0m2jIcG8yXt1OaBSazkuRlRepMtDVwMGF4xOWXuRVv+G5" +
                        "oiTsbOez9tQAcx+KH0W1Pn9Q9/zzOJyF9AS8J1UDE7c7rKwXGDnuTBU1BwdAGyB8" +
                        "7QIDAQAB"
        );
        java.security.Security.addProvider(
                new org.bouncycastle.jce.provider.BouncyCastleProvider()
        );
    }

    public static String sign(String privateKey, String data) {
        try {
            Signature rsaSignature = Signature.getInstance("SHA256withRSA");
            PrivateKey pk = getPrivateKeyFromString(privateKey);

            rsaSignature.initSign(pk);
            rsaSignature.update(data.getBytes());
            return encode64(rsaSignature.sign());
        } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String encryptWithBex(String dataStr) {
        byte[] data = dataStr.getBytes(StandardCharsets.UTF_8);
        StringBuilder encypted = new StringBuilder();
        for (int i = 0; i <= data.length / 245; i++) {
            byte[] subData = Arrays.copyOfRange(data, i * 245, (i + 1) * 245);
            String subEncrypted = encrypt(PUBLIC_KEY, subData);

            encypted.append(subEncrypted).append("|:*:|");
        }

        return encypted.toString();
    }

    public static String encrypt(PublicKey key, byte[] plaintext) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            return encode64(cipher.doFinal(plaintext));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] decrypt(PrivateKey key, byte[] ciphertext) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, key);
            return cipher.doFinal(ciphertext);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean verifyBexSign(String data, String signature) {
        try {
            Signature rsaSignature = Signature.getInstance("SHA256withRSA");
            rsaSignature.initVerify(PUBLIC_KEY);
            rsaSignature.update(data.getBytes());
            return rsaSignature.verify(decode64(signature));
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return false;
    }

    private static PrivateKey getPrivateKeyFromString(String privateKey) {
        try {
            byte[] privateBytes = decode64(privateKey);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static PublicKey getPublicKeyFromString(String publicKey) {
        try {
            byte[] publicBytes = decode64(publicKey);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return keyFactory.generatePublic(keySpec);
        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String encode64(byte[] data) {
        return new String(Base64.getEncoder().encode(data));
    }

    private static byte[] decode64(String data) {
        return Base64.getDecoder().decode(data);
    }
}
<?php

class EncryptionUtil
{

    const FORMATTED_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuZj/TQ9ZRY5KnsA3HMPqbNwI32J+Bisyv7KX7IRJh5rN5LW3g7t6pulArLIEU3sn28ZQEQ+GCb9yvk6zIUoqKBqH0H+gvxOtsklOUkFRgh+/FghNDoe0OzkXTLjQKhh6MRMBR9l3cws9nA2cu+M5kw67F8j0+4SogHJ+VS1wA2kfWx58PNDIg9DtAVwmD1JbjAziPONv0wHSa8oNgia9Tx6ia6FS4nfjRNqpVqI0m2jIcG8yXt1OaBSazkuRlRepMtDVwMGF4xOWXuRVv+G5oiTsbOez9tQAcx+KH0W1Pn9Q9/zzOJyF9AS8J1UDE7c7rKwXGDnuTBU1BwdAGyB87QIDAQAB";

    public static function sign($privateKey, $data)
    {
        $result = openssl_sign($data, $signature, self::getPrivateKeyFromString($privateKey), "sha256WithRSAEncryption");

        if (!$result) {
            throw new Exception("Sign error");
        }

        return base64_encode($signature);
    }

    private static function getPrivateKeyFromString($privateKey, $passphrase = "")
    {
        $result = openssl_pkey_get_private(self::formatKey($privateKey, "private"), $passphrase);

        if (!$result) {
            throw new Exception("Invalid key specification");
        }

        return $result;
    }

    private static function formatKey($unformattedKey, $keyType)
    {
        $result = "";
        $lineCharacter = 0;

        if ($keyType == "public") {
            $lineCharacter = 64;
            $result = wordwrap($unformattedKey, $lineCharacter, "\n", true);
            $result = "-----BEGIN PUBLIC KEY-----\n" . $result . "\n-----END PUBLIC KEY-----";
        } else {
            $lineCharacter = 65;
            $result = wordwrap($unformattedKey, $lineCharacter, "\n", true);
            $result = "-----BEGIN RSA PRIVATE KEY-----\n" . $result . "\n-----END RSA PRIVATE KEY-----";
        }
        return $result;

    }

    public static function verifyBexSign($ticketId, $signature)
    {
        $result = openssl_verify($ticketId, base64_decode($signature), self::getPublicKeyFromString(self::FORMATTED_PUBLIC_KEY), "sha256WithRSAEncryption");

        if ($result == 1) {
            return true;
        } else if ($result == 0) {
            return false;
        } else {
            throw new Exception(openssl_error_string());
        }

        return true;

    }

    private static function getPublicKeyFromString($publicKey)
    {
        $result = openssl_pkey_get_public(self::formatKey($publicKey, "public"));
        if (!$result) {
            throw new Exception("Invalid key specification");
        }

        return $result;
    }

    public static function encryptWithBex($vposConfig)
    {
        //Assumes 1024 bit key and encrypts in chunks.
        $maxlength = 245;
        $i = 0;
        $encryptedArray = [];
        while ($vposConfig && $vposConfig !== "") {
            $input = substr($vposConfig, 0, $maxlength);
            $vposConfig = substr($vposConfig, $maxlength);
            $result = EncryptionUtil::encryptBex($input);

            if ($result) {
                $encryptedArray[$i] = $result;
            } else {
                throw new Exception("Invalid key specification");
                break;
            }
            $i++;
        }
        return join("|:*:|", $encryptedArray);
    }

    public static function encryptBex($parameter)
    {
        if (openssl_public_encrypt($parameter, $encrypted, self::getPublicKeyFromString(self::FORMATTED_PUBLIC_KEY))) {
            $data = base64_encode($encrypted);
        } else {
            throw new Exception("Invalid key specification");
        }
        return $data;
    }
}

?>
using Org.BouncyCastle.Security;
using System;
using System.Text;
using Org.BouncyCastle.Crypto;
using BexCsharpSDK.Merchant.Request;
using System.Security.Cryptography;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using System.Linq;

namespace BexCsharpSDK.Merchant.Security
{
    /// <summary>
    /// This class provides two methods for signing data, and verifing data.
    /// </summary>
    public sealed class EncryptionUtil
    {
        private static string PublicKey = @"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuZj/TQ9ZRY5KnsA3HMPq" +
                                          @"bNwI32J+Bisyv7KX7IRJh5rN5LW3g7t6pulArLIEU3sn28ZQEQ+GCb9yvk6zIUoq" +
                                          @"KBqH0H+gvxOtsklOUkFRgh+/FghNDoe0OzkXTLjQKhh6MRMBR9l3cws9nA2cu+M5" +
                                          @"kw67F8j0+4SogHJ+VS1wA2kfWx58PNDIg9DtAVwmD1JbjAziPONv0wHSa8oNgia9" +
                                          @"Tx6ia6FS4nfjRNqpVqI0m2jIcG8yXt1OaBSazkuRlRepMtDVwMGF4xOWXuRVv+G5" +
                                          @"oiTsbOez9tQAcx+KH0W1Pn9Q9/zzOJyF9AS8J1UDE7c7rKwXGDnuTBU1BwdAGyB8" +
                                          @"7QIDAQAB";

        /// <summary>
        /// Sign data with your private key.
        /// </summary>
        /// <param name="privateKeyString">Your private key</param>
        /// <param name="data">Data to sign</param>
        /// <returns></returns>
        public static string Sign(string privateKeyString, string data)
        {
            var privateKey = PrivateKeyFactory.CreateKey(Convert.FromBase64String(privateKeyString));
            var bytes = new ASCIIEncoding().GetBytes(data);

            ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
            signer.Init(true, privateKey);
            signer.BlockUpdate(bytes, 0, bytes.Length);
            var signature = signer.GenerateSignature();
            return Convert.ToBase64String(signature);
        }

        /// <summary>
        /// Verify incoming data with incoming signature
        /// </summary>
        /// <param name="data">Data to verify</param>
        /// <param name="signature">Verify data with this parameter</param>
        /// <returns></returns>
        public static bool VerifyBexSignature(string data, string signature)
        {
            var dataBytes = new ASCIIEncoding().GetBytes(data);
            var signatureBytes = Convert.FromBase64String(signature);

            ISigner signer = SignerUtilities.GetSigner("SHA256withRSA");
            var publicKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(PublicKey));
            signer.Init(false, publicKey);
            signer.BlockUpdate(dataBytes, 0, dataBytes.Length);
            return signer.VerifySignature(signatureBytes);
        }

        public static string EncryptWithBex(string data)
        {
            var dataBytes = new ASCIIEncoding().GetBytes(data);

            var encrypted = new StringBuilder();
            for (int i = 0; i <= dataBytes.Length / 245; i++)
            {
                var sub = dataBytes.Skip(i * 245).Take(245).ToArray<byte>();
                var subEncrypted = Encrypt(sub);
                encrypted.Append(subEncrypted).Append("|:*:|");
            }
            return encrypted.ToString();
        }

        public static string EncryptWithBex(string data)
        {
            return Encrypt(new ASCIIEncoding().GetBytes(data));
        }

        public static string Encrypt(byte[] data)
        {
            var engine = new Pkcs1Encoding(new RsaEngine());
            var publicKey = PublicKeyFactory.CreateKey(Convert.FromBase64String(PublicKey));
            engine.Init(true, publicKey);
            var encrypted = engine.ProcessBlock(data, 0, data.Length);

            return Convert.ToBase64String(encrypted);
        }
    }
}

İmza oluşturma

EncryptionUtil class'ını kullanarak SIGNATURE oluşturun.

// Java EncryptionUtil sınıfı kullanılarak örnek imzalama işlemi

// Sign signature
String privateKey = "...";

String signature = EncryptionUtil.sign(privateKey, {MERCHANT-ID});
<?php

// PHP EncryptionUtil sınıfı kullanılarak örnek imzalama işlemi

// Sign signature
$privateKey = "...";

EncryptionUtil::sign({MERCHANT-ID}, $privateKey);

?>
// CSharp EncryptionUtil sınıfı kullanılarak örnek imzalama işlemi

// Sign signature
string PrivateKey = "...";

string Signature = EncryptionUtil.Sign(PrivateKey, {MERCHANT-ID});

Örnek İmzalama İşlemi Değişken Açıklama
PRIVATE KEY {PRIVATE-KEY} MIICdgIB…xolJg==
DATA {MERCHANT-ID} 219be6b7-b3ca-4bd1-9886-a16d40b0bfe2
BEKLENEN SONUÇ {SIGNATURE} IGNoNOR/qq+GSQBJBsBuaTgNEWl…/KUye2dR4P8ut6WmZ4qbqE=

Şifreleme

EncryptionUtil class'ını kullanarak EXTRA parametrelerini şifreleyin.

// Java EncryptionUtil kullanılarak örnek şifreleme işlemi

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

Map<String, String> extraMap = new LinkedHashMap<>();

extraMap.put("customItems", "%3CItem%20name%3D%22ACENTE_KODU%22%20value%3D%2221016%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22MUSTERI%22%20value%3D%226210060402%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22POLICE_NO%22%20value%3D%22243149023%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SUBE_KODU%22%20value%3D%222101500009%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22URUN%22%20value%3D%2237101-Emtia%20Nakli(Abonman%20szle%C5%9Fmesine%20ba%C4%9Fl%C4%B1)%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22KOMISYON%22%20value%3D%226.12%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SICIL%22%20value%3D%2228284%22%3E%3C%2FItem%3E%0A");
extraMap.put("Cari_Pol_No", "123ZE");

try{
     String extraJsonString = new ObjectMapper().writeValueAsString(extraMap);
     String encryptedExtra EncryptionUtil.encryptWithBex(extraJsonString);
}catch(Exception e) {
   throw new RuntimeException(e);
}
<?php
// PHP EncryptionUtil kullanılarak örnek şifreleme işlemi

$extraMap = array(
   "customItems" => "%3CItem%20name%3D%22ACENTE_KODU%22%20value%3D%2221016%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22MUSTERI%22%20value%3D%226210060402%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22POLICE_NO%22%20value%3D%22243149023%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SUBE_KODU%22%20value%3D%222101500009%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22URUN%22%20value%3D%2237101-Emtia%20Nakli(Abonman%20szle%C5%9Fmesine%20ba%C4%9Fl%C4%B1)%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22KOMISYON%22%20value%3D%226.12%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SICIL%22%20value%3D%2228284%22%3E%3C%2FItem%3E%0A",

   "Cari_Pol_No" => "123ZE"
);

$encryptedExtra = EncryptionUtil::encryptWithBex(json_encode($extraMap));

?>

// CSharp EncryptionUtil kullanılarak örnek şifreleme işlemi

using Newtonsoft.Json;

var extraMap = new Dictionary<string, double>();

// Initialise to zero...

extraMap["customItems"] = "%3CItem%20name%3D%22ACENTE_KODU%22%20value%3D%2221016%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22MUSTERI%22%20value%3D%226210060402%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22POLICE_NO%22%20value%3D%22243149023%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SUBE_KODU%22%20value%3D%222101500009%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22URUN%22%20value%3D%2237101-Emtia%20Nakli(Abonman%20szle%C5%9Fmesine%20ba%C4%9Fl%C4%B1)%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22KOMISYON%22%20value%3D%226.12%22%3E%3C%2FItem%3E%0A%3CItem%20name%3D%22SICIL%22%20value%3D%2228284%22%3E%3C%2FItem%3E%0A";
extraMap["Cari_Pol_No"] = "123ZE";

var encryptedExtra = EncryptionUtil.encryptWithBex(JsonConvert.SerializeObject(extraMap));

3. Adres Entegrasyonu

BKM Express üzerinden kullanıcılarınızın adres bilgilerini alarak ödeme işlemini sağlayabilirsiniz.

Adres Entegrasyonu akışının çalışması için https://test-api.bkmexpress.com.tr/docs/ sayfasında yer alan entagrasyon adımlarının tümünün tamamlanmış olması gerekmektedir. Aşağıdaki adımlar ise adres entegrasyonunu kullanabilmeniz için yapmanız gereken değişikliklerdir.

  1. Adres Entegrasyonu akışının çalışması için Ticket Token üretilirken “addres” alanının değeri “true” olarak gönderilmelidir.
  2. Adres Entegrasyonu akışı başlatılan bir işlem için, kullanıcı BKM Express uygulamasında OTP kodunu girip ödemesini tamamlamak istediğinde iş yeri server’ına yapılan Nonce çağrısı içerisinde kullanıcının seçtiği adres bilgisi iş yerine gönderilir.
  3. İş yerinin bu adres bilgisini alması ve gerekli kontrollerini yapıp nonce’ı onaylaması beklenmektedir.
  4. Nonce sürecinde ödemenin başarılı geçildiği bilgisi iş yerine iletildiğinde, daha önce iletilen adres bilgisi ile iş yerinin siparişi tamamlaması gerekmektedir.

ÖNEMLİ Kullanıcı adresi BKM Express içerisinde seçtiğinden kullanıcıya onaylatacağınız mesafeli satış sözleşmesi ve ön bilgilendirme formu, BKM Express içerisinde adres seçildikten sonra görüntülenecektir. Bu nedenle Mesafeli Satış Sözleşmesi ve Ön Bilgilendirme Formu adımını da tamamlamanız gerekmektedir.

2.1 Builder Kullanılarak Ticket Token Üretilmesi (Sipariş Numarası, Kampanya Kodu, TCKN, Email ve Adres 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/installment");  // opsiyonel ("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")

$builder->address(true);  // opsiyonel (adres entegrasyonları kullananlar için)

$builder->agreementUrl("https://isyeri.com/agreement"); // opsiyonel ("Mesafeli satış ve ön bilgilendirme formu için sizin sitenize yönlenecek url") adres entegrasyonları için zorunlu

?>


  request = TicketRequest.Builder.newPayment()
                            .amount("1000,56")
                            .orderId("123456")
                            .campaignCode("my campaign")
                            .installmentUrl("https://isyeri.com/installment")
                            .nonceUrl("https://isyeri.com/nonce")
                            .tckn("10000000146", true)
                            .msisdn("5051234567", true)
                            .agreementUrl("https://isyeri.com/agreement")
                            .address(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
                        .agreementUrl("https://isyeri.com/agreement")
                        .address(true)
                        .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. 2.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. 2.2 Siparişin Uygunluğunu Kontrol Edin (Nonce)

5. Adres entegrasyonu(address): Adres entegrasyonu yapmak isteyen işyerlerinin ticket oluşurken bu bilgiyi iletmesi gerekmektedir. Eğer address alanı true olarak iletilirse, NonceRequest içerisinde işyerine kullanıcının seçtiği adres bilgisi iletilir. Address bilgisini ileten işyerleri agreementUrl değişkenini de iletmelidir.

6. Sözleşme url'i(agreementUrl): Mesafeli satış sözleşmesi ve önbilgilendirme formununun güncel halini ödeme aşamasından önce göstermek isteyen işyerleri, sözleşmeyi kendi siteleri üzerinde göstermek için bir url iletilir. Adres bilgileri nonce aşamasına gelmeden verdiğiniz url'e post edilir ve bu istek sonucunda dönen html kullanıcıya gösterilir.


<?php
//Ticket oluşturulurken adres entegrasyonu için paremetrenin geçilmesi
$builder = Builder::newPayment("payment");

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

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

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

$builder->address(true);  // opsiyonel (adres entegrasyonları kullananlar için)

$builder->agreementUrl("https://isyeri.com/agreement"); // opsiyonel ("Mesafeli satış ve ön bilgilendirme formu için sizin sitenize yönlenecek url") adres entegrasyonları için zorunlu
$ticketResponse = $merchantService->oneTimeTicketWithBuilder($merchantResponse->getToken(), $builder);
?>


//Ticket oluşturulurken adres entegrasyonu için paremetrenin geçilmesi
request = TicketRequest.Builder.newPayment()
                            .amount("1000,56")
                            .installmentUrl("https://isyeri.com/installment")
                            .nonceUrl("https://isyeri.com/nonce")
                            .agreementUrl("https://isyeri.com/agreement")
                            .address(true)
                            .build();


Token ticket = bex.merchantService().createOneTimeTicket(connection, tr); (edited)
//Ticket oluşturulurken adres entegrasyonu için paremetrenin geçilmesi
ticketRequest = new TicketRequest.Builder()
                        .newPayment()
                        .amount("1000,56") // sipariş toplam tutarı
                        .campaignCode("my campaign") // kampanya kodu
                        .installmentUrl("https://isyeri.com/installment")
                        .nonceUrl("https://isyeri.com/nonce")
                        .agreementUrl("https://isyeri.com/agreement")
                        .address(true)
                        .build();

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

<?php
class NonceRequest {
    ...
    public function getDeliveryAddress()
    {
        return $this->reply->deliveryAddress;
    }

    public function getBillingAddress()
    {
        return $this->reply->billingAddress;
    }
}
?>

// Nonce request içerisinde aşağıdaki gibi Address alanları iletilecektir.
public class NonceRequest {
    ...

    public Address getDeliveryAddress() {
        return this.reply.getDeliveryAddress();
    }

    public Address getBillingAddress() {
        return this.reply.getBillingAddress();
    }
    ...
}    

// Nonce request'inde fatura ve teslimat adreslerine aşağıdaki şekilde erişebilirsiniz.
request.billingAddress;
request.deliveryAddress;

<?php
class Address
{
    private $addressType;
    private $name;
    private $surname;
    private $companyName;
    private $address;
    private $telephone;
    private $taxNumber;
    private $taxOffice;
    private $county;
    private $city;
    private $tckn;
    private $email;
    ..
}


class AddressType
{
    const INDIVIDUAL = "B";
    const CORPORATE = "K";
}

public class Address {

    private AddressType addressType;
    private String name;
    private String surname;
    private String companyName;
    private String address;
    private String telephone;
    private String taxNumber;
    private String taxOffice;
    private String county;
    private String city;
    private String tckn;
    private String email;

    ....
}

public enum AddressType {
    B("individual"),
    K("corporate");
    ...
}
public class Address
    {
        public enum AddressType {B, K}
        public AddressType addressType { get; set; }
        public String name { get; set; }
        public String surname { get; set; }
        public String companyName { get; set; }
        public String address { get; set; }
        public String telephone { get; set; }
        public String taxNumber { get; set; }
        public String taxOffice { get; set; }
        public String county { get; set; }
        public String city { get; set; }
        public String tckn { get; set; }
        public String email { get; set; }
    }

2.2 Siparişin Uygunluğunu Kontrol Edin (Nonce)

Nonce sırasında kullanıcının adresine ilişkin size iletilecek bilgiler;

Alan Adı Açıklama
String email e-posta adresi->login olduğu mail adresi bilgisi
AddressType addressType adres tipi -> B ya da K olabilir. B : bireysel K: kurumsal.Bireysel için tckn değeri zorunludur. Kurumsal için taxOffice,taxNumber ve companyName değerleri zorunludur.
String ad ad
String surname soyad
String address adres -> Adress entegrasyonu kullanılacaksa bu değer true olmalı. Kullanılmayacaksa iletilmemelidir.
String county ilçe -> adrese ait ilçe
String city il -> adrese ait il
String telephone telefon numarası
String tckn ilçe -> adress tipi bireysel olması durumunda doldurulması zorunlu alan
String companyName ilçe -> adress tipi kurumsal olması durumunda doldurulması zorunlu alan
String taxNumber ilçe -> adress tipi kurumsal olması durumunda doldurulması zorunlu alan.Vergi kimlik numarası.
String taxOffice ilçe -> adress tipi kurumsal olması durumunda doldurulması zorunlu alan.Vergi dairesi adı.

Mesafeli Satış Sözleşmesi ve Ön Bilgilendirme Formu’nun BKM Express’te Gösterilmesi


//BKM Express tarafından iframe içerisinden agreement url'e yapılacak istek
curl 'https://isyeri.com/agreementUrl' --data '
ticketId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
orderId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
amount=1000%2C52&
deliveryAddress.addressType=B&
deliveryAddress.city=%C4%B0zmir&
deliveryAddress.address=qweqwq&
deliveryAddress.companyName=&
deliveryAddress.county=Bay%C4%B1nd%C4%B1r&
deliveryAddress.email=zeynep%40bkm.com&
deliveryAddress.name=weqeqe&
deliveryAddress.surname=qweqwe&
deliveryAddress.taxNumber=&
deliveryAddress.taxOffice=&
deliveryAddress.tckn=44444444444&
deliveryAddress.telephone=5333333333&
billingAddress.addressType=B&
billingAddress.city=%C4%B0zmir&
billingAddress.address=qweqwq&
billingAddress.companyName=&
billingAddress.county=Bay%C4%B1nd%C4%B1r&
billingAddress.email=zeynep%40bkm.com&
billingAddress.name=weqeqe&
billingAddress.surname=qweqwe&
billingAddress.taxNumber=&
billingAddress.taxOffice=&
billingAddress.tckn=44444444444&
billingAddress.telephone=5333333333' --compressed


//BKM Express tarafından iframe içerisinden agreement url'e yapılacak istek
curl 'https://isyeri.com/agreementUrl' --data '
ticketId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
orderId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
amount=1000%2C52&
deliveryAddress.addressType=B&
deliveryAddress.city=%C4%B0zmir&
deliveryAddress.address=qweqwq&
deliveryAddress.companyName=&
deliveryAddress.county=Bay%C4%B1nd%C4%B1r&
deliveryAddress.email=zeynep%40bkm.com&
deliveryAddress.name=weqeqe&
deliveryAddress.surname=qweqwe&
deliveryAddress.taxNumber=&
deliveryAddress.taxOffice=&
deliveryAddress.tckn=44444444444&
deliveryAddress.telephone=5333333333&
billingAddress.addressType=B&
billingAddress.city=%C4%B0zmir&
billingAddress.address=qweqwq&
billingAddress.companyName=&
billingAddress.county=Bay%C4%B1nd%C4%B1r&
billingAddress.email=zeynep%40bkm.com&
billingAddress.name=weqeqe&
billingAddress.surname=qweqwe&
billingAddress.taxNumber=&
billingAddress.taxOffice=&
billingAddress.tckn=44444444444&
billingAddress.telephone=5333333333' --compressed

//BKM Express tarafından iframe içerisinden agreement url'e yapılacak istek
curl 'https://isyeri.com/agreementUrl' --data '
ticketId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
orderId=17355c4c-f3a3-4573-9780-fb38dd7eee0a&
amount=1000%2C52&
deliveryAddress.addressType=B&
deliveryAddress.city=%C4%B0zmir&
deliveryAddress.address=qweqwq&
deliveryAddress.companyName=&
deliveryAddress.county=Bay%C4%B1nd%C4%B1r&
deliveryAddress.email=zeynep%40bkm.com&
deliveryAddress.name=weqeqe&
deliveryAddress.surname=qweqwe&
deliveryAddress.taxNumber=&
deliveryAddress.taxOffice=&
deliveryAddress.tckn=44444444444&
deliveryAddress.telephone=5333333333&
billingAddress.addressType=B&
billingAddress.city=%C4%B0zmir&
billingAddress.address=qweqwq&
billingAddress.companyName=&
billingAddress.county=Bay%C4%B1nd%C4%B1r&
billingAddress.email=zeynep%40bkm.com&
billingAddress.name=weqeqe&
billingAddress.surname=qweqwe&
billingAddress.taxNumber=&
billingAddress.taxOffice=&
billingAddress.tckn=44444444444&
billingAddress.telephone=5333333333' --compressed


//BKM Express tarafından post ile yapılan isteğe cevap olarak dönmeniz gereken sözleşmeler için örnek html kodu
<!DOCTYPE HTML>
<html lang="en">
<head>
    <style>
        table {
            border-collapse: collapse;
            width: 100%;
            font-size: small;
        }

        th, td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }
    </style>
</head>
<body>
<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>
<div>
    <div style=" padding: 10px;overflow: scroll;-webkit-overflow-scrolling: touch">
        <h5 style="text-align: center;font-weight: bold;letter-spacing: 0.5px">
            Yeni ekledigimiz ozelliklerle birlikte kullanici sozlesmemizi yeniledik.</h5>
        <br/>
        <div style="height: 365px">
            <div>
                <h4>Siparis Bilgisi</h4>
                <table>
                    <tr>
                        <th>
                            Kalem
                        </th>
                        <th>
                            Deger
                        </th>
                    </tr>
                    <tr>
                        <td>ticketId:</td>
                        <td><?php echo $_POST['ticketId']; ?></td>
                    </tr>
                    <tr>
                        <td>orderId:</td>
                        <td> <?php echo $_POST['orderId']; ?></td>
                    </tr>
                    <tr>
                        <td>totalAmount:</td>
                        <td> <?php echo $_POST['amount']; ?></td>
                    </tr>
                </table>
            </div>

            <div>
                <h4>Teslimat Adresi Bilgisi</h4>
                <table>
                    <tr>
                        <th>
                            Kalem
                        </th>
                        <th>
                            Deger
                        </th>
                    </tr>
                    <tr>
                        <td>Adres Tipi:</td>
                        <td><?php echo $_POST['deliveryAddress_addressType']; ?></td>
                    </tr>
                    <tr>
                        <td>Il :</td>
                        <td><?php echo $_POST['deliveryAddress_city']; ?></td>
                    </tr>
                    <tr>
                        <td>Ilce:</td>
                        <td><?php echo $_POST['deliveryAddress_county']; ?></td>
                    </tr>
                    <tr>
                        <td>Acik Adres :</td>
                        <td><?php echo $_POST['deliveryAddress_address']; ?></td>
                    </tr>
                    <tr>
                        <td>Şirket Unvani :</td>
                        <td><?php echo $_POST['deliveryAddress_companyName']; ?></td>
                    </tr>
                    <tr>
                        <td>Email :</td>
                        <td><?php echo $_POST['deliveryAddress_email']; ?></td>
                    </tr>
                    <tr>
                        <td>Ad:</td>
                        <td><?php echo $_POST['deliveryAddress_name']; ?></td>
                    </tr>
                    <tr>
                        <td>Soyad:</td>
                        <td><?php echo $_POST['deliveryAddress_surname']; ?></td>
                    </tr>
                    <tr>
                        <td>Vergi Kimlik Numarasi :</td>
                        <td><?php echo $_POST['deliveryAddress_taxNumber']; ?></td>
                    </tr>
                    <tr>
                        <td>Vergi Dairesi</td>
                        <td><?php echo $_POST['deliveryAddress_taxOffice']; ?></td>
                    </tr>
                    <tr>
                        <td>TCKN:</td>
                        <td><?php echo $_POST['deliveryAddress_tckn']; ?></td>
                    </tr>
                    <tr>
                        <td>Telefon Numarasi</td>
                        <td><?php echo $_POST['deliveryAddress_telephone']; ?></td>
                    </tr>
                </table>
            </div>

            <div>
                <h4>Fatura Adresi Bilgisi</h4>
                <table>
                    <tr>
                        <td>Adres Tipi:</td>
                        <td><?php echo $_POST['billingAddress_addressType']; ?></td>
                    </tr>
                    <tr>
                        <td>Il :</td>
                        <td><?php echo $_POST['billingAddress_city']; ?></td>
                    </tr>
                    <tr>
                        <td>Ilce:</td>
                        <td><?php echo $_POST['billingAddress_county']; ?></td>
                    </tr>
                    <tr>
                        <td>Acik Adres :</td>
                        <td><?php echo $_POST['billingAddress_address']; ?></td>
                    </tr>
                    <tr>
                        <td>Şirket Unvani :</td>
                        <td><?php echo $_POST['billingAddress_companyName']; ?></td>
                    </tr>
                    <tr>
                        <td>Email :</td>
                        <td><?php echo $_POST['billingAddress_email']; ?></td>
                    </tr>
                    <tr>
                        <td>Ad:</td>
                        <td><?php echo $_POST['billingAddress_name']; ?></td>
                    </tr>
                    <tr>
                        <td>Soyad:</td>
                        <td><?php echo $_POST['billingAddress_surname']; ?></td>
                    </tr>
                    <tr>
                        <td>Vergi Kimlik Numarasi :</td>
                        <td><?php echo $_POST['billingAddress_taxNumber']; ?></td>
                    </tr>
                    <tr>
                        <td>Vergi Dairesi</td>
                        <td><?php echo $_POST['billingAddress_taxOffice']; ?></td>
                    </tr>
                    <tr>
                        <td>TCKN:</td>
                        <td><?php echo $_POST['billingAddress_tckn']; ?></td>
                    </tr>
                    <tr>
                        <td>Telefon Numarasi</td>
                        <td><?php echo $_POST['billingAddress_telephone']; ?></td>
                    </tr>
                </table>
            </div>
        </div>
    </div>
    <div style="width:100%">
        <input onclick='acceptAgreement()' style="width:1%" id="acceptCheck" name="acceptCheck" type="checkbox" />
        <label for="acceptCheck">
            <a>Kullanıcı sözleşmesini</a>okudum, anladım, kabul ediyorum.
        </label>
    </div>
</div>
</body>

</html>

//BKM Express tarafından post ile yapılan isteğe cevap olarak dönmeniz gereken sözleşmeler için örnek html kodu
<!DOCTYPE HTML>
<html lang="tr" xmlns="http://www.w3.org/1999/html">

<body>
<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>
<div>
    <div style=" padding: 10px;width: 360px;height: 380px;overflow: scroll;-webkit-overflow-scrolling: touch;border: thin dotted #d8d8d8;">
        <h5 style="text-align: center;font-weight: bold;letter-spacing: 0.5px">
            Yeni eklediğimiz özelliklerle birlikte kullanıcı sözleşmemizi yeniledik.</h5>
        <br/>
        <div>
            ticketId: ${model.ticketId};
            orderId: ${model.orderId};
            totalAmount: ${model.amount};

            billingAddress.addressType: ${model.billingAddress.addressType};
            billingAddress.name: ${model.billingAddress.name};
            billingAddress.surname: ${model.billingAddress.surname};
            billingAddress.companyName: ${model.billingAddress.companyName};
            billingAddress.address: ${model.billingAddress.address};
            billingAddress.telephone: ${model.billingAddress.telephone};
            billingAddress.taxNumber: ${model.billingAddress.taxNumber};
            billingAddress.taxOffice: ${model.billingAddress.taxOffice};
            billingAddress.county: ${model.billingAddress.county};
            billingAddress.city: ${model.billingAddress.city};
            billingAddress.tckn: ${model.billingAddress.tckn};
            billingAddress.email: ${model.billingAddress.email};

            deliveryAddress.addressType: ${model.deliveryAddress.addressType};
            deliveryAddress.name: ${model.deliveryAddress.name};
            deliveryAddress.surname: ${model.deliveryAddress.surname};
            deliveryAddress.companyName: ${model.deliveryAddress.companyName};
            deliveryAddress.address: ${model.deliveryAddress.address};
            deliveryAddress.telephone: ${model.deliveryAddress.telephone};
            deliveryAddress.taxNumber: ${model.deliveryAddress.taxNumber};
            deliveryAddress.taxOffice: ${model.deliveryAddress.taxOffice};
            deliveryAddress.county: ${model.deliveryAddress.county};
            deliveryAddress.city: ${model.deliveryAddress.city};
            deliveryAddress.tckn: ${model.deliveryAddress.tckn};
            deliveryAddress.email: ${model.deliveryAddress.email};

        </div>
    </div>
    <div style="width:100%">
        <input onclick='acceptAgreement()' style="width:1%" id="acceptCheck" name="acceptCheck" type="checkbox" />
        <label for="acceptCheck">
            <a>Kullanıcı sözleşmesini</a>okudum, anladım, kabul ediyorum.
        </label>
    </div>
</div>
</body>

</html>


//BKM Express tarafından post ile yapılan isteğe cevap olarak dönmeniz gereken sözleşmeler için örnek html kodu
<!DOCTYPE HTML>
<html lang="tr" xmlns="http://www.w3.org/1999/html">

<body>
<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>
<div>
    <div style=" padding: 10px;width: 360px;height: 380px;overflow: scroll;-webkit-overflow-scrolling: touch;border: thin dotted #d8d8d8;">
        <h5 style="text-align: center;font-weight: bold;letter-spacing: 0.5px">
            Yeni eklediğimiz özelliklerle birlikte kullanıcı sözleşmemizi yeniledik.</h5>
        <br/>
        <div>
            ticketId: ${model.ticketId};
            orderId: ${model.orderId};
            totalAmount: ${model.amount};

            billingAddress.addressType: ${model.billingAddress.addressType};
            billingAddress.name: ${model.billingAddress.name};
            billingAddress.surname: ${model.billingAddress.surname};
            billingAddress.companyName: ${model.billingAddress.companyName};
            billingAddress.address: ${model.billingAddress.address};
            billingAddress.telephone: ${model.billingAddress.telephone};
            billingAddress.taxNumber: ${model.billingAddress.taxNumber};
            billingAddress.taxOffice: ${model.billingAddress.taxOffice};
            billingAddress.county: ${model.billingAddress.county};
            billingAddress.city: ${model.billingAddress.city};
            billingAddress.tckn: ${model.billingAddress.tckn};
            billingAddress.email: ${model.billingAddress.email};

            deliveryAddress.addressType: ${model.deliveryAddress.addressType};
            deliveryAddress.name: ${model.deliveryAddress.name};
            deliveryAddress.surname: ${model.deliveryAddress.surname};
            deliveryAddress.companyName: ${model.deliveryAddress.companyName};
            deliveryAddress.address: ${model.deliveryAddress.address};
            deliveryAddress.telephone: ${model.deliveryAddress.telephone};
            deliveryAddress.taxNumber: ${model.deliveryAddress.taxNumber};
            deliveryAddress.taxOffice: ${model.deliveryAddress.taxOffice};
            deliveryAddress.county: ${model.deliveryAddress.county};
            deliveryAddress.city: ${model.deliveryAddress.city};
            deliveryAddress.tckn: ${model.deliveryAddress.tckn};
            deliveryAddress.email: ${model.deliveryAddress.email};

        </div>
    </div>
    <div style="width:100%">
        <input onclick='acceptAgreement()' style="width:1%" id="acceptCheck" name="acceptCheck" type="checkbox" />
        <label for="acceptCheck">
            <a>Kullanıcı sözleşmesini</a>okudum, anladım, kabul ediyorum.
        </label>
    </div>
</div>
</body>

</html>


//Kullanıcı sözleşmeyi onayladığında BKM Express uygulamasına dönüş için kullanılması gereken javascript fonksiyonu

<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>


//Kullanıcı sözleşmeyi onayladığında BKM Express uygulamasına dönüş için kullanılması gereken javascript fonksiyonu

<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>


//Kullanıcı sözleşmeyi onayladığında BKM Express uygulamasına dönüş için kullanılması gereken javascript fonksiyonu

<script>
    function acceptAgreement() {
        window.parent.postMessage("close", "*");
    }
</script>

Adres ve ödeme bilgileri seçildikten sonra mesafeli satış sözleşmesi ve ön bilgilendirme formunu hukuki zorunluluklardan dolayı işyerinin sitesi üzerinde gösterilmesi gerekmektedir. Bunun için aşağıdaki adımları takip etmelisiniz;

  1. Ticket oluştururken gönderdiğiniz agreementUrl adresine BKM Express uygulaması içerisinde iframe açılıp, post ile adres ve işlem bilgileri iletilir.
  2. Bu aşamada post isteğini karşılayıp sayfanız üzerinde html ile sözleşmeleri göstermeniz gerekmektedir.
  3. Bu html içerisindeki sözleşmeleri kullanıcı onayladığında kendi sunucunuz üzerinde bu sözleşmelerin onaylandığını tutup, size vereceğimiz javascript kod örneği ile sözleşme onayını tamamlamalısınız.
  4. Sizden aldığımız onay ile BKM Express uygulamasında ödeme işlemine devam edilir.

4. İptal İade Servisi

BKM Express üzerinden gerçekleşen sanal pos işlemlerin İptal / İade sürecini sağlayan servistir.İptal / İade işlemleri işyeri tarafından referanslı işlemde token; işlem tipi ve tutar bilgisi ile başlatılır. İşyeri İptal / İade servisini her çağırdığında tekil (unique) bir referans numarası iletir, gerektiği durumlarda karşılıklı olarak işlemler bu tekil numara ile takip edilir.

İptal – iade hizmeti için kullanılacak olan web servislerin çalışma prensipleri aşağıdaki gibidir.

doReversalWithRef Webservisi

Ödemesi BKM tarafından gerçekleştirilen işlemler için iptal –iade işlemlerinin gerçekleştirileceği web servistir. İşlem; tutar, işlem tipi ve token bilgileri ile başlatılır.

doReversalWithRef Preprod Endpoint Adresi:

https://preprod.bkmexpress.com.tr/BKMExpress/BKMExpressReversalRestService/reversalWithRef.do

doReversalWithRef Production Endpoint Adresi:

https://www.bkmexpress.com.tr/BKMExpress/BKMExpressReversalRestService/reversalWithRef.do

doReversalWithRef Request Parametreleri

İSTEK PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
uniqueReferans String m 50 doReversalWithNoRef işleminin referans numarası.
merchantId String m 36 İşyeri merchant id’si.
requestType String m 1 İptal için 1;
iade için 2; gönderilmelidir.
amount String m 20 İptal / iade edilecek tutar bilgisi.
“0000,00” formatında iletilir.
currency String m 3 İşlemin döviz kodu. 949 gibi.
posUid String c 50 POS’a giderken kullanılacak kullanıcı adıdır.
posPwd String c 50 POS’a giderken kullanılacak şifredir.
transactionToken String m 50 BKM tarafından ödemesi yapılmış işleme ait token bilgisi yazılır.
extra String o   İptal iade işlemlerinde banka bazında gerekli olabilecek parametrelerin iletileceği alan(JSON formatta)
ts String m 17 yyyyMMdd-hh:mm:ss formatında
s String m   Tüm alanların tablodaki sırayla concat edilerek “SHA-256 with RSA” ile imzalanmış hali -> “Extra” parametresini imzaya dahil etmeyiniz.

//Normal entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "akapi",
  "posPwd": "TEST1234",
  "extra": "{"ClientId":"100111222", "storekey":"TEST1234"}",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}


//Normal entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "akapi",
  "posPwd": "TEST1234",
  "extra": "{"ClientId":"100111222", "storekey":"TEST1234"}",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}


//Normal entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "akapi",
  "posPwd": "TEST1234",
  "extra": "{"ClientId":"100111222", "storekey":"TEST1234"}",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}


//Kuştüyü entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "",
  "posPwd": "",
  "extra": "",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}


//Kuştüyü entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "",
  "posPwd": "",
  "extra": "",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}


//Kuştüyü entegrasyon için örnek doReversalWithRef Request İsteği:

{
  "merchantId": "2CBB2A88-1768-4565-B052-7DF37738DBCF",
  "requestType": "1",
  "amount": "12,31",
  "currency": "949",
  "transactionToken": "78ccd398-6ff6-431c-beeb-f1c9a90a8a14",
  "posUid": "",
  "posPwd": "",
  "extra": "",
  "uniqueReferans": "182709220424024254",
  "ts": "20190118-14:51:33",
  "s": "TKkP/kkIhgtj+2u8CiXRjsCtIuibNVBTQIk/bjMztx09nm0//AKjGRRT2kCjPzC1Yx7QUTRej/cCZE/jTWCrU/8W/jsojbgJO4MLjPOqLyI1B64FOKVeA9u1y+GUT9tN7XJTCTzpOz0OqqKqrTH1YNOKPlwslLfC22KzMB2KfIPCIUS+QFAVaIaGt4qjf4FAK7HcdDfU72eiY21cOuTzUbuQK+hsO5KEQY1B2j++04oeqvgKMkfejGHiM2nl0wcZwzQgJT9AOJvxWspJRVR1fA0gZobyOPrhlYWk48Fj0gTgTiggcdr3yYHyvCXrUHYD3RENY6mIhXF2/v0pFc++QQ=="
}

doReversalWithRef Request “s” alanı için İmza Sıralaması: uniqueReferans , merchantId , requestType , amount , currency , posUid , posPwd , transactionToken, ts

ÖNEMLİ: BKM Express Entegrasyonunuz Kuştüyü alt yapısındaysa posUid ve posPwd alanlarını null gönderebilirsiniz ve null olduğu için imza datanıza eklemeyiniz.Eğer web servis entegrasyonunu kullanıyor iseniz, posUid ve posPwd alanlarını dolu göndermeniz ve imza sıralamasına alanları eklemeniz gerekir.

doReversalWithRef Response Parametreleri

DÖNÜŞ PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
uniqueReferans String m 50 İşyerinin her işlem için gönderdiği unique referans numarası.
ts String m 17 yyyyMMdd-hh:mm:ss formatında
s String m   Tüm alanların tablodaki sırayla concat edilerek “SHA-256 with RSA” ile imzalanmış hali
>code String m 3 Bkz: doReversalWithRef hata kodları tablosu
>message String m 1024 Bkz: doReversalWithRef hata kodları tablosu
PosResult complex m    
>orderId String c <1024 Sipariş numarası
>authCode String c <1024 Otorizasyon kodu
>posResponse String c <1024 APPROVED ya da DECLINED değeri alır.
 >posResultCode String   c <1024   APPROVED ise 00, DECLINED ise bankanın döndüğü hata kodu bulunur.
>posResultMessage String  c <1024  Bankanın döndüğü hata mesajı bulunur.
>referansNumber String  c <1024  Sanal POS’tan gelen referans numarası.
 >posTransactionId String   <1024    Sanal POS’tan gelen transaction ID.
>groupId String   c <1024  
>cardBin String   c <1024 İşlem yapılan kart BIN’i.
>cardBank String   c <1024 İşlem yapılan kart bankasını EFT kodu.
>noflnst İnt c   Taksit sayısı.
>posBank string c <1024 Sanal POS bankasının EFT kodu.

doReversalWithRef Response “s” alanı için İmza Sıralaması aşağıdaki gibi olmalıdır;

uniqueReferans , PosResult , ts

PosResult parametresininde kendi içinde imza sıralaması var, aşağıdaki gibi olmalıdır;

orderId,authCode,posResponse,posResultCode,posResultMessage,referansNumber, posTransactionId,groupId,cardBin,cardBank,noflnst,posBank

doReversalWithRef Hata Kodları

resCode resMsg
0 Success
1 System Error
2 Invalid Input Parameters
3 Time Synchronization Error
4 MAC verification Failed
5 Undefined merchant id
6 NonUnique Reference Id
7 Virtual Pos Error
8 Invalid Acquirer Bank ID
9 Invalid Transaction Token

5. BIN Servisi

İşyerinin E-Ticaret Bin Listesini alabileceği rest servistir.

getBinList Preprod Endpoint Adresi:

https://preprod.bkmexpress.com.tr/BKMExpress/service/bin/getBinList.do

getBinList Production Endpoint Adresi:

https://www.bkmexpress.com.tr/BKMExpress/service/bin/getBinList.do


//getBinList örnek istek

{
"uniqueRefNo": "64e7a855-7e2a-46fa-ac17-5becc42f1449",
"merchantId": "size iletilen merchantid",
"sign": "uniqueRefNomerchantId şifrelenmiş hali"
}


//getBinList örnek istek

{
"uniqueRefNo": "64e7a855-7e2a-46fa-ac17-5becc42f1449",
"merchantId": "size iletilen merchantid",
"sign": "uniqueRefNomerchantId şifrelenmiş hali"
}


//getBinList örnek istek

{
"uniqueRefNo": "64e7a855-7e2a-46fa-ac17-5becc42f1449",
"merchantId": "size iletilen merchantid",
"sign": "uniqueRefNomerchantId şifrelenmiş hali"
}

getBinList Request Parametreleri

İSTEK PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
uniqueRefNo String m max 64 İşyerinin her sorgulama işlemi için göndereceği unique referans numarası.
merchantId String m 32 İşyerinin tanımlı merchant id’si.
sign String m   Yukarıdaki alanların tablodaki sırayla concat edilerek “SHA-256 with RSA” ile imzalanmış hali(uniqrefnomerchantid)

getBinList Request İmza sıralaması : uniqueRefNo, merchantId

getBinList Response Parametreleri

DÖNÜŞ PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
resultCode int m   Dönüş kodu. (bkz. Dönüş Kodları)
0: Başarılı
Diğer değerler: Hata kodu içerir.
(Bkz hata kodları)
resultMsg String m <1024 Dönüş mesajı. (bkz. Dönüş Kodları)
uniqueRefNo String m 64 İşyeri her sorgulama işlemi için göndereceği unique referans numarası.
s String m   Yukarıdaki alanların tablodaki sırayla concat edilerek “SHA-256 with RSA” ile imzalanmış hali. (İmza sıralamasına aşağıdaki alanlar dahil değildir)
> cardType String m   Kart tipi debit or credit
> isBusinessCard String m   Kart tipi
>memberName String m   Banka adı
>memberNo String m   Banka kodu
>prefixNo int m   Bin no

getBinList Response imza sıralaması : resultCode, resultMsg , uniqueRefNo

getBinList Hata Kodları

resCode resMsg
0 Success
1 System Error(loglar incelenmeli)
2 MAC verification Failed
3 Invalid Input Parameters

6. Flow QR Servisi

BKM Express Flow 2.0 entgrasyonumuz üzerinden size dönülen ticket token id'yi QR'a çevirerek ödeme işlemi alabilirsiniz.

6.1 QR Oluşturma Servisi (getEmvQrForLogin) :

https://test-api.bkmexpress.com.tr/docs/ sayfasında yer alan entagrasyon adımlarının tümünün tamamlanmış olması gerekmektedir.Aşağıdaki adımlar ise QR entegrasyonunu kullanabilmeniz için yapmanız gereken değişikliklerdir.

• “Bex.init” metodunda size dönülen ticket token id bilgisi ile aşağıdaki servise istek göndererek, QR data bilgisine ulaşabilirsiniz.

• QR datayı kullanacağınız QR generator tool üzerinden QR formatına çevirebilirsiniz.

• Sayfanızda oluşturduğunuz QR’ı BKM Express uygulaması ile okuttuğunuzda kullanıcı BKM Express uygulamasında kart seçim sayfasına yönlenecektir. Bu adımda backend tarafında geliştirdiğiniz installment adresinize ulaşacaktır.

• BKM Express uygulamasında kullanıcı kartını seçip OTP bilgisini girerek ödeme işlemini tamamlar. Bu adımda ödeme işlemi tamamlanmadan önce backend tarafında geliştirdiğiniz nonce adresinize ulaşacaktır.Nonce’dan ok cevabınız sonrası merchantnonceresponse’u çağırarak ilgili posdan ödeme işlemi tamamlanır ve ödeme sonucu NonceResultResponse ‘a dönülür.

QR Oluşturma Endpoint URL: (Test Ortam)

https://test-api.bkmexpress.com.tr/v1/user/getEmvQrForLogin

// Örnek QR oluşturma için gönderilen istek:

{"merchantId": "219be6b5-e3cd-4ad1-9843-a16340a0bfe2",
"token": "076c22d7-7a2f-42a2-85b8-8e1e873de730"}

// Örnek QR oluşturmada dönülen cevap:

{
    "code": "OK-FE-CON-001",
    "call": "user/getEmvQrForLogin",
    "description": "Başarılı bağlantı.",
    "message": "getEmvQrForLogin called.",
    "result": "ok",
    "parameters": {},
    "data": "0002010102122690000400FF01230000000000000000000000002122019100107250312816585513180040480000501106011070142746000403400720012345678901234567890905TDVMA1001N5204000053039495802TR590060011"
}
//data = EmvQrText

getEmvQrForLogin Request Parametreleri

İSTEK PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
merchantId String m 36 İşyerinin tanımlı merchant id’si.
token String m <1024 BEX.init aşamasında dönülen ticket token id değeri yazılır.

getEmvQrForLogin Response Parametreleri

Cevap İçeriği
code alanı Bu alan içerisinde istek sonuç kodu döner.Hata kodları için tıklayın.
call alanı Çağırılan servisin adı
description alanı Açıklama
message alanı Dönülen Mesaj
result alanı Açıklama
paramaters alanı Parametre
data alanı EMV formatında QR data içeriği

6.2 QR Sorgualama Servisi (queryQrStatus) :

Kullanıcınız QR'ı BKM Express uygulaması üzerinden okuttuğunda mobilden işlemine devam ederken , QR'ın statüsüne göre sayfanızda Loading mesajı gösterebilirsiniz. QR ‘ın statüsünü öğrenmek için ise aşağıdaki servisi kullanabilirsiniz. Dönülen statüye göre ilgili sayfanıza redirect edebilirsiniz.

QR Sorgulama Endpoint URL: (Test Ortam)

https://test-api.bkmexpress.com.tr/v1/user/queryQrStatus

// Örnek QR statü sorgulama için gönderilen istek:

{"token": "4d5a6506-2eb7-4ecd-8ff9-6c65b69f40bb"}

// Örnek QR statü sorgulama için dönülen response:

{
    "code": "OK-FE-CON-001",
    "call": "user/queryQrStatus",
    "description": "Başarılı bağlantı.",
    "message": "queryQrStatus called.",
    "result": "ok",
    "parameters": {},
    "data": {
        "status": "C",
        "resultCode": 0,
        "resultMsg": "Success"
    }
}
// Status: C:Created, R:Read , F:Fail, S:Success

queryQrStatus Request Parametreleri

İSTEK PARAMETRESİ Tipi

Zorunlu(m)/

Opsiyonel(o)

Uzunluk AÇIKLAMA
token String m <1024 getEmvQrForLogin servisine ilettiğiniz token değeri yazılır.

queryQrStatus Response Parametreleri

Cevap İçeriği
code alanı Bu alan içerisinde istek sonuç kodu döner.Hata kodları için tıklayın.
call alanı Çağırılan servisin adı
description alanı Açıklama
message alanı Dönülen Mesaj
result alanı Açıklama
paramaters alanı Parametre
data alanı data içeriği tablosundaki değerler dönülür
data İçeriği
status alanı QR'ın statüsü
resultCode alanı Cevap Kodu
resultMsg alanı Dönülen Mesaj

Statüler:

C (Created): Sayfanızda QR oluştu.

R (Read) : Sayfanızda QR Okundu.

F (Fail) : Sayfanızda QR iptal edildi veya ödeme işlemi başarılı tamamlanamadı.

S (Success) : Sayfanızda QR ile ödeme işlemi başarılı tamamlandı.

6.3 QR Ödeme İşlemi Sorgulama:

QR ödeme işlemin durumunu sorgulamak için işlem sorgulama servisini kullanabilirsiniz.İşlem sorgulama servisini kullanmak için tıklayın.

6.4 QR İptal / İade Servisi:

QR ile BKM Express üzerinden gerçekleşen işlemin sanal pos İptal / İade 'sini sağlayabilirsiniz.İptal/İade servisini kullanmak için tıklayın.