TransactionListener
Call the TransactionListener API to monitor transaction processes.
Note: Implementing the TransactionListener API requires the following imports:
- com.iap.android.nfc.model.APTransactionContext
- com.iap.android.nfc.core.apdu.walletinterface.walletdatatypes.TransactionInfo
- com.iap.android.nfc.core.apdu.exception.ExtendedReasonCode
Method signature
public interface TransactionListener {
void onTransactionStart();
void onTransactionComplete(@Nullable APTransactionContext transactionInfo);
void onTransactionFailed(@NotNull String errorCode, @Nullable TransactionInfo transactionInfo, @Nullable ExtendedReasonCode extendedReasonCode);
void onTransactionAuth();
}
// Register listener
ACTapManager.getInstance(context).setTransactionListener(new TransactionListener())Request parameters
Method | Item | Type | Description |
onTransactionStart | / | / | No parameters. Called when a transaction starts or when the SDK receives the first APDU command. |
onTransactionComplete | transactionInfo | Called when a transaction completes or when the SDK receives the final command. | |
onTransactionFailed | errorCode | String | The error code returned when a transaction fails. For more information, see Result codes. |
transactionInfo | TransactionInfo | The transaction information returned when a transaction fails. | |
extendedReasonCode | ExtendedReasonCode | The extended reason code providing additional failure details. | |
onTransactionAuth | / | / | No parameters. Called when a transaction requires authentication. When called, |
APTransactionContext
Item | Type | Description |
mcc | String | The merchant category code (MCC). |
currencyCode | byte[] | The transaction currency code. |
amount | byte[] | The transaction amount. |
transactionRange | String | The transaction risk level under EMV standards, which varies by country and region. Valid values are:
|
richTransactionType | String | Type of transactions. Valid values are:
|
transactionInfo | TransactionInfo | Retained for backward compatibility. |
purpose | String | The purpose of the transaction. Valid values are:
|
expectedUserActionOnPoi | String | The expected user action to authorize this transaction at the point of interaction.
|
conditionsOfUse | String | Whether this transaction is local or cross-border. Valid values are:
|
merchantName | String | The merchant name. |
countryCode | String | The terminal country code. |
Response parameters
N/A
Sample
class Demo implements TransactionListener {
@Override
public void onTransactionStart() {
log("received onTransactionStart");
}
@Override
public void onTransactionComplete(@Nullable APTransactionContext transactionInfo) {
log("received onTransactionComplete");
}
@Override
public void onTransactionFailed(@NonNull String errorCode, @Nullable TransactionInfo transactionInfo, @Nullable ExtendedReasonCode extendedReasonCode) {
log("received onTransactionFailed " + errorCode);
}
@Override
public void onTransactionAuth() {
log("received onTransactionAuth");
Intent intent = new Intent(this, AuthActivity.class);
startActivity(intent);
}
}
Note:
- The
onTransactionCompletecallback receives an APTransactionContext, whileonTransactionFailedreceives TransactionInfo. This asymmetry is intentional.- extendedReasonCode provides additional detail about a transaction failure and may be null.
Handling a tap failure
Register a TransactionListener once, after initialization. A tap ends in either onTransactionComplete or onTransactionFailed. If the payment requires authentication, onTransactionAuth fires first.
ACTapManager manager = ACTapManager.getInstance(getApplication());
manager.setTransactionListener(new TransactionListener() {
@Override
public void onTransactionStart() {
// A tap has begun.
}
@Override
public void onTransactionComplete(@Nullable APTransactionContext transactionInfo) {
// The tap finished. Show the payment result.
}
@Override
public void onTransactionFailed(@NotNull String errorCode,
@Nullable TransactionInfo transactionInfo,
@Nullable ExtendedReasonCode extendedReasonCode) {
// Log both: errorCode groups the failure, extendedReasonCode says why.
Log.w("TapPayment", "failed errorCode=" + errorCode
+ " reason=" + extendedReasonCode);
if ("10020".equals(errorCode)) {
// Tap broke off. Ask the user to tap again.
} else if ("10022".equals(errorCode)) {
// Declined. Tell the user.
} else if ("CARD_ERROR".equals(errorCode)) {
// Card problem. It may only need credentials.
if (manager.isPaymentAvailable()
== TokenStatus.TOKEN_STATUS_ACTIVATED_WITH_NO_CREDENTIALS) {
manager.replenish(null);
}
} else if ("WALLET_CANCEL_REQUEST".equals(errorCode)) {
// Your app stopped it. Nothing to fix.
} else if (errorCode.isEmpty()) {
// Terminal sent an unusable command. The tap usually carries on.
}
}
@Override
public void onTransactionAuth() {
// The payment needs the user to authenticate. Start your auth flow.
}
});Note:
- One tap can produce more than one failure callback. A malformed command does not end the tap. The terminal may send another command, which triggers
onTransactionFailedagain. A definitive failure callback may follow. Do not treat the first callback as the only one.- If the
isSwitchNewTransactionoption is enabled, the empty-string andCARD_ERRORcases are reported as10022instead.