EN | 中文
- Overview
- UI Integration - Hosted Payment Page (HPP)
- UI Integration - Embedded Element
- Low-level API Integration
- Contributing & Feedback
The Airwallex Android SDK provides a comprehensive toolkit for integrating payment functionality into your Android application. It offers prebuilt UI components for rapid integration, embeddable elements for a customized look, and low-level APIs for full control over the payment experience.
This guide covers SDK setup, configuration, and integration. It assumes familiarity with Android development, Android Studio, and Gradle.
| Category | Methods | Notes |
|---|---|---|
| Cards | Visa, Mastercard, UnionPay, Discover, JCB, Diners Club |
PCI-DSS compliance is required when using Low-level API Integration |
| Google Pay | Google Pay |
|
| E-Wallets | Alipay, AlipayHK, DANA, GCash, Kakao Pay, Touch ‘n Go, WeChat Pay, and more |
Choose the integration option that best suits your needs:
| Option | Description | Multiple payment methods | Single payment method |
|---|---|---|---|
| UI Integration - Hosted Payment Page (HPP) | Launch a complete, SDK-managed payment flow with prebuilt screens for payment method selection, card input, and checkout. Supports customizable theming and dark mode. Recommended for most use cases. | ![]() |
![]() |
| UI Integration - Embedded Element | Embed Airwallex's PaymentElement directly into your own activity or view using Jetpack Compose. You retain full control over the host layout and navigation while leveraging the SDK's payment UI components. |
![]() |
![]() |
| Low-level API Integration | Build a fully custom payment UI using the SDK's core APIs. Gives you direct access to payment method retrieval, card tokenization, payment confirmation, and consent management. Requires PCI-DSS compliance for card payments. | ![]() |
![]() |
A fully functional demo application is available in the sample directory. It demonstrates integrating with the Airwallex Android SDK using its prebuilt UI components to manage the checkout flow, including specifying a shipping address and selecting a payment method.
To run the demo app:
-
Clone the repository:
git clone git@github.com:airwallex/airwallex-payment-android.git -
Open Android Studio and import the project by selecting the
build.gradlefile from the cloned repository. -
(Optional) To test with your own API keys, go to Airwallex Account settings > API keys, then copy
Client IDandAPI keytoSettings.kt:
private const val API_KEY = replace_with_api_key
private const val CLIENT_ID = replace_with_client_id
- (Optional) To enable WeChat Pay, register your app on WeChat Pay, then set your App ID in
Settings.kt:
private const val WECHAT_APP_ID = "put your WeChat app id here"
- Run the
sampleproject.
For testing, you can use the test card numbers provided by Airwallex.
- Android API level 21 (Lollipop) and above
- Approximate SDK size: ~3.1 MB
The Airwallex Android SDK provides prebuilt UI components to simplify payment integration in your Android application.
The Airwallex Android SDK is available through Maven Central.
Add the following dependencies to your app-level build.gradle:
dependencies {
// Core module (required)
implementation 'io.github.airwallex:payment:6.6.1'
// Add payment methods you want to support
implementation 'io.github.airwallex:payment-card:6.6.1' // Card payments
implementation 'io.github.airwallex:payment-redirect:6.6.1' // Redirect-based payments
implementation 'io.github.airwallex:payment-wechat:6.6.1' // WeChat Pay
implementation 'io.github.airwallex:payment-googlepay:6.6.1' // Google Pay
}Initialize the SDK in your Application class:
import com.airwallex.android.AirwallexStarter
import com.airwallex.android.core.AirwallexConfiguration
import com.airwallex.android.core.Environment
import com.airwallex.android.card.CardComponent
import com.airwallex.android.googlepay.GooglePayComponent
import com.airwallex.android.redirect.RedirectComponent
import com.airwallex.android.wechat.WeChatComponent
AirwallexStarter.initialize(
application,
AirwallexConfiguration.Builder()
.enableLogging(true) // Set to false in production
.saveLogToLocal(false) // Use your own logging strategy if needed
.setEnvironment(environment) // Set the appropriate environment
.setSupportComponentProviders(
listOf(
CardComponent.PROVIDER,
WeChatComponent.PROVIDER,
RedirectComponent.PROVIDER,
GooglePayComponent.PROVIDER
)
)
.build()
)You can customize the appearance of the Airwallex SDK UI including theme color and dark mode preferences. This applies to both Hosted Payment Page Integration and Embedded Element integration.
You can override the default theme color using Android's theme system:
<color name="airwallex_tint_color">@color/your_custom_color</color>Note: Alternatively, you can set theme color via Appearance.themeColor in your PaymentElementConfiguration (see configuration examples below). Appearance also supports dark mode configuration.
The Airwallex Android SDK supports two payment flows:
-
Standard Flow: Create PaymentIntent on your server before presenting the payment UI. This is the traditional approach where the payment amount and details are known upfront.
-
Express Checkout: Provide a
PaymentIntentProviderorPaymentIntentSourcethat creates the PaymentIntent on demand after collecting payment details from the user. This is useful when:- You want to minimize upfront server calls
- You want to reduce the chance of PaymentIntent expiration by creating it only when the user is actively proceeding with payment
- You want to avoid creating PaymentIntents for users who abandon the checkout flow early
- You need real-time validation of inventory or stock availability at the moment of payment
Both flows are fully supported and you can choose the one that best fits your use case.
For the Standard Flow, you need to create a Payment Intent on your server before presenting the payment UI.
For Express Checkout, you'll create the PaymentIntent within your PaymentIntentProvider or PaymentIntentSource implementation when the SDK requests it.
-
Obtain an access token: Generate this using your Client ID and API key from Account settings > API keys and call the Authentication API.
-
Create a customer (optional): Use the
/api/v1/pa/customers/createendpoint to save customer details. -
Create a Payment Intent: Call
/api/v1/pa/payment_intents/createand get theclient_secretfrom the response.
Create an appropriate session object based on your payment scenario. You can choose between two approaches:
- Standard Flow: Create PaymentIntent upfront on your server, then pass it to the SDK
- Express Checkout: Provide a PaymentIntentProvider to create PaymentIntent on demand after collecting payment details
📝 Important - Where to Create the Session:
- For Hosted Payment Page (HPP) using
AirwallexStarter: Create the session in your calling activity, then pass it toAirwallexStarter.presentEntirePaymentFlow()or similar methods. The SDK will launch its own activities to handle the payment flow.- For Embedded Element using
PaymentElement: Create the session in the Activity (or its ViewModel) that hosts thePaymentElement. The session should be created before callingPaymentElement.create(). For better architecture, store the session in a ViewModel to survive configuration changes (e.g., screen rotation).
Standard Flow (PaymentIntent created upfront):
import com.airwallex.android.core.model.PaymentIntent
import com.airwallex.android.core.AirwallexPaymentSession
// call https://www.airwallex.com/docs/api#/Payment_Acceptance/Payment_Intents/_api_v1_pa_payment_intents_create/post api
// and get intent id, client secret from response.
val paymentIntent = PaymentIntent(
id = "REPLACE_WITH_YOUR_PAYMENT_INTENT_ID",
clientSecret = "REPLACE_WITH_YOUR_CLIENT_SECRET",
amount = 1.toBigDecimal(),
currency = "USD"
)
val paymentSession = AirwallexPaymentSession.Builder(
paymentIntent = paymentIntent,
countryCode = countryCode,
googlePayOptions = googlePayOptions // Optional
)
.setRequireBillingInformation(true)
.setRequireEmail(requireEmail)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setHidePaymentConsents(false)
.setPaymentMethods(listOf()) // Empty list for all available methods
.build()Express Checkout Flow (PaymentIntent created on demand):
import com.airwallex.android.core.AirwallexPaymentSession
import com.airwallex.android.core.PaymentIntentProvider
import com.airwallex.android.core.PaymentIntentSource
// Option 1: Using PaymentIntentProvider (callback-based, Java-compatible)
class MyPaymentIntentProvider : PaymentIntentProvider {
override val currency: String = "USD"
override val amount: BigDecimal = 100.toBigDecimal()
override fun provide(callback: PaymentIntentProvider.PaymentIntentCallback) {
// Make API call to create PaymentIntent when needed
myApiService.createPaymentIntent { result ->
when (result) {
is Success -> callback.onSuccess(result.paymentIntent)
is Error -> callback.onError(result.exception)
}
}
}
}
val provider = MyPaymentIntentProvider()
val session = AirwallexPaymentSession.Builder(
paymentIntentProvider = provider,
countryCode = countryCode,
customerId = customerId, // Optional
googlePayOptions = googlePayOptions // Optional
)
.setRequireBillingInformation(true)
.setRequireEmail(requireEmail)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setHidePaymentConsents(false)
.setPaymentMethods(listOf())
.build()
// Option 2: Using PaymentIntentSource (suspend-based, recommended for Kotlin)
class MyPaymentIntentSource : PaymentIntentSource {
override val currency: String = "USD"
override val amount: BigDecimal = 100.toBigDecimal()
override suspend fun getPaymentIntent(): PaymentIntent {
// Make API call using suspend functions
return myApiService.createPaymentIntent()
}
}
val source = MyPaymentIntentSource()
val session = AirwallexPaymentSession.Builder(
paymentIntentSource = source,
countryCode = countryCode,
customerId = customerId, // Optional
googlePayOptions = googlePayOptions // Optional
)
.setRequireBillingInformation(true)
.setRequireEmail(requireEmail)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setHidePaymentConsents(false)
.setPaymentMethods(listOf())
.build()import com.airwallex.android.core.AirwallexRecurringSession
val recurringSession = AirwallexRecurringSession.Builder(
customerId = customerId,
clientSecret = clientSecret,
currency = currency,
amount = amount,
nextTriggerBy = nextTriggerBy,
countryCode = countryCode
)
.setRequireEmail(requireEmail)
.setShipping(shipping)
.setRequireCvc(requireCVC)
.setMerchantTriggerReason(merchantTriggerReason)
.setReturnUrl(returnUrl)
.setPaymentMethods(listOf())
.build()Standard Flow (PaymentIntent created upfront):
import com.airwallex.android.core.AirwallexRecurringWithIntentSession
import com.airwallex.android.core.model.PaymentIntent
val recurringWithIntentSession = AirwallexRecurringWithIntentSession.Builder(
paymentIntent = paymentIntent,
customerId = customerId,
nextTriggerBy = nextTriggerBy,
countryCode = countryCode
)
.setRequireEmail(requireEmail)
.setRequireCvc(requireCVC)
.setMerchantTriggerReason(merchantTriggerReason)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setPaymentMethods(listOf())
.build()Express Checkout Flow (PaymentIntent created on demand):
import com.airwallex.android.core.AirwallexRecurringWithIntentSession
import com.airwallex.android.core.PaymentIntentProvider
import com.airwallex.android.core.PaymentIntentSource
// Option 1: Using PaymentIntentProvider
val provider = MyPaymentIntentProvider() // Same provider implementation as above
val session = AirwallexRecurringWithIntentSession.Builder(
paymentIntentProvider = provider,
customerId = customerId,
nextTriggerBy = nextTriggerBy,
countryCode = countryCode
)
.setRequireEmail(requireEmail)
.setRequireCvc(requireCVC)
.setMerchantTriggerReason(merchantTriggerReason)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setPaymentMethods(listOf())
.build()
// Option 2: Using PaymentIntentSource (recommended for Kotlin)
val source = MyPaymentIntentSource() // Same source implementation as above
val session = AirwallexRecurringWithIntentSession.Builder(
paymentIntentSource = source,
customerId = customerId,
nextTriggerBy = nextTriggerBy,
countryCode = countryCode
)
.setRequireEmail(requireEmail)
.setRequireCvc(requireCVC)
.setMerchantTriggerReason(merchantTriggerReason)
.setReturnUrl(returnUrl)
.setAutoCapture(autoCapture)
.setPaymentMethods(listOf())
.build()import com.airwallex.android.core.Airwallex
import com.airwallex.android.AirwallexStarter
import com.airwallex.android.core.AirwallexPaymentStatus
AirwallexStarter.presentEntirePaymentFlow(
activity = activity,
session = session,
paymentResultListener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// Handle the payment result
}
}
)import com.airwallex.android.core.Airwallex
import com.airwallex.android.AirwallexStarter
import com.airwallex.android.core.AirwallexPaymentStatus
AirwallexStarter.presentCardPaymentFlow(
activity = activity,
session = session,
paymentResultListener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// Handle the payment result
}
}
)import com.airwallex.android.view.AirwallexAddPaymentDialog
import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
val dialog = AirwallexAddPaymentDialog(
activity = activity,
session = session,
paymentResultListener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// Handle the payment result
}
}
)
dialog.show()Allow users to provide shipping details:
import com.airwallex.android.AirwallexStarter
import com.airwallex.android.core.Airwallex
AirwallexStarter.presentShippingFlow(
activity = activity,
shipping = shipping, // Optional
shippingResultListener = object : Airwallex.ShippingResultListener {
override fun onCompleted(status: AirwallexShippingStatus) {
// Handle shipping result
}
}
)After payment completion, verify the status:
import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.model.RetrievePaymentIntentParams
airwallex.retrievePaymentIntent(
params = RetrievePaymentIntentParams(
paymentIntentId = paymentIntentId,
clientSecret = clientSecret
),
listener = object : Airwallex.PaymentListener<PaymentIntent> {
override fun onSuccess(response: PaymentIntent) {
// Handle successful response
}
override fun onFailed(exception: AirwallexException) {
Log.e(TAG, "Retrieve PaymentIntent failed", exception)
}
}
)- Ensure Google Pay is enabled on your Airwallex account
- Include the Google Pay module when installing the SDK as per Installation
Configure Google Pay options to restrict as well as provide extra context. For more information, please refer to GooglePayOptions class:
val googlePayOptions = GooglePayOptions(
allowedCardAuthMethods = listOf("CRYPTOGRAM_3DS"),
billingAddressParameters = BillingAddressParameters(BillingAddressParameters.Format.FULL),
shippingAddressParameters = ShippingAddressParameters(listOf("AU", "CN"), true)
)The following card networks are supported for Google Pay:
- AMEX
- DISCOVER
- JCB
- MASTERCARD
- VISA
- MAESTRO (only when
countryCodeis set toBR)
The Airwallex SDK provides PaymentElement - a flexible component that allows you to embed payment UI directly into your own activity or view. This gives you full control over the host UI while leveraging Airwallex's prebuilt payment components.
Unlike Hosted Payment Page Integration where the SDK launches its own activities (PaymentMethodsActivity, AddPaymentActivity), Embedded Element integration lets you:
- Embed payment UI in your own activity/view
- Control the surrounding UI and layout
- Customize the container styling
- Integrate seamlessly with your app's navigation flow
Both integration methods support the same customization options via PaymentElementConfiguration (theme color, dark mode, button text, Google Pay display).
Key Difference - Session Creation:
- Hosted Payment Page (HPP): Create session in your calling activity → Pass to
AirwallexStartermethods - Embedded Element: Create session in the activity that hosts
PaymentElement(or its ViewModel) → Pass toPaymentElement.create()
Add the same dependencies as Hosted Payment Page Integration:
dependencies {
// Core module (required)
implementation 'io.github.airwallex:payment:6.6.1'
// Add payment methods you want to support
implementation 'io.github.airwallex:payment-card:6.6.1'
implementation 'io.github.airwallex:payment-redirect:6.6.1'
implementation 'io.github.airwallex:payment-wechat:6.6.1'
implementation 'io.github.airwallex:payment-googlepay:6.6.1'
}Configure the SDK in your Application class (same as Hosted Payment Page Integration - see Initialization).
PaymentElement.create() is a suspending function that initializes and fetches required data for the payment UI. You can either use PaymentFlowlistener interface or lambda callbacks.
Both variants return Result<PaymentElement> which contains either:
Successwith thePaymentElementinstanceFailurewith the error
Configure the payment UI using PaymentElementConfiguration:
Shows only card input:
import com.airwallex.android.core.AirwallexSupportedCard
// Use default (all supported cards: Visa, Amex, Mastercard, Discover, JCB, Diners Club, UnionPay)
val configuration = PaymentElementConfiguration.Card()
// Or customize supported card brands and appearance
val customConfiguration = PaymentElementConfiguration.Card(
supportedCardBrands = listOf(
AirwallexSupportedCard.VISA,
AirwallexSupportedCard.MASTERCARD
),
checkoutButton = PaymentElementConfiguration.CheckoutButton(title = "Pay Now"),
appearance = Appearance(themeColor = 0xFF612FFF.toInt())
)Note: By default, supportedCardBrands includes all cards from AirwallexSupportedCard (Visa, Amex, Mastercard, Discover, JCB, Diners Club, UnionPay). All other parameters are optional with sensible defaults.
Shows multiple payment methods with Tab or Accordion layout:
val configuration = PaymentElementConfiguration.PaymentSheet(
layout = PaymentMethodsLayoutType.TAB, // TAB or ACCORDION
googlePayButton = PaymentElementConfiguration.GooglePayButton(
showsAsPrimaryButton = true, // true: show as primary button, false: show in list
buttonType = null // null: auto (BUY for one-off, SUBSCRIBE for recurring)
),
checkoutButton = PaymentElementConfiguration.CheckoutButton(
title = null // null: auto ("Pay" for one-off, "Confirm" for recurring)
),
appearance = Appearance(
themeColor = 0xFF612FFF.toInt(), // Custom theme color (ARGB format), null for default
isDarkTheme = null // true: dark, false: light, null: follow system
)
)Layout Options:
PaymentMethodsLayoutType.TAB- Tab-based layout for payment methodsPaymentMethodsLayoutType.ACCORDION- Accordion-based layout for payment methods
Google Pay Button:
showsAsPrimaryButton = true- Google Pay appears as a prominent button above other payment methodsshowsAsPrimaryButton = false- Google Pay appears in the list alongside other payment methodsbuttonType- Button type (BUY, SUBSCRIBE, etc.), null for automatic selection
Checkout Button:
title- Custom button text, null for automatic ("Pay" or "Confirm")
Payment Appearance:
themeColor- Custom theme color in ARGB format (e.g.,0xFF612FFF), null for defaultisDarkTheme- true (dark mode), false (light mode), null (follow system)
Here's a complete example of embedding the payment element in your own activity:
import android.os.Bundle
import android.view.View
import androidx.activity.ComponentActivity
import androidx.lifecycle.lifecycleScope
import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentSession
import com.airwallex.android.core.AirwallexPaymentStatus
import com.airwallex.android.core.PaymentMethodsLayoutType
import com.airwallex.android.core.model.PaymentIntent
import com.airwallex.android.view.composables.PaymentElement
import com.airwallex.android.view.composables.PaymentElementConfiguration
import com.yourapp.databinding.ActivityCheckoutBinding
import kotlinx.coroutines.launch
class CheckoutActivity : ComponentActivity() {
private lateinit var binding: ActivityCheckoutBinding
private val airwallex: Airwallex by lazy { Airwallex(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCheckoutBinding.inflate(layoutInflater)
setContentView(binding.root)
setupPaymentElement()
}
private fun setupPaymentElement() {
// Show loading indicator
binding.progressBar.visibility = View.VISIBLE
binding.composeView.visibility = View.GONE
lifecycleScope.launch {
// Create session in this activity (see "Create an Airwallex Session" section)
// For better architecture, create and store the session in a ViewModel
// to survive configuration changes
val paymentIntent = PaymentIntent(
id = "your_payment_intent_id",
clientSecret = "your_client_secret",
amount = 100.toBigDecimal(),
currency = "USD"
)
val session = AirwallexPaymentSession.Builder(
paymentIntent = paymentIntent,
countryCode = "US"
).build()
// Configure payment element
val configuration = PaymentElementConfiguration.PaymentSheet(
layout = PaymentMethodsLayoutType.TAB,
googlePayButton = PaymentElementConfiguration.GooglePayButton(showsAsPrimaryButton = true)
)
// Create PaymentElement
val result = PaymentElement.create(
session = session,
airwallex = airwallex,
configuration = configuration,
onLoadingStateChanged = { isLoading ->
// Optional: Handle loading state changes during payment
binding.progressBar.visibility = if (isLoading) View.VISIBLE else View.GONE
},
onPaymentResult = { status ->
// Handle payment result
when (status) {
is AirwallexPaymentStatus.Success -> {
// Payment successful
showSuccess(status.paymentIntentId)
}
is AirwallexPaymentStatus.Failure -> {
// Payment failed
showError(status.exception.message)
}
is AirwallexPaymentStatus.Cancel -> {
// User cancelled payment
showCancelled()
}
is AirwallexPaymentStatus.InProgress -> {
// Payment in progress (e.g., waiting for 3DS)
// Loading is handled by onLoadingStateChanged
}
}
},
onError = { throwable ->
// Optional: Handle errors during element initialization or payment
// If not provided, SDK will show default error dialog
showError(throwable.message)
}
)
// Handle creation result
result.onSuccess { paymentElement ->
// Hide loading, show payment element
binding.progressBar.visibility = View.GONE
binding.composeView.visibility = View.VISIBLE
// Render the payment UI
binding.composeView.setContent {
paymentElement.Content()
}
}.onFailure { throwable ->
// Failed to initialize payment element
binding.progressBar.visibility = View.GONE
showError(throwable.message)
}
}
}
private fun showSuccess(paymentIntentId: String?) {
// Show success UI
}
private fun showError(message: String?) {
// Show error UI
}
private fun showCancelled() {
// Handle cancellation
}
}Layout XML (activity_checkout.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp">
<!-- Your custom UI elements -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Payment Methods"
android:textSize="20sp"
android:textStyle="bold"
android:layout_marginBottom="16dp" />
<!-- Loading indicator -->
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
<!-- ComposeView for PaymentElement -->
<androidx.compose.ui.platform.ComposeView
android:id="@+id/composeView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>or you can check EmbeddedElementActivity in our demo app.
For Java developers, PaymentElement provides Java-friendly static methods that handle Kotlin coroutines internally, using the familiar two-step pattern: create + renderIn.
Full Implementation Reference: See EmbeddedElementJavaActivity.java in the sample app for a complete working example.
Key Integration Code:
import com.airwallex.android.view.composables.PaymentElement;
import com.airwallex.android.view.composables.PaymentElementCallback;
import com.airwallex.android.view.PaymentFlowListener;
// Configure payment element
PaymentElementConfiguration configuration = new PaymentElementConfiguration.PaymentSheet(
PaymentMethodsLayoutType.TAB,
new PaymentElementConfiguration.GooglePayButton(true, null), // showsAsPrimaryButton, buttonType
new PaymentElementConfiguration.CheckoutButton(null), // title
null // appearance
);
// Create payment flow listener to handle results
PaymentFlowListener listener = new PaymentFlowListener() {
@Override
public void onPaymentResult(@NonNull AirwallexPaymentStatus status) {
if (status instanceof AirwallexPaymentStatus.Success) {
// Handle success
} else if (status instanceof AirwallexPaymentStatus.Failure) {
// Handle failure
}
}
@Override
public void onLoadingStateChanged(boolean isLoading, @NonNull Context context) {
// You can implement your own loading UI or use the default implementation (shows/hides loading dialog)
PaymentFlowListener.super.onLoadingStateChanged(isLoading, context);
}
@Override
public void onError(@NonNull Throwable exception, @NonNull Context context) {
// You can implement your own error handling or use the default implementation (shows error dialog)
PaymentFlowListener.super.onError(exception, context);
}
};
// Show loading state
binding.progressBar.setVisibility(View.VISIBLE);
binding.composeView.setVisibility(View.GONE);
// Step 1: Create PaymentElement (handles coroutines internally)
PaymentElement.create(
session, // AirwallexSession
airwallex, // Airwallex instance
configuration, // PaymentElementConfiguration
listener, // PaymentFlowListener
new PaymentElementCallback() {
@Override
public void onSuccess(@NonNull PaymentElement element) {
// Hide loading
binding.progressBar.setVisibility(View.GONE);
binding.composeView.setVisibility(View.VISIBLE);
// Step 2: Render the PaymentElement in ComposeView
element.renderIn(binding.composeView);
}
@Override
public void onFailure(@NonNull Throwable error) {
// Hide loading and handle error
binding.progressBar.setVisibility(View.GONE);
showError(error.getMessage());
}
}
);Java Integration:
- Handles Kotlin coroutines internally (no need for suspend function interop)
- Uses familiar callback patterns for Java developers
- Separates creation and rendering for maximum flexibility
- You control when and how to show loading states
- Works with both Payment Sheet and Card-only modes
Two-Step Pattern:
PaymentElement.create()- Creates and initializes the element (async operation)element.renderIn()- Renders the UI in your ComposeView (called in success callback)
Note: While Java integration is fully supported, we recommend using Kotlin for the best development experience with Embedded Elements.
Key Differences from Hosted Payment Page Integration:
| Feature | Hosted Payment Page Integration | Embedded Element Integration |
|---|---|---|
| Entry Point | AirwallexStarter.presentPaymentFlow() |
PaymentElement.create() |
| Activity Ownership | SDK owns the activity | You own the activity |
| UI Container | SDK activities | Your ComposeView |
| Layout Control | Limited (SDK-controlled) | Full (you control surrounding UI) |
| Initialization | Launch activity | Suspending function |
| Callbacks | AirwallexCheckoutListener |
PaymentFlowListener or lambdas |
You can build your own entirely custom UI on top of our low-level APIs.
The Airwallex Android SDK is compatible with apps supporting Android API level 21 and above.
- Install the SDK The Components are available through Maven Central, you only need to add the Gradle dependency.
To install the SDK, in your app-level build.gradle, add the following:
dependencies {
// It's required
implementation 'io.github.airwallex:payment-components-core:6.6.1'
// Select the payment method you want to support, ignore the components you don't need.
implementation 'io.github.airwallex:payment-card:6.6.1'//only support card
implementation 'io.github.airwallex:payment-googlepay:6.6.1'//only support google pay
implementation 'io.github.airwallex:payment-redirect:6.6.1'//only support redirect
}After setting up the SDK, you are required to config your SDK with some parameters. Before using Airwallex SDK to confirm payment intents and complete the payments, you shall create payment intents in your own server, to make sure you maintain information in your own system
We provide some parameters that can be used to debug the SDK, you can call it in Application
import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexConfiguration
Airwallex.initialize(
this,
AirwallexConfiguration.Builder()
.enableLogging(true) // Enable log in sdk, best set to false in release version
.saveLogToLocal(false)// Save the Airwallex logs locally. If you have your own saving strategy, please set this to false.
.setEnvironment(environment)
.setSupportComponentProviders(
listOf(
CardComponent.PROVIDER,
WeChatComponent.PROVIDER,
RedirectComponent.PROVIDER,
GooglePayComponent.PROVIDER
)
)
.build()
)Create Payment Intent (On the Merchant’s server)
Create an AirwallexSession object
import com.airwallex.android.core.Airwallex
val airwallex = Airwallex(activity)The following APIs can be used independently depending on your payment scenario. They are not sequential steps.
Before invoking the payment API, you need to follow the steps to Set up Google Pay
import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
// NOTE: We only support AirwallexPaymentSession (one off session), no recurring session for Google Pay at the moment.
// Also make sure you pass GooglePayOptions to the session. Refer to [Set up Google Pay].
airwallex.startGooglePay(
session = session,
listener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// You can handle different payment statuses and perform UI action respectively here
}
}
)import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
airwallex.startRedirectPay(
session = session,
paymentType = "alipayhk",
listener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// You can handle different payment statuses and perform UI action respectively here
}
}
)import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
// Confirm intent with card and billing
airwallex.confirmPaymentIntent(
session = session,
card = PaymentMethod.Card.Builder()
.setNumber("4012000300000021")
.setName("John Citizen")
.setExpiryMonth("12")
.setExpiryYear("2029")
.setCvc("737")
.build(),
billing = null,
saveCard = false,//set saveCard to true to save the card information while making the payment.
listener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// You can handle different payment statuses and perform UI action respectively here
}
}
) import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
airwallex.confirmPaymentIntent(
session = session,
paymentConsentId = "cst_xxxxxxxxxx",
listener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// You can handle different payment statuses and perform UI action respectively here
}
}
) import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.AirwallexPaymentStatus
import com.airwallex.android.core.AirwallexPaymentSession
import com.airwallex.android.core.model.PaymentConsent
airwallex.confirmPaymentIntent(
session = session,
paymentConsent = paymentConsent,
listener = object : Airwallex.PaymentResultListener {
override fun onCompleted(status: AirwallexPaymentStatus) {
// You can handle different payment statuses and perform UI action respectively here
}
}
) import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.model.RetrieveAvailablePaymentMethodParams
val methods = airwallex.retrieveAvailablePaymentMethods(
session = session,
params = RetrieveAvailablePaymentMethodParams.Builder(
clientSecret = getClientSecretFromSession(session),
pageNum = 1
)
.setActive(true)
.setTransactionCurrency(session.currency)
.setCountryCode(session.countryCode)
.build()
) import com.airwallex.android.core.Airwallex
import com.airwallex.android.core.model.RetrieveAvailablePaymentConsentsParams
import com.airwallex.android.core.model.PaymentConsent
val consents = airwallex.retrieveAvailablePaymentConsents(
RetrieveAvailablePaymentConsentsParams.Builder(
clientSecret = clientSecret,
customerId = customerId,
pageNum = 1
)
.setNextTriggeredBy(nextTriggerBy)
.setStatus(PaymentConsent.PaymentConsentStatus.VERIFIED)
.build()
)We welcome contributions of any kind including new features, bug fixes, and documentation improvements. We also appreciate the time you take to try out our sample code and welcome your feedback.
Here are a few ways to get in touch:
- For generally applicable issues and feedback, create an issue in this repository.
- pa_mobile_sdk@airwallex.com - For personal support at any phase of integration






