Online Payment
This guide describes the end-to-end online payment flow between a Business device (sender) and a Customer device (receiver) using Bluetooth Low Energy.
Prerequisites
- SDK initialized and configured. See: Android VipasoSDK
- Business user and Customer user are authenticated on their respective devices
Flow overview
- Customer starts listening for payment events via BLE
- Business sends a payment request via BLE
- Information is exchanged between Business and Customer devices once connected
- The payment request is shown to the Customer, who can accept or cancel
- If approved, the Customer sends an acceptance back to the Business device
- Payment execution and finalization occur with the backend on both sides
Offline scenarios:
- If one side is offline, the online side handles the payment and shares the result
- If both are offline, payments require pre-authorization on the Customer instrument (experimental)
For full guidance on fully offline flows, see: Android — Offline payment.
1) Business — Send payment request via BLE
The Business device broadcasts a payment request. The call returns when the first Customer accepts it.
import io.vipaso.vipaso.sdkApi.payment.business.response.VipasoPaymentResult
val result: VipasoPaymentResult = Vipaso.payment.business.sendPaymentRequestViaBle(
amount = "12.00",
currency = "USD",
paymentReference = null // optional
)
when (result) {
is VipasoPaymentResult.PaymentSuccessful -> {
val id = result.paymentId
val amount = result.amount
val tip = result.tip
val currency = result.currency
// Handle success
}
is VipasoPaymentResult.PaymentCancelled -> {
// The Business user cancelled the payment
}
is VipasoPaymentResult.PaymentFailed -> {
val error = result.error
// Handle unrecoverable error on the Business side
}
}
Possible VipasoPaymentResult
outcomes:
PaymentSuccessful(paymentId: UUID, amount: String, tip: String, currency: String)
PaymentCancelled(paymentId: UUID)
PaymentFailed(paymentId: UUID, error: Throwable)
To stop or cancel:
// Cancel current payment and terminate BLE
autoCancel = Vipaso.payment.business.cancelPayment()
// Stop BLE advertising without cancelling an ongoing payment
Vipaso.payment.business.stopBle()
2) Customer — Listen and accept
The Customer device listens for incoming payment requests via BLE and accepts or declines.
import io.vipaso.vipaso.sdkApi.payment.customer.response.VipasoCustomerPaymentEvent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
val bleEvents: Flow<VipasoCustomerPaymentEvent> = Vipaso.payment.customer.receivePaymentRequestsViaBle()
scope.launch {
bleEvents.collect { event ->
when (event) {
is VipasoCustomerPaymentEvent.PaymentRequestReceived -> {
val paymentId = event.paymentId
val amount = event.amount
val currency = event.currency
val businessUserId = event.businessUserID
val operatorId = event.operatorId
val businessUserName = event.businessUserName
// Decide to accept or decline
}
is VipasoCustomerPaymentEvent.PaymentSuccessful -> {
// Payment completed successfully
}
is VipasoCustomerPaymentEvent.PaymentCancelled -> {
// Payment was cancelled
}
is VipasoCustomerPaymentEvent.AnotherUserPaid -> {
// Another user accepted and paid
}
is VipasoCustomerPaymentEvent.PaymentFailed -> {
val error = event.error
// Handle error
}
}
}
}
To accept a received request, send VipasoPaymentAcceptanceRequest
:
import io.vipaso.vipaso.sdkApi.payment.customer.response.VipasoPaymentAcceptanceRequest
import java.util.UUID
val acceptance = VipasoPaymentAcceptanceRequest(
paymentId = UUID.fromString("<payment-id-from-event>"),
amount = "12.00",
tip = "0.00", // optional
currency = "USD",
instrumentId = "instrument-id",
isDelegatedInstrument = true // set true for delegated instruments
)
Vipaso.payment.customer.acceptPayment(acceptance)
3) Cancel or stop
To cancel or stop listening:
// Reject/cancel a pending payment by ID
Vipaso.payment.customer.cancelPayment("<payment-id>")
// Stop BLE scanning
Vipaso.payment.customer.stopBle()