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
- 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.
- 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
- Open the app/build.gradle file in your code editor, and add the
flatDirrepository. Include the libs directory as a local repository by adding the following code block inside theandroidorrepositoriessection:
repositories {
flatDir {
dirs 'libs' // Points to the libs folder
}
}Sample
android {
// ... other configurations (for example, compileSdk, buildToolsVersion)
}
repositories {
flatDir { dirs 'libs' } // Add this line
}
dependencies {
// ... dependencies
}- Declare the AAR dependency: Replace the remote SDK dependency with the local AAR file in the
dependenciesblock:
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:
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:
-raspdenylist class com.iap.android.nfc.**
-raspdenylist native lib*.soWarning: 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:
LibApplicationACTapManagerNFCWrapperManagerNFCCoreDefaultCryptoEngineNFCDefaultCryptoEngineFactory- The
Applicationsubclass 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:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}# 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:
<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:
<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:
<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 |
| 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. |
(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.
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, |
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:
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.