Alipay+ DocsAlipay+ Docs

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

copy
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

APTransactionContext

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, onTransactionFailed is also called with error code 10003. For more information, see Result codes.

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:

  • LOW_VALUE: A low-value transaction.
  • HIGH_VALUE : A high-value transaction.
  • UNKNOWN: The transaction range could not be determined.

richTransactionType

String

Type of transactions.

Valid values are:

  • PURCHASE: Ordinary transaction
  • REFUND: Refund
  • CASH: Cash withdrawal
  • TRANSIT: Transportation transaction
  • PURCHASE_WITH_CASHBACK: Purchase with cashback
  • UNKNOWN: Unknown type

transactionInfo

TransactionInfo

Retained for backward compatibility.

purpose

String

The purpose of the transaction. 

Valid values are:

  • AUTHORIZE: Pre-authorization.
  • AUTHENTICATE: Authentication required.
  • UNKNOWN: Unknown purpose.

expectedUserActionOnPoi

String

The expected user action to authorize this transaction at the point of interaction.

  • NONE: No action is required at the terminal.
  • ONLINE_PIN: Use online pin to authorize this transaction.
  • SIGNATURE: Use signature to authorize this transaction.
  • ONLINE_PIN_OR_SIGNATURE: Use online pin or signature to authorize this transaction.
  • UNKNOWN: Unexpected results are returned.

conditionsOfUse

String

Whether this transaction is local or cross-border. 

Valid values are:

  • DOMESTIC: This transaction is a local transaction.
  • INTERNATIONAL: This transaction is a cross-border transaction.
  • UNKNOWN: The type of this transaction is unknown.

merchantName

String

The merchant name.

countryCode

String

The terminal country code.

Response parameters

N/A

Sample

copy
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 onTransactionComplete callback receives an APTransactionContext, while onTransactionFailed receives 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.

copy
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 onTransactionFailed again. A definitive failure callback may follow. Do not treat the first callback as the only one.
  • If the isSwitchNewTransaction option is enabled, the empty-string and CARD_ERROR cases are reported as 10022 instead.