Building your Android app integration with Catch's SDK.

👍

Interested In Integrating With Catch?

To make use of the tools described in this documentation, you will need a merchant account with Catch. Please reach out to our merchant partnerships team ([email protected]).

Overview

The Catch Android SDK provides components for developing applications that integrate with Catch on merchant storefront native Android apps. It's designed to be used in tandem with Catch's Transaction APIs to implement the frontend portion of the overall integration.

The Catch Android SDK provides the following main categories of functionality:

  • UI widgets: various components which applications can display and control in the user interface (UI). All Catch widgets are available as Android views as well as Composable functions (Jetpack Compose).
  • Checkout flow control: an interface for applications to open Catch checkouts.

API Reference documentation is also available at: https://getcatch.github.io/catch-android-sdk/index.html

Demo App

The Sample app provides a showcase of the Catch Android SDK widgets and other features in isolation. This may be used as a reference companion alongside this documentation.

Compatibility

The Catch Android SDK is compatible with the following versions:

Installation

The Catch Android SDK is available on Maven Central. Add catch-android-sdk to your build.gradle dependencies:

dependencies {
  implementation 'com.getcatch:catch-android-sdk:1.0.1'
}
dependencies {
  implementation("com.getcatch:catch-android-sdk:1.0.1")
}

Initialization

The Catch Android SDK should be initialized in the onCreate function of your app's Application class.

class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Catch.initialize(
            context = this,
            publicKey = /* Your public key  */,
            options = CatchOptions()
        )
    }
}

The initialize function accepts three parameters: context, publicKey, and options.

  • context - An Android context, which in this case will be the application class as this should be initialized within the onCreate of the application class.
  • publicKey - A required string representing the merchant’s public API key.
  • options - A CatchOptions object which specifies optional configuration settings to control global behavior of the SDK. If the options parameter is omitted, the Catch SDK will fallback to default values.

UI Widgets

Overview

The Catch SDK offers a set of preconfigured UI Widgets which can be easily added into your applications. Each widget is available as a a Composable and as an Android view. For more information on each of the available UI widgets and their use cases, checkout the reference documentation:

Styling Widgets

Theme

The first method of styling widgets is by using a CatchColorTheme. There are four default Catch themes which configure the look and feel of widgets. These preconfigured themes can be set on a global level or on an individual widget.

These preconfigured themes can be set on a global level to impact the appearance of all UI widgets:

// At SDK initialization
Catch.initialize(
  context = this,
  publicKey = /* Your public key  */,
  options = CatchOptions(
  	colorTheme = CatchColorTheme.Dark
	)
)

// At anytime after initialization
Catch.setColorTheme(CatchColorTheme.Dark)

Otherwise, they may be set on an individual widget if you do not wish for all widgets to use the same theme.

Callout(
  price=1000,
  colorTheme=CatchColorTheme.Dark,
)
val calloutView = findViewById<CalloutView>(R.id.callout_view_id)
calloutView.price = 1000
calloutView.colorTheme = CatchColorTheme.Dark
<com.getcatch.android.ui.views.CalloutView
    android:id="@+id/custom_callout"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:colorTheme="dark" />

Any widget-level theme will override any theming set on the global level.

Configurable Styles

The Catch Android SDK also allows for fine tuned customization with configurable styles.

Styles can be configured on a global level when initializing the SDK. For example, to update the global text styling, set the desired customizations in CatchStyleConfig within the CatchOptions that are passed into the initialize function:

val customTextStyle = WidgetTextStyle(
	fontSize = 16f,
	textTransform = TextTransform.UPPERCASE,
)
val styleConfig = CatchStyleConfig(widgetTextStyle = customTextStyle)
val options = CatchOptions(styleConfig = styleConfig)
Catch.initialize(
	publicKey = /* Your public key  */,
	context = this,
	options = options,
)

Overrides can also be set on the widget-level at the time of widget initialization. For example, the following code applies the text customizations to an individual callout widget:

val customTextStyle = WidgetTextStyle(
	fontSize = 16f,
	textTransform = TextTransform.UPPERCASE,
)

val calloutStyleOverrides = InfoWidgetStyle(
  textStyle=customTextStyle
)

Callout(
  price=1000,
  styleOverrides=calloutStyleOverrides,
)
val customTextStyle = WidgetTextStyle(
	fontSize = 16f,
	textTransform = TextTransform.UPPERCASE,
)

val calloutStyleOverrides = InfoWidgetStyle(
  textStyle=customTextStyle
)

val calloutView = findViewById<CalloutView>(R.id.callout_view_id)
calloutView.styleOverrides = calloutStyleOverrides

To provide an easy API for both developers using Compose and developers using view based UIs, several of the custom style configuration classes can be created with two methods. Compose provides a class for Color and for FontWeight that can be used in the primary constructors of some of style config classes. For apps that do not have Compose dependencies, the style config classes can be instantiated using the static .create() function. These .create() functions allow you to pass in the Catch SDK's own ColorValue class and FontWeight class, not requiring any other dependencies.

The classes that provide these two creation methods are:

Here is an example of how you would create a BenefitTextStyle in both a compose app and a view based app.

import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight

BenefitTextStyle(
  fontWeight = FontWeight.W700,
  earnFontColor = Color.Green,
  redeemFontColor = Color.Magenta,
)
// App without Compose dependencies
import com.getcatch.android.ui.styles.values.ColorValue
import com.getcatch.android.ui.styles.values.FontWeight

BenefitTextStyle.create(
  fontWeight = FontWeight.W700,
  earnFontColor = ColorValue(0xFFFF0000),
  redeemFontColor = ColorValue(0xFF00FF00)
)

To view all of the styles that you can configure and a note on hierarchy, see the API reference documentation for CatchStyleConfig.

Checkout Flow Control

Overview

To open a Catch checkout flow, applications need to initialize a CatchCheckoutController in the onCreate of your checkout Activity or Fragment.

import com.getcatch.android.ui.activities.checkout.CatchCheckoutController

class CheckoutActivity : AppCompatActivity() {
  lateinit var catchCheckoutController: CatchCheckoutController

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    CatchCheckoutController(
      this,
      this::onCheckoutConfirmed,
      this::onCheckoutCanceled
    )
  }

  fun onCheckoutConfirmed() {}
  
  fun onCheckoutCanceled() {}
}

To open a Catch checkout with the CatchCheckoutController you can call the openCheckout method.

This function accepts two parameters: checkoutId and prefill.

  • checkoutId is required and should be a string representing the ID of the checkout being opened
  • prefill is a CheckoutPrefill object which specifies prefill values to use in the checkout flow to speed up a customer's checkout experience.

🚧

Ahead of using the openCheckout() function, applications are responsible for creating a Checkout object using Catch's Transaction APIs. A successful call to Catch's POST Checkout endpoint will return a checkout ID in the body of its response, which should subsequently be supplied as the first argument to openCheckout().

The openCheckout() function does not return any value or expect to throw any exceptions. Any checkoutIds passed to openCheckout() are not validated ahead of opening the checkout flow. If a given checkoutId turns out not to be valid, Catch's checkout UI will display error messaging to the consumer indicating that their checkout could not be loaded. If the consumer encounters an error during the checkout flow (e.g. they're unable to link a bank account successfully, etc), Catch's checkout UI will be responsible for handling such errors and displaying relevant information to the consumer. The call to openCheckout(), in other words, is essentially a full handoff from the merchant application to Catch's checkout application.

Handling terminations

🚧

Enforce defined progression from Checkout to Purchase

Your application should not attempt to create a new Purchase until the consumer has confirmed their Checkout and triggered a successful termination of the Catch checkout flow.

There are two circumstances in which a Catch checkout flow is terminated and control is handed back to the merchant application:

  1. A consumer successfully completes the checkout flow
  2. A consumer explicitly cancels their checkout flow

In the case of a successfully completed checkout, the application is responsible for creating a Purchase with Catch using the Transaction APIs POST Purchase endpoint and subsequently displaying a confirmation page.

In the case of a canceled checkout flow, the application may display content as seen fit (for example, it might show the consumer the page they were on before they opened the Catch checkout flow).