Skip to content

Android / Kotlin

Add JitPack to your project-level settings.gradle.kts:

dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}

Add the dependencies to your module-level build.gradle.kts:

dependencies {
implementation("com.github.Sanwohq.android:sanwo:0.1.1")
implementation("com.github.Sanwohq.android:paystack:0.1.1")
}
  • Min SDK 24
  • Kotlin
import com.sanwohq.sanwo.Sanwo
import com.sanwohq.paystack.paystackProvider
class CheckoutActivity : AppCompatActivity() {
private val sanwo = Sanwo(
provider = paystackProvider,
publicKey = "pk_test_xxxxxxxxxxxx"
)
private val launcher = sanwo.registerForCheckoutResult(this) { result ->
when (result) {
is CheckoutResult.Successful -> {
Log.d("Sanwo", "Paid! Ref: ${result.reference}")
}
is CheckoutResult.Cancelled -> {
Log.d("Sanwo", "User cancelled")
}
is CheckoutResult.Failed -> {
Log.d("Sanwo", "Failed: ${result.error}")
}
}
}
fun pay() {
val options = CheckoutOptions(
amount = 500000, // 5,000.00 NGN in kobo
currency = "NGN",
customer = CheckoutCustomer(email = "customer@example.com")
)
sanwo.launchCheckout(this, launcher, options)
}
}
val sanwo = Sanwo(
provider = paystackProvider,
publicKey = "pk_test_xxxxxxxxxxxx",
debug = false, // optional
timeout = 120 // optional, seconds
)
Parameter Type Required Default Description
provider SanwoProvider Yes Provider from a provider package
publicKey String Yes Your provider public key
debug Boolean No false Enable debug logging
timeout Int No 120 Timeout in seconds
val options = CheckoutOptions(
amount = 500000,
currency = "NGN",
customer = CheckoutCustomer(email = "customer@example.com"),
reference = "order_abc123", // optional
channels = listOf("card", "bank"), // optional
metadata = mapOf("plan" to "premium"),// optional
extra = mapOf("split_code" to "SPL_xxx") // optional, provider-specific
)
Property Type Required Description
amount Long Yes Amount in minor units (kobo, cents, paisa)
currency String Yes ISO 4217 currency code
customer CheckoutCustomer Yes Customer with at least an email
reference String? No Your unique transaction reference
channels List<String>? No Allowed payment channels
metadata Map<String, Any>? No Arbitrary metadata
extra Map<String, Any>? No Provider-specific options

A sealed class with three variants:

sealed class CheckoutResult {
data class Successful(
val reference: String,
val providerResponse: Any?
) : CheckoutResult()
object Cancelled : CheckoutResult()
data class Failed(
val error: String
) : CheckoutResult()
}

Register the result handler in your activity or fragment. The launcher is reusable.

// Register once (must be called before onStart)
private val launcher = sanwo.registerForCheckoutResult(this) { result ->
// handle result
}
// Launch checkout whenever needed
fun pay() {
sanwo.launchCheckout(this, launcher, options)
}

Use the callback-based API and forward onActivityResult:

sanwo(activity, options) { result ->
// handle result
}
// Don't forget to forward:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
sanwo.onActivityResult(requestCode, resultCode, data)
}

Subscribe to lifecycle events. on() returns an unsubscribe function.

val unsubscribe = sanwo.on(SanwoEvent.SUCCESS) { payload ->
Log.d("Sanwo", "Payment succeeded: ${payload["reference"]}")
}
// Later
unsubscribe()
Event Description
SanwoEvent.STARTED Checkout initiated
SanwoEvent.OPENED Checkout UI visible
SanwoEvent.LOADED Provider UI finished loading
SanwoEvent.SUCCESS Payment successful
SanwoEvent.CANCELLED User dismissed checkout
SanwoEvent.FAILED Payment failed
SanwoEvent.CLOSED Checkout UI dismissed
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.sanwohq.sanwo.*
import com.sanwohq.paystack.paystackProvider
class MainActivity : AppCompatActivity() {
private val sanwo = Sanwo(
provider = paystackProvider,
publicKey = "pk_test_xxxxxxxxxxxx"
)
private val checkoutLauncher = sanwo.registerForCheckoutResult(this) { result ->
when (result) {
is CheckoutResult.Successful -> {
Toast.makeText(
this,
"Paid! Ref: ${result.reference}",
Toast.LENGTH_LONG
).show()
}
is CheckoutResult.Cancelled -> {
Toast.makeText(this, "Cancelled", Toast.LENGTH_SHORT).show()
}
is CheckoutResult.Failed -> {
Toast.makeText(
this,
"Failed: ${result.error}",
Toast.LENGTH_LONG
).show()
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Track events
sanwo.on(SanwoEvent.LOADED) { _ ->
Log.d("Sanwo", "Checkout UI loaded")
}
findViewById<Button>(R.id.payButton).setOnClickListener {
val options = CheckoutOptions(
amount = 500000,
currency = "NGN",
customer = CheckoutCustomer(email = "customer@example.com"),
reference = "order_${System.currentTimeMillis()}"
)
sanwo.launchCheckout(this, checkoutLauncher, options)
}
}
}

You can use the same Sanwo instance from a Compose activity:

class ComposeCheckoutActivity : ComponentActivity() {
private val sanwo = Sanwo(
provider = paystackProvider,
publicKey = "pk_test_xxxxxxxxxxxx"
)
private val launcher = sanwo.registerForCheckoutResult(this) { result ->
// handle result
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Button(onClick = {
sanwo.launchCheckout(
this@ComposeCheckoutActivity,
launcher,
CheckoutOptions(
amount = 500000,
currency = "NGN",
customer = CheckoutCustomer(email = "customer@example.com")
)
)
}) {
Text("Pay ₦5,000")
}
}
}
}