> For the complete documentation index, see [llms.txt](https://docs.verifone.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.verifone.com/psdk-latest/reference-material/code-labs/fi-payments.md).

# Fully Integrated (FI) Payments

{% columns %}
{% column width="41.66666666666667%" %} <i class="fa-clock">:clock:</i> 10 minutes reading time\ <i class="fa-calendar">:calendar:</i> Last updated: 16th June, 2026
{% endcolumn %}

{% column width="24.999999999999986%" %}

{% endcolumn %}

{% column %}

{% endcolumn %}
{% endcolumns %}

FI (Fully Integrated) is a PSDK payment mode that gives the POS application direct control over every step of the payment transaction flow. Unlike Semi Integrated Payments — where the SDK manages card reading, cryptogram generation, and host handoff internally — FI exposes each step as an individual request/response pair so the POS can drive the full transaction lifecycle.

FI supports all card entry methods: **EMV Contact (chip)**, **Magnetic Stripe (swipe)**, **Contactless (NFC/tap)**, and **Manual (keyed entry)** — see [FiEntryMode](https://docs.verifone.com/psdk-api-latest/java/index/fientrymode) in the API Reference. The transaction flow differs by entry method — EMV Contact involves additional Gen AC steps for chip cryptogram processing, while MSR, CTLS, and Manual flows complete after Card Acquisition.

{% hint style="success" %}
**No login or session required.** After `initialize()` and `connect()` succeed, call `getFiManager()` directly. Login and session setup are only needed for Semi Integrated Payments.
{% endhint %}

***

## Supported Transaction Types

See [FiTransactionType](https://docs.verifone.com/psdk-api-latest/java/index/fitransactiontype) in the API Reference for all supported transaction types (`PURCHASE`, `CASH_ADVANCE`, `VOID_PURCHASE`, `PAYMENT_WITH_CASH_BACK`, `REFUND`, `VOID_REFUND`, `BALANCE_INQUIRY`).

***

## Semi Integrated Payments vs FI Payments

FI is one of three payment integration models available in PSDK:

| Transaction Step           | Full-PSDK (Semi Integrated Payments) | Slim-PSDK                     | FI (Fully Integrated)                                                                                                                         |
| -------------------------- | ------------------------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| Login required             | Yes                                  | Yes                           | **No**                                                                                                                                        |
| Session required           | Yes                                  | Yes                           | **No**                                                                                                                                        |
| EMV flow control           | SDK-managed                          | **POS-managed**               | **POS-managed**                                                                                                                               |
| Host authorization handoff | SDK handles                          | **POS handles**               | **POS handles**                                                                                                                               |
| Online PIN                 | SDK handles                          | SDK handles                   | **SDK handles; encrypted PIN block in Card Acquisition response (MSR/CTLS or NON\_QC\_GEN\_AC mode) or First Gen AC response (NON\_QC mode)** |
| Entry point                | `startPayment()`                     | `startPayment()`              | `getFiManager()`                                                                                                                              |
| Response delivery          | `handlePaymentCompletedEvent`        | `handlePaymentCompletedEvent` | `handleFiCardAcquisitionResponseEvent`, etc.                                                                                                  |

***

## Transaction Flow Classification

The FI flow splits into two paths based on card entry method:

{% tabs %}
{% tab title="EMV Contact (ICC)" %}
Contact chip cards require the full 4-step EMV flow. The EMV kernel on the terminal performs cryptogram generation in two stages — First Gen AC (ARQC) before host authorization, and Second Gen AC (TC/AAC) after.

```
Card Acquisition → First Gen AC → Host Authorization → Second Gen AC
```

Depending on the `quickChipMode` set in the Card Acquisition request, some steps can be combined:

| QuickChip Mode  | Behaviour                                                                                                                                                                                                            |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `NON_QC`        | Full 4-step flow. Card Acquisition, First Gen AC, Host Authorization, and Second Gen AC are separate steps.                                                                                                          |
| `NON_QC_GEN_AC` | Card Acquisition and First Gen AC are combined into a single step. Skip the separate `requestFiFirstGenAC()` call and proceed directly to host authorization.                                                        |
| `QC`            | Card Acquisition, First Gen AC, and Second Gen AC are all combined into a single step. The terminal completes the full EMV cryptogram flow internally and returns the final result in the Card Acquisition response. |

**Applies to:** `FiEntryMode.ICC` only.
{% endtab %}

{% tab title="MSR / CTLS / Manual" %}
For MSR and Manual entry, the flow completes after Card Acquisition — there is no EMV kernel involved, so First Gen AC and Second Gen AC are not applicable and must not be called.

```
Card Acquisition → Host Authorization (POS responsibility)
```

For CTLS (contactless), First Gen AC is completed internally at the end of Card Acquisition. The ARQC is returned as part of the Card Acquisition response — skip the separate `requestFiFirstGenAC()` call and proceed directly to host authorization. Second Gen AC is not applicable for CTLS.

```
Card Acquisition (First Gen AC included) → Host Authorization
```

**Applies to:** `FiEntryMode.MAG_STRIPE`, `FiEntryMode.CTLS`, `FiEntryMode.MANUAL`.
{% endtab %}
{% endtabs %}

{% hint style="warning" %}
Always check `FiCardData.getEntryMode()` from the Card Acquisition response before deciding whether to call `requestFiFirstGenAC()` and `requestFiSecondGenAC()`. Calling these for non-ICC entry modes is not supported.
{% endhint %}

***

## Transaction Flows

{% @plantuml/diagram content="@startuml
skinparam defaultFontName Arial
skinparam activityBackgroundColor #F5F5F5
skinparam activityBorderColor #999999
skinparam arrowColor #555555
skinparam diamondBackgroundColor #F5F5F5
skinparam diamondBorderColor #999999

legend
▶ POS → PSDK (API call out)
◄ PSDK → POS (event callback)
plain = process step
endlegend

start

:▶ requestFiCardAcquisition();
:◄ handleFiCardAcquisitionResponseEvent();

if (getEntryMode() == ICC?) then (yes)
:▶ requestFiFirstGenAC();
:◄ handleFiFirstGenACResponseEvent()\n<i>\[9F27 cryptogram type, EMV tags]</i>;
if (9F27 == ARQC?) then (yes)
:Host Authorization\n<i>(POS sends ARQC to acquirer host)</i>;
:▶ requestFiSecondGenAC()\n<i>\[IssuerAuthData, Scripts]</i>;
:◄ handleFiSecondGenACResponseEvent()\n<i>\[TC / AAC cryptogram]</i>;
else (TC or AAC — offline decision)
endif
else (no — MSR / CTLS / Manual)
:Host Authorization\n<i>(POS sends card data to acquirer host)</i>;
endif

:Completion;
stop
@enduml" %}

### EMV Contact (ICC) Flow

Full 4-step flow for chip card transactions.

{% @plantuml/diagram content="@startuml
skinparam sequenceMessageAlign center
skinparam responseMessageBelowArrow true

participant "POS Application" as POS
participant "PSDK" as PSDK
participant "Terminal" as TERM
participant "Acquirer Host" as HOST

POS -> PSDK: initialize()
PSDK -> TERM: connect
PSDK --> POS: STATUS\_INITIALIZED

note over POS, PSDK: No login or session required

group Step 1: Card Acquisition (all entry methods)
POS -> PSDK: getFiManager()\n.requestFiCardAcquisition()
PSDK -> TERM: FiCardAcquisitionRequest
TERM --> PSDK: FiCardAcquisitionResponse
PSDK --> POS: handleFiCardAcquisitionResponseEvent()\n\[check getEntryMode() == ICC]
end

group Step 2: First Gen AC (ICC only)
POS -> PSDK: getFiManager()\n.requestFiFirstGenAC()
PSDK -> TERM: FiFirstGenACRequest
TERM --> PSDK: FiFirstGenACResponse
PSDK --> POS: handleFiFirstGenACResponseEvent()\n\[ARQC 9F26, EMV tags]
end

group Step 3: Host Authorization (POS responsibility)
POS -> HOST: Authorization request\n(ARQC, EMV tags)
HOST --> POS: AuthResponseCode,\nIssuerAuthData, IssuerScripts
end

group Step 4: Second Gen AC (ICC only)
POS -> PSDK: getFiManager()\n.requestFiSecondGenAC()\n(TC or AAC, IssuerAuthData, Scripts)
PSDK -> TERM: FiSecondGenACRequest
TERM --> PSDK: FiSecondGenACResponse
PSDK --> POS: handleFiSecondGenACResponseEvent()\n\[TC/AAC cryptogram, final EMV tags]
end
@enduml" %}

### MSR / CTLS / Manual Flow

Simplified flow for non-chip entry methods. No Gen AC steps.

{% @plantuml/diagram content="@startuml
skinparam sequenceMessageAlign center
skinparam responseMessageBelowArrow true

participant "POS Application" as POS
participant "PSDK" as PSDK
participant "Terminal" as TERM
participant "Acquirer Host" as HOST

POS -> PSDK: initialize()
PSDK -> TERM: connect
PSDK --> POS: STATUS\_INITIALIZED

note over POS, PSDK: No login or session required

group Step 1: Card Acquisition (all entry methods)
POS -> PSDK: getFiManager()\n.requestFiCardAcquisition()
PSDK -> TERM: FiCardAcquisitionRequest
TERM --> PSDK: FiCardAcquisitionResponse
PSDK --> POS: handleFiCardAcquisitionResponseEvent()\n\[encrypted card data, track data, entry mode]
end

note over POS: No Gen AC steps for MSR / CTLS / Manual

group Step 2: Host Authorization (POS responsibility)
POS -> HOST: Authorization request\n(encrypted card data)
HOST --> POS: Authorization response
end
@enduml" %}

***

{% hint style="info" %}
**API Reference**

* [FiManager](https://docs.verifone.com/psdk-api-latest/java/index/fimanager) — all available Request API FI methods
* [CommerceListener2](https://docs.verifone.com/psdk-api-latest/java/index/commercelistener2) — all Response API FI callback methods
  {% endhint %}

{% hint style="warning" %}
Always check `event.getStatus()` before accessing the response payload. Always null-check the response object — a `null` response indicates a parse error on the terminal side.
{% endhint %}

***

## Transaction Steps

{% stepper %}
{% step %}

## Step 1 — Card Acquisition (all entry methods)

Card Acquisition is the first step of an FI transaction. It instructs the terminal to display prompts to the cardholder and read the card (chip, swipe, or contactless). The terminal returns card data including the entry mode and, when applicable, an encrypted Online PIN block. This step is common to all entry methods.

Card Acquisition can be initiated immediately after `initialize()` — no session or login is needed.

### QuickChip Mode and First Gen AC (ICC only)

The `quickChipMode` parameter controls whether the EMV kernel performs the First Gen AC step internally during Card Acquisition. This parameter is only relevant for ICC (chip) entry.

See [FiQuickChipMode](https://docs.verifone.com/psdk-api-latest/java/index/fiquickchipmode) in the API Reference for all Quick Chip processing modes (`NON_QC`, `QC`, `NON_QC_GEN_AC`).

### Card Entry Method

See [FiEntryMode](https://docs.verifone.com/psdk-api-latest/java/index/fientrymode) in the API Reference for all supported card entry modes (`MAG_STRIPE`, `ICC`, `CTLS`, `MANUAL`).

### Card Entry Method Restrictions

`requestFiFirstGenAC()` and `requestFiSecondGenAC()` are only available for **Contact EMV (chip)** card entries. These calls are **not** supported for:

* Magnetic stripe (swipe)
* Contactless (tap / NFC)
* Manual / keyed entry

Check `FiCardData.getEntryMode()` from the Card Acquisition response to determine whether First Gen AC and Second Gen AC are applicable before calling them.

See [FiCardAcquisitionRequest](https://docs.verifone.com/psdk-api-latest/java/index/ficardacquisitionrequest) in the API Reference for all request parameters.

{% tabs %}
{% tab title="Java" %}
{% code title="Send Card Acquisition request" lineNumbers="true" %}

```java
// FI is available immediately after initialize() — no login or session needed
FiManager fiManager = paymentSdk.getFiManager();

// FiCustomFlags carries QuickChip mode and other behavioral settings
FiCustomFlags customFlags = new FiCustomFlags(
    "en",                       // language (ISO 639-1)
    FiMerchantDecision.ARQC,    // merchantDecision (offline decision; ARQC = go online)
    false,                      // displayCardDecision
    false,                      // displayPinTryExceeded
    true,                       // displayAmount
    true,                       // displayAppExp
    true,                       // msrFallback (allow MSR fallback for ICC)
    FiQuickChipMode.NON_QC,     // quickChip (NON_QC | QC | NON_QC_GEN_AC)
    false,                      // cashback
    false,                      // dcc
    false,                      // ctlsRequestArqc
    "Prompt",                   // cvv (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    "Prompt",                   // expiry (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    true,                       // expiryCheck (true = validate expiry date; false = skip)
    false,                      // luhnCheck (manual entry only)
    "*"                         // maskDisplay (manual entry only)
);

FiCardAcquisitionRequest request = new FiCardAcquisitionRequest(
    new ArrayList<>(Arrays.asList(  // forceEntryModes (at least one required)
        FiEntryMode.ICC,            // EMV Contact (chip)
        FiEntryMode.CTLS,           // Contactless (NFC/tap)
        FiEntryMode.MAG_STRIPE      // Magnetic stripe (swipe)
    )),
    "10.00",                        // totalAmount
    FiTransactionType.PURCHASE,     // transactionType
    "0.00",                         // amountOther (cashback or secondary amount)
    "0840",                         // currencyCode (ISO 4217 numeric, e.g. USD)
    "0840",                         // countryCode (ISO 3166-1 numeric, e.g. US)
    "260618",                       // transactionDate (YYMMDD)
    "120000",                       // transactionTime (HHMMSS)
    "00000001",                     // sequenceCounter (8-digit zero-padded)
    customFlags,                    // customFlags
    Arrays.asList(                  // displayPrompts (up to 4 lines)
        "Welcome",
        "Please Tap, Insert or Swipe Card"
    ),
    false,                          // cardRemovalPrompt
    false,                          // applicationSelectionCallbackEnable
    false,                          // unsolicitedNotification
    Arrays.asList(                  // requestedTags (EMV tags to return)
        "9F10", "9F26", "9F27", "9F36", "9F34"
    )
);

Status status = fiManager.requestFiCardAcquisition(request);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Send Card Acquisition request" lineNumbers="true" %}

```kotlin
// FI is available immediately after initialize() — no login or session needed
val fiManager = paymentSdk.getFiManager()

// FiCustomFlags carries QuickChip mode and other behavioral settings
val customFlags = FiCustomFlags(
    "en",                        // language (ISO 639-1)
    FiMerchantDecision.ARQC,     // merchantDecision (offline decision; ARQC = go online)
    false,                       // displayCardDecision
    false,                       // displayPinTryExceeded
    true,                        // displayAmount
    true,                        // displayAppExp
    true,                        // msrFallback (allow MSR fallback for ICC)
    FiQuickChipMode.NON_QC,      // quickChip (NON_QC | QC | NON_QC_GEN_AC)
    false,                       // cashback
    false,                       // dcc
    false,                       // ctlsRequestArqc
    "Prompt",                    // cvv (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    "Prompt",                    // expiry (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    true,                        // expiryCheck (true = validate expiry date; false = skip)
    false,                       // luhnCheck (manual entry only)
    "*"                          // maskDisplay (manual entry only)
)

val request = FiCardAcquisitionRequest(
    mutableListOf(               // forceEntryModes (at least one required)
        FiEntryMode.ICC,
        FiEntryMode.CTLS,
        FiEntryMode.MAG_STRIPE
    ),
    "10.00",                     // totalAmount
    FiTransactionType.PURCHASE,  // transactionType
    "0.00",                      // amountOther (cashback or secondary amount)
    "0840",                      // currencyCode (ISO 4217 numeric, e.g. USD)
    "0840",                      // countryCode (ISO 3166-1 numeric, e.g. US)
    "260618",                    // transactionDate (YYMMDD)
    "120000",                    // transactionTime (HHMMSS)
    "00000001",                  // sequenceCounter (8-digit zero-padded)
    customFlags,
    listOf(                      // displayPrompts (up to 4 lines)
        "Welcome",
        "Please Tap, Insert or Swipe Card"
    ),
    false,                       // cardRemovalPrompt
    false,                       // applicationSelectionCallbackEnable
    false,                       // unsolicitedNotification
    listOf("9F10", "9F26", "9F27", "9F36", "9F34")  // requestedTags
)

val status = fiManager.requestFiCardAcquisition(request)
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Send Card Acquisition request" lineNumbers="true" %}

```swift
// FI is available immediately after initialize() — no login or session needed
let fiManager = paymentSdk.getFiManager()

// FiCustomFlags carries QuickChip mode and other behavioral settings
let customFlags = FiCustomFlags(
    language: "en",
    merchantDecision: .arqc,
    displayCardDecision: false,
    displayPinTryExceeded: false,
    displayAmount: true,
    displayAppExp: true,
    msrFallback: true,
    quickChip: .nonQc,
    cashback: false,
    dcc: false,
    ctlsRequestArqc: false,
    cvv: "Prompt",              // Prompt | DoNotPrompt | AllowBypass
    expiry: "Prompt",           // Prompt | DoNotPrompt | AllowBypass
    expiryCheck: true,          // true = validate expiry date; false = skip
    luhnCheck: false,
    maskDisplay: "*"
)

let request = FiCardAcquisitionRequest(
    forceEntryModes: [.icc, .ctls, .magStripe],
    totalAmount: "10.00",
    transactionType: .purchase,
    amountOther: "0.00",
    currencyCode: "0840",
    countryCode: "0840",
    transactionDate: "260618",
    transactionTime: "120000",
    sequenceCounter: "00000001",
    customFlags: customFlags,
    displayPrompts: ["Welcome", "Please Tap, Insert or Swipe Card"],
    cardRemovalPrompt: false,
    applicationSelectionCallbackEnable: false,
    unsolicitedNotification: false,
    requestedTags: ["9F10", "9F26", "9F27", "9F36", "9F34"]
)

let status = fiManager.requestFiCardAcquisition(request)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Send Card Acquisition request" lineNumbers="true" %}

```csharp
// FI is available immediately after initialize() — no login or session needed
var fiManager = paymentSdk.GetFiManager();

// FiCustomFlags carries QuickChip mode and other behavioral settings
var customFlags = new FiCustomFlags(
    "en",                        // language (ISO 639-1)
    FiMerchantDecision.Arqc,     // merchantDecision (offline decision; Arqc = go online)
    false,                       // displayCardDecision
    false,                       // displayPinTryExceeded
    true,                        // displayAmount
    true,                        // displayAppExp
    true,                        // msrFallback (allow MSR fallback for ICC)
    FiQuickChipMode.NonQc,       // quickChip (NonQc | Qc | NonQcGenAc)
    false,                       // cashback
    false,                       // dcc
    false,                       // ctlsRequestArqc
    "Prompt",                    // cvv (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    "Prompt",                    // expiry (manual entry only: Prompt | DoNotPrompt | AllowBypass)
    true,                        // expiryCheck (true = validate expiry date; false = skip)
    false,                       // luhnCheck (manual entry only)
    "*"                          // maskDisplay (manual entry only)
);

var request = new FiCardAcquisitionRequest(
    new List<FiEntryMode> {      // forceEntryModes (at least one required)
        FiEntryMode.Icc,
        FiEntryMode.Ctls,
        FiEntryMode.MagStripe
    },
    "10.00",                     // totalAmount
    FiTransactionType.Purchase,  // transactionType
    "0.00",                      // amountOther
    "0840",                      // currencyCode (ISO 4217 numeric)
    "0840",                      // countryCode (ISO 3166-1 numeric)
    "260618",                    // transactionDate (YYMMDD)
    "120000",                    // transactionTime (HHMMSS)
    "00000001",                  // sequenceCounter (8-digit zero-padded)
    customFlags,
    new List<string> {           // displayPrompts (up to 4 lines)
        "Welcome",
        "Please Tap, Insert or Swipe Card"
    },
    false,                       // cardRemovalPrompt
    false,                       // applicationSelectionCallbackEnable
    false,                       // unsolicitedNotification
    new List<string> { "9F10", "9F26", "9F27", "9F36", "9F34" }  // requestedTags
);

var status = fiManager.RequestFiCardAcquisition(request);
```

{% endcode %}
{% endtab %}
{% endtabs %}

Once Card Acquisition is initiated, the terminal handles the cardholder interaction. Wait for the `handleFiCardAcquisitionResponseEvent` callback in your `CommerceListener2` implementation to receive the result.

The response contains the card data and entry mode. When `quickChipMode` is `QC` or `NON_QC_GEN_AC`, the response also includes `authenticationMethods` and, if applicable, an encrypted Online PIN block — the ARQC has already been generated and `requestFiFirstGenAC()` can be skipped.

{% tabs %}
{% tab title="Java" %}
{% code title="Handle Card Acquisition response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiCardAcquisitionResponseEvent(FiCardAcquisitionResponseEvent event) {
    FiCardAcquisitionResponse response = event.getFiCardAcquisitionResponse();
    if (response == null) {
        // Parse error — check event.getStatus() and event.getMessage()
        return;
    }

    FiCardData cardData = response.getFiCardData();

    // Check entry mode — First Gen AC and Second Gen AC are only available
    // for Contact EMV (chip). Not supported for swipe, tap, or keyed entry.
    String entryMode = cardData.getEntryMode();
    boolean isContactEmv = "ICC".equals(entryMode);

    // For QC / NON_QC_GEN_AC: authMethods and ARQC tags are already returned here.
    // Skip requestFiFirstGenAC() and proceed to host authorization.
    List<String> authMethods = response.getAuthenticationMethods();

    // Online PIN block — present when the cardholder entered a PIN
    Optional<FiOnlinePin> onlinePin = response.getFiOnlinePin();
    if (onlinePin.isPresent() && !onlinePin.get().getBypassed()) {
        // Forward these to your acquirer host for PIN verification
        String encryptedPinBlock = onlinePin.get().getEncryptedData();
        String ksn             = onlinePin.get().getKSN();
        FiPinBlockFormat format = onlinePin.get().getBlockFormat();
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle Card Acquisition response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiCardAcquisitionResponseEvent(event: FiCardAcquisitionResponseEvent) {
    val response = event.fiCardAcquisitionResponse
    if (response == null) {
        // Parse error — check event.status and event.message
        return
    }

    val cardData = response.fiCardData

    // Check entry mode — First Gen AC and Second Gen AC are only available
    // for Contact EMV (chip). Not supported for swipe, tap, or keyed entry.
    val entryMode = cardData.entryMode
    val isContactEmv = entryMode == "ICC"

    // For QC / NON_QC_GEN_AC: authMethods and ARQC tags are already returned here.
    // Skip requestFiFirstGenAC() and proceed to host authorization.
    val authMethods = response.authenticationMethods

    // Online PIN block — present when the cardholder entered a PIN
    val onlinePin = response.fiOnlinePin
    if (onlinePin != null && !onlinePin.bypassed) {
        // Forward these to your acquirer host for PIN verification
        val encryptedPinBlock = onlinePin.encryptedData
        val ksn = onlinePin.ksn
        val format = onlinePin.blockFormat
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle Card Acquisition response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiCardAcquisitionResponseEvent(_ event: FiCardAcquisitionResponseEvent) {
    guard let response = event.fiCardAcquisitionResponse else {
        // Parse error — check event.status and event.message
        return
    }

    let cardData = response.fiCardData

    // Check entry mode — First Gen AC and Second Gen AC are only available
    // for Contact EMV (chip). Not supported for swipe, tap, or keyed entry.
    let entryMode = cardData.entryMode
    let isContactEmv = entryMode == "ICC"

    // For QC / NON_QC_GEN_AC: authMethods and ARQC tags are already returned here.
    let authMethods = response.authenticationMethods

    // Online PIN block — present when the cardholder entered a PIN
    if let onlinePin = response.fiOnlinePin, !onlinePin.isBypassed {
        // Forward these to your acquirer host for PIN verification
        let encryptedPinBlock = onlinePin.encryptedData
        let ksn = onlinePin.ksn
        let format = onlinePin.blockFormat
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle Card Acquisition response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiCardAcquisitionResponseEvent(FiCardAcquisitionResponseEvent e) {
    var response = e.GetFiCardAcquisitionResponse();
    if (response == null) {
        // Parse error — check e.GetStatus() and e.GetMessage()
        return;
    }

    var cardData = response.GetFiCardData();

    // Check entry mode — First Gen AC and Second Gen AC are only available
    // for Contact EMV (chip). Not supported for swipe, tap, or keyed entry.
    string entryMode = cardData.GetEntryMode();
    bool isContactEmv = entryMode == "ICC";

    // For QC / NON_QC_GEN_AC: authMethods and ARQC tags are already returned here.
    var authMethods = response.GetAuthenticationMethods();

    // Online PIN block — present when the cardholder entered a PIN
    var onlinePin = response.GetFiOnlinePin();
    if (onlinePin != null && !onlinePin.GetBypassed()) {
        // Forward these to your acquirer host for PIN verification
        string encryptedPinBlock = onlinePin.GetEncryptedData();
        string ksn = onlinePin.GetKSN();
        FiPinBlockFormat format = onlinePin.GetBlockFormat();
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Online PIN:** When `getFiOnlinePin()` is present and `getBypassed()` is `false`, the cardholder entered their PIN. The encrypted PIN block must be forwarded to your acquirer host — it is never decrypted by PSDK or the POS.
{% endhint %}
{% endstep %}

{% step %}

## Step 2 — First Gen AC / ARQC (ICC only)

{% hint style="warning" %}
**Skip this step when:**

* `quickChipMode` was `QC` or `NON_QC_GEN_AC` — the ARQC is already included in the `FiCardAcquisitionResponse`.
* The card entry method is **not Contact EMV (chip)** — First Gen AC is not available for swipe, tap, or keyed entries.
  {% endhint %}

After a successful Contact EMV Card Acquisition using `NON_QC` mode, request First Gen AC to instruct the EMV kernel on the terminal to generate an Authorization Request Cryptogram (ARQC), which is then sent to the acquirer host for online authorization.

The POS specifies which EMV tags it wants the terminal to return in the response. The ARQC (`9F26`), Cryptogram Information Data (`9F27`), and ATC (`9F36`) are required for the host authorization request in the next step.

See [FiFirstGenACRequest](https://docs.verifone.com/psdk-api-latest/java/index/fifirstgenacrequest) in the API Reference for all request parameters.

{% tabs %}
{% tab title="Java" %}
{% code title="Send First Gen AC request" lineNumbers="true" %}

```java
// FiFirstGenACCustomFlags wraps the merchant decision and display options
FiFirstGenACCustomFlags customFlags = new FiFirstGenACCustomFlags(
    FiMerchantDecision.ARQC,    // merchantDecision (ARQC = request online auth)
    false,                       // displayCardDecision
    false                        // displayPinTryExceeded
);

FiFirstGenACRequest request = new FiFirstGenACRequest(
    FiTransactionType.PURCHASE,  // transactionType (must match Card Acquisition)
    "10.00",                     // totalAmount
    "0.00",                      // amountOther (cashback or secondary amount)
    customFlags,                 // customFlags
    false,                       // cardRemovalPrompt
    false,                       // unsolicitedNotification
    Arrays.asList(               // requestedTags (EMV tags to return)
        "9F10", "9F26", "9F27", "9F36", "9F34"
    )
);

Status status = fiManager.requestFiFirstGenAC(request);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Send First Gen AC request" lineNumbers="true" %}

```kotlin
// FiFirstGenACCustomFlags wraps the merchant decision and display options
val customFlags = FiFirstGenACCustomFlags(
    FiMerchantDecision.ARQC,    // merchantDecision (ARQC = request online auth)
    false,                       // displayCardDecision
    false                        // displayPinTryExceeded
)

val request = FiFirstGenACRequest(
    FiTransactionType.PURCHASE,  // transactionType (must match Card Acquisition)
    "10.00",                     // totalAmount
    "0.00",                      // amountOther (cashback or secondary amount)
    customFlags,
    false,                       // cardRemovalPrompt
    false,                       // unsolicitedNotification
    listOf("9F10", "9F26", "9F27", "9F36", "9F34")  // requestedTags
)

val status = fiManager.requestFiFirstGenAC(request)
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Send First Gen AC request" lineNumbers="true" %}

```swift
// FiFirstGenACCustomFlags wraps the merchant decision and display options
let customFlags = FiFirstGenACCustomFlags(
    merchantDecision: .arqc,
    displayCardDecision: false,
    displayPinTryExceeded: false
)

let request = FiFirstGenACRequest(
    transactionType: .purchase,
    totalAmount: "10.00",
    amountOther: "0.00",
    customFlags: customFlags,
    cardRemovalPrompt: false,
    unsolicitedNotification: false,
    requestedTags: ["9F10", "9F26", "9F27", "9F36", "9F34"]
)

let status = fiManager.requestFiFirstGenAC(request)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Send First Gen AC request" lineNumbers="true" %}

```csharp
// FiFirstGenACCustomFlags wraps the merchant decision and display options
var customFlags = new FiFirstGenACCustomFlags(
    FiMerchantDecision.Arqc,    // merchantDecision (Arqc = request online auth)
    false,                       // displayCardDecision
    false                        // displayPinTryExceeded
);

var request = new FiFirstGenACRequest(
    FiTransactionType.Purchase,  // transactionType (must match Card Acquisition)
    "10.00",                     // totalAmount
    "0.00",                      // amountOther
    customFlags,
    false,                       // cardRemovalPrompt
    false,                       // unsolicitedNotification
    new List<string> { "9F10", "9F26", "9F27", "9F36", "9F34" }  // requestedTags
);

var status = fiManager.RequestFiFirstGenAC(request);
```

{% endcode %}
{% endtab %}
{% endtabs %}

Handle the response in the `handleFiFirstGenACResponseEvent` callback. The EMV tags required for host authorization (DE55) are available in `Response.EmvTags`. If `quickChipMode` was `QC` or `NON_QC_GEN_AC`, these tags are instead available in `CardData.EmvTags` from the `handleFiCardAcquisitionResponseEvent` callback.

{% tabs %}
{% tab title="Java" %}
{% code title="Handle First Gen AC response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiFirstGenACResponseEvent(FiFirstGenACResponseEvent event) {
    if (event.getStatus() != StatusCode.SUCCESS) {
        // Handle failure — event.getMessage() contains the reason
        return;
    }

    FiFirstGenACResponse response = event.getFiFirstGenACResponse();
    Map<String, String> emvTags = response.getEmvTags();

    // Retrieve EMV tags required for DE55 host authorization request:
    String arqc   = emvTags.get("9F26"); // Application Cryptogram (ARQC)
    String cid    = emvTags.get("9F27"); // Cryptogram Information Data
    String iad    = emvTags.get("9F10"); // Issuer Application Data
    String un     = emvTags.get("9F37"); // Unpredictable Number
    String atc    = emvTags.get("9F36"); // Application Transaction Counter
    String aip    = emvTags.get("82");   // Application Interchange Profile
    String tvr    = emvTags.get("95");   // Terminal Verification Results
    String date   = emvTags.get("9A");   // Transaction Date
    String txnType= emvTags.get("9C");   // Transaction Type
    String amount = emvTags.get("9F02"); // Amount, Authorized
    String amtOth = emvTags.get("9F03"); // Amount, Other
    String currCd = emvTags.get("5F2A"); // Transaction Currency Code
    String cntyCd = emvTags.get("9F1A"); // Terminal Country Code
    String termCap= emvTags.get("9F33"); // Terminal Capabilities
    String termTyp= emvTags.get("9F35"); // Terminal Type
    String addCap = emvTags.get("9F40"); // Additional Terminal Capabilities
    String dfName = emvTags.get("84");   // Dedicated File Name (AID)
    String appVer = emvTags.get("9F09"); // Application Version Number
    String cvmRes = emvTags.get("9F34"); // CVM Results
    String aid    = emvTags.get("9F06"); // Application Identifier
    String txnSeq = emvTags.get("9F41"); // Transaction Sequence Counter
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle First Gen AC response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiFirstGenACResponseEvent(event: FiFirstGenACResponseEvent) {
    if (event.status != StatusCode.SUCCESS) {
        // Handle failure — event.message contains the reason
        return
    }

    val response = event.fiFirstGenACResponse
    val emvTags = response.emvTags

    // Retrieve EMV tags required for DE55 host authorization request:
    val arqc    = emvTags["9F26"] // Application Cryptogram (ARQC)
    val cid     = emvTags["9F27"] // Cryptogram Information Data
    val iad     = emvTags["9F10"] // Issuer Application Data
    val un      = emvTags["9F37"] // Unpredictable Number
    val atc     = emvTags["9F36"] // Application Transaction Counter
    val aip     = emvTags["82"]   // Application Interchange Profile
    val tvr     = emvTags["95"]   // Terminal Verification Results
    val date    = emvTags["9A"]   // Transaction Date
    val txnType = emvTags["9C"]   // Transaction Type
    val amount  = emvTags["9F02"] // Amount, Authorized
    val amtOth  = emvTags["9F03"] // Amount, Other
    val currCd  = emvTags["5F2A"] // Transaction Currency Code
    val cntyCd  = emvTags["9F1A"] // Terminal Country Code
    val termCap = emvTags["9F33"] // Terminal Capabilities
    val termTyp = emvTags["9F35"] // Terminal Type
    val addCap  = emvTags["9F40"] // Additional Terminal Capabilities
    val dfName  = emvTags["84"]   // Dedicated File Name (AID)
    val appVer  = emvTags["9F09"] // Application Version Number
    val cvmRes  = emvTags["9F34"] // CVM Results
    val aid     = emvTags["9F06"] // Application Identifier
    val txnSeq  = emvTags["9F41"] // Transaction Sequence Counter
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle First Gen AC response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiFirstGenACResponseEvent(_ event: FiFirstGenACResponseEvent) {
    guard event.status == .success else {
        // Handle failure — event.message contains the reason
        return
    }

    let response = event.fiFirstGenACResponse
    let emvTags = response.emvTags

    // Retrieve EMV tags required for DE55 host authorization request:
    let arqc    = emvTags["9F26"] // Application Cryptogram (ARQC)
    let cid     = emvTags["9F27"] // Cryptogram Information Data
    let iad     = emvTags["9F10"] // Issuer Application Data
    let un      = emvTags["9F37"] // Unpredictable Number
    let atc     = emvTags["9F36"] // Application Transaction Counter
    let aip     = emvTags["82"]   // Application Interchange Profile
    let tvr     = emvTags["95"]   // Terminal Verification Results
    let date    = emvTags["9A"]   // Transaction Date
    let txnType = emvTags["9C"]   // Transaction Type
    let amount  = emvTags["9F02"] // Amount, Authorized
    let amtOth  = emvTags["9F03"] // Amount, Other
    let currCd  = emvTags["5F2A"] // Transaction Currency Code
    let cntyCd  = emvTags["9F1A"] // Terminal Country Code
    let termCap = emvTags["9F33"] // Terminal Capabilities
    let termTyp = emvTags["9F35"] // Terminal Type
    let addCap  = emvTags["9F40"] // Additional Terminal Capabilities
    let dfName  = emvTags["84"]   // Dedicated File Name (AID)
    let appVer  = emvTags["9F09"] // Application Version Number
    let cvmRes  = emvTags["9F34"] // CVM Results
    let aid     = emvTags["9F06"] // Application Identifier
    let txnSeq  = emvTags["9F41"] // Transaction Sequence Counter
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle First Gen AC response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiFirstGenACResponseEvent(FiFirstGenACResponseEvent e) {
    if (e.GetStatus() != StatusCode.Success) {
        // Handle failure — e.GetMessage() contains the reason
        return;
    }

    var response = e.GetFiFirstGenACResponse();
    var emvTags = response.GetEmvTags();

    // Retrieve EMV tags required for DE55 host authorization request:
    string arqc    = emvTags["9F26"]; // Application Cryptogram (ARQC)
    string cid     = emvTags["9F27"]; // Cryptogram Information Data
    string iad     = emvTags["9F10"]; // Issuer Application Data
    string un      = emvTags["9F37"]; // Unpredictable Number
    string atc     = emvTags["9F36"]; // Application Transaction Counter
    string aip     = emvTags["82"];   // Application Interchange Profile
    string tvr     = emvTags["95"];   // Terminal Verification Results
    string date    = emvTags["9A"];   // Transaction Date
    string txnType = emvTags["9C"];   // Transaction Type
    string amount  = emvTags["9F02"]; // Amount, Authorized
    string amtOth  = emvTags["9F03"]; // Amount, Other
    string currCd  = emvTags["5F2A"]; // Transaction Currency Code
    string cntyCd  = emvTags["9F1A"]; // Terminal Country Code
    string termCap = emvTags["9F33"]; // Terminal Capabilities
    string termTyp = emvTags["9F35"]; // Terminal Type
    string addCap  = emvTags["9F40"]; // Additional Terminal Capabilities
    string dfName  = emvTags["84"];   // Dedicated File Name (AID)
    string appVer  = emvTags["9F09"]; // Application Version Number
    string cvmRes  = emvTags["9F34"]; // CVM Results
    string aid     = emvTags["9F06"]; // Application Identifier
    string txnSeq  = emvTags["9F41"]; // Transaction Sequence Counter
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
**EMV Tags for DE55 Host Authorization Request**

The following tags are typically required by the acquirer host in the DE55 field of the ISO 8583 authorization request. Request these tags in `requestedTags` on `FiFirstGenACRequest` (or `FiCardAcquisitionRequest` when using `QC` / `NON_QC_GEN_AC` mode) and retrieve them from `Response.EmvTags` in `handleFiFirstGenACResponseEvent`, or from `CardData.EmvTags` in `handleFiCardAcquisitionResponseEvent` when steps are combined.
{% endhint %}

| Tag           | Name                                  | Notes                                            |
| ------------- | ------------------------------------- | ------------------------------------------------ |
| `9F26`        | Application Cryptogram (ARQC)         | Mandatory                                        |
| `9F27`        | Cryptogram Information Data           | Mandatory                                        |
| `9F10`        | Issuer Application Data               | Mandatory                                        |
| `9F37`        | Unpredictable Number                  | Mandatory                                        |
| `9F36`        | Application Transaction Counter (ATC) | Mandatory                                        |
| `82`          | Application Interchange Profile (AIP) | Mandatory                                        |
| `95`          | Terminal Verification Results (TVR)   | Mandatory                                        |
| `9A`          | Transaction Date                      | Mandatory                                        |
| `9C`          | Transaction Type                      | Mandatory                                        |
| `9F02`        | Amount, Authorized                    | Mandatory                                        |
| `9F03`        | Amount, Other                         | Mandatory (cashback; `000000000000` if not used) |
| `5F2A`        | Transaction Currency Code             | Mandatory                                        |
| `9F1A`        | Terminal Country Code                 | Mandatory                                        |
| `9F33`        | Terminal Capabilities                 | Mandatory                                        |
| `9F35`        | Terminal Type                         | Mandatory                                        |
| `9F40`        | Additional Terminal Capabilities      | Mandatory                                        |
| `84`          | Dedicated File Name (AID)             | Mandatory                                        |
| `9F09`        | Application Version Number            | Mandatory                                        |
| `9F34`        | CVM Results                           | Mandatory                                        |
| `9F06`        | Application Identifier (AID)          | Mandatory                                        |
| `9F41`        | Transaction Sequence Counter          | Mandatory                                        |
| `9B`          | Transaction Status Information        | Conditional — some acquirers                     |
| `9F53`        | Transaction Category Code             | Conditional — contactless (Visa)                 |
| `9F6E`        | Third Party Data                      | Conditional — contactless                        |
| `9F0D`        | Issuer Action Code — Default          | Conditional — some acquirers                     |
| `9F0E`        | Issuer Action Code — Denial           | Conditional — some acquirers                     |
| `9F0F`        | Issuer Action Code — Online           | Conditional — some acquirers                     |
| {% endstep %} |                                       |                                                  |

{% step %}

## Step 3 — Host Authorization (all entry methods)

After receiving the ARQC from First Gen AC (or from Card Acquisition when using `QC` / `NON_QC_GEN_AC` mode), the POS is responsible for sending an authorization request to its acquirer host and waiting for the response. PSDK is not involved in this step.

For **ICC / CTLS**, include the ARQC and associated EMV tags from First Gen AC (or the Card Acquisition response for QC modes). For **MSR / Manual**, include the encrypted card data from the Card Acquisition response.

The host response provides the following fields needed for Second Gen AC:

| Field                     | Description                                                          |
| ------------------------- | -------------------------------------------------------------------- |
| `AuthResponseCode`        | `"3030"` = approved (EMV tag 8A, 4 chars), other = declined/referred |
| `IssuerAuthData` (tag 91) | Issuer authentication data for ARPC verification on terminal         |
| `IssuerScript71`          | Issuer script executed **before** Second Gen AC (optional)           |
| `IssuerScript72`          | Issuer script executed **after** Second Gen AC (optional)            |

Once you have the host response, proceed to Second Gen AC to complete the EMV transaction on the terminal for ICC card entry.
{% endstep %}

{% step %}

## Step 4 — Second Gen AC / TC or AAC (ICC only)

{% hint style="warning" %}
**ICC only.** Do not call this for MSR, CTLS, or Manual entry modes.
{% endhint %}

Second Gen AC is the final step of the EMV transaction. The POS passes the host authorization result back to the terminal, which generates a Transaction Certificate (TC = approved) or Application Authentication Cryptogram (AAC = declined).

Set `merchantDecision` to `TC` when the host approves, and `AAC` when the host declines or the POS decides to decline locally.

See [FiSecondGenACRequest](https://docs.verifone.com/psdk-api-latest/java/index/fisecondgenacrequest) in the API Reference for all request parameters.

{% tabs %}
{% tab title="Java" %}
{% code title="Send Second Gen AC request" lineNumbers="true" %}

```java
// FiSecondGenACHostData carries the host authorization result
FiSecondGenACHostData hostData = new FiSecondGenACHostData(
    "3030",                  // authResponseCode (EMV tag 8A, 4 chars; "3030" = approved)
    "0000000000000000",      // issuerAuthData (EMV tag 91, hex-encoded)
    "",                      // issuerScript71 (tag 71, empty if not provided by host)
    ""                       // issuerScript72 (tag 72, empty if not provided by host)
);

// FiSecondGenACCustomFlags carries the merchant decision and display options
FiSecondGenACCustomFlags customFlags = new FiSecondGenACCustomFlags(
    FiMerchantDecision.TC,   // merchantDecision (TC = approved, AAC = declined)
    true                     // displayCardDecision (show result on terminal)
);

FiSecondGenACRequest request = new FiSecondGenACRequest(
    hostData,                // hostData
    customFlags,             // customFlags
    true,                    // cardRemovalPrompt
    Arrays.asList(           // requestedTags (final EMV tags to return)
        "9F10", "9F26", "9F27", "9F34", "9F36"
    )
);

Status status = fiManager.requestFiSecondGenAC(request);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Send Second Gen AC request" lineNumbers="true" %}

```kotlin
// FiSecondGenACHostData carries the host authorization result
val hostData = FiSecondGenACHostData(
    "3030",                  // authResponseCode (EMV tag 8A, 4 chars; "3030" = approved)
    "0000000000000000",      // issuerAuthData (EMV tag 91, hex-encoded)
    "",                      // issuerScript71 (tag 71, empty if not provided by host)
    ""                       // issuerScript72 (tag 72, empty if not provided by host)
)

// FiSecondGenACCustomFlags carries the merchant decision and display options
val customFlags = FiSecondGenACCustomFlags(
    FiMerchantDecision.TC,   // merchantDecision (TC = approved, AAC = declined)
    true                     // displayCardDecision (show result on terminal)
)

val request = FiSecondGenACRequest(
    hostData,
    customFlags,
    true,                    // cardRemovalPrompt
    listOf("9F10", "9F26", "9F27", "9F34", "9F36")  // requestedTags
)

val status = fiManager.requestFiSecondGenAC(request)
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Send Second Gen AC request" lineNumbers="true" %}

```swift
// FiSecondGenACHostData carries the host authorization result
let hostData = FiSecondGenACHostData(
    authResponseCode: "3030",
    issuerAuthData: "0000000000000000",
    issuerScript71: "",
    issuerScript72: ""
)

// FiSecondGenACCustomFlags carries the merchant decision and display options
let customFlags = FiSecondGenACCustomFlags(
    merchantDecision: .tc,
    displayCardDecision: true
)

let request = FiSecondGenACRequest(
    hostData: hostData,
    customFlags: customFlags,
    cardRemovalPrompt: true,
    requestedTags: ["9F10", "9F26", "9F27", "9F34", "9F36"]
)

let status = fiManager.requestFiSecondGenAC(request)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Send Second Gen AC request" lineNumbers="true" %}

```csharp
// FiSecondGenACHostData carries the host authorization result
var hostData = new FiSecondGenACHostData(
    "3030",                  // authResponseCode (EMV tag 8A, 4 chars; "3030" = approved)
    "0000000000000000",      // issuerAuthData (EMV tag 91, hex-encoded)
    "",                      // issuerScript71
    ""                       // issuerScript72
);

// FiSecondGenACCustomFlags carries the merchant decision and display options
var customFlags = new FiSecondGenACCustomFlags(
    FiMerchantDecision.Tc,   // merchantDecision (Tc = approved, Aac = declined)
    true                     // displayCardDecision
);

var request = new FiSecondGenACRequest(
    hostData,
    customFlags,
    true,                    // cardRemovalPrompt
    new List<string> { "9F10", "9F26", "9F27", "9F34", "9F36" }
);

var status = fiManager.RequestFiSecondGenAC(request);
```

{% endcode %}
{% endtab %}
{% endtabs %}

Handle the final result in the `handleFiSecondGenACResponseEvent` callback. The returned EMV tags should be stored with your transaction record.

{% tabs %}
{% tab title="Java" %}
{% code title="Handle Second Gen AC response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiSecondGenACResponseEvent(FiSecondGenACResponseEvent event) {
    if (event.getStatus() != StatusCode.SUCCESS) {
        // Handle failure — event.getMessage() contains the reason
        return;
    }

    // Transaction is complete. Store the returned EMV tags with your transaction record.
    // Key tags:
    //   9F26  TC/AAC cryptogram
    //   9F27  Cryptogram Information Data (confirms TC vs AAC)
    //   9F34  CVM Results
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle Second Gen AC response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiSecondGenACResponseEvent(event: FiSecondGenACResponseEvent) {
    if (event.status != StatusCode.SUCCESS) {
        // Handle failure — event.message contains the reason
        return
    }

    // Transaction is complete. Store the returned EMV tags with your transaction record.
    // Key tags:
    //   9F26  TC/AAC cryptogram
    //   9F27  Cryptogram Information Data (confirms TC vs AAC)
    //   9F34  CVM Results
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle Second Gen AC response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiSecondGenACResponseEvent(_ event: FiSecondGenACResponseEvent) {
    guard event.status == .success else {
        // Handle failure — event.message contains the reason
        return
    }

    // Transaction is complete. Store the returned EMV tags with your transaction record.
    // Key tags:
    //   9F26  TC/AAC cryptogram
    //   9F27  Cryptogram Information Data (confirms TC vs AAC)
    //   9F34  CVM Results
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle Second Gen AC response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiSecondGenACResponseEvent(FiSecondGenACResponseEvent e) {
    if (e.GetStatus() != StatusCode.Success) {
        // Handle failure — e.GetMessage() contains the reason
        return;
    }

    // Transaction is complete. Store the returned EMV tags with your transaction record.
    // Key tags:
    //   9F26  TC/AAC cryptogram
    //   9F27  Cryptogram Information Data (confirms TC vs AAC)
    //   9F34  CVM Results
}
```

{% endcode %}
{% endtab %}
{% endtabs %}
{% endstep %}
{% endstepper %}

***

## Utility Operations

The FI API provides additional operations that can be used at any point during the transaction flow.

### Check Card Present Status

Use `requestFiCardPresentStatus()` to verify the card is still on the reader before proceeding to the next step. This is particularly useful between First Gen AC and Second Gen AC while waiting for the host response.

{% tabs %}
{% tab title="Java" %}
{% code title="Check card present status" lineNumbers="true" %}

```java
FiCardPresentStatusRequest request = new FiCardPresentStatusRequest(
    30,                                         // timeOut (seconds, 1–3600)
    false,                                      // cardRemoveRequest
    false,                                      // waitForCardRemoval
    Arrays.asList("Please keep card on reader") // messages (max 2 entries)
);

fiManager.requestFiCardPresentStatus(request);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Check card present status" lineNumbers="true" %}

```kotlin
val request = FiCardPresentStatusRequest(
    30,                                          // timeOut (seconds, 1–3600)
    false,                                       // cardRemoveRequest
    false,                                       // waitForCardRemoval
    listOf("Please keep card on reader")         // messages (max 2 entries)
)

fiManager.requestFiCardPresentStatus(request)
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Check card present status" lineNumbers="true" %}

```swift
let request = FiCardPresentStatusRequest(
    timeOut: 30,
    cardRemoveRequest: false,
    waitForCardRemoval: false,
    messages: ["Please keep card on reader"]
)

fiManager.requestFiCardPresentStatus(request)
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Check card present status" lineNumbers="true" %}

```csharp
var request = new FiCardPresentStatusRequest(
    30,                                          // timeOut (seconds, 1–3600)
    false,                                       // cardRemoveRequest
    false,                                       // waitForCardRemoval
    new List<string> { "Please keep card on reader" }  // messages (max 2 entries)
);

fiManager.RequestFiCardPresentStatus(request);
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Java" %}
{% code title="Handle Card Present Status response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiCardPresentStatusResponseEvent(FiCardPresentStatusResponseEvent event) {
    // StatusCode.SUCCESS = card is present and ready
    if (event.getStatus() != StatusCode.SUCCESS) {
        // Card removed — abort or notify the operator
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle Card Present Status response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiCardPresentStatusResponseEvent(event: FiCardPresentStatusResponseEvent) {
    // StatusCode.SUCCESS = card is present and ready
    if (event.status != StatusCode.SUCCESS) {
        // Card removed — abort or notify the operator
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle Card Present Status response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiCardPresentStatusResponseEvent(_ event: FiCardPresentStatusResponseEvent) {
    // .success = card is present and ready
    if event.status != .success {
        // Card removed — abort or notify the operator
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle Card Present Status response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiCardPresentStatusResponseEvent(FiCardPresentStatusResponseEvent e) {
    // StatusCode.Success = card is present and ready
    if (e.GetStatus() != StatusCode.Success) {
        // Card removed — abort or notify the operator
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Read EMV Tags (ICC / CTLS)

{% hint style="danger" %}
**Not yet available.** This feature is planned for a future phase.
{% endhint %}

Use `requestFiGetEMVTags()` to read specific EMV tags from the card kernel at any point during the transaction.

{% tabs %}
{% tab title="Java" %}
{% code title="Read EMV tags" lineNumbers="true" %}

```java
fiManager.requestFiGetEMVTags(new FiGetEMVTagsRequest(
    Arrays.asList(
        "9F26", "9F27", "9F10", "9F34", "9F36", "9F37",
        "9F02", "9F03", "9F1A", "9F33", "9F35", "9F40",
        "95", "9B", "9C", "5F2A", "82", "84", "9F06", "9F09"
    )
));
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Read EMV tags" lineNumbers="true" %}

```kotlin
fiManager.requestFiGetEMVTags(FiGetEMVTagsRequest(
    listOf(
        "9F26", "9F27", "9F10", "9F34", "9F36", "9F37",
        "9F02", "9F03", "9F1A", "9F33", "9F35", "9F40",
        "95", "9B", "9C", "5F2A", "82", "84", "9F06", "9F09"
    )
))
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Read EMV tags" lineNumbers="true" %}

```swift
fiManager.requestFiGetEMVTags(FiGetEMVTagsRequest(
    tags: [
        "9F26", "9F27", "9F10", "9F34", "9F36", "9F37",
        "9F02", "9F03", "9F1A", "9F33", "9F35", "9F40",
        "95", "9B", "9C", "5F2A", "82", "84", "9F06", "9F09"
    ]
))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Read EMV tags" lineNumbers="true" %}

```csharp
fiManager.RequestFiGetEMVTags(new FiGetEMVTagsRequest(
    new List<string> {
        "9F26", "9F27", "9F10", "9F34", "9F36", "9F37",
        "9F02", "9F03", "9F1A", "9F33", "9F35", "9F40",
        "95", "9B", "9C", "5F2A", "82", "84", "9F06", "9F09"
    }
));
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Java" %}
{% code title="Handle Get EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiGetEMVTagsResponseEvent(FiGetEMVTagsResponseEvent event) {
    if (event.getStatus() != StatusCode.SUCCESS) {
        return;
    }
    // Map of tag hex string → tag value hex string
    Map<String, String> tags = event.getFiGetEMVTagsResponse().getEmvTags();
    String arqc = tags.get("9F26");
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle Get EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiGetEMVTagsResponseEvent(event: FiGetEMVTagsResponseEvent) {
    if (event.status != StatusCode.SUCCESS) {
        return
    }
    // Map of tag hex string → tag value hex string
    val tags = event.fiGetEMVTagsResponse.emvTags
    val arqc = tags["9F26"]
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle Get EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiGetEMVTagsResponseEvent(_ event: FiGetEMVTagsResponseEvent) {
    guard event.status == .success else { return }
    // Dictionary of tag hex string → tag value hex string
    let tags = event.fiGetEMVTagsResponse.emvTags
    let arqc = tags["9F26"]
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle Get EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiGetEMVTagsResponseEvent(FiGetEMVTagsResponseEvent e) {
    if (e.GetStatus() != StatusCode.Success) {
        return;
    }
    // Dictionary of tag hex string → tag value hex string
    var tags = e.GetFiGetEMVTagsResponse().GetEmvTags();
    string arqc = tags["9F26"];
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Write EMV Tags (ICC / CTLS)

{% hint style="danger" %}
**Not yet available.** This feature is planned for a future phase.
{% endhint %}

Use `requestFiSetEMVTags()` to set tags in the card kernel before Gen AC to inject transaction data.

{% tabs %}
{% tab title="Java" %}
{% code title="Write EMV tags" lineNumbers="true" %}

```java
fiManager.requestFiSetEMVTags(new FiSetEMVTagsRequest(
    Map.of(
        "9C",    "00",           // transaction type
        "9F02",  "000000001000"  // authorised amount
    )
));
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Write EMV tags" lineNumbers="true" %}

```kotlin
fiManager.requestFiSetEMVTags(FiSetEMVTagsRequest(
    mapOf(
        "9C"   to "00",           // transaction type
        "9F02" to "000000001000"  // authorised amount
    )
))
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Write EMV tags" lineNumbers="true" %}

```swift
fiManager.requestFiSetEMVTags(FiSetEMVTagsRequest(
    tags: [
        "9C":    "00",           // transaction type
        "9F02":  "000000001000"  // authorised amount
    ]
))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Write EMV tags" lineNumbers="true" %}

```csharp
fiManager.RequestFiSetEMVTags(new FiSetEMVTagsRequest(
    new Dictionary<string, string> {
        { "9C",    "00" },           // transaction type
        { "9F02",  "000000001000" }  // authorised amount
    }
));
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Java" %}
{% code title="Handle Set EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```java
@Override
public void handleFiSetEMVTagsResponseEvent(FiSetEMVTagsResponseEvent event) {
    if (event.getStatus() != StatusCode.SUCCESS) {
        // Tag write failed — check event.getMessage()
    }
    // Tags written successfully — proceed with Gen AC
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Handle Set EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```kotlin
override fun handleFiSetEMVTagsResponseEvent(event: FiSetEMVTagsResponseEvent) {
    if (event.status != StatusCode.SUCCESS) {
        // Tag write failed — check event.message
    }
    // Tags written successfully — proceed with Gen AC
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Handle Set EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```swift
func handleFiSetEMVTagsResponseEvent(_ event: FiSetEMVTagsResponseEvent) {
    if event.status != .success {
        // Tag write failed — check event.message
    }
    // Tags written successfully — proceed with Gen AC
}
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Handle Set EMV Tags response (CommerceListener2)" lineNumbers="true" %}

```csharp
public void HandleFiSetEMVTagsResponseEvent(FiSetEMVTagsResponseEvent e) {
    if (e.GetStatus() != StatusCode.Success) {
        // Tag write failed — check e.GetMessage()
    }
    // Tags written successfully — proceed with Gen AC
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Abort

Cancel any in-flight FI operation.

{% tabs %}
{% tab title="Java" %}
{% code title="Abort FI operation" lineNumbers="true" %}

```java
fiManager.requestFiAbort(new FiAbortRequest(true /* clearDisplay */));
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code title="Abort FI operation" lineNumbers="true" %}

```kotlin
fiManager.requestFiAbort(FiAbortRequest(true /* clearDisplay */))
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}
{% code title="Abort FI operation" lineNumbers="true" %}

```swift
fiManager.requestFiAbort(FiAbortRequest(clearDisplay: true))
```

{% endcode %}
{% endtab %}

{% tab title="C#" %}
{% code title="Abort FI operation" lineNumbers="true" %}

```csharp
fiManager.RequestFiAbort(new FiAbortRequest(true /* clearDisplay */));
```

{% endcode %}
{% endtab %}
{% endtabs %}

***

## Error Handling

All FI response events carry a status code accessible via `event.getStatus()`.

| Condition                                   | Behaviour                                                                  |
| ------------------------------------------- | -------------------------------------------------------------------------- |
| Parse failure (malformed terminal response) | `getFiCardAcquisitionResponse()` returns `null`; status is `GENERAL_ERROR` |
| Terminal declines card                      | Status reflects decline code; response may still be populated              |
| In-flight operation aborted                 | Response event fires with abort status                                     |

{% hint style="danger" %}
Always null-check the response payload before accessing card data:

```java
FiCardAcquisitionResponse response = event.getFiCardAcquisitionResponse();
if (response == null) {
    Log.e(TAG, "FI error: " + event.getStatus() + " — " + event.getMessage().orElse("no message"));
    return;
}
```

{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.verifone.com/psdk-latest/reference-material/code-labs/fi-payments.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
