DIGIHCE SDK Documentation
Complete reference for integrating NFC HCE payments into your Android application.
Quick Start
Get NFC payments running in your app in under 5 minutes.
Add the SDK dependency to your build.gradle.kts
Initialize the SDK in your Application.onCreate()
Create a reader and start collecting payments
Installation
Add the DIGIHCE Maven repository and SDK dependency:
dependencyResolutionManagement {
repositories {
maven {
url = uri("https://maven.hce.vas.et/releases")
credentials {
username = "token"
password = providers.gradleProperty("DIGIHCE_TOKEN").get()
}
}
}
}dependencies {
implementation("com.digihce:sdk:1.0.0")
}Alternative: AAR file
If using the AAR distribution, place the file in app/libs/ and add implementation(files("libs/digihcesdk.aar")) to your dependencies.
Initialization
Initialize the SDK in your Application class with your API key:
class SampleApp : Application() {
override fun onCreate() {
super.onCreate()
DigiHceSdk.init(applicationContext) {
apiKey = "digi_live_xxxxxxxxxxxx"
aid = "F0746C6272507961" // optional, uses default
environment = Environment.SANDBOX // or PRODUCTION
cardIdentity = CardIdentity(
name = "User A",
accountId = "ACC-12345",
msisdn = "+251912345678" // optional, for USSD 2FA
)
cardEnabled = true
}
}
}What happens during init()
- Validates API key with backend via
POST /sdk/activate - Receives JWT session token (24h TTL) and encryption key material
- Stores credentials in EncryptedSharedPreferences
- Dynamically registers the AID for NFC payment routing
Collecting Payments
Use the reader API to accept NFC tap payments from payers:
val reader = DigiHceSdk.createReader(activity)
// Start collecting — returns a Flow scoped to this session
val sessionFlow: Flow<DigiHceEvent> = reader.collect(
amount = "100.00",
currency = "ETB"
)
// Observe events
sessionFlow.collect { event ->
when (event) {
is DigiHceEvent.ChargeCompleted -> {
showSuccess(event.result)
}
is DigiHceEvent.ChargePending2FA -> {
showWaiting("Awaiting USSD confirmation...")
}
is DigiHceEvent.TransactionReversed -> {
showReversed(event.reason)
}
is DigiHceEvent.Error -> {
showError(event.error)
}
}
}
// Stop when done
reader.stop()The reader is lifecycle-aware and automatically cleans up when the Activity is destroyed.
Sending Payments (Push)
Prepare a push payment that broadcasts via HCE when another device taps:
// Prepare server-signed payment payload
val result: Result<TransactionResult> = DigiHceSdk.preparePayment(
amount = "50.00",
currency = "ETB"
)
when {
result.isSuccess -> {
// HCE now broadcasts the signed payload
// On tap + CONFIRM → emits PaymentSent
showReady("Tap to send payment")
}
result.isFailure -> {
showError(result.exceptionOrNull())
}
}
// Cancel if needed
DigiHceSdk.cancelPayment()Events & Callbacks
Flow API (recommended)
DigiHceSdk.events.collect { event ->
when (event) {
is DigiHceEvent.ChargeReceived -> { }
is DigiHceEvent.ChargePending2FA -> { }
is DigiHceEvent.ChargeCompleted -> { }
is DigiHceEvent.PaymentSent -> { }
is DigiHceEvent.PaymentReceived -> { }
is DigiHceEvent.TransactionReversed -> { }
is DigiHceEvent.Error -> { }
is DigiHceEvent.SdkDeactivated -> { }
}
}Callback API (alternative)
DigiHceSdk.setListener(object : DigiHceListener {
override fun onChargeReceived(result: TransactionResult) {}
override fun onChargePending2FA(transactionId: String) {}
override fun onChargeCompleted(result: TransactionResult) {}
override fun onPaymentSent(result: TransactionResult) {}
override fun onPaymentReceived(result: TransactionResult) {}
override fun onTransactionReversed(id: String, reason: String) {}
override fun onError(error: DigiHceError) {}
override fun onSdkDeactivated(reason: String) {}
})Data Models
data class CardIdentity(
val name: String,
val accountId: String,
val msisdn: String? = null // for USSD 2FA
)
data class TransactionResult(
val transactionId: String,
val status: TransactionStatus,
val amount: String,
val currency: String,
val counterparty: String,
val timestamp: Long,
val serverReceipt: String?
)
enum class TransactionStatus {
SETTLED,
PENDING_2FA,
REVERSED,
FAILED,
PENDING_SYNC // offline payer, awaiting connectivity
}Security Architecture
The SDK implements 8 layers of security:
API Key Gating
Session tokens via POST /sdk/activate
Server-Signed Transactions
ECDSA P-256 signed transaction tokens
Encrypted NFC Payloads
AES-256-GCM with per-transaction keys
USSD 2FA
Configurable per-MSISDN with amount thresholds
License Validation
Periodic checks every 6 hours
Certificate Pinning
SHA-256 TLS pin with backup rotation
SDK Obfuscation
ProGuard with string encryption
Device Integrity
Device fingerprint bound to session
Error Handling
sealed class DigiHceError {
data class AuthFailed(val message: String) : DigiHceError()
data class NfcUnavailable(val message: String) : DigiHceError()
data class TransactionFailed(
val transactionId: String?,
val message: String
) : DigiHceError()
data class NetworkError(val message: String) : DigiHceError()
data class LicenseExpired(val message: String) : DigiHceError()
data class CardDisabled(val message: String) : DigiHceError()
}APDU Status Words