Payment Integration - Stripe, Klarna & Vipps
The Reachu Kotlin SDK includes production-ready integrationswith Stripe, Klarna, and Vipps payment processors. Handle credit cards, digital wallets, and buy-now-pay-later options seamlessly.
Overview
Supported Payment Methods: - Stripe - Credit/debit cards with PaymentSheet
- Klarna - Buy now, pay later (native and web)
- Vipps - Norwegian mobile payment
- More coming soon - PayPal and more
Prerequisites
Stripe Setup
- Add Stripe SDK
dependencies {
implementation("com.stripe:stripe-android:20.37.0")
}
- Configure Stripe
import com.stripe.android.PaymentConfiguration
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Initialize Stripe with publishable key
PaymentConfiguration.init(
applicationContext,
"pk_test_your_publishable_key"
)
}
}
Klarna Setup
- Add Klarna Mobile SDK
dependencies {
implementation("com.klarna.mobile:sdk:2.0.0")
}
- Configure in reachu-config.json
{
"payment": {
"klarna": {
"mode": "native",
"clientToken": "YOUR_KLARNA_CLIENT_TOKEN"
}
}
}
Vipps Setup
Vipps doesn't require a separate SDK. The integration uses web-based flows with deep links.
Stripe Integration
Initialize Payment Intent
import io.reachu.ReachuUI.Managers.stripeIntent
import kotlinx.coroutines.launch
suspend fun initializeStripePayment(cartManager: CartManager): PaymentIntentStripeDto? {
return cartManager.stripeIntent(returnEphemeralKey = true)
}
Present Payment Sheet
import com.stripe.android.paymentsheet.PaymentSheet
import com.stripe.android.paymentsheet.PaymentSheetResult
fun presentStripePayment(
activity: Activity,
paymentIntent: PaymentIntentStripeDto,
onResult: (PaymentSheetResult) -> Unit
) {
val paymentSheet = PaymentSheet(
activity = activity,
paymentIntentClientSecret = paymentIntent.clientSecret,
configuration = PaymentSheet.Configuration(
merchantDisplayName = "Your Store"
)
)
paymentSheet.presentWithPaymentIntent(
paymentIntentClientSecret = paymentIntent.clientSecret,
configuration = PaymentSheet.Configuration(
merchantDisplayName = "Your Store"
),
callback = onResult
)
}
Handle Payment Result
presentStripePayment(activity, paymentIntent) { result ->
when (result) {
is PaymentSheetResult.Completed -> {
// Payment successful
updateCheckoutStatus("paid")
}
is PaymentSheetResult.Canceled -> {
// User canceled
}
is PaymentSheetResult.Failed -> {
// Payment failed
showError(result.error.message)
}
}
}
Klarna Integration
Native Payment (Recommended)
Klarna native payment uses the official Klarna Mobile SDK for a seamless in-app experience.
Step 1: Initialize Klarna Native
import io.reachu.ReachuUI.Managers.initKlarnaNative
import io.reachu.sdk.domain.models.KlarnaNativeInitInputDto
import kotlinx.coroutines.launch
fun initializeKlarnaNative(
cartManager: CartManager,
countryCode: String = "NO",
currency: String = "NOK"
) {
scope.launch {
val input = KlarnaNativeInitInputDto(
countryCode = countryCode,
currency = currency,
returnUrl = "reachu://klarna/callback"
)
val result = cartManager.initKlarnaNative(input)
if (result != null) {
// Launch Klarna native activity
launchKlarnaNativeActivity(result.clientToken)
}
}
}
Step 2: Launch Klarna Native Activity
import android.content.Intent
import io.reachu.ReachuUI.KlarnaNativeActivity
fun launchKlarnaNativeActivity(clientToken: String) {
val intent = Intent(this, KlarnaNativeActivity::class.java).apply {
putExtra("client_token", clientToken)
putExtra("category", "pay_now") // or "pay_later", "slice_it"
}
startActivityForResult(intent, KLARNA_NATIVE_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == KLARNA_NATIVE_REQUEST_CODE) {
when (resultCode) {
Activity.RESULT_OK -> {
val authToken = data?.getStringExtra("auth_token")
authToken?.let { confirmKlarnaPayment(it) }
}
Activity.RESULT_CANCELED -> {
val error = data?.getStringExtra("error")
showError(error ?: "Payment canceled")
}
}
}
}
Step 3: Confirm Payment
import io.reachu.ReachuUI.Managers.confirmKlarnaNative
import kotlinx.coroutines.launch
fun confirmKlarnaPayment(authToken: String) {
scope.launch {
val result = cartManager.confirmKlarnaNative(
authorizationToken = authToken,
autoCapture = true
)
if (result != null) {
// Payment confirmed
updateCheckoutStatus("paid")
}
}
}
Web Payment (Fallback)
If native payment is not available, use Klarna web payment:
import android.content.Intent
import io.reachu.ReachuUI.KlarnaWebActivity
fun launchKlarnaWebPayment(
htmlSnippet: String,
successUrl: String,
cancelUrl: String
) {
val intent = Intent(this, KlarnaWebActivity::class.java).apply {
putExtra("html_snippet", htmlSnippet)
putExtra("success_url", successUrl)
putExtra("cancel_url", cancelUrl)
}
startActivity(intent)
}
The KlarnaWebActivity automatically detects success/cancel redirects and emits events via DeepLinkBus.
Vipps Integration
Initialize Vipps Payment
import io.reachu.ReachuUI.Managers.vippsInit
import kotlinx.coroutines.launch
fun initializeVippsPayment(
cartManager: CartManager,
email: String,
returnUrl: String = "reachu://vipps/callback"
) {
scope.launch {
val result = cartManager.vippsInit(
email = email,
returnUrl = returnUrl
)
if (result != null) {
// Open Vipps payment URL
openUrl(result.paymentUrl)
}
}
}
Handle Deep Link Return
Register deep link handler in AndroidManifest.xml:
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="reachu" android:host="vipps" />
</intent-filter>
</activity>
Handle in MainActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle deep link
intent?.data?.let { uri ->
if (uri.scheme == "reachu" && uri.host == "vipps") {
val status = uri.getQueryParameter("status")
if (status == "success") {
updateCheckoutStatus("paid")
}
}
}
}
Payment Method Selection
The SDK automatically resolves available payment methods based on configuration and backend:
val checkoutOverlay = RCheckoutOverlay(cartManager, checkoutDraft)
// Get allowed payment methods
val allowedMethods = checkoutOverlay.allowedPaymentMethods
// Check if method is allowed
if (checkoutOverlay.isMethodAllowed(PaymentMethod.Klarna)) {
// Show Klarna option
}
// Select payment method
checkoutOverlay.selectPaymentMethod(PaymentMethod.Stripe)
Error Handling
All payment methods include comprehensive error handling:
try {
val result = cartManager.initKlarnaNative(input)
// Handle success
} catch (e: SdkException) {
when (e) {
is AuthException -> {
// Handle authentication error
}
is ValidationException -> {
// Handle validation error
}
is RateLimitException -> {
// Handle rate limit
}
else -> {
// Handle other errors
}
}
}
Best Practices
- Always handle errors: Wrap payment calls in try-catch blocks
- Show loading states: Display loading indicators during payment processing
- Validate inputs: Ensure all required fields are filled before initiating payment
- Test thoroughly: Test all payment flows in sandbox/test mode before production
- Handle deep links: Properly configure and handle deep links for web-based payments
Next Steps
- UI Components - See checkout overlay implementation
- API Reference - Complete payment API documentation
- Examples - See complete payment examples