This object exposes APIs to interact with the PoS side. This includes authentication and initiating and listing payments.

Setup

The recommended way is to have a singleton instance of VipasoPoS in your code with a passed delegate/listener instance that will receive all authentication state change events.

Configuration

When you create the instance, you can pass some configuration parameters to update the base path and the BLE settings. You can also pass a VipasoPOSDelegate (iOS), VipasoPosListener (Android), instance, that will receive notifications when the authentication state changes.

iOS

VipasoPOS(
    config: VipasoConfiguration(
        paymentBasePath: Config.basePath,
        bleServiceUUID: Config.bleServiceUUID,
        bleStatusUUID: Config.bleStatusUUID,
        bleWriteUUID: Config.bleWriteUUID
    ),
    delegate: delegate
)

Android

The instance that you have to create to access the library is VipasoPos. It takes two parameters to create this instance, Context and VipasoConfiguration.

data class VipasoConfiguration(
    val paymentBasePath: String,
    val bleServiceUuid: String,
    val bleStatusUuid: String,
    val bleWriteUuid: String,
	  val bleReadUuid: String
)

val vipasoConfiguration = VipasoConfiguration(
            paymentBasePath = "https://your.base.path",
            bleServiceUuid = "your service UUID",
            bleWriteUuid = "your Bluetooth Write UUID",
            bleStatusUuid = "your Bluetooth Status UUID",
            bleReadUuid = "your Bluetooth Read UUID"
        )
)

Once the parameters are ready, you can create VipasoPos instance anywhere. You can also use Dependency Injection to handle the instance creation and can be injected anywhere in your project, as follow :

// Instance Creation
val vipasoPos : VipasoPos = VipasoPosImpl(context = context, vipasoConfiguration = vipasoConfiguration, listener = listener)

// Instance Creation using Dependency Injection Dagger Hilt
@Module
@InstallIn(SingletonComponent::class)
class VipasoPosModule {

    @Provides
    @Singleton
    fun provideVipasoPos(
        @ApplicationContext context: Context,
        configuration: VipasoConfiguration,
        listener: VipasoPosListener?
    ): VipasoPos {
        return VipasoPosImpl(configuration, context, listener)
    }

    @Provides
    fun provideVipasoConfig(@ApplicationContext context: Context): VipasoConfiguration {
        return VipasoConfiguration(
            paymentBasePath = "https://your.base.path",
            bleServiceUuid = "your service UUID",
            bleWriteUuid = "your Bluetooth Write UUID",
            bleStatusUuid = "your Bluetooth Status UUID",
            bleReadUuid = "your Bluetooth Read UUID"
        )
    }
}

Observing SDK events

By implementing the VipasoPosListener (Android) or VipasoPOSDelegate (iOS) interface and passing it to the SDK, the client-side developer can subscribe to authentication state change events. You can pass the listener/delegate at init. Setting it automatically fires an event with the latest authentication state of the user. As the user signs up, logs in or out, an event will arrive and the app can be updated accordingly.accordingly.

iOS example

extension RootCoordinator: VipasoPOSDelegate {
    func onAuthenticationStateChange(vipaso: VipasoPOSProtocol, authenticated: Bool) {
        if authenticated {
            displayMainCoordinator()
        } else {
            displayAuthenticationCoordinator()
        }
    }
}

Android example

override fun onAuthenticationStateChange(authenticated: Boolean) {
    isAuthenticated.value = authenticated
}

Authentication

There is not signup support on the PoS side on purpose. We have a proper merchant registration flow in place that is outside of the applications' scope.

Login

You can log in with the merchant details you received from us. You pass the e-mail address as identifier with a password, the SDK will store your session token securely and the observer will be notified.

iOS

let request = LoginRequest(identifier: email, password: password)
vipasoPOS.login(request: request) { result in
    switch result {
    case .success:
        print("success")
    case .failure(let error):
        print("error: \(error.localizedDescription)")
    }
}

Android

val email : String = "[email protected]"
 val password : String = "password"

 val response = vipasoPos.login(LoginRequest(email, password))
        if (response.data != null) {
            print("success")
        } else {
            print(response.error?.message)
        }

Logging out

Simply calling the exposed logout function, the SDK will remove the stored session token and the observer will be notified.

Merchant data

Fetching merchant info

To get all info about the merchant, use fetchMerchant.

func fetchMerchant(completion: @escaping (Result<FetchMerchantResponse, VipasoError>) -> Void)

This will return a merchant object with the following data.

public struct VipasoMerchant {
    public var id: String?
    public var name: String?
    public var operatorID: String?
}

Payments

List transactions

Listing your payment transaction history is a simple fetch call without any parameters.

iOS

vipasoPOS.fetchPayments(page: 3, status: .completed) { result in
    switch result {
    case .success(let response):
        print("success: \(response.payments)")
    case .failure(let error):
        print("error: \(error.localizedDescription)")
    }
}

Android

val response = vipasoPos.fetchPayments(page: 3, status: VipasoPaymentPagaStatus.COMPLETED)
        if (response.data != null) {
            print(response.payments)
        } else {
            print(response.error?.message)
        }

Initiating a payment

To create a new payment, you can use initiatePayment. You only need to set the expected payment details and the SDK will return you a payment id. You can then share that id with the Pay side (for example over BLE) and it can start executing the payment.

iOS

let request = InitiatePaymentRequest(
    amount: "10.00",
    currency: "EUR"
)
vipasoPOS.initiatePayment(request: request) { result in
    switch result {
    case .success(let response):
        print("success: \(response.paymentID)")
    case .failure(let error):
        print("error: \(error.localizedDescription)")
    }
}

Android

val amount : String = "23"
val currency : String = "EUR"

val request = InitiatePaymentRequest(amount = amount, currency = currency)

val response = vipasoPos.initiatePayment(request)
if (response.data != null) {
            print(response.paymentId)
        } else {
            print(response.error?.message)
        }

Requesting payment via BLE

After you created the payment id in the initiatePayment call, you can advertise it with initiateBLEPayment so any Pay app who is close enough can receive your payment request.

iOS

let paymentRequest = PaymentRequest(paymentID: paymentID)
vipasoPOS.initiateBLEPayment(request: paymentRequest) { result in
    switch result {
    case .success(let response):
        print("success: \(response)")
    case .failure(let error):
        print("error: \(error.localizedDescription)")
    }
}

Android

val request: PaymentRequest = PaymentRequest("paymentId")

val response = vipasoPos.initiateBLEPayment(request)
if (response.data != null) {
            print(response)
        } else {
            print(response.error?.message)
        }

Fetching payment details

Fetching the details of a payment is a simple fetch call, you only need to set the payment id.

iOS

let request = FetchPaymentDetailsRequest(paymentID: paymentID)
vipasoPOS.fetchPaymentDetails(request: request) { result in
    switch result {
    case .success(let response):
        print("success: \(response.payment)")
    case .failure(let error):
        print("error: \(error.localizedDescription)")
    }
}

Android

val paymentId : String = "paymentId"

val request = FetchPaymentDetailsRequest(paymentId)
val response = vipasoPos.fetchPaymentDetails(request)

if (response.data != null) {
            print(response.payment)
        } else {
            print(response.error?.message)
        }

Offline Payments

Send Offilne Payment request

Initiates an Offilne Payment request. Returns with a payment response if any of the possible payees close by successfully accepts the payment.

iOS

vipasoPOS.sendOfflinePaymentRequestViaBle(request: paymentRequest) { result in
		switch result {
		case .success(let response):
        print("success: \(response)")
		case .failure(let error):
        print("error: \(error.localizedDescription)")
		}
}

Receives a VipasoOfflinePaymentRequestmodel as an input parameter and returns with aVipasoPOSOfflinePaymentResponsemodel.

public struct VipasoOfflinePaymentRequest: Codable, Equatable {
    public var paymentID: String
    public var merchantID: String
    public var operatorID: String
    public var amount: String
    public var currency: String
    public var createdAt: String
}

public struct VipasoPOSOfflinePaymentResponse: Codable, Equatable {
    public var paymentID: String
    public var amount: String
    public var tip: String
    public var currency: String
    public var createdAt: String
}

Android

Cancel Offilne Payment

Cancels the payment with the supplied paymentID

iOS

vipasoPOS?.cancelOfflineBLEPayment(paymentID: paymentID)

Android

Stop Offilne Payment

Stops the payment and demolishes the Payment BLE stack.

NOTE: Only use this only after the payment finished (either with success, cancellation or failure).

iOS

vipasoPOS.stopOfflineBLE()

Android

Sync Offline Payments

Synchronizes the Offline Payments stored in the mobile app.

iOS

vipasoPay.syncPayments { result in  
		switch result {  
			case .success(let response):  
				print("success: \(response)")    
			case .failure(let error):  
				print("completion success/error")   
		}  
}

NOTE: Should be called when the device comes online. The iOS SDK does not do synchronization unless this method is called.

Android



Feature flags

Fetching feature flags

We support adding custom feature flags so you can remote control what your users have access to in their apps. The SDK fetches them under the hood and exposes an API to read them on the client-side. The API prefers using cached flags from the database.

iOS

/// Fetches available feature flags
/// - Parameter completion: Fetching feature flags completion handler
func fetchFeatureFlags(
    completion: @escaping (Result<FetchFeatureFlagsResponse, VipasoError>) -> Void
)

Android

suspend fun fetchFeatureFlags(): VipasoResponse<FetchFeatureFlagsResponse>

What’s Next