POS
Vipaso Pos SDK makes it easy to add both online and offline payment capabilities via BLE to your Android app with simple merchant authentication and transaction handling
Table of Contents
- Prerequisites
- Setup and Configuration
- Error Handling
- SDK Overview
- Managed Authentication (PosManagedAuthApi)
- Delegated Authentication (PosDelegatedAuthApi)
- User Management (PosUserApi)
- Payment Processing (PosPaymentApi)
Prerequisites
SDK Version Requirements
- Android Compile SDK: 34 (Your app App Compile SDK must be 34 or higher)
- Android Target SDK = 34
- Android Min SDK: 26 (Your app App Min SDK must be 26 or higher)
Required Permissions
The following permissions must be added to your app's AndroidManifest.xml
file:
<!-- BLE feature requirement -->
<uses-feature
android:name="android.hardware.bluetooth_le"
android:required="true" />
<!-- Bluetooth permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Location permissions (for Android 10 and below) -->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
android:maxSdkVersion="30" />
<!-- Bluetooth permissions for Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"
tools:targetApi="s" />
<!-- Network permission -->
<uses-permission android:name="android.permission.INTERNET" />
For Android 12 (API level 31) and above, you will need to request runtime permissions for BLUETOOTH_SCAN
and BLUETOOTH_CONNECT
. For Android 11 and below, ACCESS_FINE_LOCATION
permission is required for BLE scanning. Make sure to properly request these permissions in your app before using the BLE payment functionality.
Setup and Configuration
Initialize the SDK
The recommended way is to initialize the Vipaso SDK using the VipasoSdkInitializer
singleton object. This will set up all necessary components and allow you to interact with the SDK features.
When initializing the SDK, you need to:
- First initialize the SDK with the appropriate mode
- Then set the configuration parameters
// Step 1: Initialize the SDK with the appropriate mode
VipasoSdkInitializer.initialize(context, VipasoSdkMode.Pos)
/*
Possible SDK modes:
- VipasoSdkMode.Pos: Pos mode (for merchants to request payments)
- VipasoSdkMode.Pay: Pay mode (for users to receive payments and pay)
- VipasoSdkMode.Full: Full mode (includes both Pos and Pay features)
*/
// Step 2: Create and set the SDK configuration
val sdkConfig = VipasoSdkConfig(
baseUrl = "https://your.base.path",
bleUuidService = UUID.fromString("your-service-uuid"),
emailSupport = "[email protected]", // Optional
timeoutPaymentStatusBackendPollingDuration = 60.seconds // Optional, defaults to 60 seconds
)
// Set the SDK configuration, you need to set this before using any of the SDK features
VipasoSdkInitializer.setSdkConfig(sdkConfig)
Accessing the SDK
The Vipaso POS SDK uses Koin for internal dependency injection. Depending on your application's DI framework, you can access the SDK in one of the following ways:
Option 1: With Dependency Injection (Koin)
As the SDK uses Koin for internal dependency injection, you can directly access SDK dependencies:
// Access VipasoPos directly from SDK's Koin container
val vipasoPos by SdkKoinProvider.koin.inject<VipasoPos>()
Option 2: With Dependency Injection (Dagger/Hilt)
If your application uses Hilt/Dagger for dependency injection, you need to re-provide the SDK dependencies:
// Re-providing dependencies from Koin DI to Hilt DI framework
// since the SDK uses Koin internally
@Module
@InstallIn(SingletonComponent::class)
class VipasoPosModule {
@Provides
@Singleton
fun provideVipasoPos(): VipasoPos {
val vipasoPos by SdkKoinProvider.koin.inject<VipasoPos>()
return vipasoPos
}
}
Option 3: Without Dependency Injection
If your app doesn't use dependency injection, you can initialize the SDK directly:
// it's possible to initialize SDK directly
val vipasoPos = VipasoPosImpl()
// Access the main APIs
val managedAuthApi: PosManagedAuthApi = vipasoPos.managedAuth
val delegatedAuthApi: PosDelegatedAuthApi = vipasoPos.delegatedAuth
val userApi: PosUserApi = vipasoPos.user
val paymentApi: PosPaymentApi = vipasoPos.payment
Error Handling
All SDK methods that can throw exceptions should be wrapped in try-catch blocks to handle potential errors:
try {
vipasoPos.payment.requestPaymentViaBle(amount, currency, merchantId, operatorId)
} catch (throwable: Throwable) {
// Handle the error
Log.e("VipasoError", "Error processing payment", throwable)
}
SDK Overview
The Vipaso POS SDK exposes its functionality through a set of specialized APIs, each handling a specific domain:
Authentication APIs
The SDK provides two different authentication approaches:
- Managed Authentication: When your app wants to use Vipaso's authentication system and identity provider.
- Delegated Authentication: When your app uses its own authentication system and identity provider.
PosManagedAuthApi
Handles merchant authentication when using Vipaso's identity provider:
- login() - Authenticate and login a merchant operator
PosDelegatedAuthApi
Handles authentication when your app uses its own identity provider:
- establishAuthentication() - Connect your app's authentication system with Vipaso
PosUserApi
Manages merchant information and login state:
- getUserLoginState() - Observe current login state
- logout() - Logout the current operator
- fetchMerchant() - Get merchant information
- fetchFeatureFlags() - Get feature flags available for the current merchant
PosPaymentApi
Processes payments and maintains payment history:
- fetchPayments() - Get list of payment transactions
- fetchPayment() - Get details for a specific payment
- requestPaymentViaBle() - Initiate a payment request via BLE
- cancelPayment() - Cancel an ongoing payment operation
- stopBle() - Stop the BLE payment request service
Managed Authentication (PosManagedAuthApi)
The PosManagedAuthApi
handles merchant operator authentication when using Vipaso's identity provider. Choose this approach when you want Vipaso to handle merchant authentication completely.
Login
Authenticate and login a merchant operator:
// Request: Login a merchant operator
val loginRequest = LoginRequest(
userIdentifer = "[email protected]", // Can be email or phone number
password = "secure_password"
)
vipasoPos.managedAuth.login(loginRequest)
// You can observe login state changes via user.getUserLoginState()
Delegated Authentication (PosDelegatedAuthApi)
The PosDelegatedAuthApi
enables integration with your own authentication system. Choose this approach when your app already has merchant accounts and you want to maintain your existing identity management while using Vipaso's payment features.
Establish Authentication
// Request: Establish authentication between your own identity provider and Vipaso SDK
vipasoPos.delegatedAuth.establishAuthentication(
// The unique identifier for the merchant operator in your system
userIdentifier = "merchant-op-123",
// A callback that receives a JWK (provided by Vipaso SDK) as input and outputs a string (you get from your backend)
connect = { jwk ->
// 1. Send the JWK to a dedicated backend endpoint provided on your domain
// 2. And then return the output string received from your backend
}
)
// Once this call returns successfully then you can use all the SDK features
User Management (PosUserApi)
The PosUserApi
manages merchant profile information, login state tracking, and merchant-specific features.
Logout
Log out the current merchant operator:
// Request: Logout current operator
vipasoPos.user.logout()
// You can observe login state changes via getUserLoginState()
Fetch Merchant
Retrieve information about the merchant associated with the current operator:
// Request: Get merchant information
val merchant = vipasoPos.user.fetchMerchant()
// Response: Merchant information
VipasoMerchant(
id = "merchant-123",
name = "Coffee Shop",
operatorId = "operator-456",
currency = "USD"
)
Fetch Feature Flags
// Request: Get feature flags for the current merchant
val featureFlags = vipasoPos.user.fetchFeatureFlags()
// Response: Set of feature flags with their states
Set<VipasoFeatureFlagWithState>(
VipasoFeatureFlagWithState(
featureFlag = "feature_name_1",
isEnabled = true
),
VipasoFeatureFlagWithState(
featureFlag = "feature_name_2",
isEnabled = false
)
)
Get User Login State
Get the current login state as a Flow that emits updates when the login state changes:
// Request: Observe login state changes
val loginStateFlow = vipasoPos.user.getUserLoginState()
// Collect login state changes
lifecycleScope.launch {
loginStateFlow.collect { loginState ->
when (loginState) {
LoginState.LoggedIn -> {
// User is logged in, show main content
showMainContent()
}
LoginState.NotLoggedIn -> {
// User is not logged in, show login screen
showLoginScreen()
}
}
}
}
Payment Processing (PosPaymentApi)
The PosPaymentApi
handles all payment-related operations for POS terminals.
Fetch Payments
Retrieve a paginated list of payment transactions with optional filtering by status:
// Request: Get list of payment transactions
val payments = vipasoPos.payment.fetchPayments(
page = 0,
status = VipasoPaymentStatus.COMPLETED
)
// Response: List of payment transactions
FetchPaymentsResponse(
payments = [
VipasoPayment(
paymentId = "payment-123",
amount = 25.50,
currency = "USD",
unifiedStatus = VipasoPaymentStatus.COMPLETED,
timestamp = 1623412345678,
instrumentId = "card-123",
instrumentType = "CARD",
description = "Coffee and sandwich",
lastUpdate = "2025-06-03T09:25:48Z",
merchant = VipasoMerchant(
merchantId = "merchant-456",
name = "Coffee Shop"
),
consumer = VipasoConsumer(
id = "user-123",
name = "John Doe"
)
),
// Additional payments...
]
)
/*
Possible VipasoPaymentStatus values:
- INITIATED: Payment has been created but processing hasn't started
- IN_PROGRESS: Payment is currently being processed
- COMPLETED: Payment has been successfully completed and funds transferred
- FAILED: Payment processing failed due to an error
- CANCELLED: Payment was cancelled by the user, merchant, or system
*/
Fetch Payment
Retrieve details for a specific payment transaction:
// Request: Get details for a specific payment
val paymentDetails = vipasoPos.payment.fetchPayment(
FetchPaymentDetailsRequest("payment-123")
)
// Response: Payment details
FetchPaymentDetailsResponse(
payment = VipasoPayment(
paymentId = "payment-123",
amount = 25.50,
currency = "USD",
unifiedStatus = VipasoPaymentStatus.COMPLETED,
timestamp = 1623412345678,
instrumentId = "card-123",
instrumentType = "CARD",
description = "Coffee and sandwich",
lastUpdate = "2025-06-03T09:25:48Z",
merchant = VipasoMerchant(
merchantId = "merchant-456",
name = "Coffee Shop"
),
consumer = VipasoConsumer(
id = "user-123",
name = "John Doe"
)
)
)
/*
Possible VipasoPaymentStatus values:
- INITIATED: Payment has been created but processing hasn't started
- IN_PROGRESS: Payment is currently being processed
- COMPLETED: Payment has been successfully completed and funds transferred
- FAILED: Payment processing failed due to an error
- CANCELLED: Payment was cancelled by the user, merchant, or system
*/
Request Payment via BLE
Initiate a payment request via BLE to nearby Vipaso Pay users. This method sends a payment request to all potential payers in range and returns when the first payer successfully accepts the payment:
You can get merchantId
and operatorId
from the fetchMerchant()
// Request: Initiate a payment request via BLE
try {
val paymentResult = vipasoPos.payment.requestPaymentViaBle(
amount = "25.50",
currency = "USD",
merchantId = "merchant-123",
operatorId = "operator-456"
)
// Process the payment result based on its type
when (paymentResult) {
is VipasoPosPaymentResult.PaymentSuccessful -> {
// Payment was successfully processed
val amount = paymentResult.amount // "25.50"
val tip = paymentResult.tip // "2.50"
val currency = paymentResult.currency // "USD"
val paymentId = paymentResult.paymentId
// Update UI with successful payment
displayPaymentSuccess(amount, tip, currency, paymentId)
}
is VipasoPosPaymentResult.PaymentCancelled -> {
// Payment was cancelled by the operator or payer
val paymentId = paymentResult.paymentId
// Update UI to show payment was cancelled
displayPaymentCancelled(paymentId)
}
is VipasoPosPaymentResult.PaymentFailed -> {
// Payment processing failed
val paymentId = paymentResult.paymentId
val error = paymentResult.error
// Handle payment failure, display error message
displayPaymentError(paymentId, error)
}
}
} catch (e: Exception) {
// Handle exceptions during payment initialization
Log.e("PaymentError", "Failed to initiate payment", e)
}
Cancel Payment Request
Cancel an ongoing payment operation that was initiated via BLE:
// Request: Cancel an ongoing payment
vipasoPos.payment.cancelPayment()
// The payment will be terminated and any Pay Devices that were already connected will receive a PaymentCancelled state.
Stop BLE
When you not interested in request payments anymore or when closing the app, it's recommended to stop the BLE payment service and clean up resources:
// Request: Terminate all BLE payment operations immediately and clean up resources
vipasoPos.payment.stopBle()
Updated 6 days ago