Alipay+ DocsAlipay+ Docs

Quick start

This guide provides step-by-step instructions to integrate the Tap to Pay SDK into your Android project using locally downloaded AAR files instead of remote dependencies. Follow these steps carefully to ensure a successful integration.

Before you begin

Ensure that the following requirements are met:

  • The latest stable version of Android Studio
  • Android 9.0 (API level 28) or later
  • Android Compile SDK Version 34 with Android Build Tools 34.0.0
  • Gradle 7.4 or later
  • JDK 17 or later
  • A physical Android device with:
    • NFC hardware with Host Card Emulation (HCE) support
    • Hardware-backed Android Keystore
    • A device screen lock configured
  • Obtain the following AAR files from your Alipay+ Solution Architect:
    • tap-payment-1.x.xx.8000.aar
    • tap-payment-ui-1.x.xx.8000.aar

Step 1: Add the SDK to your project

1.1 Add the AAR File

  1. Locate or create the libs directory:
    • Locate the libs directory in the root folder of your app module, typically at app/.
    • If the libs directory doesn't exist, create a new folder named libs within the app/ directory.
  1. Copy the AAR file:
    • Copy the downloaded tap-payment-1.x.xx.8000.aar and tap-payment-ui-1.x.xx.8000.aar file into the app/libs/ directory.
    • Double-check to ensure that the filenames are correct, including the version numbers.

1.2 Update your gradle configuration

  1. Open the app/build.gradle file in your code editor, and add the flatDir repository. Include the libs directory as a local repository by adding the following code block inside the android or repositories section:
copy
repositories {
    flatDir {
        dirs 'libs'  // Points to the libs folder
    }
}

Sample

copy
android {
    // ... other configurations (for example, compileSdk, buildToolsVersion)  
}

repositories {
    flatDir { dirs 'libs' }  // Add this line
}

dependencies {
    // ... dependencies  
}
  1. Declare the AAR dependency: Replace the remote SDK dependency with the local AAR file in the dependencies block:
copy
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])  // Add this line
    // ... other dependencies  
}

1.3 Add other required dependency

Add the required Fastjson dependency with the following code:

copy
fast-json = { group = "com.alibaba", name = "fastjson", version.ref = "fast-json-version"}
fast-json-version = "1.1.76.android_noneautotype"

implementation(libs.fast.json)
implementation 'com.airbnb.android:lottie:6.6.7'

1.4 Configure DexGuard exclusions (if applicable)

If your wallet app is hardened with DexGuard, exclude the Tap to Pay SDK from RASP instrumentation, as the SDK is already protected with DexProtector.

Compatible DexGuard version: 9.14.5 or later.

Add the following rules to the DexGuard configuration file of your host app. The default configuration file is dexguard-project.txt:

copy
-raspdenylist class com.iap.android.nfc.**
-raspdenylist native lib*.so

Warning: Do not add these rules to proguard-rules.pro. ProGuard and R8 do not recognize the -raspdenylist option.

The rules above exclude the following SDK classes from re-instrumentation. Do not hook these classes, as doing so may cause runtime errors or security failures:

  • LibApplication
  • ACTapManager
  • NFCWrapperManager
  • NFCCoreDefaultCryptoEngine
  • NFCDefaultCryptoEngineFactory
  • The Application subclass of your wallet app (host app, not part of the SDK)

If your wallet app uses a hardening tool other than DexGuard, configure equivalent exclusion rules to prevent the tool from re-instrumenting or hooking the SDK packages or native libraries.

1.5 Configure ProGuard/R8 keep rules

The Tap to Pay SDK does not bundle these rules in its consumer ProGuard file, so the AAR does not add them to your build automatically. You must add them manually, including the -keep rules for the Tap to Pay SDK classes. If you enable minification in your release build, add the following to your app's proguard-rules.pro:

copy
buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}
copy
# Keep the NFC SDK classes (the AAR does not ship these consumer rules)
-keep class com.iap.android.nfc.** { *; }
-dontwarn com.iap.android.nfc.**

# Preserve JNI method names so that libv.so resolves its native bindings
-keepclasseswithmembernames,includedescriptorclasses class * {
    native <methods>;
}

# Metadata that the SDK reads through reflection and serialization
-keepattributes *Annotation*,RuntimeVisibleAnnotations,Exceptions,Signature,InnerClasses,EnclosingMethod
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep class * implements java.io.Serializable { *; }

The SDK also relies on the native libraries libv.so and libdexprotector.so, and on the white-box asset files packaged inside the AAR. Do not add packaging or resource-exclusion rules that remove them from your APK.

If you use DexGuard, keep these rules in proguard-rules.pro. DexGuard reads them. Only the -raspdenylist rules in 1.4 belong in the DexGuard configuration file.

Note: -keep class * implements java.io.Serializable { *; } is intentionally broad because the SDK deserializes card profile and RPC models through reflection. Contact your Alipay+ Solution Architect before you narrow this rule.

1.6 Sync and build

In Android Studio, click Sync Now to apply the changes.

Step 2: Configure Android Manifest

2.1 Declare permissions and hardware features

Add the following to your AndroidManifest.xml:

copy
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />

2.2 Define the HCE service

Add the following XML snippet to your app's AndroidManifest.xml. This declares your custom HCE service, configures its behavior, and specifies the Application Identifiers (AIDs) it supports:

copy
<service
  android:name=".MyNFCHCEService"
  android:exported="true"
  android:enabled="true"
  android:permission="android.permission.BIND_NFC_SERVICE">
  <intent-filter>
    <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
  </intent-filter>
  <meta-data
    android:name="android.nfc.cardemulation.host_apdu_service"
    android:resource="@xml/apdu_service_config" />
</service>

2.3 Create the HCE service configuration file

Create the res/xml/apdu_service_config.xml file to define the metadata of your HCE service:

copy
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
  android:apduServiceBanner="@drawable/your_service_banner"
  android:description="@string/your_service_description"
  android:requireDeviceUnlock="false">

  <aid-group
    android:category="payment"
    android:description="@string/your_aid_group_description">
     <aid-filter android:name="325041592E5359532E4444463031" />
     <aid-filter android:name="A0000000041010"/>
  </aid-group>
</host-apdu-service>

Key attributes in the metadata:

  • android:apduServiceBanner: A drawable resource displayed in Tap to Pay payment selection UIs, for example, use a 120 x 40 dp logo to represent your wallet app.
  • android:description: A string resource describing your service, for example, "Tap & Pay with Alipay+ Tap to Pay".
  • android:requireDeviceUnlock: Controls whether the device must be unlocked before Android routes APDUs to this service.

Value

Behavior

true

The device must be unlocked. If a tap is detected while the device is locked, Android prompts the user to unlock before processing the tap.

false

(default)

The service can handle taps from the lock screen. This is the recommended setting for contactless payment and transit apps.

Step 3: Initialize the Alipay+ Tap to Pay SDK

3.1 Initialize the SDK

Set up configurations in the APNFCConfigobject, and then call the init API to initialize the SDK.

copy
public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        ACTapManager manager = ACTapManager.getInstance(this);

        // 1. Build configuration
        APNFCConfig config = APNFCConfig.newBuilder()
            .setNeedConfirmActivate(true)
            .setAuthType(NFCAuthMode.FLEXIBLE_WITHOUT_UPPER_AMOUNT)
            .setShowCoreLog(BuildConfig.DEBUG)
            .setSupportLockScreenPay(false)
            .build();
        // 2. Initialize SDK
        manager.init(config);
        ...
    }
}

3.2 Register mandatory SPI plugins and set transaction listener

Register the following eight SPI plugins to enable wallet services.

Plugin

Function

NFCRequestProxy

Proxies requests to the server.

LoggerProxy

Prints out SDK logs.

ConfigProxy

Remotely manages SDK configurations.

ThreadPoolService

Implements and manages your own thread pool.

TransactionPermit

Enables final authorization decisions during transactions based on specific criteria.

NFCMonitor

Detects the SDK's execution status.

DeviceFingerPrintService

Requests device fingerprints from the MPP.

EncryptionProxy

Encrypts or decrypts sensitive data.

Note: You must register all SPI plugins before calling connect(). Missing plugins will cause activation or transaction failures.

Set the TransactionListener API to handle transaction processes. The table below describes each function of the API.

Function

Description

onTransactionStart()

Call this function when a transaction starts or when the SDK receives the first APDU command.

onTransactionComplete(@Nullable APTransactionContext transactionInfo)

Call this function when a transaction completes or when the SDK receives the final command.

onTransactionFailed(@NotNull String errorCode, @Nullable TransactionInfo transactionInfo)

Call this function when a transaction fails.

onTransactionAuth()

Call this function when a transaction requires authentication. When called, onTransactionFailed is also called with error code 10003.

copy
public class BaseApplication extends Application {

    @Override
    public void onCreate() {
        
        ...
        
        // 3. Register mandatory SPI plugins
        manager.registerPlugin(NFCRequestProxy.class, new YourNetworkProxy());
        manager.registerPlugin(LoggerProxy.class, new YourLogger());
        manager.registerPlugin(ThreadPoolService.class, new YourThreadPool());
        manager.registerPlugin(ConfigProxy.class, new YourConfigProxy());
        manager.registerPlugin(TransactionPermit.class, new YourTransactionPermit());
        manager.registerPlugin(NFCMonitor.class, new YourMonitor());
        manager.registerPlugin(DeviceFingerPrintService.class, new YourDeviceFingerPrint());
        manager.registerPlugin(EncryptionProxy.class, new YourEncryptionProxy());

        // 4. Set transaction listener
        manager.setTransactionListener(new TransactionListener() {
            @Override
            public void onTransactionStart() {
                // Handle transaction start
            }

            @Override
            public void onTransactionComplete(APTransactionContext info) {
                // Handle successful transaction
            }

            @Override
            public void onTransactionFailed(String errorCode, TransactionInfo info,
                    ExtendedReasonCode reason) {
                // Handle transaction failure
            }

            @Override
            public void onTransactionAuth() {
                // Trigger user authentication (CDCVM)
            }
        });
    }
}

3.3 Implement the HCE Service Class

Create a class (for example, MyNFCHCEService) that extends HostApduService to handle APDU commands from the NFC readers:

copy
import android.os.Bundle;
import android.util.Log;
import android.nfc.cardemulation.HostApduService;
import com.iap.android.nfc.ACTapManager;
import com.iap.android.nfc.core.apdu.utils.ApduByteArray;

public class MyNFCHCEService extends HostApduService {

    @Override
    public void onCreate() {
        super.onCreate();
        // Connect with the actual user ID obtained from your backend login flow.
        // This must be the same UID used during activatePayment().
        String userId = YourSessionManager.getCurrentUserId();
        ACTapManager.getInstance(getApplication()).connect(userId, null);
    }

    @Override
    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
        Log.d("HCE_SERVICE", "received: " + ApduByteArray.of(commandApdu).toHexString());
        byte[] response = ACTapManager.getInstance(getApplication())
            .processApduCommands(commandApdu);
        Log.d("HCE_SERVICE", "return: " + ApduByteArray.of(response).toHexString());
        return response;
    }

    @Override
    public void onDeactivated(int reason) {
        ACTapManager.getInstance(getApplication()).transactionDeactivate();
    }
}

Next steps

After integrating the SDK, complete the following steps:

  • Refer to Alipay+ Tap to Pay integration to implement specific payment scenarios
  • Add the SDK to the whitelist. This prevents conflicts between the wallet's built-in security software and the SDK.
  • Test your wallet on the top 20 local device models to ensure it does not crash in production.