Skip to main content

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

  1. Add Stripe SDK
build.gradle.kts
 dependencies {
implementation("com.stripe:stripe-android:20.37.0")
}

  1. Configure Stripe
Application.kt
 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

  1. Add Klarna Mobile SDK
build.gradle.kts
 dependencies {
implementation("com.klarna.mobile:sdk:2.0.0")
}

  1. Configure in reachu-config.json
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

PaymentManager.kt
import io.reachu.ReachuUI.Managers.stripeIntent
import kotlinx.coroutines.launch

suspend fun initializeStripePayment(cartManager: CartManager): PaymentIntentStripeDto? {
return cartManager.stripeIntent(returnEphemeralKey = true)
}

Present Payment Sheet

StripePayment.kt
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

Klarna native payment uses the official Klarna Mobile SDK for a seamless in-app experience.

Step 1: Initialize Klarna Native

KlarnaPayment.kt
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

MainActivity.kt
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

KlarnaPayment.kt
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:

KlarnaWebPayment.kt
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

VippsPayment.kt
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)
}
}
}

Register deep link handler in AndroidManifest.xml:

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:

MainActivity.kt
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:

RCheckoutOverlay.kt
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

  1. Always handle errors: Wrap payment calls in try-catch blocks
  2. Show loading states: Display loading indicators during payment processing
  3. Validate inputs: Ensure all required fields are filled before initiating payment
  4. Test thoroughly: Test all payment flows in sandbox/test mode before production
  5. Handle deep links: Properly configure and handle deep links for web-based payments

Next Steps


Ready to integrate payments?