The smarter way
  • Getting Started
  • USER GUIDE
    • Payment Gateway
    • Currencies
    • Apple Pay
      • Setup MPGS
      • Setup Cybersource
    • Payment Tracking
      • Payment Transactions Insights
      • Payment Transactions States
      • Notifications, URLs & Timing
    • Plugins
      • Payment Request
      • E-Commerce
      • Bulk payment request
    • Features
      • Refund & Void Access Control
      • Two-Step Refund & Void Authorization
    • Integration
    • Configuration
      • Global Configuration
      • Webhooks Configuration
      • Transaction Report Configuration
      • How to Get API Keys
      • URL Shortener Configuration
    • Notification Communication Channels
      • Email Notifications
      • SMS Notifications
      • WhatsApp Notifications
        • Integrated WhatsApp Channel
        • Manual WhatsApp Channel
      • Notification Templates
      • Notification Process: Automatic and Manual
    • Satellite
    • Real Estate
      • Regular Activities
        • Property management
        • Tenant and Contract Management
          • Tenant & Contract Dashboard
          • Tenant Management
          • Contract Management
            • Add New Contract
            • Contract Action
              • Renew Contract
              • Terminate Contract
              • Manual Payment
              • Suspend Contract
              • Resume Contract
              • Advance Payment
        • Generate Invoice
        • Invoices Management
        • Maintenance
        • Transactions
        • Auditing and Rolling Back Activities
      • Merchant First Journey
  • developer
    • Getting Started
    • Tokenization
    • Authentication
    • Payment Methods
    • Checkout API
    • Operations
    • User Cards
    • Payment Status-Inquiry
    • Auto-Debit
    • Invoice API
    • Message Notifications
    • Upload Attachment
    • Checkout SDK
      • Web
      • iOS
      • Android
      • Flutter
    • Webhooks
      • Payment Notification
      • Operation Notification
      • Signing Mechanism
      • Integration Guides
        • Laravel Webhook Receiver Guide
        • .NET Webhook Receiver Guide
    • Test Cards
Powered by GitBook
On this page
  • Installation
  • Android
  • iOS
  • UI
  • Android
  • SDK Configuration
  • Language
  • Light and Dark Theme
  • SDK Initialization
  • Properties
  • Callbacks
  • Android
  • iOS
  • Example
  • Customization Theme
  • Properties Description
  • Data types description
  • Example
  • STC Pay
  • KNET - Apple Pay
  • Onsite Checkout
  • Error Reporting
  • Cyber Security Measures
  • Rooting and Jailbreak Detection
  • FAQ
  1. developer
  2. Checkout SDK

Flutter

PreviousAndroidNextWebhooks

Last updated 1 month ago

The Checkout SDK is a Flutter framework (library) developed by Ottu, designed to seamlessly integrate an Ottu-powered into Flutter applications for both iOS and Android platforms. This framework functions as a wrapper over the corresponding native SDKs, ensuring a smooth and efficient payment experience.

With the Checkout SDK, both the visual appearance and the forms of payment available during the checkout process can be fully customized to meet specific requirements.

To integrate the Checkout SDK, the library must be added to the Flutter application and initialized with the following parameters:

Additionally, optional configurations such as the to be accepted and the styling for the checkout interface can be specified.

To install the Flutter SDK plugin, the following section must be added to the pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter

  ottu_flutter_checkout:
    # To use ottu_flutter_checkout SDK from a local source, uncomment the line below 
    # and comment out the three lines specifying the Git repository.
    # path: ../ottu_flutter_checkout

    git:
      url: https://github.com/ottuco/ottu-flutter.git
      ref: main

And then run flutter pub get command in the terminal.

After adding the dependency, run the following command in the terminal to fetch the required packages: flutter pub get

Minimum Requirements

The SDK can be used on devices running Android 8 (Android SDK 26) or higher.

Minimum Requirements

The SDK can be used on devices running iOS 15 or higher.

The SDK UI is embedded as a fragment within any part of an activity in the merchant's application.

Example:

If only one payment option is available and it is a wallet, the UI is automatically minimized.

The SDK supports two languages: English and Arabic, with English set as the default.

The SDK automatically applies the language based on the device settings, eliminating the need for manual adjustments within the application.

However, if the transaction is created in a different language and setup preload is enabled, texts retrieved from the backend (such as fee descriptions) will be displayed in the transaction language, regardless of the device’s language settings.

The SDK supports automatic UI adjustments based on the device's theme settings (light or dark mode).

To initialize the SDK, an instance of CheckoutArguments must be passed as an argument to the OttuCheckoutWidget object.

It is used to define the Ottu merchant domain and must be set to the root domain of the Ottu account, excluding the https:// or http:// prefix.

For example, if the Ottu URL is https://example.ottu.com, the corresponding merchant_id is example.ottu.com.

This property is required to ensure that the checkout process is correctly linked to the associated Ottu merchant account.

It is a unique identifier for the payment transaction associated with the checkout process.

Available options for formsOfPayment:

  • applePay: The Apple Pay payment method is supported, allowing purchases to be made using Apple Pay-enabled devices.

  • cardOnsite: A direct (onsite) payment method, where customers are required to enter their card details directly within the SDK.

  • redirect: A payment method where customers are redirected to an external payment gateway or a third-party processor to complete the transaction.

  • stcPay: A method where customers enter their mobile number and authenticate using an OTP sent to their mobile device.

An ApiTransactionDetails class object is used to store transaction details. If provided, transaction details will not be requested from the backend, thereby reducing processing time.

A theme class object is used for UI customization. All fields are optional and may include values for background colors, text colors, and fonts for various UI components.

The callbacks are handled by the native frameworks. Please see the links here:

It is not necessary to modify anything for the callbacks, as they are managed by the native SDK.

However, the following examples demonstrate how they function on both platforms:

The callbacks are defined within the body of the Checkout.init function:

val sdkFragment = Checkout.init(
  context = checkoutView.context,
  builder = builder,
  setupPreload = apiTransactionDetails,
  successCallback = {
    Log.e("TAG", "successCallback: $it")
    showResultDialog(checkoutView.context, it)
  },
  cancelCallback = {
    Log.e("TAG", "cancelCallback: $it")
    showResultDialog(checkoutView.context, it)
  },
  errorCallback = { errorData, throwable ->
    Log.e("TAG", "errorCallback: $errorData")
    showResultDialog(checkoutView.context, errorData, throwable)
  },

Here is an example of a delegate:

extension CheckoutPlatformView: OttuDelegate {
    
    public func errorCallback(_ data: [String: Any]?) {
        debugPrint("errorCallback\n")
        DispatchQueue.main.async {
            self.paymentViewController?.view.isHidden = true
            self.paymentViewController?.view.setNeedsLayout()
            self.paymentViewController?.view.layoutIfNeeded()
            self._view.heightHandlerView.setNeedsLayout()
            self._view.heightHandlerView.layoutIfNeeded()
            self._view.setNeedsLayout()
            self._view.layoutIfNeeded()
            
            let alert = UIAlertController(
                title: "Error",
                message: data?.debugDescription ?? "",
                preferredStyle: .alert
            )
            alert.addAction(
                UIAlertAction(title: "OK", style: .cancel)
            )
            debugPrint("errorCallback, show alert\n")
            self.paymentViewController?.present(alert, animated: true)
        }
    }
    
    public func cancelCallback(_ data: [String: Any]?) {
        debugPrint("cancelCallback\n")
        DispatchQueue.main.async {
            var message = ""
            
            if let paymentGatewayInfo = data?["payment_gateway_info"] as? [String: Any],
               let pgName = paymentGatewayInfo["pg_name"] as? String,
               pgName == "kpay" {
                message = paymentGatewayInfo["pg_response"].debugDescription
            } else {
                message = data?.debugDescription ?? ""
            }
            
            self.paymentViewController?.view.isHidden = true
            self.paymentViewController?.view.setNeedsLayout()
            self.paymentViewController?.view.layoutIfNeeded()
            self._view.heightHandlerView.setNeedsLayout()
            self._view.heightHandlerView.layoutIfNeeded()
            self._view.setNeedsLayout()
            self._view.layoutIfNeeded()
            
            let alert = UIAlertController(
                title: "Cancel",
                message: message,
                preferredStyle: .alert
            )
            alert.addAction(
                UIAlertAction(title: "OK", style: .cancel)
            )
            debugPrint("cancelCallback, show alert\n")
            self.paymentViewController?.present(alert, animated: true)
        }
    }
    
    public func successCallback(_ data: [String: Any]?) {
        debugPrint("successCallback\n")
        DispatchQueue.main.async {
            self.paymentViewController?.view.isHidden = true
            self._view.paymentSuccessfullLabel.isHidden = false
            self.paymentViewController?.view.setNeedsLayout()
            self.paymentViewController?.view.layoutIfNeeded()
            self._view.heightHandlerView.setNeedsLayout()
            self._view.heightHandlerView.layoutIfNeeded()
            self._view.setNeedsLayout()
            self._view.layoutIfNeeded()
            
            let alert = UIAlertController(
                title: "Success",
                message: data?.debugDescription ?? "",
                preferredStyle: .alert
            )
            alert.addAction(
                UIAlertAction(title: "OK", style: .cancel)
            )
            debugPrint("successCallback, showing alert\n")
            self.paymentViewController?.present(alert, animated: true)
        }
    }
}
final checkoutArguments = CheckoutArguments(
  merchantId: state.merchantId,
  apiKey: state.apiKey,
  sessionId: state.sessionId ?? "",
  amount: amount,
  showPaymentDetails: state.showPaymentDetails,
  apiTransactionDetails: state.preloadPayload == true ? _apiTransactionDetails : null,
  formsOfPayment: formOfPayments?.isNotEmpty == true ? formOfPayments : null,
  theme: _theme,
);

Scaffold(
  appBar: AppBar(
    backgroundColor: Theme.of(context).colorScheme.inversePrimary,
    title: Text(widget.title),
  ),
  body: SingleChildScrollView(
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        SizedBox(height: 46),
        Text(
          "Customer Application",
          textAlign: TextAlign.center,
          style: ts.TextStyle(fontSize: 24),
        ),
        // Start of Merchant content
        const Padding(
          padding: EdgeInsets.all(12.0),
          child: Text(
            "Some users UI elements, Some users UI elements, "
            "Some users UI elements, Some users UI elements, "
            "Some users UI elements",
          ),
        ),
        // End of Merchant content
        Padding(
          padding: const EdgeInsets.all(12.0),
          child: ValueListenableBuilder<int>(
            valueListenable: _checkoutHeight,
            builder: (BuildContext context, int height, Widget? child) {
              return SizedBox(
                height: height.toDouble(),
                child: OttuCheckoutWidget(arguments: widget.checkoutArguments),
              );
            },
          ),
        ),
        const SizedBox(height: 20),
      ],
    ),
  ),
);

To access the actual code samples, navigate to the lib directory.

Additionally, the android and ios directories contain platform-specific code relevant to each respective environment.

The class responsible for defining the theme is called CheckoutTheme. It utilizes additional component classes, including:

  • ButtonComponent

  • LabelComponent

  • TextFieldComponent

The CheckoutTheme class consists of objects representing various UI components. While the component names generally align with those listed above, they also contain platform-specific fields for further customization.

Below is the structure of the Customization theme class:

class CheckoutTheme extends Equatable {
  @_UiModeJsonConverter()
  final CustomerUiMode uiMode;
  
  final TextStyle? mainTitleText;
  final TextStyle? titleText;
  final TextStyle? subtitleText;
  final TextStyle? feesTitleText;
  final TextStyle? feesSubtitleText;
  final TextStyle? dataLabelText;
  final TextStyle? dataValueText;
  final TextStyle? errorMessageText;

  final TextFieldStyle? inputTextField;

  final ButtonComponent? button;
  final RippleColor? backButton;
  final ButtonComponent? selectorButton;
  final SwitchComponent? switchControl;
  final Margins? margins;

  final ColorState? sdkBackgroundColor;
  final ColorState? modalBackgroundColor;
  final ColorState? paymentItemBackgroundColor;
  final ColorState? selectorIconColor;
  final ColorState? savePhoneNumberIconColor;
}

Specifies the device theme mode, which can be set to one of the following:

  • light – Forces the UI to use light mode.

  • dark – Forces the UI to use dark mode.

  • auto – Adapts the UI based on the device's system settings.

All properties in the CheckoutTheme class are optional, allowing users to customize any of them as needed.

General

Property Name
Description
Data Type

mainTitleText

Font and color for all “Captions”

titleText

Font and color for payment options in the list

subtitleText

Font and color for payment options details (like expiration date)

Fees

Property Name
Description
Data Type

feesTitleText

Font and color of fees value in the payment options list

feesSubtitleText

Font and color of fees description in the payment options list

Data

Property Name
Description
Data Type

dataLabelText

Font and color of payment details fields (like “Amount”)

dataValueText

Font and color of payment details values

Other

Property Name
Description
Data Type

errorMessageText

Font and color of error message text in pop-ups

Property Name
Description
Data Type

inputTextField

Font and color of text in any input field (including disabled state)

Property Name
Description
Data Type

sdkbackgroundColor

The main background of the SDK view component

modalBackgroundColor

The background of any modal window

paymentItemBackgroundColor

The background of an item in payment options list

selectorIconColor

The color of the icon of the payment

savePhoneNumberIconColor

The color of “Diskette” button for saving phone number

Property Name
Description
Data Type

button

Background, text color and font for any button

backButton

Color of the “Back” navigation button

selectorButton

Background, text color and font for payment item selection button

Property Name
Description
Data Type

switch

Colors of the switch background and its toggle in different states (on, off and disabled)

Property Name
Description
Data Type

margins

Top, left, bottom and right margins between component

Property Name
Description
Data Type

color

Main color integer value

Int

colorDisabled

Disabled stated color integer value

Int

Property Name
Description
Data Type

color

Main color integer value

Int

rippleColor

Ripple color integer value

Int

colorDisaled

Disabled stated color integer value

Int

Property Name
Description
Data Type

textColor

Main color integer value

fontType

Font resource ID

Int

Property Name
Description
Data Type

background

Background color integer value

primaryColor

Text color

focusedColor

Selected text color

text

Text value

error

Text value

Property Name
Description
Data Type

rippleColor

Button background color

fontType

Button text font ID

Int

textColor

Button text color

Property Name
Description
Data Type

checkedThumbTintColor

Toggle color in checked state

Int

uncheckedThumbTintColor

Toggle color in unchecked state

Int

checkedTrackTintColor

Track color in checked state

Int

uncheckedTrackTintColor

Track color in unchecked state

Int

checkedTrackDecorationColor

Decoration color in checked state

Int

uncheckedTrackDecorationColor

Decoration color in unchecked state

Int

Property Name
Data Type

left

Int

top

Int

right

Int

bottom

Int

To build the theme, the user must follow similar steps as described in the corresponding file of the test app.

Here is a code snippet demonstrating the process:

final checkoutTheme = ch.CheckoutTheme(
  uiMode: ch.CustomerUiMode.dark,
  titleText: ch.TextStyle(),
  modalBackgroundColor: ch.ColorState(color: Colors.amber));

If the STC Pay integration between Ottu and STC Pay has been completed, the Checkout SDK will automatically handle the necessary checks to display the STC Pay button seamlessly.

  • The session_id and pg_codes provided during initialization must be associated with the STC Pay Payment Service. This ensures that the STC Pay option is available for the customer.

  • In the Android SDK, the STC Pay button is displayed regardless of whether the customer has entered a mobile number while creating the transaction.

Due to compliance requirements, for iOS, the KNET payment gateway requires a popup notification displaying the payment result after each failed payment. This notification is triggered only in the cancelCallback, but only if a response is received from the payment gateway.

As a result, the user cannot retry the payment without manually clicking on Apple Pay again.

The popup notification mentioned above is specific to the KNET payment gateway.Other payment gateways may have different requirements or notification mechanisms, so it is essential to follow the respective documentation for each integration.

To properly handle the KNET popup notification, the following Swift code snippet must be implemented into the payment processing flow:

This is only iOS-related stuff, so the callbacks are native and so they are in Swift language.

func cancelCallback(_ data: [String: Any]?) {
    var message = ""
    
    if let paymentGatewayInfo = data?["payment_gateway_info"] as? [String: Any],
       let pgName = paymentGatewayInfo["pg_name"] as? String,
       pgName == "kpay" {
        message = paymentGatewayInfo["pg_response"].debugDescription
    } else {
        message = data?.debugDescription ?? ""
    }
    
    navigationController?.popViewController(animated: true)
    
    let alert = UIAlertController(
        title: "Cancel",
        message: message,
        preferredStyle: .alert
    )
    
    alert.addAction(UIAlertAction(title: "OK", style: .cancel))
    self.present(alert, animated: true)
}

Function Breakdown

The above code performs the following checks and actions:

  1. Checks if the cancelCallback object contains payment gateway information

    • It verifies whether the payment_gateway_info field is available in the response.

  2. Identifies if the payment gateway used is KNET

    • It checks if the pg_name property equals kpay, confirming that the transaction was processed using KNET.

  3. Check the above two conditions are met by retrieving the payment gateway response

    • If the gateway response (pg_response) is available, it is displayed; otherwise, a default message (Payment was cancelled.) is used.

  4. Navigates back and displays an alert

    • The user is returned to the previous screen (navigationController?.popViewController(animated: true)).

    • A popup notification is displayed using self.present(alert, animated: true), informing the user about the failed payment.

The Onsite Checkout payment option enables direct payments to be performed within the mobile SDK.

The SDK provides a UI where the user can enter their Cardholder Data (CHD). Additionally, if allowed by the backend, the user has the option to save the card for future payments, storing it as a tokenized payment.

The onsite checkout screen appears identical to its counterpart on native platforms.

Android Example

iOS

The SDK utilizes Sentry for error logging and reporting. It is initialized based on the configuration provided by SDK Studio.

However, since the SDK is a framework embedded within the merchant's app, conflicts may arise if the app also integrates Sentry.

To prevent conflicts, the merchant can disable Sentry within the Checkout SDK by setting the is_enabled flag to false in the configuration.

The Flutter SDK does not perform rooting or jailbreak detection independently. Instead, these security checks are entirely handled by the native SDKs.

For more details, refer to the following links:

  • tokenPay

  • redirect

  • stcPay

  • cardOnsite

  • applePay (iOS only)

Merchants can configure the forms of payment displayed according to their needs.

For example, to display only the STC Pay button, use:

formsOfPayment = [stcPay]

This ensures that only the STC Pay button is shown. The same approach applies to other payment methods.

The SDK requires a device running:

  • Android 8 or higher (API level 26 or higher)

  • iOS 14 or higher

To ensure consistency, the current device language should be taken into account when specifying a language code in the transaction creation request of the .

The appropriate theme is applied during , aligning with the device's configuration. Similar to language settings, no manual adjustments are required within the application.

The Checkout SDK is initialized using the CheckoutArguments class, which includes the listed below.

For a detailed implementation example, refer to the section.

string required

string required

It is the Ottu , used for authentication when communicating with Ottu's servers during the checkout process.

Ensure that only the public key is used. The must remain confidential and must never be shared with any clients.

string required

This identifier is automatically generated when a payment transaction is created. For further details on how to use the session_id parameter in the , refer to the documentation.

array optional

The formsOfPayment parameter is used to customize the forms of payment displayed in the . By default, all forms of payment are enabled.

tokenPay: A method utilizing , ensuring that customer payment information is securely stored and processed.

object optional

object optional

For more details, refer to .

unit required

Callback functions are used to retrieve the payment status. These must be provided directly to the Checkout initialization function. For more information, please check .

The code samples can be found .

If a property is not set, the default value (as specified in the Figma design ) will be applied automatically.

When the Checkout SDK is initialized with the and payment gateway codes (), the SDK will verify the following conditions:

The SDK supports the following :

Yes, customization is supported. For more details, refer to the section.

Checkout API
tokenization
here
here
Rooting and Jailbreak Detection
Android
iOS
UI
Android
SDK Configuration
Language
Light and Dark Theme
SDK initialization
SDK Initialization
properties
Example
Properties
merchantId
apiKey
sessionId
Checkout API
session_id
formsOfPayment
setupPreload
theme
successCallback, errorCallback, and successCallback
here
Callbacks
Android
iOS
Example
Customization Theme
uiMode
Properties Description
Texts
Text Fields
Colors
Buttons
Switch
Margins
Data types description
Color
RippleColor
Text
TextField
Button
Switch
Margin
Example
STC Pay
KNET - Apple Pay
Onsite Checkout
Error Reporting
Cyber Security Measures
FAQ
1️
What forms of payment are supported by the SDK?
forms of payment
2️
What are the minimum system requirements for SDK integration?
3️
Can I customize the appearance beyond the provided themes?
Customization Theme
Text
Text
Text
Text
Text
Text
Text
Text
TextField
Color
Color
Color
Color
Color
Button
RippleColor
Button
Switch
Margin
Color
Color
Color
Color
Text
Text
RippleColor
Color
iOS Callbacks
iOS
forms of payment
theme
Installation
checkout process
API public key
private key
checkout process
API key
merchant_id
session_id
session_id
pg_codes
Android Customization Theme
Android Callbacks
Android