BEX Lite SDK Entegrasyonu
Bu doküman, BEX Lite SDK'nın iOS 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ı:
BKMExpress.initialize(context:)ile oturum ve iş parametrelerinin tanımlanmasıyla birAPInesnesi elde edilmesi - Backend ile ilk senkronizasyon:
initializeçağrısı başarılı olduğunda sözleşmeler ve şifreleme anahtarı otomatik olarak hazırlanır - Cüzdan durumu:
checkStatus()ile kullanıcının mevcut durumunun sorgulanması - 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ındanpaymentTokenilecontrolPaymentçağrısıyla nihai işlem sonucunun alınması (ekranlar sizin uygulamanızdadır)
Tüm operasyonlar Swift Concurrency (async/await) ile yürütülür ve UI tarafı tamamen sizin kontrolünüzdedir.
2. Teknik Gereksinimler
- Minimum iOS sürümü:
iOS 15.0+ - Dil: Swift
- Asenkron yapı: Swift Concurrency (async/await)
- UI Çerçeveleri: SwiftUI ve UIKit için ayrı bileşenler mevcuttur; SwiftUI bileşenleri UIKit desteklenmeyen platformlarda (örn. macOS) çalışmaz
3. Kurulum
BEX Lite SDK yalnızca Swift Package Manager ile dağıtılmaktadır.
3.1. Xcode Proje Ayarlarından Ekleme
Projenizin Package Dependencies bölümünden gerekli sürüm bilgisini girerek SDK'yı ekleyebilirsiniz.
3.2. Package.swift ile Ekleme
Başka bir Swift Package içinde kullanılacaksa:
Package.swiftdosyanızdakidependenciesparametresine bağımlılığı ekleyin:
.package(url: "https://github.com/BKMExpress/iOS-Lite-SDK.git", branch: "main")
- Bağımlılığı kullanmak istediğiniz target'in
dependencieskısmına SDK product'ını ekleyin:
"BKMExpressLiteSDK"
4. Başlangıç Akışı
4.1. SDK Başlatma Parametreleri
BKMExpress.InitializationContext, ödeme oturumunun temel iş parametrelerini taşır:
- authToken: Backend'inizin oluşturduğu, SDK başlatma çağrısında kullanılacak token
- merchantID: İş yeri (merchant) tanımlayıcısı
- merchantUserID: İş yerinizdeki kullanıcı kimliği
- gsmNo: Kullanıcının GSM numarası (
BKMExpress.GSMNOstruct'ı olarak; örn."5XXXXXXXXX") - currencyCode: Ödeme para birimi kodu (büyük harf ISO 4217 formatında; örn.
"TRY","USD","EUR"). Desteklenmeyen bir değer gönderilirse backendINVALID_CURRENCYhatası döner (bkz. Bölüm 9.1). - mode: API sunucu ortamı (
BKMExpress.Mode:.test,.preprod,.production)
Örnek:
let context = BKMExpress.InitializationContext(
authToken: "backend_initial_token",
merchantID: "MERCHANT_ID",
merchantUserID: "merchant_user_id",
gsmNo: try .init("5XXXXXXXXX"),
currencyCode: "TRY", // ISO 4217 para birimi kodu
mode: .test // veya .preprod, .production
)
BKMExpress.GSMNOstruct'ı kendi doğrulama kurallarını işletir: 10 haneli, yalnızca rakamlardan oluşan ve 5 ile başlayan bir numara beklenir. Aksi hâldeInitializationErrorfırlatılır.
4.2. SDK'yı Başlatma ve API Nesnesini Alma
BKMExpress.initialize(context:) çağrısı, oturumu başlatır ve tüm SDK işlemlerini yürüteceğiniz
API nesnesini döndürür. Bu çağrı ödeme akışına girmeden önce, API nesnesini kullanacak ekranın
bir önceki adımında yapılmalıdır.
func pairButtonTapped() async {
do {
let api = try await BKMExpress.initialize(context: context)
// API nesnesini kullanacak ekrana tercih ettiğiniz DI mekanizmasıyla iletin.
// Örn: delegate?.bkmExpressInitialized(api)
} catch {
showAlert("BKM Express başlatılamadı.")
}
}
Önemli: Optional kontrollerinden kaçınmak için
APInesnesini kullanacağınız ekranda oluşturmak yerine bir önceki ekranda oluşturup DI ile iletmeniz tavsiye edilir.
4.3. Başlangıçta Önerilen Akış (Ekran Yönlendirme)
SDK başlatıldıktan sonra checkStatus() sonucuna göre uygulamada açılacak ilk ekran belirlenir.
Tipik başlangıç senaryoları:
.unregistered: Kullanıcı hiç kayıtlı değildir. Kayıt akışı (register) veya kart ekleme ekranı gösterilmelidir..unlinked: Kullanıcı kayıtlıdır ancak iş yeriyle eşleştirme yapmamıştır. "Cüzdan bağlama" ekranı gösterilmeli velinkAccount()bu ekrandan tetiklenmelidir..linked(cards): Cüzdan bağlıdır ve kart listesi gösterilebilir. Kart listeleme/seçim ekranı açılmalı, kullanıcı aksiyonlarına göre kart ekleme/silme/ödeme akışlarına ilerlenmelidir.
5. Örnek Akış: SDK Başlatma ve Cüzdan Durumu
Tipik başlangıç senaryosu:
BKMExpress.initialize(context:)ile oturum başlatma veAPInesnesini almacheckStatus()ile kullanıcının mevcut cüzdan durumu ve gösterilecek ilk ekranın belirlenmesi
func startBKMExpressFlow() async {
do {
let api = try await BKMExpress.initialize(context: context)
let status = try await api.checkStatus()
switch status {
case let .linked(cards):
showCardList(cards)
case .unlinked:
showLinkWalletScreen(api: api)
case .unregistered:
showRegistrationScreen(api: api)
}
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
Burada tüm UI ekranları (showCardList, showLinkWalletScreen, showRegistrationScreen vb.)
iş yeri tarafından tasarlanır ve yönetilir.
5.1. Bekleyen Sözleşmeler (Agreements) ve Onaylar
BKMExpress.initialize(context:) başarılı olduğunda bekleyen sözleşmeler SDK içinde hazır hâle
gelir. Bu sözleşmelere api.pendingAgreements() metoduyla erişilir.
let agreements = api.pendingAgreements()
Örnek sözleşme alanları:
id: Sözleşmenin tanımlayıcısıcode: Sözleşme kodu (örn."TERMS_OF_USE","KVKK")kind: Sözleşme türü (.agreementveya.info)title: Sözleşmenin başlığıcontent: Sözleşmenin içeriğinin bulunduğu URLlabel: Checkbox yanında gösterilecek metinlabelHighlight: Label içinde vurgulanacak metinmandatory: Onayın zorunlu olup olmadığı
Notlar:
kind == .agreementolan kayıtlar için UI'da checkbox gösterilmelidir (metin:label, highlight:labelHighlight).kind == .infoolan kayıtlar için checkbox gösterilmez (örn. KVKK).- SDK, backend'e onay gönderirken tüm
pendingAgreementskayıtlarını işler.
5.1.1. Sözleşme UI Gereksinimi (Tek Checkbox)
SDK'nın sunduğu standalone agreement checkbox bileşeni kullanılmalıdır.
Önemli: Checkbox bileşeninin UI hiyerarşinizde yalnızca bir adet bulunduğundan emin olun. Aksi takdirde onay mekanizması beklendiği gibi çalışmayabilir.
SwiftUI — Renk Özelleştirme
BKMExpressAgreementCheckboxView varsayılan görünümüyle kullanılabilir; isteğe bağlı
özelleştirme parametreleri de mevcuttur:
HStack {
BKMExpressAgreementCheckboxView(
isSelected: $isCheckboxSelected,
checkmarkTint: Color(hex: "#FFFFFF"),
borderColor: Color(hex: "#BDBDBD"),
errorTintColor: .red,
disabledTintColor: .gray
)
Text(agreement.label)
}
UIKit — Renk Özelleştirme
BKMExpressAgreementCheckbox, UIControl subclass'ıdır. Renkleri doğrudan property'ler
aracılığıyla ayarlayabilirsiniz:
let checkbox = BKMExpressAgreementCheckbox()
checkbox.tintColor = UIColor(hex: "#00B9C8")
checkbox.checkmarkColor = .white
checkbox.borderColor = UIColor(hex: "#BDBDBD")
checkbox.disabledTintColor = UIColor(hex: "#80BDBDBD")
checkbox.errorTintColor = .red
5.1.2. Onayların Gönderimi
Checkbox durumuna göre SDK, tüm pendingAgreements için backend'e otomatik olarak onay
gönderir. Kullanıcı sözleşmeleri onaylanmazsa backend MISSED_MANDATORY_AGREEMENT (36) hatasını
döndürür.
6. Cüzdan Bağlama ve OTP Doğrulama
6.1. Cüzdanı İş Yerine Bağlama
func linkBKMExpress() async {
do {
let response = try await api.linkAccount()
switch response {
case .recheck:
// Hesap bağlandı; kart listesi için checkStatus() yeniden çağrılmalıdır.
let status = try await api.checkStatus()
handleCheckStatus(status)
case let .verificationRequired(otp):
showOtpScreen(otp: otp)
}
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
6.2. OTP Doğrulama
Her OTP nesnesi (LinkOTP, StoreCardOTP, RegisterOTP, PaymentOTP) aynı arayüzü
(BKMExpress.OTP protokolü) paylaşır. Kullanıcı OTP'yi girdikten sonra:
func verifyOTP(otp: some BKMExpress.OTP, code: String) async {
do {
let result = try await otp.verify(code: code)
handleOtpSuccess(result)
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
OTP'yi yeniden göndermek için:
func resendOTP(otp: some BKMExpress.OTP) async {
do {
let newInfo = try await otp.resend()
// newInfo ile OTP ekranı güncellenir.
// Dilerseniz aynı bilgiye otp.info üzerinden de erişebilirsiniz.
updateOtpUI(info: newInfo)
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
7. Kart Yönetimi ve Güvenli Kart Girişi
SDK, kart numarasını kurum uygulamanızdan tamamen izole eden BKMExpressCardNumberField (UIKit)
ve BKMExpressCardNumberView (SwiftUI) bileşenlerini sunar. Bu sayede uygulamanız PCI-DSS kapsamı
dışında tutulur; ham kart numarası yalnızca SDK içinde kalır.
7.1. SwiftUI ile Güvenli Kart Girişi
// Bu view oluşturulmadan önce başarılı initialize() çağrısının yapıldığından emin olunuz.
struct AddCardScreen: View {
@State var cardNumber: BKMExpress.CardNumber?
@State var isCheckboxSelected = false
var body: some View {
VStack {
BKMExpressCardNumberView(
font: .systemFont(ofSize: 17),
placeholder: "Kart Numarası",
number: $cardNumber
)
// iOS 26 ve sonrasında font modifier ile de kullanılabilir:
// BKMExpressCardNumberView(placeholder: "Kart Numarası", number: $cardNumber)
// .font(.system(size: 17))
if let agreement = agreements.first(where: { $0.kind == .agreement }) {
HStack {
BKMExpressAgreementCheckboxView(isSelected: $isCheckboxSelected)
Text(agreement.label)
}
}
Button("Kartı Kaydet") {
Task { await storeCard() }
}
}
}
}
Önemli: Entegratör uygulama hiçbir noktada ham kart numarasına erişemez.
cardNumberbinding'i yalnızca SDK'nın type-safeBKMExpress.CardNumberwrapper'ını içerir.
BKMExpressCardNumberView'ün AttributedString placeholder kabul eden bir versiyonu da
mevcuttur:
BKMExpressCardNumberView(
font: .systemFont(ofSize: 17),
attributedPlaceholder: attributedPlaceholder,
number: $cardNumber
)
7.2. UIKit ile Güvenli Kart Girişi (BKMExpressCardNumberField)
BKMExpressCardNumberField bir UITextField subclass'ıdır ve subclass edilebilir. text ile
attributedText gibi özellikler güvenlik nedeniyle kapatılmıştır. Bileşenin original delegate'i
(UITextFieldDelegate) yerine bkmExpressDelegate kullanılmalıdır.
// Bu controller oluşturulmadan önce başarılı initialize() çağrısının yapıldığından emin olunuz.
class AddCardViewController: UIViewController, BKMExpressCardNumberFieldDelegate {
let cardNumberField = BKMExpressCardNumberField()
let checkbox = BKMExpressAgreementCheckbox()
override func viewDidLoad() {
super.viewDidLoad()
cardNumberField.bkmExpressDelegate = self
checkbox.addTarget(self, action: #selector(checkboxChanged), for: .valueChanged)
// Layout kurulumu...
}
func bkmExpressCardNumberField(
_ field: BKMExpressCardNumberField,
didReceiveValidCardNumber cardNumber: BKMExpress.CardNumber
) {
// Geçerli bir kart numarası alındı; gerekirse devam tuşunu aktifleştirebilirsiniz.
}
@objc func checkboxChanged(_ checkbox: BKMExpressAgreementCheckbox) {
print("Checkbox durumu: \(checkbox.isSelected)")
}
}
Interface Builder kullanıyorsanız
bkmExpressDelegateatamasını koddan yapmalısınız.
Bu bileşende:
textveattributedTextözellikleri güvenlik nedeniyle erişime kapatılmıştır.- Kopyala/kes işlemleri engellenir; ham metin hiçbir zaman dışarı çıkmaz.
- Tek güvenli çıktı, RSA-OAEP ile şifreli
BKMExpress.CardNumbernesnesidir.
7.3. Kart Ekleme (storeCard)
func storeCard() async {
guard let number = cardNumber else { return }
let expiryDate = try! BKMExpress.CardExpiryDate(month: 12, year: 2026)
do {
let response = try await api.storeCard(
context: .init(
number: number,
expiryDate: expiryDate,
alias: nil // İsteğe bağlı kart adı
)
)
switch response {
case let .added(cards):
showCardList(cards)
case let .verificationRequired(otp):
showOtpScreen(otp: otp)
}
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
7.4. Kart Silme (deleteCard)
func deleteCard(id: BKMExpress.Card.ID) async {
do {
let response = try await api.deleteCard(id: id)
switch response {
case let .cardDeleted(cards):
showCardList(cards)
case .accountDeleted:
// Son kart silindi; BKM Express hesabı da silindi.
showRegistrationScreen()
}
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
7.5. Ödeme Başlatma ve İşlem Kontrolü (controlPayment)
startPayment / startPaymentWithRegisteredCard çağrısı sırasında kullandığınız successUrl ve failUrl değerleri, ödeme init isteğiyle birlikte BEX backend’ine gönderilir. Amaç, ödeme süreci (3D Secure dahil) tamamlandığında iş yeri backend’inizin ilgili adrese yönlendirilerek veya sunucu bildirimi alarak ödeme sonucunu öğrenmesini sağlamaktır.
startPayment / startPaymentWithRegisteredCard çağrısı, backend'in kararına göre 3D Secure
bilgisi, OTP nesnesi veya doğrudan PaymentToken döndürebilir. Ödeme işleminin nihai
durumunu almak için elinizdeki PaymentToken ile controlPayment çağrılır.
Non-3D ve OTP'siz senaryo (init yanıtında .control(token) geldiğinde):
func startAndControlPayment(cardID: BKMExpress.Card.ID) async {
do {
let response = try await api.startPayment(
context: .init(
cardID: cardID,
security: .none,
amount: 100.00,
orderID: "ORDER_123",
installmentCount: .init(1)!
)
)
switch response {
case let .control(token):
let result = try await api.controlPayment(token: token)
showPaymentResult(result)
case let .otp(otp):
showOtpForPayment(otp: otp)
case let .tds(tdsInfo):
showTdsWebView(tdsInfo: tdsInfo)
}
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
3D Secure tamamlandıktan sonra (WebView'da işlem bitti anlamına gelen yönlendirme/callback
algılandığında), init aşamasında sakladığınız TDSInfo.paymentToken ile:
func onTdsCompleted(token: BKMExpress.PaymentToken) async {
do {
let result = try await api.controlPayment(token: token)
showPaymentResult(result)
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
Ödeme OTP'si sonrası (PaymentOTP.verify cevabında PaymentToken geldiğinde):
func onPaymentOtpVerified(otp: BKMExpress.PaymentOTP, code: String) async {
do {
let token = try await otp.verify(code: code)
let result = try await api.controlPayment(token: token)
showPaymentResult(result)
} catch let error as BKMExpress.Failure {
showError(error.message)
}
}
8. API Referansı (Özet)
Bu bölümde SDK'nın public API yüzeyi özetlenmektedir. Tüm çağrılar Swift Concurrency (async/await) tabanlıdır.
8.1. BKMExpress
Tekil giriş noktasıdır. initialize(context:) ile API nesnesi elde edilir.
8.1.1. initialize
static func initialize(
context: BKMExpress.InitializationContext
) async throws(BKMExpress.Failure) -> BKMExpress.API
- context:
authToken,merchantID,merchantUserID,gsmNo,currencyCode,modeparametrelerini içerir. - Başarılı olduğunda sözleşmeler ve şifreleme anahtarı otomatik olarak hazırlanır.
- Hata durumunda
BKMExpress.Failurefırlatır.
8.2. BKMExpress.API
Tüm metotlar async throws(BKMExpress.Failure) imzasına sahiptir; Swift Concurrency bağlamından
çağrılmalıdır.
8.2.1. checkStatus
func checkStatus() async throws(Failure) -> CheckStatusResponse
Cüzdan durumunu sorgular. Dönen CheckStatusResponse:
.linked([Card]): Kullanıcının hesabı vardır, bağlıdır ve kart listesi döner..unlinked: Kullanıcının hesabı vardır ancak bağlama yapılmamıştır..unregistered: Kullanıcı kayıtlı değildir.
8.2.2. linkAccount
func linkAccount() async throws(Failure) -> LinkAccountResponse
Cüzdanı iş yerine bağlar. Dönen LinkAccountResponse:
.recheck: Hesap başarıyla bağlandı; kart listesi içincheckStatus()yeniden çağrılmalıdır..verificationRequired(LinkOTP): OTP doğrulaması gerekiyor; dönenLinkOTPnesnesi üzerindenverify(code:)çağrılmalıdır.
8.2.3. storeCard
func storeCard(
context: StoreCardContext
) async throws(Failure) -> StoreCardResponse
Yeni kart ekler. StoreCardContext şu alanları içerir: number (CardNumber), expiryDate
(CardExpiryDate), alias (isteğe bağlı). Dönen StoreCardResponse:
.added([Card]): Kart eklendi; güncellenmiş kart listesi döner..verificationRequired(StoreCardOTP): OTP doğrulaması gerekiyor.
8.2.4. deleteCard
func deleteCard(id: BKMExpress.Card.ID) async throws(Failure) -> DeleteCardResponse
Kayıtlı bir kartı siler. Dönen DeleteCardResponse:
.cardDeleted([Card]): Kart silindi; güncellenmiş kart listesi döner..accountDeleted: Kullanıcının son kartı ve BKM Express hesabı silindi.
8.2.5. register
func register(
context: RegisterContext
) async throws(Failure) -> RegisterResponse
Telefon numarasını kart bilgisiyle "kısmi" kayıt eder. RegisterContext şu alanları içerir:
number (CardNumber), expiryDate (CardExpiryDate), alias (isteğe bağlı). Dönen
RegisterResponse:
.verificationRequired(RegisterOTP): OTP doğrulaması gerekiyor.
8.2.6. startPayment (Kayıtlı Kart ile Ödeme)
Kayıtlı bir kart (cardID) ile ödeme başlatır. Güvenlik türü PaymentSecurity ile seçilir:
.tds: 3D Secure; yanıttaTDSInfo(htmlForm, tdsURL vb.) beklenir..otp: OTP doğrulamalı non-3D ödeme..none: Doğrulama mekanizması olmaksızın ödeme.
Önemli:
PaymentSecurityyalnızca istemci tarafı tercihtir. İş kuralı veya banka, tercihinizden bağımsız farklı bir akış döndürebilir. Her zaman yanıttaki case'e göre akış seçilmelidir.
successUrl ve failUrl alanları, ödeme sürecinin tamamlanma durumunu iş yeri backend’inize
bildirmek amacıyla kullanılır. SDK bu adresleri mobil uygulama içinden doğrudan çağırmaz; startPayment / startPaymentWithRegisteredCard ile tetiklenen ödeme init isteklerinde BEX backend’ine iletilir. Böylece 3D Secure veya banka tarafı akışı sonunda iş yeri
sunucunuz, ödemenin başarılı veya başarısız sonuçlandığını sunucu tarafında öğrenebilir.
func startPayment(
context: StartPaymentContext
) async throws(Failure) -> StartPaymentResponse
StartPaymentContext şu alanları içerir: cardID, security (PaymentSecurity), amount
(Decimal), orderID, date, transactionID (UUID), installmentCount
(InstallmentCount), successUrl, failUrl.
Dönen StartPaymentResponse:
.tds(TDSInfo): 3D Secure doğrulaması gerekiyor..otp(PaymentOTP): OTP doğrulaması gerekiyor..control(PaymentToken): Ödeme sonucu doğrulama gerektirmeksizin kontrol edilebilir.
8.2.7. startPaymentWithRegisteredCard (Yeni Kart ile Ödeme)
Kayıtlı olmayan bir kart ile ödeme başlatır ve kartı kullanıcının hesabına kaydeder. successUrl / failUrl davranışı startPayment ile aynıdır. Parametreler ve PaymentSecurity semantiği startPayment ile aynıdır.
func startPaymentWithRegisteredCard(
context: StartPaymentWithRegisteredCardContext
) async throws(Failure) -> StartPaymentResponse
StartPaymentWithRegisteredCardContext şu alanları içerir: card (CardNumber + CardExpiryDate
- opsiyonel
alias),security,amount,currencyCode(CurrencyCode),orderID,date,transactionID,installmentCount,successUrl,failUrl.
8.2.8. controlPayment (İşlem / Ödeme Sonucu Sorgulama)
PaymentToken ile işlemin güncel sonucunu backend'den sorgular. Bu token genellikle
startPayment / startPaymentWithRegisteredCard yanıtındaki .control(token) case'inden veya
ödeme OTP'si onayı sonrası PaymentOTP.verify(code:) dönüşünden elde edilir. 3D Secure akışında,
kullanıcı banka sayfasında işlemi tamamladıktan sonra TDSInfo.paymentToken ile çağrı yapılır.
func controlPayment(
token: PaymentToken
) async throws(Failure) -> ControlPaymentResponse
Dönen ControlPaymentResponse şu başlıca alanları içerir: success, message, code,
orderID, successAmount, authCode, hostRefCode, hostRefNum, cardNumber (maskeli),
tarih ve terminal bilgileri.
8.2.9. pendingAgreements
func pendingAgreements() -> [Agreement]
Kart ekleme ve kayıt akışlarında kullanıcıya gösterilmesi gereken sözleşmeleri döndürür. Bu
metot, initialize çağrısının ardından geçerli hâle gelir.
8.3. Sonuç Tipleri
Tüm API metotları typed throws ile BKMExpress.Failure fırlatır:
- Başarı: Metodun dönüş değeri doğrudan kullanılır.
- Hata:
catch let error as BKMExpress.Failureile yakalanır;error.messageson kullanıcılara gösterilebilir.
8.4. Veri Modelleri (Özet)
Başlıca veri modelleri:
- BKMExpress.Card:
id,alias,maskedCardNumber,imageURL,bankInformation,bin,createTime - BKMExpress.Card.BankInformation:
bankShortName,cardType,cardScheme,cardBrand,bankCode - BKMExpress.OTPInfo:
id,sender,referenceNumber,receiver,durationInSeconds,length,resendTimeInSeconds - BKMExpress.TDSInfo:
htmlForm,tdsURL,orderID,paymentToken,code,message,success,bankTransactionID - BKMExpress.ControlPaymentResponse:
success,message,code,orderID,successAmount,authCode,hostRefCode,hostRefNum,cardNumber,bankTransactionID,bankTransactionDate,transactionDate,paymentID,secureType,installmentvb. - BKMExpress.Agreement:
id,code,kind(.agreement/.info),title,content(URL),label,labelHighlight,mandatory - BKMExpress.CardExpiryDate:
month,year,formatted; tamsayılar,"mm/yyyy"string'i veyaDateobjesinden oluşturulabilir - BKMExpress.CurrencyCode: Geçerli ISO 4217 kodunu temsil eder; statik
.TRY,.USD,.EURsabitleri mevcuttur - BKMExpress.InstallmentCount: Pozitif tamsayıdan oluşturulur;
0ve negatif değerler içinnildöner (failable initializer) - BKMExpress.PaymentSecurity:
.otp,.tds,.none
Örnek kart modeli:
let card: BKMExpress.Card
// card.id.rawValue -> "019d2dad-34bc-7b00-959d-0bef3009afa5"
// card.maskedCardNumber -> "123456******1234"
// card.alias -> "Maaş Kartım"
// card.bin -> "12345678"
// card.imageURL -> URL(string: "https://...default_card.png")
// card.bankInformation.cardType -> "CreditCard"
// card.bankInformation.cardBrand -> "Troy"
// card.bankInformation.bankShortName -> "TESTBANK"
8.5. BKMExpress.Failure
Başlıca hata türleri (Failure.Kind):
.session: Oturum hatası.encryption: Şifreleme hatası.server(code: Int): Backend kaynaklı hata;codealanıyla eşleştirme yapılabilir
Son kullanıcılara gösterilecek mesaj için error.message (veya error.localizedDescription)
alanı kullanılmalıdır.
catch let error as BKMExpress.Failure {
if case let .server(code) = error.kind, code == 1049 {
// Geçersiz para birimi — kullanıcıya bilgi verin
}
showAlert(error.message)
}
Not:
error.message/error.localizedDescriptiondeğerleri Türkçe metinler içerir.
9. Hata Yönetimi
9.1. Bilinen API Hata Kodları
Backend belirli iş kuralı ihlallerinde BKMExpress.Failure ile kind == .server(code:) üzerinden
hata döner:
| Kod | Başlık | Açıklama |
|---|---|---|
| 1049 | INVALID_CURRENCY | Gönderilen currencyCode değeri desteklenmiyor. Geçerli bir ISO 4217 kodu kullanın. |
| 36 | MISSED_MANDATORY_AGREEMENT | Zorunlu kullanıcı sözleşmesi onaylanmamış. |
INVALID_CURRENCY durumu:
Bu hata initialize(context:) çağrısında InitializationContext.currencyCode alanına geçersiz
bir değer gönderildiğinde tetiklenir. error.kind == .server(code: 1049) olarak döner;
error.message doğrudan kullanıcıya gösterilebilir.
do {
let api = try await BKMExpress.initialize(context: context)
} catch let error as BKMExpress.Failure {
if case let .server(code) = error.kind, code == 1049 {
// Geçersiz para birimi — kullanıcıya bilgi verin veya varsayılana dönün
}
showAlert(error.message)
}
9.2. Kart Numarası Bileşeni Hataları
Bileşenlerden kart numarası elde etmeye çalışırken dönen hatalar BKMExpress.CardNumberFailure
tipinde typed throws ile fırlatılır:
.empty: Kart numarası alanı boş..short: Kart numarası gerekenden kısa..invalidLuhn: Kart numarası Luhn algoritmasına uymuyor.
Uyarı: Bu hatalar özellikle lokalize edilmemiştir. Son kullanıcıya
localizedDescriptionile gösterim yapılmamalıdır. Her case için kendi belirlediğiniz mesajları, mimarinize uygun hata yönetim mekanizmanızla kullanıcıya göstermeniz gerekmektedir.
do {
let number = try cardNumberField.cardNumber()
// number kullanılabilir
} catch let failure as BKMExpress.CardNumberFailure {
switch failure {
case .empty:
showFieldError("Lütfen kart numarası giriniz.")
case .short:
showFieldError("Kart numarası çok kısa.")
case .invalidLuhn:
showFieldError("Geçersiz kart numarası.")
}
}
9.3. Genel Hata Yönetimi (Uygulama Örneği)
do {
let status = try await api.checkStatus()
handleStatus(status)
} catch let error as BKMExpress.Failure {
showAlert(error.message)
// İsteğe bağlı: error.kind'a göre (session, encryption, server) loglama
}