BEX Lite SDK — Entegrasyon Kılavuzu
Bu doküman, BEX Lite SDK’nın Android uygulamanıza güvenli, kurumsal ve PCI-DSS uyumlu biçimde
nasıl entegre edileceğini açıklar.
SDK, arkaplan işlemleri ve güvenli kart verisi yönetiminden sorumludur; ekran akışları, UI
bileşenleri ve müşteri deneyimi tamamen entegratör kuruma aittir.
1. Genel Bakış
Yüksek seviyede entegrasyon akışı aşağıdaki adımlardan oluşur:
- SDK’nın başlatılması:
BexLiteSdk.initile oturum ve iş parametrelerinin tanımlanması - İstemcinin alınması:
BexLiteSdk.getPaymentClient()ileBexPaymentClientörneğinin elde edilmesi - Backend ile ilk senkronizasyon:
initializeSdk()ve ardındancheckStatus()çağrıları - Cüzdan / kart akışı: Cüzdan bağlama, OTP doğrulama, kart ekleme/silme ve kart seçimi
- Ödeme ve sonuç:
startPayment(veyastartPaymentWithRegisteredCard), gerekirse 3D / ödeme OTP akışı; ardındanpaymentTokenilecontrolTransactionçağrısıyla nihai işlem sonucunun alınması (ekranlar sizin uygulamanızdadır)
Tüm operasyonlar Kotlin coroutines ile yürütülür ve **UI tarafı tamamen sizin kontrolünüzdedir. **
2. Teknik Gereksinimler
- Minimum Android sürümü:
minSdk 24 - Derleme hedefi:
compileSdk 36 - Dil: Kotlin (1.9+ önerilir)
- Asenkron yapı: Kotlin Coroutines
- Maven artifact:
com.bkm.mobil:sdk:0.0.6
3. Kurulum (Gradle)
Modül (app veya ilgili feature modülü) build.gradle.kts dosyasına aşağıdaki bağımlılık eklenmelidir:
// Maven artifact: com.bkm.mobil:sdk:0.0.6
dependencies {
implementation("com.bkm.mobil:sdk:0.0.6")
}
Repository tanımını proje kökündeki settings.gradle.kts veya üst seviye
build.gradle dosyasına eklenmesi yeterlidir (Artifactory / Nexus URL ve kimlik bilgileri BKM
tarafından paylaşılır).
4. Başlangıç Akışı
4.1. SDK Init Parametreleri
SdkInitParams, ödeme oturumunun temel iş parametrelerini taşır:
- token: Backend’inizin oluşturduğu, SDK init çağrısında kullanılacak başlangıç token’ı
- merchantId: İş yeri (merchant) tanımlayıcısı
- gsmNo: Kullanıcının GSM numarası (örn.
"5XXXXXXXXX") - merchantUserId: İş yerinizdeki kullanıcı kimliği
- transactionId: İşlem / sipariş ile ilişkilendirilecek benzersiz işlem kimliği
- environment: API sunucu ortamı (
BexEnvironment:DEV,TEST,PREPROD,PROD).
Örnek:
val initParams = SdkInitParams(
token = "backend_initial_token",
merchantId = "MERCHANT_ID",
gsmNo = "5XXXXXXXXX",
merchantUserId = "merchant_user_id",
transactionId = "ORDER_OR_TX_ID",
environment = BexEnvironment.DEV // veya TEST, PREPROD, PROD
)
4.2. SDK’yı Başlatma
SDK, uygulama ömrü boyunca tek sefer başlatılmalıdır. Önerilen nokta, ödeme akışına girmeden
önce (örneğin ilk ödeme ekranını açarken) Activity veya Fragment bağlamında yapılacak bir
çağrıdır.
BexLiteSdk.init(
context = this,
initParams = initParams,
)
Ardından istemci alınır:
val client: BexPaymentClient = BexLiteSdk.getPaymentClient()
BexLiteSdk.getPaymentClient()çağrısı yalnızcainitsonrası geçerlidir; aksi haldeIllegalStateExceptionfırlatılır.
4.3. Başlangıçta önerilen 4 akış (ekran yönlendirme)
SDK ilk senkronizasyonunun ardından (initializeSdk()), checkStatus() sonucundaki screen alanına göre
uygulamada açılacak ilk ekran belirlenmelidir. Tipik başlangıç senaryoları aşağıdaki gibidir:
LinkScreen: Kullanıcının iş yeri ile cüzdan eşleştirmesi gerekmektedir. Uygulamada “cüzdan bağlama” ekranı gösterilmelidir velinkAccount()çağrısı bu ekrandan tetiklenmelidir.EnterOtpScreen: Devam eden bir OTP adımı bulunmaktadır. Uygulamada OTP giriş ekranı gösterilmeli veverifyOTP(...)ile doğrulama yapılmalıdır.DashboardScreen: Cüzdan bağlıdır ve kart listesi gösterilebilir. Uygulamada kart listeleme/seçim ekranı açılmalı, kullanıcı aksiyonlarına göre kart ekleme/silme/ödeme akışlarına ilerlenmelidir.- Diğer / bilinmeyen değerler: Geriye dönük uyumluluk veya beklenmeyen durumlar için genel bir fallback
ekranı ve yeniden deneme (örn.
checkStatus()tekrar çağrısı) stratejisi uygulanmalıdır.
5. Örnek Akış: SDK Başlatma ve Cüzdan Durumu
Tipik başlangıç senaryosu:
initializeSdk()ile backend ile ilk senkronizasyoncheckStatus()ile kullanıcının mevcut cüzdan durumu ve gösterilecek ilk ekranın belirlenmesi
lifecycleScope.launch {
when (val initResult = client.initializeSdk()) {
is BexResult.Success -> {
// initResult.data: bekleyen sözleşmeler + sözleşme açıklaması metni
val pendingAgreements = initResult.data.pendingAgreements
when (val checkResult = client.checkStatus()) {
is BexResult.Success -> {
val wallet = checkResult.data
when (wallet.screen) {
"LinkScreen" -> showLinkWalletScreen()
"DashboardScreen" -> showCardList(wallet.cards ?: emptyList())
"EnterOtpScreen" -> wallet.otpData?.let { showOtpScreen(it) }
else -> showGenericFallbackScreen()
}
}
is BexResult.Error -> showError(checkResult.error)
}
}
is BexResult.Error -> showError(initResult.error)
}
}
Burada tüm UI ekranları (showLinkWalletScreen, showCardList, showOtpScreen vb.) iş yeri
tarafından tasarlanır ve yönetilir.
5.1. Bekleyen Sözleşmeler (Agreements) ve Onaylar (Approvals)
initializeSdk() başarılı olduğunda backend, kullanıcıdan onay bekleyen sözleşmeleri döndürür:
pendingAgreements: Sözleşme listesi
Örnek pendingAgreements dönüşü:
"pendingAgreements": [
{
"id": 1,
"code": "TERMS_OF_USE",
"type": "AGREEMENT",
"contentType": "HTML",
"title": "Kullanıcı Sözleşmesi",
"content": "<p>Kullanım Koşulları ...</p>",
"labelHighlight": "Kullanıcı Sözleşmesi",
"label": "Kullanıcı Sözleşmesini onaylıyorum.",
"mandatory": true
},
{
"id": 2,
"code": "KVKK",
"type": "INFO",
"contentType": "URL",
"title": "BKM EXPRESS KVKK Aydınlatma Metni",
"content": "https://bkmexpress.com.tr/KVKK",
"labelHighlight": "",
"label": "",
"mandatory": false
}
]
Notlar:
type = "AGREEMENT"olan kayıtlar için UI’da checkbox gösterilmelidir (metin:label, highlight:labelHighlight).type = "INFO"olan kayıtlar için UI’da checkbox gösterilmez (ör. KVKK).- SDK, backend’e consent gönderirken tüm
pendingAgreementskayıtlarını işler/gönderir.
5.1.1. Sözleşme UI gereksinimi (tek checkbox)
- SDK’nın sunduğu standalone agreement checkbox bileşeni kullanılmalıdır.
- Checkbox yanındaki metin uygulamada
labelile gösterilebilir:[cb][text].
Compose - renk özelleştirme
BEXAgreementCheckbox varsayılan Material3 checkbox renklerini kullanır. İsterseniz aşağıdaki gibi
renkleri özelleştirebilirsiniz:
Row {
BEXAgreementCheckbox(
colors = BEXAgreementCheckboxDefaults.colors(
checkedColor = Color(0xFF00B9C8),
uncheckedColor = Color(0xFFBDBDBD),
checkmarkColor = Color.White
),
onCheckedChange = { isChecked ->
// Örn. butonu enable/disable edebilirsiniz
// isSaveEnabled = isChecked
}
)
Text(text = agreement.label)
}
XML/View - renk özelleştirme
BEXAgreementCheckboxView için app: attribute’ları ile tint renklerini ayarlayabilirsiniz:
<com.bkm.mobil.sdk.lite.ui.BEXAgreementCheckboxView android:id="@+id/agreementCheckbox"
android:layout_width="wrap_content" android:layout_height="wrap_content"
app:bexAgreementCheckedColor="#00B9C8" app:bexAgreementUncheckedColor="#BDBDBD"
app:bexAgreementDisabledCheckedColor="#7F00B9C8"
app:bexAgreementDisabledUncheckedColor="#80BDBDBD" app:bexAgreementCheckmarkColor="#FFFFFF" />
XML/View - drawable özelleştirme (opsiyonel)
Varsayılan durumda BEXAgreementCheckboxView, AppCompat’in standart checkbox button drawable’ını
kullanır. İsterseniz:
- Sadece button drawable override:
<com.bkm.mobil.sdk.lite.ui.BEXAgreementCheckboxView android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:bexAgreementButtonDrawable="@drawable/my_checkbox_button" />
- Tight mode (intrinsic inset yok, background selector ile çizim):
<com.bkm.mobil.sdk.lite.ui.BEXAgreementCheckboxView android:layout_width="24dp"
android:layout_height="24dp" app:bexAgreementTightMode="true"
app:bexAgreementTightBackground="@drawable/my_checkbox_selector" />
View tarafında kullanıcı etkileşimini yakalamak için Kotlin/Java ile
agreementCheckbox.setOnApprovalChangedListener { checked -> ... }kullanabilirsiniz.
5.1.2. Onayların gönderimi
- Checkbox durumuna göre SDK, tüm
pendingAgreementsiçin backend’e otomatik olarak onay gönderir:- Checked →
ACCEPTED - Unchecked →
REJECTED(backend bu durumda hata döndürür)
- Checked →
Backend’e giden örnek alan:
"agreementConsents": [
{"id": 1, "status": "ACCEPTED"},
{"id": 2, "status": "ACCEPTED"}
]
Kullanıcı sözleşmeleri onaylanmazsa backend şu hatayı döndürür:
MISSED_MANDATORY_AGREEMENT( 36).
6. Cüzdan Bağlama ve OTP Doğrulama
6.1. Cüzdanı İş Yerine Bağlama
lifecycleScope.launch {
when (val linkResult = client.linkAccount()) {
is BexResult.Success -> {
val data = linkResult.data
when (data.screen) {
"EnterOtpScreen" -> data.otpData?.let { showOtpScreen(it) }
"WalletScreen" -> checkStatus()
else -> showGenericFallbackScreen()
}
}
is BexResult.Error -> showError(linkResult.error)
}
}
6.2. OTP Doğrulama
Kullanıcı OTP’yi girdikten sonra:
lifecycleScope.launch {
val otpData = currentOtpData // OTP ekranına getiren yanıttan aldığınız veri
when (val result = client.verifyOTP(
otpValue = userOtpInput,
transactionId = otpData.transactionId,
otpRefNo = otpData.otpRefNo
)) {
is BexResult.Success -> {
// Gelen ekrana göre (dashboard, tekrar link vb.) UI güncellenmelidir
handleOtpSuccess(result.data)
}
is BexResult.Error -> showError(result.error)
}
}
Gerektiğinde OTP yeniden gönderimi için resendOTP benzer şekilde kullanılabilir.
7. Kart Yönetimi ve Güvenli Kart Girişi
SDK, kart numarasını kurum uygulamanızdan tamamen izole eden BEXSecureCardNumberField
bileşenini sunar.
Bu sayede uygulamanız PCI-DSS kapsamı dışında tutulur; ham kart numarası yalnızca SDK içerisinde
kalır.
7.1. Compose ile Güvenli Kart Girişi
import androidx.compose.runtime.*
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import com.bkm.mobil.sdk.lite.ui.BEXSecureCardNumberField
import com.bkm.mobil.sdk.lite.ui.rememberBEXSecureCardNumberState
import com.bkm.mobil.sdk.lite.api.BexLiteSdk
import kotlinx.coroutines.launch
@Composable
fun AddCardSection() {
val scope = rememberCoroutineScope()
val cardState = rememberBEXSecureCardNumberState()
val client = BexLiteSdk.getPaymentClient()
val pendingAgreements =
remember { emptyList<AgreementItem>() } // initResult.data.pendingAgreements
val agreement = remember { pendingAgreements.firstOrNull { it.type == "AGREEMENT" } }
Column {
BEXSecureCardNumberField(state = cardState)
// [cb][text]
agreement?.let {
Row {
BEXAgreementCheckbox()
Text(text = it.label)
}
}
Button(onClick = {
scope.launch {
val expiry = "1226" // MMYY formatında son kullanma tarihi
val tokenizedPan = cardState.getTokenizedPan(expiry) ?: return@launch
when (val res = client.storeCard(
tokenizedPan = tokenizedPan,
aliasName = null
)) {
is BexResult.Success -> handleCardInsertSuccess(res.data)
is BexResult.Error -> showError(res.error)
}
}
}) {
Text("Kartı Kaydet")
}
}
}
- Önemli: Entegratör uygulama hiçbir noktada ham kart numarasına erişmez.
- Kart ekleme
storeCard(BexTokenizedPan, aliasName?)ile yapılır;BexTokenizedPan, güvenli kart bileşeninden (getTokenizedPan) üretilir.aliasNameisteğe bağlı kart adıdır (nullolabilir). storeCardçağrısı, gerekirse OTP gereksiniminiCardInsertResult.otpDataüzerinden bildirir; akış sizin UI’niz üzerinden devam eder.
Kısmi kayıt (registerWithTokenizedPan) için de aynı BexTokenizedPan kullanılır; ham PAN veya
son kullanma tarihi uygulama koduna alınmaz:
when (val res = client.registerWithTokenizedPan(
tokenizedPan = tokenizedPan,
aliasName = null
)) {
is BexResult.Success -> handleRegisterSuccess(res.data)
is BexResult.Error -> showError(res.error)
}
7.2. XML / View Bazlı Güvenli Kart Girişi (BEXSecureCardNumberEditText)
XML tabanlı ekranlarda güvenli kart girişi için BEXSecureCardNumberEditText bileşeni
kullanılabilir. Ham kart numarası bu bileşenden de hiçbir zaman dışarı çıkmaz; yalnızca şifreli
token üretilir.
XML Kullanımı:
<com.bkm.mobil.sdk.lite.ui.BEXSecureCardNumberEditText android:id="@+id/secureCardInput"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:background="@drawable/bg_secure_card_input" android:padding="16dp"
android:contentDescription="@string/card_number_field" app:bexCardHint="•••• •••• •••• ••••"
app:bexCardTextColor="@color/on_surface" app:bexCardHintColor="@color/outline"
app:bexCardTextSize="18sp" app:bexCardLetterSpacing="0.08" app:bexCardShowUnderline="false" />
Kotlin Kullanımı:
val secureInput = findViewById<BEXSecureCardNumberEditText>(R.id.secureCardInput)
// Örn. "MMYY" formatında son kullanma tarihi
val expiry = "1226"
lifecycleScope.launch {
val tokenizedPan = secureInput.getTokenizedPan(expiry) ?: return@launch
when (val res = client.storeCard(tokenizedPan, aliasName = null)) {
is BexResult.Success -> handleCardInsertSuccess(res.data)
is BexResult.Error -> showError(res.error)
}
// Kısmi kayıt örneği (aynı tokenizedPan):
// when (val reg = client.registerWithTokenizedPan(tokenizedPan)) { ... }
}
Bu bileşende:
getTextvesetTextçağrıları her zamanIllegalStateExceptionfırlatır (ham PAN erişimini engellemek için).- Kopyala-yapıştır, otomatik doldurma ve ham metnin erişilebilirlik ağaçlarına sızması engellenmiştir.
- Tek güvenli çıktı, RSA-OAEP ile şifrelenmiş ve Base64 kodlanmış
BexTokenizedPannesnesidir.
7.3. Ödeme Başlatma ve İşlem Kontrolü (controlTransaction)
startPayment / startPaymentWithRegisteredCard çağrısı, backend’in kararına göre 3D Secure
sayfası,
OTP ekranı veya doğrudan paymentToken döndürebilir. Ödeme işleminin banka tarafındaki
nihai
durumunu (onay/red, tutar, slip bilgileri vb.) almak için elinizdeki paymentToken ile
controlTransaction çağrılır.
paymentToken kaynakları (özet):
TransactionInitByCardIdResult.paymentToken: Ödeme init yanıtında (3D veya non-3D).OtpControlResult.paymentToken: Ödeme OTP akışındaverifyOTPbaşarılı olduktan sonra (ekran / iş kuralı backend’e göre değişir; demo uygulama belirli birscreen+ dolu token kombinasyonunda kontrol çağrısı yapar).
Non-3D ve OTP’siz senaryo (init yanıtında paymentToken var ve bir sonraki adım doğrudan
kontrol):
lifecycleScope.launch {
when (val payRes = client.startPayment(
orderId = orderId,
cardId = cardId,
amount = amount,
paymentSecurity = paymentSecurity
)) {
is BexResult.Success -> {
val data = payRes.data
val token = data.paymentToken
if (!token.isNullOrBlank() /* && ekran / iş kuralınıza göre kontrol adımı */) {
when (val ctrl = client.controlTransaction(paymentToken = token)) {
is BexResult.Success -> showPaymentResult(ctrl.data) // TransactionControlResult
is BexResult.Error -> showError(ctrl.error)
}
} else if (data.otpData != null) {
showOtpForPayment(data.otpData!!)
}
// 3D: tdsUrl/htmlForm ile WebView; tamamlanınca aynı init’ten gelen token ile controlTransaction
}
is BexResult.Error -> showError(payRes.error)
}
}
3D Secure tamamlandıktan sonra (ör. yönlendirme / callback URL’si uygulamanızda “işlem bitti”
anlamına geldiğinde), init aşamasında sakladığınız paymentToken ile kontrol:
lifecycleScope.launch {
when (val ctrl = client.controlTransaction(paymentToken = paymentTokenFromInit)) {
is BexResult.Success -> showPaymentResult(ctrl.data)
is BexResult.Error -> showError(ctrl.error)
}
}
Ödeme OTP’si sonrası (verifyOTP cevabında paymentToken geldiğinde):
lifecycleScope.launch {
when (val res = client.verifyOTP(otpValue, transactionId, otpRefNo)) {
is BexResult.Success -> {
val token = res.data.paymentToken
if (!token.isNullOrBlank()) {
when (val ctrl = client.controlTransaction(paymentToken = token)) {
is BexResult.Success -> showPaymentResult(ctrl.data)
is BexResult.Error -> showError(ctrl.error)
}
} else {
// Backend’in döndüğü screen / cards ile devam
}
}
is BexResult.Error -> showError(res.error)
}
}
controlTransaction, ağ geçici hatalarında maxAttempts (varsayılan 2) ile sınırlı yeniden
dener; sunucu/API hatalarında genelde tek seferlik hata döner. Ayrıntılar için Bölüm 8.2.11
bakınız.
8. API Referansı (Özet)
Bu bölümde, SDK’nın public API yüzeyi özetlenmektedir. Tüm çağrılar Kotlin ve coroutine tabanlıdır.
8.1. BexLiteSdk
Tekil giriş noktasıdır. Önce init, ardından getPaymentClient() kullanılır.
8.1.1. init
BexLiteSdk.init(
context: Context,
initParams: SdkInitParams
)
- context: Uygulama veya Activity context (applicationContext önerilir).
- initParams:
token,merchantId,gsmNo,merchantUserId,transactionId,environment(varsayılanBexEnvironment.DEV).
Not:
initçağrılmadangetPaymentClient()çağrılırsaIllegalStateExceptionfırlatılır.
8.1.2. getPaymentClient
val client: BexPaymentClient = BexLiteSdk.getPaymentClient()
init sonrası çağrılır. Dönen istemci ile tüm ödeme ve cüzdan işlemleri gerçekleştirilir.
8.2. BexPaymentClient
Tüm metotlar suspend fonksiyondur; coroutine içinden çağrılmalıdır.
8.2.1. initializeSdk
suspend fun initializeSdk(): BexResult<SdkInitResult>
Backend ile SDK başlatma (token, encKey). Init parametreleri BexLiteSdk.init ile sağlanır.
Başarılı olduğunda:
SdkInitResult.pendingAgreements: bekleyen sözleşmeler
Hata durumunda BexResult.Error(BexSdkError) döner.
8.2.2. checkStatus
suspend fun checkStatus(): BexResult<WalletCheckResult>
Cüzdan durumunu sorgular. Dönen WalletCheckResult şu alanları içerir:
- screen: Gösterilmesi önerilen ekran (
LinkScreen,DashboardScreen,EnterOtpScreenvb.) - cards: Kullanıcıya ait kart listesi (
List<BexCardInfo>?) - otpData: OTP akışı için gerekli bilgiler (
OtpData?)
8.2.3. linkAccount
suspend fun linkAccount(): BexResult<LinkWalletResult>
Cüzdanı iş yerine bağlar. Sonuçta screen ve gerekiyorsa otpData bulunur; OTP ekranı entegratör
tarafından gösterilir.
8.2.4. verifyOTP
suspend fun verifyOTP(
otpValue: String,
transactionId: String,
otpRefNo: String
): BexResult<OtpControlResult>
OTP doğrulama işlemini gerçekleştirir. transactionId ve otpRefNo değerleri, OTP ekranına getiren
yanıttaki OtpData içinden alınmalıdır.
8.2.5. resendOTP
suspend fun resendOTP(
transactionId: String,
otpRefNo: String
): BexResult<OtpResendResult>
Aynı işlem için OTP’nin yeniden gönderilmesini sağlar. transactionId ve otpRefNo, ilgili
OtpData içinden alınır.
8.2.6. storeCard
suspend fun storeCard(
tokenizedPan: BexTokenizedPan,
aliasName: String? = null
): BexResult<CardInsertResult>
Yeni kart ekler. merchantId init parametrelerinden alınır. tokenizedPan, yalnızca
BEXSecureCardNumberField / BEXSecureCardNumberEditText üzerinden üretilen şifreli değerdir (
Bölüm 7). aliasName isteğe bağlı kart adıdır.
Sonuç OTP gerektiriyorsa CardInsertResult.otpData dolu dönebilir (backend kararıdır).
8.2.7. cardDelete
suspend fun cardDelete(cardId: String): BexResult<CardDeleteResult>
Kayıtlı bir kartı siler. Başarılı yanıtta güncellenmiş kart listesi CardDeleteResult.cards içinde
döner.
8.2.8. registerWithTokenizedPan
suspend fun registerWithTokenizedPan(
tokenizedPan: BexTokenizedPan,
aliasName: String? = null
): BexResult<RegisterResult>
Kısmi kayıt akışını yürütür; ham kart numarası veya son kullanma tarihi parametre olarak **yoktur
**.
GSM numarası SDK init’inden (SdkInitParams.gsmNo) alınır.
8.2.9. startPayment (KartId ile Ödeme Başlatma)
Kayıtlı bir kart (cardId) ile ödeme başlatır. Güvenlik türü PaymentSecurity ile seçilir:
TDS: 3D Secure init endpoint’i;tdsUrl/htmlFormbeklenir.OTP: Non-3D init; istek gövdesindewithOtp = true.NONE: Non-3D init; istek gövdesindewithOtp = false.
Önemli: withOtp ve PaymentSecurity yalnızca istemci tarafı tercihidir. İş kuralı veya
banka, OTP veya NONE göndermenize rağmen OTP döndürmeyebilir veya tersine OTP zorunlu
kılabilir. Her zaman yanıttaki otpData, screen, paymentToken ve 3DS alanlarına göre
akış seçilmelidir.
suspend fun startPayment(
orderId: String,
cardId: String,
amount: Double,
paymentSecurity: PaymentSecurity = PaymentSecurity.NONE,
currency: String = "TRY",
installmentCount: Int = 1
): BexResult<TransactionInitByCardIdResult>
8.2.10. startPaymentWithRegisteredCard (tokenizedPan / encData ile Ödeme Başlatma)
Kayıtlı cardId yerine, güvenli kart bileşeninden üretilen BexTokenizedPan (encData olarak)
ile ödeme başlatır. Parametreler ve PaymentSecurity semantiği startPayment ile
aynıdır.
suspend fun startPaymentWithRegisteredCard(
orderId: String,
tokenizedPan: BexTokenizedPan,
amount: Double,
paymentSecurity: PaymentSecurity = PaymentSecurity.NONE,
currency: String = "TRY",
installmentCount: Int = 1
): BexResult<TransactionInitByCardIdResult>
8.2.11. controlTransaction (İşlem / Ödeme Sonucu Sorgulama)
paymentToken ile işlemin güncel sonucunu backend’den sorgular. Bu token genellikle
startPayment / startPaymentWithRegisteredCard yanıtında veya ödeme OTP’si sonrası verifyOTP
yanıtında (OtpControlResult.paymentToken) gelir. 3D Secure akışında, kullanıcı banka
sayfasında
işlemi tamamladıktan sonra (WebView tamamlanma veya redirect sonrası) init sırasında aldığınız
paymentToken ile çağrı yapılır.
suspend fun controlTransaction(
paymentToken: String,
maxAttempts: Int = 2
): BexResult<TransactionControlResult>
- paymentToken: Boş veya yalnızca boşluk olamaz; aksi halde hata döner.
- maxAttempts: En az
1olacak şekilde kullanılır. SDK, ağ / bilinmeyen geçici hatalarda en fazla bu kadar deneme yapabilir;Apitipindeki sunucu hatalarında yeniden denemez. Yanıttasuccess == truegörülür görülmez başarılı sonuç döner; aksi halde son yanıt veya hata ileBexResultüretilir.
Örnek (init sonrası doğrudan kontrol):
lifecycleScope.launch {
when (val payRes = client.startPayment(orderId, cardId, amount, paymentSecurity)) {
is BexResult.Success -> {
val token = payRes.data.paymentToken
if (!token.isNullOrBlank()) {
when (val ctrl = client.controlTransaction(paymentToken = token)) {
is BexResult.Success -> {
val r = ctrl.data
if (r.success == true) {
// r.authCode, r.successAmount, r.orderId vb.
} else {
// r.message, r.code ile kullanıcı bilgilendirmesi
}
}
is BexResult.Error -> showError(ctrl.error)
}
}
}
is BexResult.Error -> showError(payRes.error)
}
}
8.3. Sonuç Tipleri (BexResult)
Tüm istemci metotları BexResult<T> döner:
- BexResult.Success(data: T): İşlem başarıyla tamamlanmıştır.
- BexResult.Error(error: BexSdkError): Hata durumunda kullanılır;
error.displayMessageson kullanıcılara gösterilebilir.
8.4. Veri Modelleri (Özet)
Başlıca veri modelleri aşağıdaki gibidir:
- WalletCheckResult:
screen,cards: List<BexCardInfo>?,otpData: OtpData? - LinkWalletResult:
screen,otpData? - OtpControlResult:
screen,cards?,cardId?,paymentToken?(ödeme kontrolü için) - OtpResendResult:
transactionId,durationTimeInSeconds,otpLength,gsmNo,otpRefNo,sender? - CardInsertResult:
screen,otpData? - RegisterResult:
screen,cards?,otpData?,transactionId? - BexCardInfo:
cardId,maskCardNumber,cardAlias,binValue,imageUrl,bankInformation,active - BexBankInformation:
cardType,cardBrandType,cardBrand,bankShortName - OtpData:
transactionId,durationTimeInSeconds,otpLength,gsmNo,otpRefNo,sender - TransactionInitByCardIdResult:
is3D,screen,paymentToken,otpData, 3D içintdsUrl/htmlForm, ek alanlarsuccess,message,code,bankTransactionId,orderId,keyvb. - TransactionControlResult: İşlem kontrolü sonucu;
success,message,code,orderId,successAmount,authCode,hostRefNum,cardNumber(maskeli), tarih ve terminal bilgileri vb. (alanların doluluğu backend yanıtına bağlıdır)
Örnek kart modeli (backend yanıtı):
{
"cardId": "019d2dad-34bc-7b00-959d-0bef3009afa5",
"maskCardNumber": "123456******1234",
"cardAlias": "Maaş Kartım",
"binValue": "12345678",
"imageUrl": "https://...default_card.png",
"bankInformation": {
"cardType": "CreditCard",
"cardBrandType": "Marka Yok",
"cardBrand": "Troy",
"bankShortName": "TESTBANK"
},
"active": true
}
8.5. BexSdkError
Başlıca hata türleri:
ApiNetworkCancelledUnauthorizedUnknown
Son kullanıcılara gösterilecek mesaj için displayMessage alanı kullanılmalıdır.
Detaylı model alanları için SDK içindeki veri sınıflarına (model paketleri) başvurulabilir.
9. Hata Yönetimi ve Sonuç Tipleri (Uygulama Örneği)
Entegre bir hata gösterimi için basit bir kullanım örneği:
when (val result = client.checkStatus()) {
is BexResult.Success -> {
// result.data ile devam edilmelidir
}
is BexResult.Error -> {
Toast.makeText(context, result.error.displayMessage, Toast.LENGTH_SHORT).show()
// İsteğe bağlı: error türüne göre (Network, Api, Unauthorized vb.) loglama
}
}