# Callback mode

> Learn how to integrate Electronic Data Capture (EDC) devices with the Antom SDK in Callback mode.

Electronic Data Capture (EDC) devices are widely used in various retail and service industries, especially in restaurants, supermarkets, and convenience stores. This document outlines how to enable EDC terminals to support event code callback mode through Antom SDK integration, allowing buyers to independently complete the payment efficiently and securely.

# Integration steps

1.  Obtain the device
2.  Install the EasyCard App and EZ Control App
3.  Integrate SDK package
4.  Instantiate the SDK
5.  Send commands to the device

## Step 1: Obtain the device

To obtain the device, please contact Antom business support for detailed information.

## Step 2: Install the EasyCard App and EZ Control App

Please contact Antom business support for the installation instructions of the EasyCard App and EZ Control App. After acquiring the equipment and completing the configuration, you can follow the following steps to complete the SDK integration.

## Step 3: Integrate the SDK package

Version requirements:

-   Android 8.1 (API level 27) or later.
-   Java 1.8 or later.

Please follow the steps below to integrate the SDK package with Maven.

1.  Add the Maven repository:

Add the Maven repository to your root _build.gradle_ file using the code snippet below.

```groovy
// Add maven repository
maven {
    credentials {
        username "antomsdk@aliyun.com"
        password "Admin1234"
    }
    url "https://globaltech.alipay.com/api/v1/file/repository/antom/"
}
```

2.  Add dependencies:

Add the dependencies in the _build.gradle_ file using the code snippet below.

```groovy
// in app build.gradle
// if there are some conflicts with existing sdk, please exclude them
dependencies {
    implementation 'com.alipay.antom.sdk:instore-core:${antom_version}'
    implementation 'com.alipay.antom.sdk:instore-edc-cmd:1.1.0'
    implementation 'com.alipay.antom.sdk:foundation-jsengine:1.0.0'
}
```

Externalize the dependency version in the _build.gradle_ file to easily manage upgrades with the "Externalize dependency version" code snippet. Replace the value of `ANTOM_VERSION` with the latest version 1.25.0.

```groovy
ext {
    antom_version = 'ANTOM_VERSION'
}
```

## Step 4: Instantiate the SDK

It is recommended to call the **init** API for global initialization at application startup to ensure that the device can respond quickly.

Create an SDK instance using `AMSEDCGlobalConfiguration` and specify basic configurations. Creating a configuration object includes the following methods:

| **Parameter name** | **Type** | **Required** | **Description** |
| --- | --- | --- | --- |
| _options_ | Map | Yes | Reserved for extension parameter information. It includes the following parameters: - _merchantId_: The merchant's ID number. Required. String type. |
| _initCallback_ | InitCallback | Yes | Initialization callback function. It includes the following parameters: - _eventCode_: The relevant result code. String type. - _result_: Specific message about the result. String type. |
| _EDCProvider_ | String | Yes | The type of the connected device. |
| _useBuiltInDialog_ | Boolean | Yes | The built-in dialog feature, where the default value is `true`. To use the event code callback mode, this value must be `false`, and you need to render the card reading process based on the event code returned by `EDCServiceEvent`. |

Call the `InitCallback` to receive the `onInitResult` callback event. The following example code shows how to handle the `onInitResult` callback event:

```java
void onInitResult(String code, String result)
```

The following example code shows how to instantiate the SDK:

```java
AMSEDCGlobalConfiguration globalConfiguration = new AMSEDCGlobalConfiguration()
globalConfiguration.setEDCProvider("KICC");
globalConfiguration.setOption("useBuiltInDialog", false);
globalConfiguration.setOption("merchantId","xxxxxxx");
globalConfiguration.setInitCallback(new AMSEDCInitCallback() {
    @Override
    public void onInitResult(String code, String message) {
        if("INIT_SUCCESS".equals(code)){

        }
    }
});
AMSEDCPayment.init(this.getApplicationContext(), globalConfiguration);
AMSEDCPayment.init(getContext(), globalConfiguration);
```

### Register UI events

The following code demonstrates how to register UI events in `AMSEDCPayment` to ensure proper handling of device status updates and user interactions.

```java
AMSEDCPayment amsEDCPayment = new AMSEDCPayment();

DeviceCommandRequest deviceCommandRequest = new KICCCommandRequest();
deviceCommandRequest.setCommandName(commandName);
deviceCommandRequest.setCommandRequestParams(requestParams);
KICCCommandCallback callback = new KICCCommandCallback() {
    @Override
    public void onSuccess(CommandResult result) {
        // On success logic
    }

    @Override
    public void onCommandFailed(CommandFailInfo commandFailInfo) {
        // Command failed logic
    }

    @Override
    public void onBusinessFailed(CommandResult result) {
        // stop countdown if any, might need to close dialog.
        stopCountdown();
        // Business failed logic
    }
};

amsEDCPayment.setEDCServiceListener(new EDCServiceListener() { // Register listener
    @Override
    public void onEvent(EDCServiceEvent edcServiceEvent) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                switch (edcServiceEvent.getCode) {
                    case "READY":
                        // Handle READY, show dialog.
                        // Start countdown based on paymentExpiryTime
                        startCountdown(paymentExpiryTime);
                        break;
                    case "PENDING_SIGNATURE":
                        // Start countdown for signature signing, 20s
                        stopCountdown();
                        startCountdown(20);
                        break;
                    case "START_TRANSACTION":
                        // Stop countdown
                        stopCountdown();
                        // Render dialog content
                        break;
                        // Might need to handle other cases based on use cases.
                    default:
                        break;
                }
            }
        });
    }
});

amsEDCPayment.sendCommand(getContext(), deviceCommandRequest, callback);

```

The table below shows the event codes that `EDCServiceEvent` may return:

| **Event Code** | **Description** |
| --- | --- |
| READY | Device is ready for card insertion. (Start countdown) |
| CARD\_DETECTED | Card insertion was detected. |
| CARD\_READ\_COMPLETED | Card reading process has completed. |
| PENDING\_SIGNATURE | Waiting for signature. (Restart countdown, timeout in 20 seconds) |
| START\_TRANSACTION | Payment in progress. (Card reading completed, stopping countdown) |
| CANCELLING | Device communication is being cancelled. |
| FALLBACK\_MAGCARDREADER | Card swipe failed, please insert a card. |
| REQUIRE\_CARD\_INSERT | Please use an IC card for transaction. |
| CARD\_TRY\_AGAIN | Please try reading the card again. |
| CARD\_MISSING | Card was not detected. |
| DEVICE\_INITIALIZE | Initializing the device. |

## Step 5: Send commands to the device

Call the **sendCommand** API to send commands and data to the specified EDC device, such as `commandName=xxxx`. For specific command implementations, please refer to [Device commands](#DzE4J).

After sending the `KICCCommandRequest` to the device, you will receive a `KICCCommandCallback` response. Sending the `KICCCommandRequest` involves the following parameters:

| **Parameter name** | **Type** | **Required** | **Description** |
| --- | --- | --- | --- |
| _commandName_ | String | Yes | The command name. Valid commands include: - **Purchase** - **PurchaseCancel** - **CashReceipt** - **CashReceiptCancel** - **GetLastTransaction** - **CommandCancel** |
| _commandRequestParams_ | JSONObject | No | Command request parameters. |
| _options_ | Map<String, String> | No | Reserved for extension parameters. |

The following code shows an example of a `KICCCommandCallback` response. It contains the following parameters:

-   _CommandResult_: The command result. It contains the following parameter:

-   _responseData_: The returned result. JSONObject type.

-   _onCommandFailed_: The device command execution failed.
-   _onBusinessFailed_: The business processing failed.

```java
KICCCommandCallback callback = new KICCCommandCallback() {
    @Override
    public void onSuccess(CommandResult result) {
        // On success logic
    }

    @Override
    public void onCommandFailed(CommandFailInfo commandFailInfo) {
        // Command failed logic
    }

    @Override
    public void onBusinessFailed(CommandResult result) {
        // Business failed logic
    }
};
mAMSEDCPayment.sendCommand(this, requestJson, callback);
```

> **Note**: If `onSuccess` is returned after sending the `CommandCancel` command, make sure to cancel the timer if a card reading countdown has been activated.

The following code shows an example of _responseData_:

```json
{
  "requestId": "123456XXXX",
  "paymentAmount": {
    "value": "$TOTAL_AMOUNT",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "$TAX",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "$TIP",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum": "0"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "XXX"
  },
  "acquirerInfo": {
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerMerchantId": "$SHOP_TIDMERCHANT_NUM",
    "acquirerApprovalNum": "$APPROVAL_NUM",
    "acquirerName": "KICC",
    "notice": "               매입사제출테스트 거래임",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  },
  "paymentResultInfo": {
    "cardBin": "52364979",
    "paymentMethodId": "",
    "issuerCode": "$CARD_NAME",
    "funding": "DEBIT/CREDIT/PREPAID",
    "paymentMethodRegion": "KR",
    "paymentMethodType": "CARD/KAKAOPAY/WECHATPAY/ALIPAY_CN/SAMSUNGPAY"
  }
}
```

The following code shows an example of _onBusinessFailed_:

```json
{
  "requestId": "c9d707ee-639d-4bf2-9a43-cc36c0a3beac",
  "result": {
    "resultCode": "PROCESS_FAIL",
    "resultMessage": "Please check network"
  },
  "acquirerInfo": {}
}
```

### Timeout

The default timeout settings for each command are as follows.

| **Command** | **Default value (seconds)** |
| --- | --- |
| **Purchase** | 95 (Require signature if the amount exceeds 50,000 KRW, and its default value is 115) > **Note**: If you need to customize the timeout setting for the **Purchase** command, ensure that it is not less than the default value. |
| **PurchaseCancel** | 85 |
| **GetLastTransaction** | 5 |
| **CommandCancel** | 5 |

### Sample code for calling the sendCommand API

```java
KICCCommandRequest deviceCommandRequest = new KICCCommandRequest();
deviceCommandRequest.setCommandName("Purchase");
deviceCommandRequest.setCommandRequestParams(new JSONObject("{\n" +
                "  \"requestId\": \"123456XXXX\",\n" +
                "  \"paymentAmount\": {\n" +
                "    \"value\": \"104\",\n" +
                "    \"currency\": \"KRW\"\n" +
                "  },\n" +
                "  \"taxAmount\": {\n" +
                "    \"value\": \"9\",\n" +
                "    \"currency\": \"KRW\"\n" +
                "  },\n" +
                "  \"tipAmount\": {\n" +
                "    \"value\": \"0\",\n" +
                "    \"currency\": \"KRW\"\n" +
                "  },\n" +
                "  \"creditPayPlan\": {\n" +
                "    \"installmentNum\": \"0\"\n" +
                "  },\n" +
                "  \"paymentExpiryTime\": \"30\",\n" +
                "  \"acquirerInfo\": {\n" +
                "    \"acquirerTerminalId\": \"0788888\",\n" +
                "    \"acquirerRegistrationNo\": \"0216001234\"\n" +
                "  }\n" +
                "}"));
KICCCommandCallback callback = new KICCCommandCallback() {
    @Override
    public void onSuccess(CommandResult result) {
        JSONObject responseData = result.getResponseData();
        Log.d(TAG, "onSuccess responseData: " + responseData);
    }

    @Override
    public void onCommandFailed(CommandFailInfo commandFailInfo) {
        Log.e(TAG, "error:" + commandFailInfo.errorCode + "：" + commandFailInfo.errorMessage);
    }

    @Override
    public void onBusinessFailed(BusinessFailInfo businessFailInfo) {
        Log.e(TAG, "error" + businessFailInfo.getErrorCode() + "：" + businessFailInfo.getErrorMessage());
    }
};
mAMSEDCPayment.sendCommand(activity, deviceCommandRequest, callback);
```

## Device commands

The following are the commands supported by KICC devices, which are invoked by calling the **sendCommand** API. For detailed information, please refer to [Send commands to the device](#LLbD3).

## **Purchase**

Use **Purchase** to initiate a payment with the following parameters:

### Request parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Merchant transaction number. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _creditPayPlan.installmentNum_ | Yes | The number of installments. | None |
| _paymentExpiryTime_ | No | Payment wait timeout, which defaults to 30s. > **Note**: When initiating a payment, you need to start the card reading countdown. Set the countdown time using _paymentExpiryTime_. | None |
| _acquirerInfo.acquirerTerminalId_ | Yes | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | Yes | Merchant business license number. | None |

The following code shows a sample of the request message:

```json
{
  "requestId": "123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum": "0"
  },
  "paymentExpiryTime": "30",
  "acquirerInfo": {
    "acquirerTerminalId": "0788888",
    "acquirerRegistrationNo": "0216001234"
  }
}
```

### Returned parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Merchant transaction number. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _taxAmount.value_ | Yes | Value-added tax amount. | None |
| _taxAmount.currency_ | Yes | Currency of the value-added tax. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _creditPayPlan.installmentNum_ | Yes | The number of installments. | None |
| _result.resultCode_ | Yes | Payment result code. | None |
| _result.resultMessage_ | Yes | Payment result message. | None |
| _acquirerInfo.acquirerResultCode_ | No | Result code returned from the acquirer. | None |
| _acquirerInfo.acquirerResultMessage_ | No | Message description returned from the acquirer. | None |
| _acquirerInfo.acquirerTerminalId_ | Yes | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | Yes | Merchant business license number. | None |
| _acquirerInfo.signData_ | No | Signature data (Only passed in signed transactions.) | None |
| _acquirerInfo.notice_ | No | Transaction description. | `" 매입사제출테스트 거래임"` `"현금영수증 문의 Tel.126-1-1 http:\/\/hometax.go.kr"` `"전표:효력없음 userLoginId 000000000602"` |
| _acquirerInfo.acquirerTransactionId_ | Yes | Transaction serial number of the acquirer. | None |
| _acquirerInfo.acquirerMerchantId_ | Yes | The store's merchant ID on the acquirer end. | None |
| _acquirerInfo.acquirerName_ | Yes | Acquirer name. | `KICC` |
| _acquirerInfo.acquirerMetaData_ | Yes | Original data returned by the acquirer, which must be provided during the refund process. | None |
| _acquirerInfo.acquirerApprovalNum_ | Yes | Transaction approval number of KICC. | None |
| _paymentResultInfo.cardBin_ | No | Payment card BIN (first eight digits of the card). The card BIN information is required during card payment. | None |
| _paymentResultInfo.paymentMethodId_ | No | Identification number. Bar code is required in the wallet payment scenario. | None |
| _paymentResultInfo.issuerCode_ | Yes | Issuer code. See the attachment [📎전체 카드사 신용카드\_발급사 매입사 정보(2023.07.25 기준) .xlsx](https://idocs-assets.marmot-cloud.com/storage/idocs87c36dc8dac653c1/yuque/idocs/2025/xlsx/0824a3ec-1cf9-447b-91f5-362c6f66133a.xlsx) for a full list. | None |
| _paymentResultInfo.funding_ | Yes | The card funding types include: Debit, Credit, and Prepaid. > **Note**: This parameter returns an empty value when paying with international cards, wallets or Samsung Pay. | None |
| _paymentResultInfo.paymentMethodRegion_ | Yes | The region code that represents the country or region of the payment method. The value of this parameter is a 2-letter [ISO country code](https://www.iso.org/obp/ui/#search) or `GLOBAL`. | None |
| _paymentResultInfo.paymentMethodType_ | Yes | The payment method used by the buyer. Valid values are: - `CARD`: Card - `SAMSUNGPAY`: Samsung PAY - `KAKAOPAY`: Kakao Pay - `WECHATPAY`: Wechat Pay - `ALIPAY_CN`: Alipay wallet | None |
| _extendInfo.AD1_ | No | Additional note 1 from the acquirer. | None |
| _extendInfo.AD2_ | No | Additional note 2 from the acquirer. | None |

The following code shows a sample of the response message:

```json
{
  "requestId": "123456XXXX",
  "paymentAmount": {
    "value": "$TOTAL_AMOUNT",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "$TAX",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "$TIP",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum": "0"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": "XXX"
  },
  "acquirerInfo": {
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerMerchantId": "$SHOP_TIDMERCHANT_NUM",
    "acquirerApprovalNum": "$APPROVAL_NUM",
    "acquirerName": "KICC",
    "notice": "               매입사제출테스트 거래임",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  },
  "paymentResultInfo": {
    "cardBin": "52364979",
    "paymentMethodId": "",
    "issuerCode": "$CARD_NAME",
    "funding": "DEBIT/CREDIT/PREPAID",
    "paymentMethodRegion": "KR",
    "paymentMethodType": "CARD/KAKAOPAY/WECHATPAY/ALIPAY_CN/SAMSUNGPAY"
  }
}
```

## PurchaseCancel

Use **PurchaseCancel** to cancel a payment with the following parameters:

### Request parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Cancel ID on the merchant side. The _requestId_ is unique for each request. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _creditPayPlan.installmentNum_ | No | The number of installments. | None |
| _acquirerInfo.acquirerMetaData_ | Yes | Original data returned by the acquirer. Pass the value of _acquirerInfo.acquirerMetaData_ returned by the **Purchase** command to this parameter. | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |

The following code shows a sample of the request message:

```json
{
  "requestId":"123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum":"0"
  },
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  }
}
```

### Returned parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Cancel ID on the merchant side. The _requestId_ is unique for each request. | None |
| _result.resultCode_ | Yes | Cancel result. | None |
| _result.resultMessage_ | Yes | Cancel result message. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _taxAmount.value_ | Yes | Value-added tax amount. | None |
| _taxAmount.currency_ | Yes | Currency of the value-added tax. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _creditPayPlan.installmentNum_ | Yes | The number of installments. | None |
| _acquirerInfo.notice_ | No | Transaction description. | `" 매입사제출테스트 거래임"` `"현금영수증 문의 Tel.126-1-1 http:\/\/hometax.go.kr"` `"전표:효력없음 userLoginId 000000000602"` |
| _acquirerInfo.__acquirerResultCode_ | Yes | Result code returned from the acquirer. | None |
| _acquirerInfo.__acquirerResultMessage_ | No | Message description returned from the acquirer. | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |
| _acquirerInfo.acquirerApprovalNum_ | Yes | Transaction approval number of KICC. | None |
| _acquirerInfo.acquirerMerchantId_ | Yes | Merchant's ID in the acquirer. | None |
| _acquirerInfo.acquirerTransactionId_ | Yes | Transaction serial number of the acquirer. | None |
| _acquirerInfo.acquirerMetaData_ | No | Original data returned by the acquirer. | None |
| _acquirerInfo.acquirerName_ | Yes | Acquirer name. | `KICC` |
| _extendInfo.AD1_ | No | Additional note 1 from the acquirer. | None |
| _extendInfo.AD2_ | No | Additional note 2 from the acquirer. | None |

The following code shows a sample of the response message:

```json
{
  "requestId":"123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "9",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum":"0"
  },
  "result":{
    "resultCode":"SUCCESS",
    "resultMessage":""
  },
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerApprovalNum": "16263485",
    "acquirerMerchantId": "608525310521",
    "acquirerName": "KICC",
    "notice": "$NOTICE"
  }
}
```

## CashReceipt

Use **CashReceipt** to perform cash tax reporting with the following parameters:

### Request parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Tax reporting ID on the merchant side. The _requestId_ is unique for each request. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _buyerType_ | No | Type of the transaction entity for cash receipt. Valid values are: - `Individual`: An individual. This is the default value. - `Business`: Enterprise. | None |
| _reportType_ | No | Tax reporting method. Valid values are: - `auto`: Automatic approval of cash receipts. This is the default value. - `manual`: Manual approval of cash receipts (proactive issuance). | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |

The following code shows a sample of the request message:

```json
{
  "requestId":"123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "buyerType": "Individual/Business",
  "reportType": "auto/manual",
  "acquirerInfo": {
    "acquirerTerminalId": "0788888",
    "acquirerRegistrationNo": "0216001234"
  }
}
```

### Returned parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | Tax reporting ID on the merchant side. The _requestId_ is unique for each request. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _taxAmount.value_ | Yes | Value-added tax amount. | None |
| _taxAmount.currency_ | Yes | Currency of the value-added tax. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _acquirerInfo.notice_ | No | Transaction description. | `" 매입사제출테스트 거래임"` `"현금영수증 문의 Tel.126-1-1 http:\/\/hometax.go.kr"` `"전표:효력없음 userLoginId 000000000602"` |
| _result.resultCode_ | Yes | Processing result. | None |
| _result.resultMessage_ | Yes | Processing result message. | None |
| _cashIdentificationNo_ | Yes | Cash receipt identification number, which is usually a phone number. | `123456*******` |
| _institutionCode_ | Yes | Tax bureau code. | None |
| _acquirerInfo.__acquirerResultCode_ | Yes | Result code returned from the acquirer. | None |
| _acquirerInfo.__acquirerResultMessage_ | No | Message description returned from the acquirer. | None |
| _acquirerInfo.acquirerTransactionId_ | Yes | Transaction serial number of the acquirer. | None |
| _acquirerInfo.acquirerMetaData_ | Yes | Original data returned by the acquirer, which must be provided when cancelling the cash tax reporting. | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |
| _acquirerInfo.acquirerApprovalNum_ | Yes | Transaction approval number of KICC. | None |
| _acquirerInfo.acquirerName_ | Yes | Acquirer name. | `KICC` |

The following code shows a sample of the response message:

```json
{
  "requestId": "123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "9",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },

  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": ""
  },
  "cashIdentificationNo": "$CARD_NO",
  "institutionCode":"$ISSUER_CODE",
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerApprovalNum": "$APPROVAL_NUM",
    "acquirerName": "KICC",
    "notice": "$NOTICE",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  }
}
```

## CashReceiptCancel

Use **cashReceiptCancel** to cancel cash tax reporting with the following parameters:

### Request parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | ID of the merchant side to cancel the tax reporting. The _requestId_ is unique for each request. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _buyerType_ | No | Type of the transaction entity for cash receipt. Valid values are: - `Individual`: An individual. This is the default value. - `Business`: Enterprise. > **Note**: The value of this parameter must be the same as the value in the **CashReceipt** request. | None |
| _reportType_ | No | Tax reporting method. Valid values are: - `auto`: Automatic approval of cash receipts. This is the default value. - `manual`: Manual approval of cash receipts (proactive issuance). > **Note**: The value of this parameter must be the same as the value in the **CashReceipt** request. | None |
| _acquirerInfo.acquirerMetaData_ | Yes | Original data returned by the acquirer. Pass the value of _acquirerInfo.acquirerMetaData_ returned by the **CashReceipt** command to this parameter. | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |

The following code shows a sample of the request message:

```json
{
  "requestId":"123456XXXX",
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "reportType": "auto/manual",
  "paymentExpiryTime":"30",
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  }
}
```

### Returned parameters

| **Parameter name** | **Required** | **Description** | **Sample** |
| --- | --- | --- | --- |
| _requestId_ | Yes | ID of the merchant side to cancel the tax reporting. The _requestId_ is unique for each request. | None |
| _paymentAmount.value_ | Yes | Total payment amount. | None |
| _paymentAmount.currency_ | Yes | Currency of the payment. | `KRW` |
| _taxAmount.value_ | Yes | Value-added tax amount. | None |
| _taxAmount.currency_ | Yes | Currency of the value-added tax. | `KRW` |
| _tipAmount.value_ | Yes | Service fee amount. | None |
| _tipAmount.currency_ | Yes | Currency of the service fee. | `KRW` |
| _acquirerInfo.notice_ | No | Transaction description. | `" 매입사제출테스트 거래임"` `"현금영수증 문의 Tel.126-1-1 http:\/\/hometax.go.kr"` `"전표:효력없음 userLoginId 000000000602"` |
| _result.resultCode_ | Yes | Processing result. | None |
| _result.resultMessage_ | Yes | Processing result message. | None |
| _cashIdentificationNo_ | Yes | Cash receipt identification number, which is usually a phone number. | `123456*******` |
| _institutionCode_ | Yes | Tax bureau code. | None |
| _acquirerInfo.acquirerMetaData_ | No | Original data returned by the acquirer. | None |
| _acquirerInfo.acquirerTransactionId_ | Yes | Transaction serial number of the acquirer. | None |
| _acquirerInfo.__acquirerResultCode_ | Yes | Result code returned from the acquirer. | None |
| _acquirerInfo.a__cquirerResultMessage_ | No | Message description returned from the acquirer. | None |
| _acquirerInfo.acquirerTerminalId_ | No | ID of the terminal device (cards and wallets usually use different ID). | None |
| _acquirerInfo.acquirerRegistrationNo_ | No | Merchant business license number. | None |
| _acquirerInfo.acquirerApprovalNum_ | Yes | Transaction approval number of KICC. | None |
| _acquirerInfo.acquirerName_ | Yes | Acquirer name. | `KICC` |

The following code shows a sample of the response message:

```json
{
  "requestId": ,
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "9",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": ""
  },
  "institutionCode":"$ISSUER_CODE",
  "cashIdentificationNo": "$CARD_NO",
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerApprovalNum": "$APPROVAL_NUM",
    "acquirerName": "KICC",
    "notice": "$NOTICE"
  }
}
```

## GetLastTransaction

Use **GetLastTransaction** to query the most recent transaction. The format of the returned parameters varies and and depends on the `responseCommand` field type. The types include:

-   **Purchase**
-   **PurchaseCancel**

The following sample code shows of a response format of **Purchase**:

```json
{
  "responseCommand":"Purchase"
  "paymentAmount": {
    "value": "104",
    "currency": "KRW"
  },
  "taxAmount": {
    "value": "9",
    "currency": "KRW"
  },
  "tipAmount": {
    "value": "0",
    "currency": "KRW"
  },
  "creditPayPlan": {
    "installmentNum": "0"
  },
  "result": {
    "resultCode": "SUCCESS",
    "resultMessage": ""
  },
  "acquirerInfo": {
    "acquirerTerminalId": "$SHOP_TID",
    "acquirerRegistrationNo": "$SHOP_BIZ_NUM",
    "acquirerResultCode": "$RESULT_CODE",
    "acquirerResultMessage": "$RESULT_MSG",
    "acquirerTransactionId": "$TRAN_SERIALNO",
    "acquirerMetaData":"ImNyZWRpdFBheVBsYW4iOiB7CiAgICAiaW5zdGFsbG1lbnROdW0iOiAiMCIKICB9LAogICJyZXN1bHQiOiB7CiAgICAicmVzdWx0Q29kZSI6ICJTVUNDRVNTIiwKICAgICJyZXN1bHRNZXNzYWdlIjogIiIKICB9Cg=="
  }
}
```

## CommandCancel

Refer to the code example below to implement the `CommandCancel` function:

> **Note**: The `CommandCancel` function can only be used before reading the card and initiating a payment.

```java
KICCCommandRequest deviceCommandRequest = new KICCCommandRequest();
deviceCommandRequest.setCommandName("CommandCancel");
deviceCommandRequest.setCommandRequestParams(new JSONObject());
KICCCommandCallback callback = new KICCCommandCallback() {
    @Override
    public void onSuccess(CommandResult result) {
        // Cancel success. Proceed to cancel timer
        stopTimer();
    }

    @Override
    public void onCommandFailed(CommandFailInfo commandFailInfo) {
        // Depending on the errorCode, might need to cancel timer.
    }

    @Override
    public void onBusinessFailed(CommandResult result) {
        // No need to handle any logic.
    }
};
mAMSEDCPayment.sendCommand(this, deviceCommandRequest, callback);
```

# Event codes

You may encounter the following types of event codes:

-   **Initialization type**: Returned by `onInitResult` during the global initialization phase.
-   **Command execution type**: Returned by `onCommandFailed` when the device command execution fails.
-   **Business processing type**: Returned by `onBusinessFailed` when the business processing fails.

| **Type** | **Event code** | **Description** | **Further action** |
| --- | --- | --- | --- |
| Initialization type | INIT\_SUCCESS | Initialization succeeded. | No further action required. |
| Initialization type | INIT\_FAILED | Initialization failed. | Please try again. |
| Initialization type | INIT\_PARAM\_ERROR | Initialization parameter error. | Please read [Step 4: Instantiate the SDK](#QptQy) and check the input parameter. |
| Command execution type | CommandInvalidResponse | Returned result of the command is incorrect. | Please try again. |
| Command execution type | CommandResponseTimeout | The command was executed, but no response was returned. See [Timeout](#xQA54) for more information. Upon receiving this event code, if the card reading timer has started, please ensure to cancel the timer. | Please try again. |
| Command execution type | CommandNotSupport | The command is not supported. | Please read [Step 5: Send commands to the device](#LLbD3) and input valid commands. |
| Command execution type | CommandDeviceBusy | The device is executing the command. | Wait for the previous command to respond and try again. |
| Command execution type | CommandParamError | Abnormal parameter. | Check the parameters of the input command. |
| Command execution type | CommandInvalid | Invalid command. The timing of `CommandCancel` is invalid. | Check the timing of `CommandCancel`, which can only be used before reading the card and initiating a payment. |
| Business processing type | REPEAT\_REQ\_REJECT | There is an existing order with the same _requestId_. | Please retry with a new _requestId_. |
| Business processing type | INVALID\_CONTRACT | Contract is invalid. | Please check the input _merchantId_ information. |
| Business processing type | ACCESS\_DENIED | Access is denied. | Contact KICC for detailed reasons and support. |
| Business processing type | PROCESS\_FAIL | A general business failure occurred. | Do not retry. Human intervention is usually needed. It is recommended that you contact Antom Technical Support to troubleshoot the issue. |
| Business processing type | PARAM\_ILLEGAL | The required parameters are not passed, or illegal parameters exist. For example, a non-numeric input, or the length and type of the parameter are incorrect. | Check and verify whether the required request parameters (including the header and body parameters) of the current API are correctly passed and valid. |
| Business processing type | ORDER\_STATUS\_INVALID | The order status is invalid. | Check the order status. |
| Business processing type | ORDER\_IS\_CANCELED | The transaction is canceled. | You cannot refund the transaction because it is canceled. |
| Business processing type | USER\_AMOUNT\_EXCEED\_LIMIT | The payment amount exceeds the user payment limit. | Create a new payment by using an amount less than or equal to the account's available balance, or contact Antom Technical Support. |
| Business processing type | USER\_BALANCE\_NOT\_ENOUGH | The payment cannot be completed because the user balance in the corresponding payment method is not enough. | Please top up the account or choose other payment methods. |
| Business processing type | INVALID\_CARD\_NUMBER | The card number used for the transaction is invalid. | Check and verify whether the required request parameters of the current API are correctly passed and valid. |
| Business processing type | IDENTITY\_VERIFY\_FAILED | Identity verification timed out or the result couldn't be retrieved. | Please confirm your identification details and try again. |
| Business processing type | UNKNOWN | Unknown scenarios. | Contact KICC for detailed reasons and support. |