diff --git a/android/androidreleasenotes.md b/android/androidreleasenotes.md index 9fda179..d681586 100644 --- a/android/androidreleasenotes.md +++ b/android/androidreleasenotes.md @@ -11,6 +11,10 @@ id: androidreleasenotes Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! ::: +## 7.1010.8 +**Fixes** + +- Minor fix in payments flow to improve error handling ## 7.1010.7 **Fixes** diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidapioverview.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidapioverview.md new file mode 100644 index 0000000..6b0f141 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidapioverview.md @@ -0,0 +1,22 @@ +--- +sidebar_position: 4 +id: androidapioverview +--- + +# Trigger Amounts + +Your test payments are sent against a test server on the Handpoint side which simulates the behavior of an acquiring bank. Funds are not moved and sensitive data from the card is fully encrypted. You can use trigger amounts to generate some specific responses from our servers: + +**Sale amounts** + +| Amount | Behaviour | +| ----------- | ----------- | +| 37.79 | Issuer response code = 01 (Refer to issuer) | +| 37.84 | Issuer response code = 05 (Not authorized) | +| 37.93 | Issuer response code = 04 (Pick up card) | +| 37.57 | Request is partially approved | +| 37.68 | Request timeout | + +:::tip +Supporting partial approval is **mandatory** for the US market. Partial authorization occurs when a payment card authorization is attempted for a transaction and there are not enough funds available in the account to cover the full amount. The issuer returns an authorization for the amount available in the account, leaving you to obtain an additional form of payment from the customer for the balance. +::: \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androiddevicemanagement.md b/android_versioned_docs/version-Android SDK 7.1010.8/androiddevicemanagement.md new file mode 100644 index 0000000..d825b7f --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androiddevicemanagement.md @@ -0,0 +1,417 @@ +--- +sidebar_position: 6 +id: androiddevicemanagement +--- + +# Terminal Management + +## Connect + +`connect` Method + +Connects to a payment terminal. Whenever the connection to the device is lost, the SDK will keep on trying to establish a connection until it’s re-established. No special actions are needed. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device` Required
[*Device*](androidobjects.md#17) | This parameter specifies which device type you want to connect to.| + +**Code example** + +```java +//Connect to a device +Device device = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); +Device device = new Device("LocalDevice", "0821032398-PAXA920", "", ConnectionMethod.ANDROID_PAYMENT); +Device device = new Device("CloudDevice", "0821032398-PAXA920", "", ConnectionMethod.CLOUD); +api.connect(device); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Each time the card reader state changes (ex : going from Connected to Disconnected) the ConnectionStatusChanged event is called. It causes the connection manager to invoke this event with the appropriate information. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| + +## Disconnect + +`disconnect` Method + +Disconnect will stop the active connection (or reconnection process). Please note that the method ignores the current state of the payment terminal and just stops the connection. Calling disconnect might result in a commmunication error if triggered during a transaction. + +**Code example** + +```java +//Disconnects from the payment terminal +api.Disconnect(); +``` + +**Events invoked** + +[**connectionStatusChanged**](androideventlisteners.md#connectionStatusChanged) + +Causes the connection manager to invoke this event with the appropriate information. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successful.| + +## Get Device Manufacturer + +`getDeviceManufacturer` Method + + +**Code example** + +```java +Manufacturer manufacturer = api.getDeviceManufacturer(); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| [*Manufacturer*](androidobjects.md#manufacturer)| The payment terminal manufacturer.| + + +## Get EMV Report + +`getEMVConfiguration` Method + +Fetches the logs from the device and reports them to the deviceLogsReady event. + +**Code example** + +```java +//Downloads logs from device +api.getDeviceLogs(); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +Invoked when the sdk has finished downloading the EMV report from the payment terminal. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + + +## Get Paired Devices + +`getPairedDevices` Method + +Returns the payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod *](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Get paired terminals +List devices = api.getPairedDevices(ConnectionMethod.XXX); +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| **`List`**| The list of payment terminals.| + +## Get Transactions Report{#getTransactionReport} + +`getTransactionsReport` Method + +Fetches your transactions report from a payment terminal. If you want to print the report, you can call [printReceipt](#print-receipt) with the string returned in [ReportResult](androideventlisteners.md#reportResult) event as parameter. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `reportConfiguration` Required
[*ReportConfiguration*](androidobjects.md#19) | This parameter specifies the filter to get transactions report.| + +**Code example** + +```java +//Get the transactions report for device "12345", from 30th April 2021 at 00:00:00, to 30th April 2021 at 23:59:59, in eurs: +List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0821122334"); +ReportConfiguration configuration = new ReportConfiguration("EUR", "20231001000000", "20231201235959", "+00:00", terminalSerialNumber); + +api.getTransactionsReport(configuration); +``` + +**Events invoked** + +[**ReportResult**](androideventlisteners.md#reportResult) + +The report will be returned to the registered ReportResult interface. + +**Returns** + + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the command was processed successfully. `False` if the sending was not successful.| + +## Flash Reset + +`deleteDeviceConfig` Method + +Sends a command to the payment terminal to delete its configuration. + +**Code example** + +```java +api.deleteDeviceConfig(); +``` + +## Print Receipt + +`printReceipt` Method + +Print on demand functionality allowing the merchant to print any HTML formatted receipt. It is possible to print images or barcodes as well as passing directly a URL to the printReceipt function. A bitmap can also be printed, in order to do so it needs to be rendered as an image and inserted into the html. + +:::tip +Receipts received in the terminal transaction result can either be a URL **OR** an HTML formatted receipt. The format can be changed by updating the `getReceiptsAsURLs` boolean when initializing the SDK [*Settings*](androidobjects.md#settings). Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `receipt` Required
*String* | The receipt must match the following [HTML Print Format](https://handpoint.atlassian.net/wiki/spaces/PD/pages/1409875969/Html+Print+Format). The Transaction Report (also called End of Day Report) can be printed from the string returned in the [ReportResult](androideventlisteners.md#reportResult) event.| + +**Code example (Prints a receipt with Handpoint logo)** + +```java +//Print a receipt with Handpoint logo (bitmap format) +String validReceipt = ""; +boolean success = api.printReceipt(validReceipt); +``` + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the receipt was sent to the printer, false otherwise.| + + +## Search Devices + +`searchDevices` Method + +Starts the search of payment terminals associated with the specified ConnectionMethod. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `method` Required
[*ConnectionMethod*](androidobjects.md#20) | The type of connection with the payment terminal (Bluetooth, Cloud, etc.).| + +**Code example** + +```java +// Starts the search for payment terminals. +// You must implement Events.DeviceDiscoveryFinished and subscribe +// to the event delegate in order to receive the result +api.searchDevices(ConnectionMethod.XXX); +``` + +**Events invoked** + +[**deviceDiscoveryFinished**](androideventlisteners.md#deviceDiscoveryFinished) + +Returns a list of payment terminals. + +## Set Locale + +`setLocale` Method + +Sets the SDK Locale (language). It is used to set the SDK language as well as the associated date and number formatting. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `locale` Required
[*SupportedLocales*](androidobjects.md#23) | The locale to be set. Supported locales are: SupportedLocales.en_CA, SupportedLocales.en_UK, SupportedLocales.en_US, SupportedLocales.hr_HR, SupportedLocales.is_IS, SupportedLocales.fr_FR, SupportedLocales.pt_PT, SupportedLocales.it_IT, SupportedLocales.no_NO, SupportedLocales.de_DE, SupportedLocales.sl_SL, SupportedLocales.et_EE| + + + + + **Code example** + +```java +// Set canadian english +api.setLocale(SupportedLocales.en_CA); +``` + +## Set log level + +`setLogLevel` Method + +Sets the log level (info, debug...) for both the payment terminal and the SDK. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `level *`
[*LogLevel*](androidobjects.md#18) | The desired log level. Can be LogLevel.None, LogLevel.Info, LogLevel.Full, LogLevel.Debug| +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which device should be used for the operations. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Sets the log level to info +api.setLogLevel(LogLevel.info); +``` + +**Events invoked** + +**None** + +No events are invoked. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` iif the operation was successfully sent to device.| + + + + +## Stop current transaction + +`stopCurrentTransaction` Method + +Stops the current transaction. A transaction can be stopped only if the last [currentTransactionStatus](androideventlisteners.md#14) event reported has the property **isCancelAllowed** set to **true**. +This operation is **not supported** for **Hilite and Hi5** devices. + +**Code example** + +```java +// Stops current transaction +if (api.stopCurrentTransaction()) { + ... +} else { + ... +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked after stop transaction. Status **UserCancelled** will be reported. + +[**endOfTransaction**](androideventlisteners.md#16) + +Transaction will fail with status **CANCELLED** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the transaction was successfully stopped, false otherwise.| + + +## Update device + +`update` Method + +The update operation checks for new software or configuration updates and initiates a download if required. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `device`
[*Device*](androidobjects.md#17) | This parameter specifies to the system which payment terminal should be used for the operation. If no device is supplied, the system will attempt to use a default one.| + +**Code example** + +```java +//Check for card reader update +api.update(); +``` + +**Events invoked** + +**None** + +The merchant should be notified about the update process. + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the operation was successfully sent to device.| + +## Get Transaction Status{#getTransactionStatus} + +`getTransactionStatus` Method + +**This functionality is only available for SmartPos devices (PAX).** + +If for any reasons you do not know if a transaction was approved or declined then this method will allow you to retrieve the status of the transaction from the Handpoint gateway. The `getTransactionStatus` method is a convenient way to retrieve the current status of a transaction based on its unique reference. This method accepts a `transactionReference` as a parameter and returns the current status of the transaction. The `transactionReference` is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object. + +The main [*FinancialStatus*](androidobjects.md#34) that can be returned as a response to this method are the following ones: + +- AUTHORISED - Transaction was successful. +- DECLINED - Transaction was declined. +- UNDEFINED (NOT FOUND) - The transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged. +- IN_PROGRESS - The transaction has been received by the gateway but the outcome is not known yet, try again after a few seconds. +- REFUNDED - Transaction was refunded. + + + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionReference` Required
*String* | The `transactionReference` ([UUID v4](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random))) is returned at the start of a transaction, as part of the [Operation Start Result](androidobjects.md#OperationStartResult) object.| + + +**Code example** + +```java +//Gets the current status of a transaction +api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**transactionResultReady**](androideventlisteners.md#transactionResultReady) + +Invoked when the result of the getTransactionStatus request is available. +*** + + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `true` if the operation was successfully.| \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androideventlisteners.md b/android_versioned_docs/version-Android SDK 7.1010.8/androideventlisteners.md new file mode 100644 index 0000000..4eae6c1 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androideventlisteners.md @@ -0,0 +1,731 @@ +--- +sidebar_position: 8 +id: androideventlisteners +--- + + + + +# Events Listeners + +## SmartposRequired + +`Events.SmartposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for a smartPOS terminal (PAX/Telpo). + +**Code example** + +```java +public final class EventHandler implements Events.SmartposRequired { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + + +## MposRequired + +`Events.MposRequired` Interface + +You must provide a class implementing this interface when initializing the SDK for an mPOS terminal (HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.MposRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + +## PosRequired + +`Events.PosRequired` Interface + +You must provide a class implementing this interface when initializing the SDK when supporting both mPOS and SmartPOS terminals (PAX/Telpo & HiLite). + +**Code example** + +```java +public final class EventHandler implements Events.PosRequired { + @Override + public void deviceDiscoveryFinished(List devices) { ... } + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { ... } + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { ... } + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { ... } + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + + [`ConnectionStatusChanged`](#connectionStatusChanged)[`CurrentTransactionStatus`](#14)[`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) [`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) + + +## Card Brand Display{#cardBrandDisplay} + +`Events.CardBrandDisplay` Interface + +An interface which needs to be implemented and added as a listener to get events providing information on the supported card brands and/or the card brand used during the transaction. + +**Methods** + +`supportedCardBrands( List cardBrandsList );` + +| Parameter | Notes | +| ----------- | ----------- | +| `cardBrandsList` Required
*List ``* | A list containing the supported card brands| + +

+ +`readCard( CardBrands usedCard );` + +| Parameter | Notes | +| ----------- | ----------- | +| `usedCard` Required
[*CardBrands*](androidobjects.md#cardBrands) | Name of the card brand| + +**Code example** + +```java +public final class EventHandler implements Events.CardBrandDisplay { + + @Override + public void supportedCardBrands(List cardBrandsList) { + // Get supported card brands + } + + @Override + public void readCard(CardBrands usedCard) { + // Get the used card brand + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Card Tokenization + +`Events.CardTokenization` Interface + +Implement this interface in order to receive events about the card tokenization. + +**Methods** + +`cardTokenized( ResumeCallback callback, CardTokenizationData cardTokenizationData)` + +| Parameter | Notes | +| ----------- | ----------- | +| `callback` Required
*ResumeCallback* | Lets the SDK continue the operation| +| `cardTokenizationData` Required
[*CardTokenizationData*](androidobjects.md#card-tokenization-data) | Object with the tokenization data.| + +```java +public final class EventHandler implements Events.CardTokenization { + + @Override + public void cardTokenized(@NonNull ResumeCallback callback, @NonNull CardTokenizationData cardTokenizationData) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Connection status changed{#connectionStatusChanged} + +`Events.ConnectionStatusChanged` Interface + +Implement this interface in order to receive connection status changes. + +**Methods** + +`connectionStatusChanged( ConnectionStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*ConnectionStatus*](androidobjects.md#connection-status) | New status of the connection| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal which sent this information.| + + +**Code example** + +```java +public final class EventHandler implements Events.ConnectionStatusChanged { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + + +## Current transaction status{#14} + +`Events.CurrentTransactionStatus` Interface + +Implement this interface in order to receive events about the current transaction. + +**Methods** + +`currentTransactionStatus( StatusInfo status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
[*StatusInfo*](androidobjects.md#status-info) | The **StatusInfo** of the current transaction| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal the request is sent from.| + + +**Code example** + +```java +public final class EventHandler implements Events.CurrentTransactionStatus { + + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Device capabilities ready{#deviceCapabilitiesReady} + + +`Events.DeviceCapabilitiesReady` Interface + +Implement this interface in case the payment terminal needs to notify the SDK of its capabilities + +**Methods** + +`deviceCapabilities( DeviceCapabilities capabilities , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `capabilities` Required
[*DeviceCapabilities*](androidobjects.md#24) | The capabilities of the terminal| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending its capabilities| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceCapabilitiesReady { + + @Override + public void deviceCapabilities(DeviceCapabilities capabilities, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + + +## Device discovery finished{#deviceDiscoveryFinished} + +`Events.DeviceDiscoveryFinished` Interface + +Implement this interface in order to receive a list of available payment terminals. The event handler defined in this interface is invoked after calling the method searchDevices + +**Methods** + +`deviceDiscoveryFinished( List devices );` + +| Parameter | Notes | +| ----------- | ----------- | +| `devices` Required
List `` | A list of available devices.| + + +**Code example** + +```java +public final class EventHandler implements Events.DeviceDiscoveryFinished { + + @Override + public void deviceDiscoveryFinished(List devices) { + // Receiving a list of connectable payment terminals + foreach(Device device in devices) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## End of transaction{#16} + +`Events.EndOfTransaction` Interface + +Implement this interface to receive an event when a transaction is complete. + +**Methods** + +`endOfTransaction( TransactionResult result , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `result` Required
[*TransactionResult*](androidobjects.md#25) | Holds all the information about the transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.EndOfTransaction { + + @Override + public void endOfTransaction(TransactionResult result, Device device) { + // Check the status of the transaction, save it, ... + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Hardware status changed{#hardwareStatusChanged} + +`Events.HardwareStatusChanged` Interface + +Implement this interface in order to receive events when the hardware status changes. + +**Methods** + +`hardwareStatusChanged( HardwareStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `status` Required
*HardwareStatus* | New status of the hardware.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.HardwareStatusChanged { + + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Log{#log} + +`Events.Log` Interface + +An interface which needs to be implemented and added as a listener to receive logging information. + +**Extends** + +[`OnMessageLogged`](#onMessageLogged) + +**Code example** + +```java +public final class EventHandler implements Events.Log { + + @Override + public void deviceLogsReady(String logs, Device device) { ... } + @Override + public void onMessageLogged(LogLevel level , String message) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## MessageHandling{#messageHandling} + +`Events.MessageHandling` Interface + +An interface which needs to be implemented and added as a listener to get events which are called when the sdk asks the application to display or hide a message. + +**Methods** + +`showMessage( String message , Boolean dismissible , int duration );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to display| +| `dismissible` Required
*Boolean* | A flag that indicates whether the message can be dismissed| +| `duration` Required
*int* | The timeout to hide the message. In milliseconds, if 0 is sent, the message should not auto dismiss.| + + +`hideMessage( String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `message` Required
*String* | Message to hide| + +**Code example** + +```java +public final class EventHandler implements Events.MessageHandling { + + @Override + public void showMessage(String message, Boolean dismissible, int duration) { + // Show message for a 'duration' period (if duration = 0 DO NOT dismiss until hideMessage(String message) event is received) and make it dismissible if the input marks it as possible + } + + @Override + public void hideMessage(String message) { + // Hide the message + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` +## On message logged{#onMessageLogged} + +`Events.OnMessageLogged` Interface + +Implement this interface to receive logs from the payment terminal. +**Methods** + +`onMessageLogged( LogLevel level , String message );` + +| Parameter | Notes | +| ----------- | ----------- | +| `level` Required
[*LogLevel*](androidobjects.md#18) | The LogLevel of the logging| +| `message` Required
*String* | The log trace which was logged by the SDK.| + + +**Code example** + +```java +public final class EventHandler implements Events.OnMessageLogged { + + @Override + public void onMessageLogged(LogLevel level, String message) { + // Process log trace + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PhysicalKeyboardEvent{#physicalKeyboardEvent} + +`Events.PhysicalKeyboardEvent` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the PAX A80 physical keyboard. + +** Methods** + +`onKeyPressed( PaxA80Keys key );` + +| Parameter | Notes | +| ----------- | ----------- | +| `key` Required
[*PaxA80Keys*](androidobjects.md#28) | The name of the key that has been pressed| + + +**Code example** + +```java +public final class EventHandler implements Events.PhysicalKeyboardEvent { + + @Override + public void onKeyPressed(String key) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## PendingResults{#pendingResults} + +`Events.PendingResults` Interface + +An interface which needs to be implemented and added as a listener to receive information about pending TransactionResults. In case of a communication failure between the SDK and the payment terminal there might be a result pending from the transaction which did not get sent to the SDK. + +**Code example** + +```java +public final class EventHandler implements Events.PendingResults { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`TransactionResultReady`](#transactionResultReady) + +## PaymentProvider + +`Events.PaymentProvider` Interface + +An interface which needs to be implemented and added as a listener to receive all available events related to financial operations. + +**Extends** + +[`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`OnMessageLogged`](#onMessageLogged) [`CurrentTransactionStatus`](#14) + + +## PrinterEvents{#printerEvents} + +`Events.PrinterEvents` Interface + +An interface which needs to be implemented and added as a listener to get events coming from the printer. + +**Methods** + +`printSuccess( );` + + + +`printError(PrintError error);` + +| Parameter | Notes | +| ----------- | ----------- | +| `error` Required
[*PrintError*](androidobjects.md#29) | Enum detailing the reason of the error| + +**Code example** + +```java +public final class EventHandler implements Events.PrinterEvents { + + @Override + public void printSuccess() { + // Successful print action + } + + @Override + public void printError(PrintError error) { + // Unable to perform print action due to error + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Report result{#reportResult} + +`Events.ReportResult` Interface + +Implement this interface to receive an event when a report result from a [getTransactionsReport](androiddevicemanagement.md#getTransactionReport) is returned. + +**Methods** + +`reportResult( TypeOfResult type , String report , DeviceStatus status , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `type` Required
[*TypeOfResult*](androidobjects.md#30) | The type of the report| +| `report` Required
*String* | The text of the report| +| `status` Required
[*DeviceStatus*](androidobjects.md#33) | The status of the device| +| `device` Required
[*Device*](androidobjects.md#17) | The terminal sending the report| + + +**Code example** + +```java +public final class EventHandler implements Events.ReportResult { + + @Override + public void reportResult(TypeOfResult type, String report, DeviceStatus status, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Events** + +[`DeviceDiscoveryFinished`](#deviceDiscoveryFinished) [`SignatureRequired`](#15) [`EndOfTransaction`](#16) [`PendingResults`](#pendingResults) + +## Signature required{#15} + +`Events.SignatureRequired` Interface + +The SignatureRequired interface must be implemented in order to receive an event when a card requires a signature as a verification method. This interface is only required for an Hilite integration, PAX and Telpo terminals automatically prompt for signature capture on the terminal. + +**Methods** + +`signatureRequired( SignatureRequest request , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `request` Required
[*SignatureRequest*](androidobjects.md#signature-request) | Holds the signature request.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.SignatureRequired { + + @Override +public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // Save merchant receipt + String merchantReceipt = signatureRequest.getMerchantReceipt(); + api.signatureResult(true); + } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Status{#status} + +`Events.Status` Interface + +An interface which needs to be implemented and added as a listener to receive connection and transaction statuses. + +**Code example** + +```java +public final class EventHandler implements Events.Status { + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { ... } + @Override + public void hardwareStatusChanged(HardwareStatus status, Device device) { ... } + @Override + public void currentTransactionStatus(StatusInfo info, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +**Extends** + +[`ConnectionStatusChanged`](#connectionStatusChanged) [`HardwareStatusChanged`](#hardwareStatusChanged) [`CurrentTransactionStatus`](#14) + +## Transaction result ready{#transactionResultReady} + +`Events.TransactionResultReady` Interface + +Implement this interface in order to receive an event after a pending TransactionResult has been recovered from the payment terminal. + +**Methods** + +`transactionResultReady( TransactionResult transactionResult , Device device );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionResult` Required
[*TransactionResult*](androidobjects.md#25) | A ***TransactionResult*** is containing all information about the recovered transaction.| +| `device` Required
[*Device*](androidobjects.md#17) | The payment terminal.| + + +**Code example** + +```java +public final class EventHandler implements Events.TransactionResultReady { + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { ... } + +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` + +## Transaction started{#transactionStarted} + +`Events.TransactionStarted` Interface + +Implement this interface in order to receive an event when a transaction is started through the Cloud API channel. + +**IMPORTANT NOTE**: This interface is **only** available for cloud-enabled devices. See [DeviceCapabilitiesReady](#deviceCapabilitiesReady) interface. + +**Methods** + + +`transactionStarted( TransactionType transactionType , BigInteger amount , Currency currency, String transactionReference );` + +| Parameter | Notes | +| ----------- | ----------- | +| `transactionType` Required
[*TransactionType*](androidobjects.md#31) | Type of transaction started| +| `amount` Required
*BigInteger* | Amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the transaction started| +| `transactionReference` Required
*String* | The transaction reference of the started transaction. `transactionReference` will be empty if the operation has not been started with one, or if it is an operation to which it does not apply (a tokenization, for example)| + +**Code example** + +```java +public final class EventHandler implements Events.TransactionStarted { + + //If the transactionReference has NOT been included in the request, it will be empty. + @Override +public void transactionStarted(TransactionType type, BigInteger amount, Currency currency, String transactionReference) { + // Notify the app user transaction has been started ... + } +} + +// Remember to register the instance of this EventHandler: +this.api.registerEventsDelegate(eventHandlerInstance); +``` diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androideventsubscribers.md b/android_versioned_docs/version-Android SDK 7.1010.8/androideventsubscribers.md new file mode 100644 index 0000000..a997f42 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androideventsubscribers.md @@ -0,0 +1,73 @@ +--- +sidebar_position: 7 +id: androideventsubscribers +--- + + +# Events Subscribers + +## Register events delegate + +`registerEventsDelegate` Method + +Registers a delegate for the SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void setEventsHandler() { + // Register this class as listener for events + this.api.registerEventsDelegate(this); + ... + } + +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was added successfully.| + + + +## Unregister events delegate + +`unregisterEventsDelegate` Method + +Unregisters an object from SDK events. + +**Parameters** + +| Parameter | Notes | +| ----------- | ----------- | +| `listener` Required
*Object* | Any object implementing one or more of the available delegate interfaces.| + +**Code example** + +```java +public class ObjectHelper implements Events.SmartposRequired, Events.Status, Events.Log, Events.TransactionStarted, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + ... + private void unsubscribeEventsDelegate() { + // Stop receiving events + this.api.unregisterEventsDelegate(this); + ... +} +``` + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| `Boolean`| `True` if the new delegate was removed successfully.| + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidintegrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidintegrationguide.md new file mode 100644 index 0000000..d9114a4 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidintegrationguide.md @@ -0,0 +1,820 @@ +--- +sidebar_position: 4 +id: androidintegrationguide +--- + + +# Integration Guides + + +**The SDK supports the following connection methods:** + +1. **[Android Native (PAX/Telpo)](#8)** +2. **[Bluetooth (HiLite)](#9)** +3. **[USB (BluePad 50+)](#10)** + +## Android Native Integration (PAX/Telpo) {#8} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android Payment devices such as PAX and Telpo. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2. SDK distribution** + +The Handpoint Android SDK is available on Maven central as well as the Handpoint internal Nexus server. Maven central contains the **production builds** while Nexus contains **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to get the **release candidates 7.xxxx.xx-RC** SDK. +- If you are integrating your software with a **PAX production terminal** you will need to get the **production** SDK. +- If you are integrating your software with an **HiLite terminal** you will need to get the **production** SDK. + + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + +**Gradle Settings** + +For production terminals (Maven): +```groovy + //Handpoint Production SDK (Production terminals) + implementation 'com.handpoint.api:sdk:7.x.x' +``` +In the `gradle.build` (Top-level build file) for production terminals (Maven): + + ```groovy + allprojects { //Handpoint Production SDK (Production terminals) + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } + } + ``` + +For debug terminals (Nexus): +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus): + + ```groovy + allprojects { //Handpoint Staging/Development SDK (Debug terminals) + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } +``` + +:::tip +If using AndroidX you will need to switch the following flags to true:

+android.enableJetifier=true

+android.useAndroidX=true +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TipConfiguration; +import com.handpoint.api.shared.TransactionResult; +import com.handpoint.api.shared.agreements.Acquirer; +import com.handpoint.api.shared.agreements.Credential; +import com.handpoint.api.shared.agreements.MerchantAuth; +import com.handpoint.api.shared.options.SaleOptions; + +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.SmartposRequired, Events.CurrentTransactionStatus, Events.ConnectionStatusChanged, Events.EndOfTransaction, Events.TransactionResultReady { + + private Hapi api; + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set default credentials. + // The shared secret is a unique string shared between the payment terminal and your application, it is unique per merchant. + // You should replace this default shared secret with the one sent by the Handpoint support team. + + //Since we're running inside the terminal, we can create a device ourselves and connect to it + Device device = new Device("some name", "address", "", ConnectionMethod.ANDROID_PAYMENT); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + //Connection Status connected + + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public OperationStartResult payWithOptions() { + SaleOptions options = new SaleOptions(); + + // Adding tipping + TipConfiguration config = new TipConfiguration(); + //Optionally + config.setHeaderName("HEADER"); + //Optionally + config.setFooter("FOOTER"); + //Optionally + config.setEnterAmountEnabled(true); + //Optionally + config.setSkipEnabled(true); + //Optionally + config.setTipPercentages(Arrays.asList(5, 10, 15, 20)); + options.setTipConfiguration(config); + + // Adding Multi MID / Custom merchant Authentication + MerchantAuth auth = new MerchantAuth(); + Credential credential = new Credential(); + //Optionally + credential.setAcquirer(Acquirer.SANDBOX); + //Optionally + credential.setMid("mid"); + //Optionally + credential.setTid("tid"); + //Add as many credentials as Acquirers your merchant have agreements with + auth.add(credential); + options.setMerchantAuth(auth); + + //Add a customer reference + options.setCustomerReference("Your customer reference"); + + //Enable pin bypass + options.setPinBypass(true); + + //Enable signature bypass + options.setSignatureBypass(true); + + //Define a budget number + options.setBudgetNumber("YOUR_BUDGET_NUMBER"); + + return this.api.sale(new BigInteger("1000"),Currency.GBP, options); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + public boolean getTrxStatus() { + //Allows you to know the status of a transaction by providing the transactionReference. + //The transactionReference must be a unique identifier (UUID v4). + //This functionality is only available for SmartPos devices (PAX) + return api.getTransactionStatus("00000000-0000-0000-0000-000000000000"); + //You will receive the TransactionResult object of this operation in transactionResultReady event + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The TransactionResult object holds details about the transaction as well as the receipts + // Useful information can be accessed through this object like the transaction ID, the amount, etc. + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // Here you are also going to receive a TransactionResult object after making a query to getTransactionStatus + } + + public void disconnect(){ + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + +## Bluetooth Integration (HiLite) {#9} + + **Introduction** + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an HiLite payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting credit/debit card transactions. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI-DSS security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` + +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // This triggers the asynchronous search for all the devices around that haven't been paired. + // You could, alternatively, search for the already paired devices + // List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Now: + // selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + //Potentially, if you know the MAC address of the device you want to connect to, you can skip the search and do it this way + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", "", ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", "port", ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} + + +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost.If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. + + +## USB Integration (BluePad 50+) {#10} + +This tutorial is guiding you through all the required steps to create a basic payment application for Android devices integrated with an BluePad 50+ payment terminal. + +The new generation of Handpoint SDK's is designed to make your life easier. Simple and created for humans, it does not require any specific knowledge of the payment industry to be able to start accepting card payments. + +At Handpoint we take care of securing every transaction so you don´t have to worry about it while creating your application. We encrypt data from the payment terminal to the bank with our point-to-point encryption solution. Our platform is always up to the latest PCI security requirements. + +:::warning +Please, start an operation (sale,refund etc.) ONLY if you have received the **InitialisationComplete** message from the **currentTransactionStatus** method +::: + + + +**Let's start programming!** + +**1. Modify the AndroidManifest.xml** + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +**2.1 In the gradle.build (app module)** + +```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } +} +```` +```groovy +dependencies { + + //Handpoint Production SDK (Production devices) + implementation 'com.handpoint.api:sdk:7.x.x' +} +``` + + +**2.2 In the gradle.build (Top-level build file)** + +```groovy +allprojects { //Handpoint Production SDK + repositories { + google() + mavenCentral() + maven { url 'https://jitpack.io' } + } +} +``` + +:::tip +During the build process, a DEX error may appear. + +To be able to build, we recommend adding the following lines to the `gradle.properties` file: + +```groovy +org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=4096m -XX:+HeapDumpOnOutOfMemoryError +org.gradle.daemon = true +org.gradle.parallel = true +org.gradle.configureondemand = true +```` +::: + + +**3. Create a Java class** + +Create a new java class called `HandpointDelegate.java` and include `com.handpoint.api.*` as a dependency: + +```java +package com.yourpackage.name; + +import android.content.Context; + +import com.handpoint.api.HandpointCredentials; +import com.handpoint.api.Hapi; +import com.handpoint.api.HapiFactory; +import com.handpoint.api.shared.ConnectionMethod; +import com.handpoint.api.shared.ConnectionStatus; +import com.handpoint.api.shared.Currency; +import com.handpoint.api.shared.Device; +import com.handpoint.api.shared.Events; +import com.handpoint.api.shared.SignatureRequest; +import com.handpoint.api.shared.StatusInfo; +import com.handpoint.api.shared.TransactionResult; + +import java.math.BigInteger; +import java.util.List; + +//Check all the events available in the Events interface. +//If you want to subscribe to more events, just add to the list of implemented interfaces. +public class HandpointDelegate implements Events.MposRequired, Events.ConnectionStatusChanged, Events.CurrentTransactionStatus, Events.SignatureRequired, Events.EndOfTransaction, Events.DeviceDiscoveryFinished, Events.TransactionResultReady { + + private Hapi api; + + + public HandpointDelegate(Context context) { + initApi(context); + } + + public void initApi(Context context) { + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + this.api = HapiFactory.getAsyncInterface(this, context, handpointCredentials); + // The api is now initialized. Yay! we've even set a shared secret! + // The shared secret is a unique string shared between the card reader and your mobile application + // It prevents other people to connect to your card reader + // You have to replace this default shared secret by the one sent by our support team + // The shared secret is unique per merchant (not per terminal) + + //Now we need to find our device and connect to it + discoverDevices(); + } + + // Now we need to connect to a device to start taking payments. + // Let's search for them: + public void discoverDevices() { + + // OPTION 1 - Search for devices asynchronously + // For Bluetooth + this.api.searchDevices(ConnectionMethod.BLUETOOTH); + // Or, for USB + this.api.searchDevices(ConnectionMethod.USB); + // This triggers the asynchronous search for all the devices around that haven't been previously paired in the case of Bluetooth, + // or which are connected via cable in the case of USB. + + // OPTION 2 - Search for devices synchronously + // Alternatively, already paired devices can be searched in the case of Bluetooth: + List devices = this.api.getPairedDevices(ConnectionMethod.BLUETOOTH); + // Or, already cable-connected devices can be searched in the case of USB: + List devices = this.api.getPairedDevices(ConnectionMethod.USB); + // And then: + selectDeviceAndConnect(devices); + // You'll receive the devices found through deviceDiscoveryFinished method. + // See: https://handpoint.com/docs/device/Android/#elem_eventsDeviceDiscoveryFinished + } + + @Override + public void deviceDiscoveryFinished(List devices) { + selectDeviceAndConnect(devices); + } + + private void selectDeviceAndConnect(List devices) { + for (Device device : devices) { + if (device.getName() != null) { + // All the devices here are datecs devices + if (/* Fill your logic here */) { + this.api.connect(device); + // Now take a look at connectionStatusChanged method + break; + } + } + } + } + + // Potentially, if you know the MAC address of the Bluetooth device you want to connect to, you can skip the search and do it this way. This is an uncommon use case though. + // This is not possible in the case of a USB connection, because a concrete UsbDevice object which represents the physically connected USB device is needed + public void connect() { + Device device = new Device("PP0513901435", "68:AA:D2:00:D5:27", null, ConnectionMethod.BLUETOOTH); + //The Address always has to be written in UPPER CASE + //new Device("name", "address", null, ConnectionMethod.BLUETOOTH); + this.api.connect(device); + } + + @Override + public void connectionStatusChanged(ConnectionStatus status, Device device) { + if (status == ConnectionStatus.Connected) { + // Connected to device + } + } + + public OperationStartResult pay() { + return this.api.sale(new BigInteger("1000"), Currency.GBP); + // Let´s start our first payment of 10.00 pounds + // Use the currency of the country in which you will be deploying terminals + } + + @Override + public void currentTransactionStatus(StatusInfo statusInfo, Device device) { + if (statusInfo.getStatus() == StatusInfo.Status.InitialisationComplete) { + // The StatusInfo object holds the different transaction statuses like reading card, pin entry, etc. + // Let's launch a payment + pay(); + } + } + + @Override + public void signatureRequired(SignatureRequest signatureRequest, Device device) { + // You'll be notified here if a sale process needs a signature verification + // A signature verification is needed if the cardholder uses an MSR or a chip & signature card + // This method will not be invoked if a transaction is made with a Chip & PIN card + // At this step, you are supposed to display the merchant receipt to the cardholder on the android device + // The cardholder must have the possibility to accept or decline the transaction + // If the cardholder clicks on decline, the transaction is VOID + // If the cardholder clicks on accept he is then asked to sign electronically the receipt + this.api.signatureResult(true); + // This line means that the cardholder ALWAYS accepts to sign the receipt + // For this sample app we are not going to implement the whole signature process + } + + @Override + public void endOfTransaction(TransactionResult transactionResult, Device device) { + // The object TransactionResult stores the different receipts + // Other information can be accessed through this object like the transaction ID, the amount... + } + + @Override + public void transactionResultReady(TransactionResult transactionResult, Device device) { + // Pending TransactionResult objects will be received through this event if the EndOfTransaction + // event was not delivered during the transaction, for example because of a network issue. + // For this sample app we are not going to implement this event. + } + + public void disconnect() { + this.api.disconnect(); + //This disconnects the connection + } +} +``` + +:::info +**Note about reconnections:** By default, the SDK will automatically reconnect to the last known device when the connection is lost. If you want to change this behaviour set the property Settings.AutomaticReconnection in HapiManager to **false**. +::: + +**We're done!** + +Sort of. With the above tutorial you've done a basic integration that can perform sale transactions. + +Explore the rest of the documentation to see more transaction types supported and possibilities. \ No newline at end of file diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidintroduction.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidintroduction.md new file mode 100644 index 0000000..5e2a9ce --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidintroduction.md @@ -0,0 +1,138 @@ +--- +sidebar_position: 1 +id: androidintroduction +--- + +# Introduction + + + + +
+
+
+

Android SDK

+
+
+ +
+ +
+
+ +

+ +:::tip +If you are currently using 6.x of the Android SDK, take a look at the [migration guide](androidmigrationguide.md) to 7.x +::: + + +The new generation of Handpoint APIs and SDKs are engineered to make your life simpler and happier. + +**Awesomely simple** + +Created for humans, coders, geeks, no need of a dark and complex knowledge of the payment industry. + +

+ +**Super secure** + +We take care of PCI compliance so you can be kept out of PCI scope. The Handpoint terminals encrypt all sensitive cardholder data so your app does not have to deal with it. + +### SDK distribution + +The Handpoint Android SDK is available on the Handpoint internal Nexus server which contains both the **production builds** and **development snapshots** of the SDK. +- If you are integrating your software with a **PAX debug terminal** you will need to use the development Snapshots, listed as -RC.X-SNAPSHOT for example **7.1010.3-RC.1-SNAPSHOT** +- If you are integrating your software with a **PAX production terminal** or with a **HiLite terminal** you will need to use the Production versions listed eg **7.1010.3** + +If in doubt regarding what version to use, we always recommend using the latest available production version, for development snapshots the recommendation is to use the latest RC (highest number) that matches the latest production SDK version published. Our support team is also available to answer any questions regarding what version to use. + +The Handpoint Android SDK is compatible with Android version 5.1.1 [(API level 22)](https://developer.android.com/about/versions/lollipop/android-5.1) and up. +The latest version is compiled with java **1.8** + + + +### AndroidManifest.xml + +We **strongly** recommend you add the following to your `AndroidManifest.xml`: + +- Inside the tag **``** -> `android:extractNativeLibs:"true"` + +```xml + + +``` + +- Inside the tag **``** -> `android:launchMode="singleTask"`: + +```xml + + ... + ... + +``` + +### Gradle Settings + +```groovy + //Handpoint Staging/Development SDK (Debug terminals) + implementation 'com.handpoint.api:sdk:7.x.x-RC.x-SNAPSHOT' +``` + In the `gradle.build` (Top-level build file) for debug terminals (Nexus) [Only applies to PAX/Telpo devices]: + + ```groovy + allprojects { + repositories { + google() + mavenCentral() + maven { + name = "Handpoint Nexus" + url = uri("urlProvided") //URL provided by Handpoint once you order a dev kit + credentials { //Credentials provided by Handpoint once you order a dev kit + username = 'usernameProvided' + password = 'passwordProvided' + } + } + } + } + ``` + +- Some considerations to keep in mind when using gradle (for both production and debug terminals) + + In the `gradle.build` (app module) add the following packaging options: + + ```groovy +android { + defaultConfig { + minSdkVersion 22 //Required to support all PAX & Telpo models + targetSdkVersion 29 //If using version targetSdkVersion 30 or higher, please note that you will need + //to add android:exported="true" or android:exported="false" in your activities + multiDexEnabled true + ndk { + abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" + } + } + + packagingOptions { + pickFirst '**/*.so' + exclude 'META-INF/*' + exclude '**/anim/*.xml' + exclude '**/layout/*.xml' + exclude 'resources.arsc' + exclude 'AndroidManifest.xml' + exclude '**/animator/*.xml' + } + } + ``` + +It is time to visit our **[Integration Guides](androidintegrationguide)** section. + +If you have any questions, do not hesitate to **[Contact Us](mailto:support@handpoint.com)**. diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidmigrationguide.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidmigrationguide.md new file mode 100644 index 0000000..0811895 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidmigrationguide.md @@ -0,0 +1,265 @@ +--- +sidebar_position: 3 +id: androidmigrationguide +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Migration from 6.X to 7.X{#1} +The new version 7.X.X of our Android SDK introduces the following changes: +1. We removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) for a simpler and smoother integration. +2. All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#OperationStartResult) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal: + - The MAIN reason why we are now returning an object is because we want to give you access to the `transactionReference` field inside the `OperationStartResult` object. The `transactionReference` field is a unique identifier for the transaction that you will receive immediately after sending the transaction request to the terminal. If for any reason you do not receive the `TransactionResult` object at the end of the transaction you will now be able to use the `transactionReference` to directly query our Gateway and know instantly if the transaction for which you do not know the outcome was approved or declined. +3. We are introducing a new feature called **duplicate payment check**. Looking back at our data we have seen that when a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are now flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the 2nd charge, this menu is pushed by our SDK and will automatically be displayed on top of your own UI when required. We are only prompting the duplicate menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature will be **enabled by default** in the Android sdk 7.0.0 and can be disabled by passing a false value as part of the sale options [`saleOptions.setCheckDuplicates(false);`](androidmigrationguide.md#4). +4. The `deviceCapabilities` event has been renamed to `supportedCardBrands`. +5. The [`saleAndTokenize`](androidtransactions#3) method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale`. + +## 1. New Interfaces + +For an easier integration with our SDK we removed the `Events.Required` interface and divided it into 3 different interfaces: + +- `Events.SmartposRequired` which are the mandatory events to subscribe to for a PAX integration. +- `Events.MposRequired` which are the mandatory events to subscribe to for an HiLite integration. +- `Events.PosRequired` which are the mandatory events to subscribe to if you are doing both a PAX AND HiLite integration. + +Here is the list of events being part of each interface: + +#### Interface SmartposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` + +#### Interface MposRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + +#### Interface PosRequired +- `Events.PendingResults` +- `Events.ConnectionStatusChanged` +- `Events.CurrentTransactionStatus` +- `Events.EndOfTransaction` +- `Events.DeviceDiscoveryFinished` +- `Events.SignatureRequired` + + + + +The changes required for each of the above scenarios is described below. + + +### Android Native Integration (PAX) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class HandpointDelegate implements + Events.SmartposRequired, + Events.CurrentTransactionStatus, + Events.ConnectionStatusChanged, + Events.EndOfTransaction, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.SmartposRequired { +``` + + + + +### Bluetooth Integration (HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.MposRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.MposRequired { +``` + + + + +### Bluetooth and Android Native Integration (PAX & HiLite) + +#### Older Implementation (Android SDK 6.X) + + + +```java +public class HandpointDelegate implements + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: + Events.Required, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus { +``` + + + + +#### Current Implementation (Android SDK 7.X) + + + +```java +public class JavaClient implements + Events.PosRequired, + Events.ConnectionStatusChanged, + Events.CurrentTransactionStatus, + Events.SignatureRequired, + Events.EndOfTransaction, + Events.DeviceDiscoveryFinished, + Events.TransactionResultReady { +``` + + + + + +```java +class KotlinClient: Events.PosRequired { +``` + + + + + +## 2. All financial operations are now returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean{#3} + +The methods affected by this change are the following: + +- [Sale](androidtransactions.md#2) +- [SaleReversal](androidtransactions.md#4) +- [Refund](androidtransactions.md#5) +- [RefundReversal](androidtransactions.md#6) +- [MotoSale](androidtransactions.md#7) +- [MotoRefund](androidtransactions.md#8) +- [MotoReversal](androidtransactions.md#9) +- [TokenizeCard](androidtransactions.md#12) +- [CardPan](androidtransactions.md#13) + + +## 3. Disabling the duplicate payment check service{#4} + +**This functionality is only available for SmartPos devices (PAX).** + +By default, the duplicate payment check service is enabled. If you want to manually disable this service you will need to set the `checkDuplicate` field to `false` using the `SaleOptions` parameter. Here is an example: + +```java +public void pay(BigInteger amount, Currency currency) { + SaleOptions saleOptions = new SaleOptions(); + saleOptions.setCheckDuplicates(false); + this.api.sale(amount, currency, saleOptions); +} +``` +You can disable the duplicate check functionality for the following financial operations: +- [Sale](androidtransactions.md#2) +- [Sale and Tokenize](androidtransactions.md#3) +- [Refund](androidtransactions.md#5) + +## 4. The `deviceCapabilities` event has been renamed to `supportedCardBrands` + + Check out the [card brand display](androideventlisteners.md#cardBrandDisplay) object. + + +## 5. The `saleAndTokenize` method has been removed. Since Android SDK 7.0.0, a `saleAndTokenizeOptions` object needs to be passed in 'options' parameter of financial operations methods like `sale` + +Check out the [Sale and Tokenize Card](androidtransactions.md#3) section. + diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidobjects.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidobjects.md new file mode 100644 index 0000000..ec9cd65 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidobjects.md @@ -0,0 +1,1216 @@ +--- +sidebar_position: 9 +id: androidobjects +--- + + + + + +# Objects + +## Transaction Result{#25} + +`TransactionResult` Object + +An object holding information about the result of a transaction. + +:::tip +`signatureUrl`: In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format. + +`customerReceipt` and `merchantReceipt`: The receipts are usually received as URLs in the transaction result from the terminal. Please note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and an URL is not generated then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. +::: + + **Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `aid`
*String* | Application Identifier of the card (EMV tag 9F06).| +| `arc`
*String* | EMV Authorisation Response Code (EMV tag 8A).| +| `authorisationCode`
*String* | Acquirer response code.| +| `balance`
[*Balance*](#balance) | Balance available on the card.| +| `budgetNumber`
*String* | Used to split payments over a period of months.| +| `cardEntryType`
[*CardEntryType *](#22) | Method used by the terminal to read the card.| +| `cardLanguagePreference`
*String* | Preferred language of the card (EMV tag 5F2D).| +| `cardSchemeName`
[*CardSchemeName*](#32) | The brand of the card.| +| `cardToken`
*String* | Token representing the PAN of the card.| +| `chipTransactionReport`
*String* | Full report of the card EMV parameters.| +| `currency`
[*Currency*](#13) | The currency used for the transaction.| +| `customerReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `customerReference`
*String* | If a customerReference was provided as an optional parameter in the transaction request it is echoed unaltered in this field.| +| `deviceStatus`
[*DeviceStatus*](#33) | Status of the device.| +| `dueAmount`
*String* | In case of a partial approval for the transaction, this field contains the amount which remains to be paid.| +| `efttimestamp`
*Date* | Time of the transaction.| +| `efttransactionID`
*String* | Handpoint unique identifier for a transaction, this id is the one to be used for a transaction to be reversed.| +| `errorMessage`
*String* | Detailed reason for the transaction error.| +| `expiryDateMMYY`
*String* | Expiry date of the card used for the operation.| +| `finStatus`
[*FinancialStatus*](#34) | The financial status contains the outcome of the transaction. For example "AUTHORISED" or "DECLINED".| +| `iad`
*String* | Issuer Application Data (EMV tag 9F10).| +| `issuerResponseCode`
*String* | Response code from the card issuer.| +| `maskedCardNumber`
*String* | Masked card number of the card used for the operation.| +| `merchantAddress`
*String* | Merchant Address.| +| `merchantName`
*String* | Merchant Name.| +| `merchantReceipt`
*String* | A URL containing the customer receipt in HTML format. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | +| `metadata`
[*Metadata*](#metadata) | If metadata was provided as an optional parameter in the transaction request it is echoed unaltered in this field| +| `mid`
*String* | Merchant Identifier.| +| `originalEFTTransactionID`
*String* | In case the transaction type is a reversal, this field will contain the identifier of the original transaction being reversed.| +| `paymentScenario`
[*PaymentScenario*](#35) | Indicates the card entry mode.| +| `recoveredTransaction`
*Boolean* | This flag is set to true if the transaction result is sent through the transaction recovery logic (network or communication failure), false otherwise.| +| `requestedAmount`
*BigInteger* | The requested amount is the transaction amount sent to the terminal.| +| `rrn`
*String* | Retrieval Reference Number, unique number assigned by the acquirer.| +| `signatureUrl`
*String* | If a digital signature is required, this is the URL containing the image of the captured signature. In case the signature can not be updated to the Handpoint servers and an URL is not generated, the terminal will send back the image binary in base64 format to your software. It is important to be able to support both the URL and the image binary format.| +| `statusMessage`
*String* | The status of the transaction, for example "Waiting for pin".| +| `tenderType`
[*TenderType*](#36) | Transaction tender type (credit / debit).| +| `tid`
*String* | Terminal Identifier.| +| `tipAmount`
*BigInteger* | Tip amount, if any, in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `tipPercentage`
*Double* | If tipping is enabled, this field will return the tip percentage added on top of the base amount.| +| `totalAmount`
*BigInteger* | The total amount is the amount the card was charged for. It is possible that the total amount is not the same as the requested amount since an additional fee can be added, with the customer's approval, via the tipping functionality.| +| `transactionID`
*String* | The transaction id is a terminal internal counter incremented for each transaction.| +| `tsi`
*String* | Transaction Status Information (EMV tag 9B).| +| `tvr`
*String* | Transaction Verification Results (EMV tag 95).| +| `type`
[*TransactionType*](#31) | The type of transaction initiated, for example "SALE".| +| `unMaskedPan`
*String* | Unmasked PAN, only received if the card is a non-payment card (loyalty).| +| `verificationMethod`
[*VerificationMethod*](#38) | cardholder verification method, for example "PIN".| +| `multiLanguageStatusMessages`
*Map* | `Map` containing the status message in a human readable format for all the supported locales.| +| `multiLanguageErrorMessages`
*Map* | `Map` containing the error message in a human readable format for all the supported locales.| +| `cardHolderName`
*String* | Name of the cardholder.| + + +**Code example** + + +```json +{ + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "123456", + "balance": null, + "budgetNumber": "", + "cardEntryType": "UNDEFINED", + "cardLanguagePreference": "", + "cardSchemeName": "MasterCard", + "cardToken": "", + "chipTransactionReport": "", + "currency": "USD", + "customerReceipt": "https://s3.[...]/customerReceipt.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "ClientApp", + "applicationVersion": "20.1.0", + "batteryCharging": "Not Charging", + "batteryStatus": "100", + "batterymV": "4126", + "bluetoothName": "PAXA920", + "externalPower": "USB", + "serialNumber": "0821032398", + "statusMessage": "Approved or completed successfully" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0422", + "finStatus": "AUTHORISED", + "iad": "0210A000002A0000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************1456", + "merchantAddress": "Plaza Soledad Torres Acosta 1 28013 Madrid", + "merchantName": "Hago la cama", + "merchantReceipt": "https://s3.[...]/merchantReceipt.html", + "metadata": { + "metadata1":"data 1", + "metadata2":"data 2", + "metadata3":"data 3", + "metadata4":"data 4", + "metadata5":"data 5", + }, + "mid": "", + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "rrn": "", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "ACQUIRER_TID", + "tipAmount": 0, + "totalAmount": 100, + "transactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "tsi": "0000", + "tvr": "0400008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "UNDEFINED", + "efttimestamp": 1615374961000, + "efttransactionID": "01236fc0-8192-11eb-9aca-ad4b0e95f241", + "requestedAmount": 100, + "tipPercentage": 0, + "recoveredTransaction": false, + "multiLanguageStatusMessages": [ + { "en_US" : "Approved or completed successfully" }, + { "fr_FR" : "Transaction approuvée" } + ], + "multiLanguageErrorMessages": [], + "cardHolderName": "cardholder name" +} +``` + +## Acquirer{#21} + +`Acquirer` Enum + +An enum representing all the supported acquirers for merchant authentication. + +**Possible values** + +`AMEX` `BORGUN` `EVO` `OMNIPAY` `POSTBRIDGE` `INTERAC` `TSYS` `VANTIV` `SANDBOX` + +**Code example** + +```java +public enum Acquirer { AMEX, + BORGUN, + EVO, + OMNIPAY, + POSTBRIDGE, + INTERAC, + TSYS, + VANTIV, + SANDBOX +} +``` + +## Balance + +`Balance` Object + +Balance available on the card + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*Integer* | The amount balance | +| `currency`
*Currency*| The balance currency | +| `sign`
[*BalanceSign*](#balance-sign) | Positive (C) or negative (D) balance. You can retrieve the balance sign using the methods isPositive() or isNegative() | + +**Code example** + +```java +Balance balance = Balance.Companion.factory( + "1000", + Currency.EUR.getAlpha(), + BalanceSign.POSITIVE_SIGN.name() + ) +``` + +## Balance Sign + +`BalanceSign` Enum + +An enum representing the balance sign. + + +**Possible values** + +`POSITIVE_SIGN('C')` `NEGATIVE_SIGN('D')` + +## Card Brands{#cardBrands} + +`CardBrands` Enum + +A string representing the supported card brands. + +**Possible values** + +`VISA` `MASTERCARD` `MAESTRO` `AMEX` `DISCOVER` `DINERS` `JCB` `INTERAC` `OTHER` + + +## Card Entry Type{#22} + +`CardEntryType` Enum + +An enum representing different card entry types. + +**Possible values** + +`UNDEFINED` `MSR` `ICC` `CNP` + +## Card Scheme Name{#32} + +`CardSchemeName` Enum + +A string representing different card brands. + +**Possible values** + +`MasterCard` `Visa` `Maestro` `American Express` `Discover` `JCB` `Diners` `UnionPay` `Interac` + + +## Card Tokenization Data + +`CardTokenizationData` Object + +An object representing the tokenized card. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `token`
*String* | Token representing the card number| +| `expiryDate`
*String*| Expiration date of the card| +| `tenderType`
[*TenderType*](#36) |ternder type of the card (credit/debit) | +| `issuerCountryCode`
*CountryCode* | The country code of the issuer of the card [(ISO 3166-1)](https://en.wikipedia.org/wiki/ISO_3166-1) | + +## Connection Method{#20} + +`ConnectionMethod` Enum + +An enum representing different connection methods with the payment terminal. + +Currently `BLUETOOTH`, `ANDROID_PAYMENT` and `USB` are the only supported types. + +**Possible values** + +`BLUETOOTH` `ANDROID_PAYMENT` `USB` + +**Code example** + +```java +//Currently BLUETOOTH, ANDROID_PAYMENT and USB are the only connection methods available. +public enum ConnectionMethod { + BLUETOOTH, + ANDROID_PAYMENT, + USB +} +``` + +## Connection Status + +`ConnectionStatus` Enum + +A list of connection statuses. Note: the events starting with Cloud[...] are exclusively for devices linked to merchants with CLOUD Api key (CLOUD mode enabled) and can be safely ignored for Android native integrations. + +**Possible values** + +`Connected` `Connecting` `Disconnected` `Disconnecting` `NotConfigured` `Initializing` `CloudConnected` `CloudInitialized` `CloudAvailable` `CloudDisconnected` `CloudUnavailable` + +## Currency{#13} + +`Currency` Enum + +An enum of currencies. + +It contains the name of the currency, its ISO code, as well as information about how many decimals the currency uses. + +**Possible values** + +`AED` `AFN` `ALL` `AMD` `ANG` `AOA` `ARS` `AUD` `AWG` `AZN` `BAM` `BBD` `BDT` `BGN` `BHD` `BIF` `BMD` `BND` `BOB` `BOV` `BRL` `BSD` `BTN` `BWP` `BYR` `BZD` `CAD` `CDF` `CHF` `CLP` `CNY` `COP` `COU` `CRC` `CUC` `CUP` `CVE` `CZK` `DJF` `DKK` `DOP` `DZD` `EEK` `EGP` `ERN` `ETB` `EUR` `FJD` `FKP` `GBP` `GEL` `GHS` `GIP` `GMD` `GNF` `GTQ` `GYD` `HKD` `HNL` `HRK` `HTG` `HUF` `IDR` `ILS` `INR` `IQD` `IRR` `ISK` `JMD` `JOD` `JPY` `KES` `KGS` `KHR` `KMF` `KPW` `KRW` `KWD` `KYD` `KZT` `LAK` `LBP` `LKR` `LRD` `LSL` `LTL` `LVL` `LYD` `MAD` `MDL` `MKD` `MMK` `MNT` `MOP` `MUR` `MVR` `MWK` `MXN` `MXV` `MYR` `MZN` `NAD` `NGN` `NIO` `NOK` `NPR` `NZD` `OMR` `PAB` `PEN` `PGK` `PHP` `PKR` `PLN` `PYG` `QAR` `RON` `RSD` `RUB` `RWF` `SAR` `SBD` `SCR` `SDG` `SEK` `SGD` `SHP` `SLL` `SOS` `SRD` `STD` `SYP` `SZL` `THB` `TJS` `TMT` `TND` `TOP` `TRY` `TTD` `TWD` `TZS` `UAH` `UGX` `USD` `UZS` `VEF` `VND` `VUV` `WST` `XAF` `XCD` `XOF` `XPF` `YER` `ZAR` `ZMK` `ZWL` + +## Device{#17} + +`Device` Object + +An object to store the information about the payment terminal in use. + +**Methods** + +**Constructor** + +```java +Device(String name, String address, UsbDevice usbDevice, ConnectionMethod connectionMethod, String sharedSecret, int timeout); +``` + +| Parameter | Notes | +| ----------- | ----------- | +| `name` Required
*String* | A name to identify the device| +| `address` Required
*String* | The address of the device you wish to connect to. E.g.: "08:00:69:02:01:FC" for bluetooth or just an identifier if your application is running directly on a PAX or Telpo device (ConnectionMethod.ANDROID_PAYMENT).| +| `usbDevice` Required
*UsbDevice* | Represents a concrete attached USB device.| +| `connectionMethod` Required
[*ConnectionMethod *](#20) | Type of connection with the payment terminal. E.g: Bluetooth| +| `sharedSecret`
*String* | Replaces the default shared secret proviced in the initialization step.| +| `timeout`
*int* | The number of miliseconds until a connection is considered timed out. If not set, the default timeout is 15 seconds.| + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Id *`
*String* | A unique identifier for the payment terminal.| + + + +**Code example** + +```java +//Create and init a new Datecs Device +Device dev = new Device("CardReader7", "08:00:69:02:01:FC", "1", ConnectionMethod.BLUETOOTH); + +//Create and init a new PAX/Telpo Device for a ANDROID_PAYMENT connection +Device dev = new Device("LocalPaxOrTelpo", "LocalHost", "null", ConnectionMethod.ANDROID_PAYMENT); +``` + +## Device Capabilities{#24} + +`DeviceCapabilities` Object + +An object holding the capabilities of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `printer`
*Boolean* | True if the terminal has printer, false otherwise| +| `cloudApi`
*Boolean*| True if the terminal is cloud-enabled, false otherwise| + +## Device Parameter + +`DeviceParameter` Enum + +An enum describing all the admin commands to send to a payment terminal. + +**Possible values** + +`BluetoothName` `BluetoothPass` `SystemTimeout` `ScreenTimeout` `SignatureTimeout` + +## Device Status{#33} + +`DeviceStatus` Object + +A class which holds the status of the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `SerialNumber`
*String* | Gets the serial number of the payment terminal| +| `BatteryStatus`
*String* | Gets the battery status of the payment terminal (in percentages)| +| `BatterymV`
*String* | Gets the battery voltage of the payment terminal| +| `BatteryCharging`
*String* | Gets the battery charging status of the payment terminal| +| `ExternalPower`
*String* | Gets the status of the payment terminal external power| +| `ApplicationName`
*String* | Gets the application name of the payment terminal| +| `ApplicationVersion`
*String* | Gets the application version of the payment terminal| + +## Financial Status{#34} + +`FinancialStatus` Enum + +An enum representing different statuses of a finalized transaction + +**Possible values** + +`UNDEFINED` `AUTHORISED` `DECLINED` `PROCESSED` `FAILED` `CANCELLED` `PARTIAL_APPROVAL` `IN_PROGRESS` `REFUNDED` `CAPTURED` + + +Description of the different financial statuses: + +| Parameter | Notes | +| ----------- | ----------- | +| `UNDEFINED` (NOT FOUND)
| Any financial status other than the below mentioned financial statuses will be `UNDEFINED`. The `UNDEFINED` (NOT FOUND) status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. This status means that the transaction does not exist in the Handpoint gateway. If this status is returned within 90s of the start of a transaction, there could be a chance that the cardholder has not inserted, swiped or tapped his card yet on the terminal and the Handpoint gateway might soon receive the transaction. If the `UNDEFINED` status is returned after 90s, it means that the transaction processed has not reached the Handpoint gateway and it will NOT be charged.| +| `AUTHORISED`
| The transaction (Sale, Refund, etc.) has been authorised. Consider this value as "successful". | +| `DECLINED`
| The transaction has been declined by the acquirer or issuer. | +| `PROCESSED`
| The `printReceipt` operation was successful.| +| `FAILED`
| Status generated due to a network error, a card which can not be read etc. As a general rule, errors are mapped to `FAILED`. This means the operation was unsuccessful and the transaction has not been charged. | +| `CANCELLED`
| The transaction has been cancelled. For example if the `stopCurrentTransaction` operation has been used or the cancel button on the terminal has been pressed. | +| `PARTIAL_APPROVAL`
| A partial approval is returned by the acquirer when funds have been partially authorized, for example if the cardholder does not have all the funds to cover the entire cost of the goods or services they are buying. The merchant can obtain the remainder of the purchase amount in another form of payment (cash, check or another card transaction for the remaining). `PARTIAL_APPROVAL` is **only** applicable to the United States market. | +| `IN_PROGRESS` *
| The `IN_PROGRESS` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The transaction is known by the gateway but the result is not available yet. Please check the status again after a few seconds. | +| `REFUNDED` *
| The `REFUNDED` status can be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. The original transaction (sale) has been refunded. | +| `CAPTURED`
| The pre-authorization has been captured and funds are being moved to the merchant account. The `CAPTURED` financial status will only be returned in case a [preAuthorizationCapture](androidtransactions.md#pre-auth-capture) message was used to complete a pre-authorization. Regular Sales do NOT need to be captured and will not return a `CAPTURED` financial status. | + + +\* Financial statuses marked with an asterisk (*) can only be returned as a response to the [get transaction status](androiddevicemanagement.md#getTransactionStatus) method. + +## Handpoint Credentials{#43} + +`HandpointCredentials` Object + +A class containing the credentials used to communicate with the payment terminal, essentially the shared secret (always required). +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sharedSecret`
*String* | `String` the value of the Shared secret.| + + +**Code example** + +```java +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + HandpointCredentials handpointCredentials = new HandpointCredentials(sharedSecret); + //We've even set a default shared secret! +} +``` + +## Handpoint API (Hapi) Factory + +`HapiFactory` Object + +A factory to provide a unified entrypoint and simplify the instantiation of the Hapi object. + +**Methods** + +**Static factory** +getAsyncInterface( Events.Required requiredListener , Context context , HandpointCredentials handpointCredentials ); + +| Parameter | Notes | +| ----------- | ----------- | +| `requiredListener` Required
[*Events.Required*](androideventlisteners.md#42) | A listener object to report the required events.| +| `context` Required
*Context* | The Android context.| +| `handpointCredentials` Required
[*HandpointCredentials*](#43) | An object containing the actor's shared secret key.| + + +**Code example** + +```java +//InitApi for Datecs devices or PAX/Telpo ConnectionMethod.ANDROID_PAYMENT +public void InitApi() +{ + String sharedSecret = "0102030405060708091011121314151617181920212223242526272829303132"; + api = HapiFactory.getAsyncInterface(this, new HandpointCredentials(sharedSecret)); + //The api is now initialized. Yay! we've even set a default shared secret +} +``` + +## Hapi Manager + +`HapiManager` Object + +A static class containing information about the current status of the SDK + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `DefaultSharedSecret`
*String* | Gets the default shared secret in use.| +| `LogLevel`
[*LogLevel*](#18) | Gets the current log level of the SDK and payment terminal.| +| `inTransaction`
*boolean* | Checks whether the SDK is in the middle of a transaction. True if the SDK is in a transaction, false otherwise.| +| `SdkVersion`
*String* | Gets the current SDK version.| +| `isTransactionResultPending`
*boolean* | In the case of a communication failure between the payment terminal and the SDK a TransactionResult might have not been delivered. This function checks if there is a pending TransactionResult. This field is only updated when connecting to a payment terminal. If this function returns true the TransactionResult (which includes the receipt) can be fetched.getPendingTransactionResult();. This function serves the same functionality as the event pendingTransactionResult(Device device), so every time this event is invoked, HapiManager.IsTransactionResultPending() is true until the result is fetched.| +| `Settings.AutomaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the payment terminal after a disconnection. The SDK internally maintains a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is true| + +**Code example** + +```java +//Check if the SDK is in transaction +boolean inTransaction = HapiManager.inTransaction(someConnectedDevice); +//Check the current logLevel +LogLevel level = HapiManager.getLogLevel(); + +//Disable automatic reconnection feature +HapiManager.Settings.AutomaticReconnection = false; +``` + +## Log Level{#18} + +`LogLevel` Enum + +An enum describing the different levels of logging available. + +**Possible values** + +`None` `Info` `Full` `Debug` + +## Manufacturer{#manufacturer} + +`Manufacturer` Enum + +A string representing different payment terminal supported manufacturers. + +**Possible values** + +`INVALID` `DATECS` `PAX` `TELPO` + +## MerchantAuth{#37} + +`MerchantAuth` Object + +An object to store merchant authentication. + +**Methods** + +```java +Constructor +MerchantAuth( ); +``` + +```java +Constructor +MerchantAuth( Credential credential ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
[*Credential*](#40) | If present, adds the given credential to the list.| + +```java +Constructor +MerchantAuth( List credentials ); +``` +| Parameter | Description | +| ----------- | ----------- | +| `credential`
*List* | If present, the list of credentials.| + +```java +Add Credential +add( Credential credential ); +``` + +| Parameter | Description | +| ----------- | ----------- | +| `credential` Required
[*Credential*](#40) | The credential to be added.| + +**Code example** + +```java +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +``` + +## Merchant Auth Credential{#40} + +`Credential` Object + +An object to store credentials (Acquirer, Mid, Tid, MCC and ExternalId) for merchant authentication. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `acquirer`
[*Acquirer *](#21) | If present, it links this credential to the specified acquirer. Required if more than one credential is provided.| +| `mid`
*String* | For this transaction, overrides the default MID (merchant ID) saved in the terminal configuration.| +| `tid`
*String* | For this transaction, overrides the default TID (terminal ID) saved in the terminal configuration.| +| `mcc`
*String* | Merchant Category Code, overrides the default MCC saved in the terminal configuration.| +| `ExternalId`
*String* | For this transaction, the External Id will be used to lookup the credential of the merchant in the Handpoint backend and process the transaction accordingly. The External id replaces the need to pass MID/TID/MCC as credentials| + +**Code example** + +```java +// Credential using Acquirer, MID, TID and MCC +Credential credential1 = new Credential(); +//Optionally +credential1.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential1.setMid(mid); +//Optionally +credential1.setTid(tid); +//Optionally +credential1.setMcc(mcc); + +// Credential using ExternalId +Credential credential2 = new Credential(); +credential2.setExternalId(externalId); +``` + +## Merchant Auth Options{#MerchantAuthOptions} + +`MerchantAuthOptions` Object + +An object to store merchant authentication options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| + +**Code example** + +```java +MerchantAuthOptions options = new MerchantAuthOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); +``` + +## Metadata{#metadata} + +`Metadata` Object + +An object to store metadata. This field can be used to pass custom data to the Handpoint gateway, it will be echoed back in the transaction result. This field will also be part of the transaction response if querying the Handpoint transaction reporting API. + +**Properties** + +| Property | Description | +| ----------- | ----------- | +| `metadata1`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata2`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata3`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata4`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `metadata5`
*String* | An arbitrary string containing any information/data. Max length 250 characters
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| + +**Code example** + +```java +// Option 1 +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +// Option 2 +Metadata metadata = new Metadata(); +metadata.setMetadata1("Data 1"); +metadata.setMetadata2("Data 2"); +metadata.setMetadata3("Data 3"); +metadata.setMetadata4("Data 4"); +metadata.setMetadata5("Data 5"); +``` + + +## Money Remittance Options + +`MoneyRemittanceOptions` Object + +An object representing options for Mastercard money remittance transactions. The recipient's first and last name and the recipient's country code are mandatory for Mastercard transactions processed by merchants with category codes 4829 and 6540. VISA transactions do not require money remittance options to be sent. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `fullName` Required
*String* | first and last name of the recipient of the funds| +| `countryCode` Required
*CountryCode* | Country code of the recipient of the funds [(ISO 3166-1 alpha-3)](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-3)| + +**Code example** + +```java +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +``` + +## MoTo Channel + +`MoToChannel` Enum + +A enum representing the channel used for the card not present transaction (MO = Mail Order / TO = Telephone Order) . + +**Possible values** + +`MO` `TO` + +## MoTo Options + +`MoToOptions` Object + +An object to store optional parameters for card not present (MoTo) transactions. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Channel`
[*MoToChannel*](#moto-channel) | MO for Mail order - TO for Telephone order| +| `Tokenize`
*Boolean* | Flag to activate tokenization of the operation, if this flag is set, a token representing the PAN of the card will be sent back by the Handpoint sytems| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + + + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("Trx3245"); +options.setTokenize(true); +options.setTokenize(false); +options.setChannel(MoToChannel.MO); +options.setChannel(MoToChannel.TO); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); +``` + +## Operation DTO + +`OperationDto` Object + +Object indicating which financial transaction type needs to be performed after tokenization of the card during a Tokenize Payment Operation. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `sale`
[*Sale*](androidtransactions.md#2) | A sale sends a payment request to the payment terminal.| +| `refund`
[*Refund*](androidtransactions.md#5) | A refund operation moves funds from the merchant account to the cardholder´s credit card.| +| `saleReversal`
[*Sale Reversal*](androidtransactions.md#4) | A sale reversal, also called sale VOID allows the user to reverse a previous sale operation.| +| `refundReversal`
[*Refund Reversal*](androidtransactions.md#6) | A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation.| + + + +## Operation Start Result {#OperationStartResult} + +`OperationStartResult` Object + +Object containing information about the financial operation being performed. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `operationStarted`
*boolean* | `true` if the operation has started. false otherwise | +| `transactionReference`
*String* | The `transactionReference` **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction. A linked refund or a reversal will **not** return a `transactionReference` because the transaction reference for those types of transactions is the same as the one received for the original financial operation.| +| `errorMessage`
*String* | Detailed reason for the transaction error. | + + +## Optional Transaction Parameters + +`OptionalParameters` Object + +A class containing optional transaction parameters supported by the payment terminal. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `Budget`
*String* | **Budget is only available for sale transactions.** A `String` representing the key for a budget number.A budget number can be used to split up an amout over a period of months. The value has to be a `String` of 2 digits representing the number of months to split the transaction to.| +| `CustomerReference`
*String* | **CustomerReference is available for all transactions.** A `String` representing the key for a customer reference.A customer reference can be used for an internal marking system. The value is sent as a `String` of a maximum 25 characters and received back when the transaction has been processed.| + +## Options{#7} + +`options` Object + +An object to store customer reference options for regular operations. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,` | + +**Code example** + +```java +Options options = new Options(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); +``` + +## Payment Scenario{#35} + +`PaymentScenario` Enum + +An enum representing different types of scenario. + +**Possible values** + +`UNKNOWN` `MAGSTRIPE` `MAGSTRIPECONTACTLESS` `CHIP` `CHIPCONTACTLESS` `CHIPFAILMAGSTRIPE` `MOTO` + +## PAX A80 Keys{#28} + +`PaxA80Keys` String + +A string representing the PAX A80 physical keyboard keys. + +**Possible values** + +`0` `1` `2` `3` `4` `5` `6` `7` `8` `9` `GREEN` `ORANGE` `RED` `FUNC` `options`
[*SaleOptions*](#4) + +## Print Error{#29} + +`PrintError` Enum + +An enum representing different errors that can come from print action. + +**Possible values** + +`Unexpected` `InvalidArgument` `CantConnectToPrinter` `NotSupported` `NoPermission` `PrinterDisabled` `NotWhitelisted` `Busy` `OutOfPaper` `DataPacketInvalid` `PrinterHasProblems` `PrinterOverheating` `PrintingUnfinished` `FontNotPresent` `FontFormatError` `TooLong` `BatteryTooLow` `PaperCutterError` `PaperCutterJam` `CoverOpen` `UnsupportedEncoding` + +## Refund Options{#6} + +`RefundOptions` Object + +An object to store all the customization options for a refund. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +RefundOptions options = new RefundOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions saleOptions = new RefundOptions(true, moneyRemittanceOptions); +``` + +## Report Configuration{#19} + +`ReportConfiguration` Object + +An object to store all the configuration for a transactions report. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `currency`
[*Currency*](#13) | The currency to filter the transactions| +| `startDate`
*String* | The start date in format 'YYYYMMDDHHmmss'.| +| `endDate`
*String* | The end date in format 'YYYYMMDDHHmmss'.| +| `timeZone`
*String* | The time zone in format '+00:00'.| +| `terminalSerialNumber`
*List* | The serial number of the terminal to fetch the transactions from (if terminalSerialNumber is empty or null, the report will show all the transactions for this merchant).| + +**Code example** + +```java +ReportConfiguration configuration = new ReportConfiguration("'USD'", "'20210430000000'", "'20210430235959'", "null"); + +If you want to add terminal serial numbers: List terminalSerialNumber = new ArrayList<>(); +terminalSerialNumber.add("0123456789"); +terminalSerialNumber.add("9876543210"); + ... ; +``` + +## Sale Options{#4} + +`SaleOptions` Object + +An object to store all the customization options for a sale. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `Metadata`
[*Metadata*](#metadata) | Object used to store metadata, this data will be echoed in the transaction result.
Valid characters: `a-z A-Z 0-9 - ( ) @ : % _ \ + . ~ # ? & / = { } " ' ,`| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleOptions options = new SaleOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); +options.setMetadata(metadata); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true,moneyRemittanceOptions); +``` + +## Sale and Tokenize Options + +`SaleAndTokenizeOptions` Object + +An object to store all the customization options for a sale and tokenize options. + +| Parameter | Description | +| ----------- | ----------- | +| `BudgetNumber`
*String* | The budget number can be used to split payments over a period of months.| +| `CustomerReference`
*String* | An arbitrary string to use as your own identifier for a transaction| +| `MerchantAuth`
[*MerchantAuth*](#37) | An object containing all the credentials used to optionally authenticate a merchant| +| `PinBypass`
*Boolean* | Bypasses PIN entry when the shopper says they don't know the PIN for the card and the merchant either knows they are the legitimate cardholder or want to give them the benefit of the doubt. PIN Bypass should be set to True if you want to enable pin bypass for a transaction| +| `SignatureBypass`
*Boolean* | Whether the terminal prompts for a signature, depends on how you configure this. The major card schemes (American Express, Diners, Discover, JCB, Mastercard, Visa, UnionPay) no longer require a signature; they regard it as optional for card-present transactions. This means you can speed up your checkout by skipping the signature prompt. But if your business requires it, you can still let the terminal prompt for a signature. The shopper then provides their signature on the touch screen of the terminal or on the printed transaction receipt. This depends on how you configure this setting. It is your responsibility to verify the signature of the shopper with the signature on the card or another form of identification. Signature Bypass should be set to True if you want to enable signature for this transaction| +| `TipConfiguration`
[*TipConfiguration*](#39) | An object containing the tip configuration for this transaction| +| `CheckDuplicates`
*Boolean* | Used to disable the duplicate payment check functionality. When a merchant is not 100% sure of the transaction outcome, they will reprocess the transaction leading to the cardholder being charged twice. In order to avoid this scenario, we are flagging the duplicate transaction and prompting a menu to the cardholder/merchant to confirm/cancel the second charge. This menu is pushed by the Handpoint SDK and will automatically be displayed on top of your own UI when required. The Handpoint SDK will only prompt the duplicate payment check menu in case the same card is used twice in a row to process a transaction for the same amount within a 5 minutes timeframe. The duplicate payment check feature is enabled by default but can be disabled by passing a false value.| +| `MoneyRemittanceOptions`
[*MoneyRemittanceOptions*](androidobjects.md#money-remittance-options) | An object representing options for Mastercard money remittance transactions.| + +**Code example** + +```java +SaleAndTokenizeOptions options = new SaleAndTokenizeOptions(); + +//If you use a customer reference +options.setCustomerReference("Your customer reference"); + +//If you need Multi MID / Custom merchant Authentication +MerchantAuth auth = new MerchantAuth(); +Credential credential = new Credential(); +//Optionally +credential.setAcquirer(YOUR_ACQUIRER); +//Optionally +credential.setMid(mid); +//Optionally +credential.setTid(tid); +//Add as many credentials as acquirers your merchant supports (for example OMNIPAY/AMEX). +auth.add(credential); +options.setMerchantAuth(auth); + +//If you need to enable pin bypass +options.setPinBypass(true); + +//If you need to disable the duplicate payment check service +options.setCheckDuplicates(false); + +//If you want to specify the budget period +//Only available for SureSwipe +options.setBudgetNumber(YOUR_BUDGET_NUMBER); + +//If you want to specify tip options +//Only available for PAX and Telpo terminals. +TipConfiguration config = new TipConfiguration(); +//Optionally +config.setHeaderName(HEADER); +//Optionally +config.setFooter(FOOTER); +//Optionally +config.setEnterAmountEnabled(true); +//Optionally +config.setSkipEnabled(true); +config.setTipPercentages(percentages); +options.setTipConfiguration(config); + +//Alternatively, you can set the tip amount directly +options.setTipConfiguration(new TipConfiguration(AMOUNT)); + +//Adding Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); +``` + + +## Settings {#settings} + +`Settings` Object + +An Object holding the SDK initialization settings + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `automaticReconnection`
*boolean* | When this property is set to true, the SDK will automatically try to reconnect to the terminal after disconnection. The SDK maintains internally a reconnection thread which keeps on trying to connect until it succeeds. The delay between reconnections is exponentially increased on every new attempt. The default value for this property is **false**| +| `autoRecoverTransactionResult`
*boolean* | The default value for this property is **false**| +| `sendToDeviceMaxAttempts`
*Integer* | Number of retry attemps when there is an error communicating with the card reader. The default value for this property is **3**| +| `timeBetweenAttempts`
*Integer* | Time in milliseconds between attempts. The default value for this property is **5000**| +| `showSDKUIComponents`
*boolean* | The default value for this property is **false**| +| `getReceiptsAsURLs`
*boolean* | The default value for this property is **false**| + + +## Signature Request + +`SignatureRequest` Object + +A class containing information about a signature verification. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `timeout`
*int* | `int` the value of the timeout in seconds.| +| `MerchantReceipt`
*String* | `String` the merchant receipt as html. Note that if the terminal is not able to upload the receipt to the Handpoint cloud servers and generate a URL then the HTML formatted receipt will be delivered to your software. It is important to be able to manage both formats. | + +## Status {#45} + +`status` Enum + +An enum containing information about the status of a transaction. + +**Possible values** + +`Undefined` `Success` `InvalidData` `ProcessingError` `CommandNotAllowed` `NotInitialised` `ConnectTimeout` `ConnectError` `SendingError` `ReceivingError` `NoDataAvailable` `TransactionNotAllowed` `UnsupportedCurrency` `NoHostAvailable` `CardReaderError` `CardReadingFailed` `InvalidCard` `InputTimeout` `UserCancelled` `InvalidSignature` `WaitingForCard` `CardInserted` `ApplicationSelection` `ApplicationConfirmation` `AmountValidation` `PinInput` `ManualCardInput` `WaitingForCardRemoval` `TipInput` `SharedSecretInvalid` `SharedSecretAuth` `WaitingSignature` `WaitingHostConnect` `WaitingHostSend` `WaitingHostReceive` `WaitingHostDisconnect` `PinInputCompleted` `PosCancelled` `RequestInvalid` `CardCancelled` `CardBlocked` `RequestAuthTimeout` `RequestPaymentTimeout` `ResponseAuthTimeout` `ResponsePaymentTimeout` `IccCardSwiped` `RemoveCard` `ScannerIsNotSupported` `ScannerEvent` `BatteryTooLow` `AccountTypeSelection` `BtIsNotSupported` `PaymentCodeSelection` `PartialApproval` `AmountDueValidation` `InvalidUrl` `WaitingCustomerReceipt` `PrintingMerchantReceipt` `PrintingCustomerReceipt` `UpdateStarted` `UpdateFinished` `UpdateFailed` `UpdateProgress` `WaitingHostPostSend` `WaitingHostPostReceive` `Rebooting` `PrinterOutOfPaper` `ErrorConnectingToPrinter` `CardTapped` `ReceiptPrintSuccess` `InvalidPinLength` `OfflinePinAttempt` `OfflinePinLastAttempt` `ProcessingSignature` `CardRemoved` `TipEntered` `CardLanguagePreference` `AutomaticPrintingStarted` `CancelOperationNotAllowed` `UpdateSoftwareStarted` `UpdateSoftwareFinished` `UpdateSoftwareFailed` `UpdateSoftwareProgress` `InstallSoftwareStarted` `InstallSoftwareFinished` `InstallSoftwareFailed` `InstallSoftwareProgress` `UpdateConfigStarted` `UpdateConfigFinished` `UpdateConfigFailed` `UpdateConfigProgress` `InitialisationComplete` + +## Status Info + +`statusInfo` Object + +A class containing information about the status of the transaction. + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `isCancelAllowed`
*Boolean* | A `boolean` letting the integrator know if the terminal will accept a stop transaction request.| +| `status`
[*Status*](#45) | A `Status` enum representing the status of the transaction.| +| `cardLanguage`
[*SupportedLocales*](#23) | The card language preference in all supported locales.| +| `multiLanguageMessages`
*Map* | `map` containing the status message in a human readable format in all the supported locales.| +| `message`
*String* | A `String` containing the status message of the transaction.| +| `deviceStatus`
[*DeviceStatus*](#33) | A `DeviceStatus` object containing information about the payment terminal.| + +## Supported Locales{#23} + +`SupportedLocales` Enum + +An enum of the SDK supported languages. + +**Possible values** + +`en_CA` `en_UK` `en_US` `es_ES` `hr_HR` `is_IS` `fr_FR` `pt_PT` `it_IT` `no_NO` `de_DE` `sl_SL` `et_EE` + + + +## Tender Type{#36} + +`TenderType` Enum + +An enum representing different tender types. + +**Possible values** + +`NOT_SET` `CREDIT` `DEBIT` + + +## Tip Configuration{#39} + +`TipConfiguration` Object + +**Constructor** + +TipConfiguration( String tipAmount ); + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount`
*String* | If present, the amount of the tip to be used for the transaction.| + + +**Properties** + +| Parameter | Description | +| ----------- | ----------- | +| `amount`
*BigInteger* | Transaction amount in the minor unit of currency (f.ex. 1000 is 10.00 GBP).| +| `baseAmount`
*BigInteger* | Base amount used to calculate the tip - in the minor unit of currency (f.ex. 1000 is 10.00 GBP). If no base amount is defined, the transaction amount is used as base amount.| +| `headerName`
*String* | Name of the tipping menu appearing on the terminal. Default: Tip| +| `tipPercentages`
*List* | List of percentages used to calculate the tip amount. **REQUIRED**| +| `enterAmountEnabled`
*Boolean* | Flag used to enable the cardholder to manually enter the tip amount. Default: true| +| `skipEnabled`
*Boolean* | Flag used to enable the cardholder to skip the tipping step. Default: true| +| `footer`
*String* | Footer note which will appear on the tipping menu. Default: Empty string| + +**Code example** + +```json +{ + "amount": "2000", + "baseAmount": "2000", + "headerName": "", + "tipPercentages": [5,10,15,20,25], + "enterAmountEnabled": true, + "skipEnabled": false, + "footer": "Thank you!!! ;)" +} +``` + + +## Transaction Type{#31} + +`TransactionType` Enum + +An enum representing different types of transactions. + +**Possible values** + +`UNDEFINED` `SALE` `VOID_SALE` `REFUND` `VOID_REFUND` `REVERSAL` `CANCEL_SALE` `CANCEL_REFUND` `TOKENIZE_CARD` `SALE_AND_TOKENIZE_CARD` `CARD_PAN` + +## Type of Result{#30} + +`TypeOfResult` Enum + +An enum representing different types of device reports. + +**Possible values** + +`STATUS` `REPORT` `BLUETOOTHNAME` `EMVCONFIGURATION` + +## Verification Method{#38} + +`VerificationMethod` Enum + +An enum representing different verification methods used in the transaction. + +**Possible values** + +`UNDEFINED` `SIGNATURE` `PIN` `PIN_SIGNATURE` `FAILED` `NOT_REQUIRED` `MOBILE_PASS_CODE` + + diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidreleasenotes.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidreleasenotes.md new file mode 100644 index 0000000..df14e7d --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidreleasenotes.md @@ -0,0 +1,486 @@ +--- +sidebar_position: 2 +id: androidreleasenotes +--- + + + +# Release Notes + +:::tip +Don’t miss any updates on our latest releases. Contact your Handpoint relationship manager to subscribe to the Handpoint Newsletter! +::: + +## 7.1010.8 +**Fixes** + +- Minor fix in payments flow to improve error handling + + +## 7.1010.7 +**Fixes** + +- Deprecated coroutines APIs have been removed to improve compatibility for integrators + + +## 7.1010.6 +**Features**: + +- Partial reversals are supported now + +- Support for PAX A3700 reader has been added + +**Fixes** + +- Processing misalignment between SDK and Gateway has been fixed + + +## 7.1010.5 +**Features**: + +A new `cardPresent` flag is supported in Integrated mode, which comes from our [REST API](/restapi/restintroduction) or its related Cloud clients [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). This new flag allows to indicate the payments flow that a Reversal operation will imply an actual present card. Please see [Handling card present reversals with Elavon acquirers](https://handpoint.atlassian.net/wiki/spaces/PD/pages/5104533505/Handling+card+present+reversals+with+Elavon+acquirers) for further information on the purpose of this flag. + + +## 7.1010.3 +**Fixes**: + +Some timeout-ed authorization requests in the reader were still reaching the gateway. This was causing double charges. + + +## 7.1010.2 +**Fixes**: + +Network stability has been improved + + +## 7.1010.1 +**Features**: + +"Cash" and "Other" transaction types now have a Transaction ID + +**Fixes**: + +- A scenario where double charges could happen has been fixed + +- The customer receipt now is fully in the card's language (when the language tag is available) + +- Some Fiserv and Elavon certification issues have been addressed + + +## 7.1009.5 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of ***Tokenized Payments Operations***, as well as supporting a new PAX card readers model: **IM25**. This new Tokenized Payments Operations feature is an expansion of our former Tokenize and Modify feature, fully replacing and complementing it. + +**Tokenized Payments Operations** enable merchants to securely capture a customer's card information (without storing the raw card details) and use that token to immediately perform a payment-related operation. This streamlines loyalty flows, subscriptions, refunds, or reversals while keeping card data safe and PCI-compliant. + +Thanks to our new Tokenize Payments Operations feature, integrators can now first tokenize card, and right after this, apply their own bussiness logic before resuming the operation to decide how the final operation will be according to customer's loyalty points, current discount policy, or some other particular use cases. + +There are two main modes for how this works, depending on integration needs: Standalone or Cloud. + +- [Standalone Tokenized Payments Operations](androidtransactions.md#standalone-tokenized-payments-operations). In this mode, Android SDK integrators can directly use the methods this SDK offers in the app they are building on top of it, to implement their loyalty, subscriptions or related uses logic. + +- [Cloud Tokenized Payments Operations](androidtransactions.md#cloud-tokenized-payments-operations). In this mode, Tokenized Payments Operations methods and flows of the Android SDK are commanded via our Cloud clients, which can be either [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) or [Windows SDK](/windows/windowsintroduction). This allows to execute all operations programmatically, offering seamless integration with their existing workflows. + + +**Fixes**: + +- Several EMV certification issues have been addressed + +- Transaction Result was not being delivered in some cases. Now it is working properly in all use cases. + +- Refunds and Reversals didn't include the transactionReference field. This has been fixed. + + +## 7.1008.6 +**Fixes**: + +- Some translations have been corrected, as well as error messages from our Gateway + + +## 7.1008.4 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1008.3 +**Features**: + +- In account type selection, the order is first "Credit" and then "Debit" now. + +**Fixes**: + +- An issue with the remove card event has been addressed + + +## 7.1008.1 +**Fixes**: + +- Several certification issues have been addressed + + +## 7.1008.0 +**Features**: + +- Brightness level control is offered as a public method now + +- Internal payments libraries of PAX devices have been updated + +**Fixes**: + +- Some EMV related issues have been solved + +- Volume controls were accessible during payment signature screen in some use cases where the shouldn't + + +## 7.1006.3 +**Fixes**: + +- Signature was missing in receipts in some use cases + + +## 7.1006.2 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1006.1 +**Fixes**: + +- Fix for language selection menu (only for Interac cards) + + +## 7.1006.0 +**Features**: + +- Now just "CARD" in shown in receipts when the card brand is not in the language library + +**Fixes**: + +- Tokenize and Modify: A second "remove card" was being displayed after providing phone number + +- Some EMV related issues have been solved + + +## 7.1005.4 +**Fixes**: + +- The RRN was missing in the ReceiptDataKeeper object + + +## 7.1005.3 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.2 +**Fixes**: + +- Operations with 0 amount and/or tip supported + +- Receipt uploaded event's behavior has been fixed + +- Transactions corrections + +- Minor fixes in tokenization + + +## 7.1005.1 +**Fixes**: + +- Several minor stability issues have been fixed + + +## 7.1005.0 +**Features**: + +- Speed improvements: We're excited to announce the release of Handpoint Android SDK version **7.1005.0**, focused on delivering significant improvements in transaction processing speeds. This update empowers your app to handle transactions quicker and more efficiently, enhancing the overall user experience for your customers. + +- Enhanced Cloud Mode Performance: Cloud initialization will now be faster, leading to quicker overall transaction processing. Cloud transactions will benefit from these optimizations as well. + +:::caution +**Cloud Mode** users: There might be a short delay in accessing your receipt after a transaction is completed in Cloud Mode. While the transaction itself will process successfully, the receipt URL you receive might return a 404 error message for a few seconds after the transaction finishes. +::: + +## 7.1004.2 +**Features**: + +Automatic Refunds. These new methods empowers users to seamlessly process refunds without the need for any physical card or card details. + +- [Automatic Refund](androidtransactions.md#automatic-refund), users can effortlessly initiate a refund transaction without requiring the cardholder to dip, tap, or swipe their card. Users only need to pass the Original Transaction ID (GUID) to the Automatic Refund function. The system will automatically process the refund, and the refunded amount will mirror the original sale amount, simplifying the entire refund process. + + +- [Automatic Partial Refunds](androidtransactions.md#automatic-partial-refund). This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). + + + By eliminating the need for physical card involvement, Automatic Refund streamlines the refund process, saving time for both merchants and customers. This efficiency boost enhances overall transaction management, contributing to a more seamless and customer-centric experience. + + +**Fixes**: + +- Inconsistency when formatting currencies using Slovenian as the locale. + + +## 7.1004.1 +**Features**: + +We're excited to announce the latest update to our Android SDK, featuring support of Mastercard MoneySend fields for money remittance merchants. In order to use this functionality, we provide you with an object called [Money Remittance Options](androidobjects.md#money-remittance-options) which must be sent for all Mastercard transactions. + +The supported operations are Sale, Sale & Tokenize, Refund, Linked Refunds, Reversals, MoTo Sale, MoTo Refund. For Linked Refunds and Reversals, Money Remittance fields should be taken from the original Sale/MoTo/Refund when using the field `originalTransactionID`. + +***Please note**: Money Remittance is available only for some acquirers and geographies. Please check with your Handpoint relationship manager about the availability of this functionality for your merchants. + +## 7.1004.0 +**Features**: + +We are introducing a new transaction type called [Pre-Authorization](androidtransactions.md#pre-auth). A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +A pre-authorized transaction can be increased or decreased ([Pre-Auth Increase](androidtransactions.md#pre-auth-increasedecrease)), for example if a tab was opened and the consumer is adding new orders going above the initial pre-authorized amount. + +A pre-authorized transaction can be captured ([Pre-Auth Capture](androidtransactions.md#pre-auth-capture)) to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +A pre-authorized transaction can be fully released ([Pre-Auth Reversal](androidtransactions.md#pre-authcapture-reversal)), for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged + +We are also introducing the [Tokenize And Modify](androidtransactions.md#tokenize-and-modify) operation. A tokenize and modify operation allows you to start a financial operation for an initial amount, tokenize the card being dipped/tapped/swiped and modify the amount before the transaction is sent for processing. This feature allows you to bring your own loyalty engine and apply for example an instant discount at the point of sale for loyal customers. + + +## 7.1002.0 +**Features**: + +We are introducing a new feature called [Get Transaction Status](androiddevicemanagement.md#getTransactionStatus). This new feature allows you to query the Handpoint Gateway for the status of a transaction at any given time. For example, in case of an app crash, timeout, or connection problem, you are now able to use the [transaction reference](androidobjects.md#OperationStartResult) returned at the start of a financial operation to get the status of a transaction in real time. You can use this feature to track the progress of your payments and troubleshoot any issues that may arise. This feature is available for all payment methods and currencies. + +- Cloud integrations: A new parameter called `transactionReference` has been added to the [transactionStarted](androideventlisteners.md#transactionStarted) method. This means that when implementing this method in a class, you need to update the method signature to include the new parameter. + +Added Estonian language 🇪🇪 + + +## 7.1001.0 +**Features**: + + We are introducing a new feature called [Transaction Metadata](androidobjects.md#metadata). This new feature helps the customer to persist and echo back some data that belongs to the customer business domain at transaction time. The Transaction Metadata is sent in the request and echoed back in the response from the gateway. In addition, customers will be able to use the Transaction Metadata to search matching transactions from our Transaction Feed API.***** + +The Transaction Metadata feature will be available when the Handpoint Android SDK **v7.1001.0** or higher is used. + +***Please note**: Transactions will be available in TXN Feed API only if the request has reached the gateway. + +- German language support. +- Support for PAX A800 devices. + +**Fixes**: +- Bug related to automatic printing. +- Log improvements. + +## 7.0.2 + +**Features**: +- Norwegian and Italian language support. + +**Fixes**: +- Card reader capabilities identification. +- Kiosk mode management. +- Log improvements for support purposes. + +## 7.0.1 + +- Removed the `Events.Required` interface and divided it into [3 different interfaces](androidmigrationguide.md#1-new-integration-interfaces) +- All [financial operations](androidmigrationguide.md#3) will now be returning an [OperationStartResult](androidobjects.md#operation-start-result) object instead of a boolean to indicate that the operation was successfully sent to the payment terminal. +- Introducing a new feature called **duplicate payment check**. +- The `deviceCapabilities` event has been renamed to `supportedCardBrands` +- For more information please check our [migration guide](androidmigrationguide.md). + +## 6.7.4 + +- `customerReference` correctly populated when card is removed in the middle of a transaction +- MOTO: Correct handling of expired access and refresh tokens +- CLOUD: Channel connection/subscription handling + +## 6.7.3 + +**Fixes**: +- MOTO: Linked Refund only with GUID. +- Correctly populated transaction result the `originalEFTTransactionID` on Linked Refunds. +- Correctly populated on transaction result amounts on "Already reversed" operations. +- Crashes identified in the field. + + +## 6.7.2 + +**Fixes**: +- MOTO: Retry token and configuration download if missing for MoTo transactions +- CLOUD: device status moving terminals between merchants. +- CLOUD: REST-API transaction result delivery. +- `requestedAmount` field in Transaction Result correctly populated. + + +## 6.7.0 + +**Features** +- A35 support added +- Swedish language support +- Field customerReference added to TransactionResult + +**Fixes**: +- Cloud client shows "Unable to process your request" while the request reach the device +- Contactless card tokenization fixed +- CVM fixed in receipts for MOTO transactions +- Amount fields are now populated in case of FAILURE and DECLINE +- Interact/AMEX certification fixes +- Fix minor issues and app crashes + +## 6.6.7 +**Fixes**: +- SCA scenarios on PAX A80 +- CLOUD: receipt printing +- Deadman mechanism for not completed trx. App dies in the middle of a trx, will be auto cancelled in the restart + +## 6.6.3 + +**Fixes**: +- DATECS: Stop reconnection loop on api.disconnect() + +## 6.6.0 + +**Features**: + - MoTo (Mail Order Telephone Order) + +**Fixes**: + - CLOUD: Connection stability. + - AID parsing for Discover cards. + - PIN input on physical keyboards. + + +## 6.5.0 + +**Features**: + - Card brand display: 2 new events deviceCapabilities (supportedCardBrands) and readCard to show the supported card brands and card used during a transaction respectively. + - Update webview for devices that do not support co-branding. + +**Fixes**: + - Correct handling of stopCurrentTransaction operation result for cloud operations. + - Pin bypass for contactless transactions. + - Automatic reconnection logic for android Datecs devices. + +## 6.4.1 + +**Fixes**: +- Automatic Cancellation parameters. + + + +## 6.4.0 + +**Features**: +- Populate operation timeout on CLOUD operations. +- Max attempts on Cancellation retries. +- Generic screen to show text messages. + +**Fixes**: +- Base amount handling in TipDialog +- Cancellation service max retry window +- Verification method on transaction result object +- Correct population of MessageReasonCode +- Error message multi-language translation +- Cardholder name for contact operations +- Amount presentation in transactions report +- Analytics and Cloud services stability moving terminals between merchants + +**Refactor**: + +- Deprecated jcenter repository +- Improved structure of cryptography module +- Legacy code removal + +## 6.3.0 + + **Features**: + +- Print Report v2. +- PAXA80 physical keyboard full support. +- Deadman mechanism for not completed trx. +- Addition of customer reference on transaction result for cancelled of timed out trx + +**Fixes**: + +- Certification scenarios. +- Unification of sdk dialogs styles. +- Card reading during tokenizations. +- Contactless light thread handling. +- Xml parsing. +- Printing html using uncommon characters. +- Monospace font for printing. +- SCA cases on contact. +- PAX A80 Pin bypass handling. +- Receipts for partial approvals. +- Correct message on empty config update. + + **Refactor**: + +- Internal Emv Classes to improve performance. +*** + +## 6.2.2 + +**Fixes**: + +- Compatibility issues with Android 11 devices. +- CLOUD: Improved logic to wake up device and start trx during device sleep mode. +*** + +## 6.2.1 + +**Fixes**: + +- Improved bluetooth connection logic (Datecs) +*** + + + +## 6.2.0 + +**Features**: + +- New Tip Dialog. +- Multi-mid Phase 2. +- Physical Keyboard PAX-A80. +- Visa debit US app selection. +- cardHolderName filed in Transaction Result object + +**Fixes**: + +- Temporarily block during consecutive operations (Datecs devices). +- Translations. +- Compatibility with Android 11. +*** + + +## 6.1.1 + +**Fixes**: + +- Translations +*** + + + +## 6.1.0 + +**Features**: + +- End of the day report. +- New printing framework. +- Transaction limit exceeds event. +- Multi-language in Status and End of Transaction → Transaction Result new fields: multiLanguageStatusMessages and multiLanguageErrorMessages. +- Support for MerchantAuth and Bypass options for Cloud + REST-API. + +**Fixes**: + +- Receipt adjustments for mobile wallets. +- Receipt adjustments for empty tags. +- Fields in TransactionResult. +- Contactless lights after card reading error. +- REST-API ACK. +- Translations +- Error handling prior connecting to device diff --git a/android_versioned_docs/version-Android SDK 7.1010.8/androidtransactions.md b/android_versioned_docs/version-Android SDK 7.1010.8/androidtransactions.md new file mode 100644 index 0000000..7df8589 --- /dev/null +++ b/android_versioned_docs/version-Android SDK 7.1010.8/androidtransactions.md @@ -0,0 +1,2028 @@ +--- +sidebar_position: 5 +id: androidtransactions +--- + +# Transaction Types + + +## Sale{#2} + +`Sale` + +A sale initiates a payment operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +api.sale(new BigInteger("1000"),Currency.GBP); + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +// Metadata +Metadata metadata = new Metadata("Data 1", "Data 2", "Data 3", "Data 4", "Data 5"); + +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.setMetadata(metadata); + +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleOptions saleOptions = new SaleOptions(true, moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Sale And Tokenize Card{#3} + +A [sale](#2) operation which also returns a card token. (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*SaleAndTokenizeOptions*](androidobjects.md#sale-and-tokenize-options) | An object to store all the customization options for a sale ([Tip Configuration](androidobjects.md#39), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a sale for 10.00 in Great British Pounds +SaleOptions options = new SaleAndTokenizeOptions(); +api.sale(new BigInteger("1000"),Currency.GBP, options); + + +//Initiate a sale for 10.00 in Great British Pounds with a tipping configuration +//This feature is only available for PAX and Telpo devices + +TipConfiguration tipConfiguration = new TipConfiguration(); +tipConfiguration.setTipPercentages(Arrays.asList(5, 10, 15, 20)); +tipConfiguration.setTipAmount(new BigInteger("1000")); +tipConfiguration.setBaseAmount(new BigInteger("1000")); +tipConfiguration.setEnterAmountEnabled(true); +tipConfiguration.setFooter("Thank you"); +tipConfiguration.setSkipEnabled(true); +SaleOptions options = new SaleOptions(); +options.setTipConfiguration(tipConfiguration); +options.toSaleAndTokenizeOptions(); + +api.sale(new BigInteger("1000"),Currency.GBP,options); + +//Initiate a sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +SaleAndTokenizeOptions saleAndTokenizeOptions= new SaleAndTokenizeOptions(moneyRemittanceOptions); + +api.sale(new BigInteger("1000"), Currency.USD, saleAndTokenizeOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + + **Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + +## Sale Reversal{#4} + +`saleReversal` + +A sale reversal, also called sale VOID allows the user to reverse a previous sale operation. This operation reverts (if possible) a specific sale identified with a transaction id. In its simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Id of the original sale transaction| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for a sale.| + +**Code example** + +```java +//Initiate a reversal for 10.00 in Great British Pounds +api.saleReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund{#5} + +`refund` + +A refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts a map with extra parameters. Note that a card is required to be swiped, dipped or tapped for this operation. For Interac (Canadian Debit Network), refunds can only be processed until Interac closes the batch of transactions at night. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*RefundOptions*](androidobjects.md#6) | An object to store all the customization options for a refund ([Metadata](androidobjects.md#metadata), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a refund for 10.00 in Great British Pounds (Linked Refund) +api.refund(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate a refund for 10.00 USD using Money Remitance options (Linked Refund) +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +RefundOptions refundOptions= new RefundOptions(true, moneyRemittanceOptions); + +api.refund(new BigInteger("1000"), Currency.GBP, "00000000-0000-0000-0000-000000000000", refundOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the Original Transaction ID (GUID) to this function. The amount to be refunded will be the same amount as the one of the original sale. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* | Links the automatic refund with a previous sale. The amount refunded will be the same as the one of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic refund +api.automaticRefund("00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic refund using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.TO); + +api.automaticRefund("00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Automatic Partial Refund + +`automaticRefund` + +A refund operation moves funds from the merchant account to the cardholder's credit card. This operation allows you to PARTIALLY refund a card automatically without requiring the cardholder to dip/tap/swipe his card. In its simplest form you only have to pass the amount, currency and the Original Transaction ID (GUID). Note that the amount can not go above the amount of the original sale. If a refund is attempted for an amount higher than the one of the original sale, the transaction will be automatically declined. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to refund - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the refund| +| `originalTransactionID` Required
*String* | Links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate an automatic partial refund for 5.00 Great British Pounds +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); + +//Initiate an automatic partial refund for 5.00 Great British Pounds using MoTo Options +MoToOptions moToOptions = new MoToOptions(); +moToOptions.setChannel(MoToChannel.MO); + +api.automaticRefund(new BigInteger("500"),Currency.GBP,"00000000-0000-0000-0000-000000000000", moToOptions); +``` + +** Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry') +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Refund reversal{#6} + +`refundReversal` + +A refund reversal, also called refund VOID allows the merchant to reverse a previous refund operation. This operation reverts (if possible) a specific refund identified with a transaction id. In it's simplest form you only have to pass the amount, currency and originalTransactionID but it also accepts a map with extra parameters. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | transaction id of the original refund| +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Initiate a refund reversal for 10.00 in Great British Pounds +api.refundReversal(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000"); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**signatureRequired**](androideventlisteners.md#15) + +Invoked if card verification requires signature. +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## MoTo Sale{#7} + +`MoToSale` + +Mail Order /Telephone Order (MOTO) sale. MOTO is a type of card-not-present (CNP) transaction in which services are paid and delivered via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +//Initiate a MoTo sale for 10.00 in Great British Pounds +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoSale(new BigInteger("1000"), Currency.EUR, options); + +//Initiate a MoTo sale for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("Test Integration", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoSale(new BigInteger("1000"), Currency.USD, moToOptions); + +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + + + +## MoTo Refund{#8} + +`moToRefund` + +A MOTO refund operation moves funds from the merchant account to the cardholder´s credit card. In it's simplest form you only have to pass the amount and currency but it also accepts the original transaction id. MOTO Refund is a type of card-not-present (CNP) transaction in which services are refunded via telephone, mail, fax, or internet communication. MOTO has become synonymous with any financial transaction where the entity taking payment does not physically see the card used to make the purchase or refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionId`
*String* | If present it links the refund with a previous sale. It effectively limits the maximum amount refunded to that of the original transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo refund ([MoTo Channel](androidobjects.md#moto-channel), [Money Remittance Options](androidobjects.md#money-remittance-options),...)| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Refund Example"); + +api.motoRefund(new BigInteger("1000"), Currency.EUR, "00000000-0000-0000-0000-000000000000",options); + + +//Initiate a MoTo refund for 10.00 USD using Money Remitance options +MoneyRemittanceOptions moneyRemittanceOptions = new MoneyRemittanceOptions("John Doe", CountryCode.USA); +MoToOptions moToOptions = new MoToOptions(moneyRemittanceOptions); + +api.motoRefund(new BigInteger("1000"), Currency.USD,"00000000-0000-0000-0000-000000000000", moToOptions); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Reversal{#9} + +`moToReversal` + +A MOTO reversal, also called VOID allows the user to reverse a previous sale/refund operation. This operation reverts (if possible) a specific operation identified with a transaction id. Note that transactions can only be reversed within a 24 hours timeframe or until the daily batch of transactions has been sent for submission. MOTO Reversal is a type of card-not-present (CNP) transaction used to reverse a previous MOTO Sale or MOTO Refund. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionId` Required
*String* | Id of the original sale transaction.| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo reversal.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Reversal Example"); + +api.motoReversal("00000000-0000-0000-0000-000000000000",options); +``` +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + + +## MoTo Pre-Auth{#10} + +`motoPreauthorization` + +A MOTO pre-auth initiates a pre-authorization operation to the card reader. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to charge - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `options`
[*MoToOptions*](androidobjects.md#moto-options) | An object to store optional parameters for a MoTo sale.| + +**Code example** + +```java +MoToOptions options = new MoToOptions(); +options.setCustomerReference("MoTo Sale Example"); + +api.motoPreauthorization(new BigInteger("1000"), Currency.EUR, options); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the sdk (ex : 'processing'). + +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#OperationStartResult)*| Object containing information about the financial operation started.| + +## Signature result + +`signatureResult` + +A signatureRequired event is invoked during a transaction when a signature verification is required (f.ex when a payment is done with a swiped or chip and sign card). The merchant is required to ask the cardholder for signature and approve (or decline) the signature. signatureResult tells the card reader if the signature was approved by passing the value true in the method. To decline a signature event then false should be passed to the card reader. Note that this event is only required for an HiLite or Hi5 integration and can be safely ignored for a PAX or Telpo integration. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `accepted` Required
*Boolean* | pass true if merchant accepts cardholder signature| + +**Code example** + +```java +//Approves signature automatically in signatureRequired event +@Override +public void signatureRequired(SignatureRequest signatureRequest, Device device){ + api.signatureResult(true); +} +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +|*[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + + +## Tip Adjustment + +`TipAdjustment` + +A tip adjustment operation allows merchants to adjust the tip amount of a sale transaction before the batch of transactions is settled by the processor at the end of the day. +Note: This functionality is only available for the restaurant industry in the United States and the processors currently supporting this functionality are TSYS and VANTIV. + +Dependencies: +The code example provided depends on RxJava, take a look a their documentation to see how to easily include this dependency in your android project. If you do not want to use RxJava or any additional dependencies then AsyncTask, provided by android, can be used instead for this asynchronous processing. Still we recommend using RxJava as it improves readability and maintainability. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `tipAmount` Required
*BigDecimal* | Tip amount added to the original (base) transaction amount - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
*ENUM* | Currency of the original transaction | +| `originalTransactionID` Required
*String* | Unique id of the original sale transaction as received from the card reader (EFTTransactionID)| + +**Code example** + +```java +Observable.fromCallable(new Callable() { + @Override + public FinancialStatus call() throws Exception { + return api.tipAdjustment(new BigDecimal(1000), currency.GBP, "2bc23910-c3b3-11e6-9e62-07b2a5f091ec"); + } +}) +.subscribeOn(Schedulers.io()) +.observeOn(AndroidSchedulers.mainThread()) +.subscribe(new Consumer() { + @Override + public void accept(@NonNull FinancialStatus status) throws Exception { + if (status == FinancialStatus.AUTHORISED) { + //SUCCESS + } else if (status == FinancialStatus.DECLINED) { + //DECLINED + } else { + //FAILED + } +}); +``` + +**Returns** + + +Result of the tip adjustment transaction, it returns a FinancialStatus, the possible values are : + +| Parameter | Notes | +| ----------- | ----------- | +| **FinancialStatus**| - **FinancialStatus.AUTHORISED** (tip adjustment approved by the processor)
- **FinancialStatus.FAILED** (system error or timeout)
- **FinancialStatus.DECLINED** (tip adjustment declined by the processor).| + +If two tip adjustments are sent for the same sale transaction, the second tip adjustment will override the first one. In case the transaction fails (not declined) we recommend that you prompt the user of the POS to retry the adjustment. + +## Tokenize Card{#12} + +`tokenizeCard` + +Returns a card token (not available for all acquirers, please check with Handpoint to know if tokenization is supported for your acquirer of choice) + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Tokenize a card +api.tokenizeCard(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Card PAN{#13} + +`cardPan` + +A cardPan request will return the full PAN of the card being swiped, dipped or tapped. Only the PANs of whitelisted card ranges will be returned by the Handpoint systems. This operation is mostly used to be able to process funds or points from loyalty cards. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `options`
[*SaleOptions*](androidobjects.md#4) | An object to store all the customization options for the transaction.| + +**Code example** + +```java +//Gets the PAN of a card +api.cardPan(); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation started. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + + + +## Pre-Auth + +`preAuthorization` + +A pre-auth initiates a pre-authorization operation to the card reader. In it's simplest form you only have to pass the amount and currency but it also accepts tip configuration and a map with extra parameters. +A pre-authorization charge, also known as a pre-auth or authorization hold, is a temporary hold placed on a customer's payment card. It's used to verify that the account is valid and has sufficient funds to cover a pending transaction, without actually debiting the cardholder's account upfront. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `preauthOptions`
[*MerchantAuthOptions*](androidobjects.md#MerchantAuthOptions) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth for 1.00 in Great British Pounds +api.preAuthorization(new BigInteger("100"),Currency.GBP); + +//With Options +MerchantAuthOptions preauthOptions = new MerchantAuthOptions(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorization(new BigInteger("100"),Currency.GBP, preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Increase/Decrease + +`preAuthorizationIncrease` + +This operation allows the merchant to increase/decrease the amount of a previously performed pre-auth operation. For example, if a tab was opened at a restaurant and the consumer is adding new orders going above the initial pre-authorized amount, it is required to increase the amount of the initial pre-authorization before capturing it. If the merchant wants to release part of a pre-auth, an increase with **negative** amount should be passed to the function. + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of the pre-auth increase, in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction ID of the original pre-auth operation| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth increase for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); + +//Initiate a pre-auth decrease for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationIncrease(new BigInteger("-100"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Pre-Auth Capture + +`preAuthorizationCapture` + +A pre-authorized transaction can be captured to actually debit the cardholder's account. Depending on the merchant category code, the capture needs to happen between 7 and 31 days after the original pre-authorization. If not captured the funds will be automatically released by the issuing bank. + +**Please note that a pre-authorization can only be captured ONCE, multiple partial captures are not allowed**. If for some reason, the pre-authorization was captured for an incorrect amount, you can attempt to reverse the capture (does not work with all acquirers). If the capture reversal was declined, the cardholder needs to come back into the store with his card to get refunded or re-authorize the transaction. Alternatively, the cardholder can give his card details over the phone to the merchant and a MOTO pre-auth or MOTO refund can be issued. + +Card schemes set specific rules around which businesses are able to use pre-auth transactions. Eligibility is determined based on the Merchant Category Code (MCC), together with the card scheme. + +Card schemes have their own set of rules on authorisation expiry. Capturing a transaction after the scheme expiry time increases the risk of a failed capture, and may also increase the interchange and/or scheme fees charged for the transaction. Card schemes can also expire an authorisation before or after the official scheme expiry period has been reached. You can often capture a payment successfully after an authorisation has expired. Depending on the card scheme, there can be a fee for late capture, and an increase in interchange fee. The risk of cardholder chargebacks increase as well. + +| Scheme | MCC | +| ----------- | ----------- | +| Mastercard | All MCCs except 5542 | +| Visa | All MCCs except 5542 | +| Discover | 3351-3441, 3501-3999, 4111, 4112, 4121, 4131, 4411, 4457, 5499, 5812, 5813, 7011, 7033, 7996, 7394, 7512, 7513, 7519, 7999 | +| American Express | All MCCs except 5542 | + +**VISA rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 3501-3999, 7011 | Lodging | 31 days | 15% | +| 3351-3500, 7512 | Car Rental | 31 days | 15% | +| 4411 | Steamship and Cruise Lines | 31 days | 15% | +| 7513 | Truck Rentals | 7 days | 15% | +| 7033 | Trailer Parks and Campgrounds | 7 days | 15% | +| 7519 | Motor Home and Recreational Vehicle Rentals | 7 days | 15% | +| 5552 | Electric Vehicle Charging | 7 days | 15% | +| 7523 | Parking and Garages | 7 days | 15% | +| 7394 | Equipment, Tool, Furniture and Appliance Rental | 7 days | none | +| 7999 | Recreation Services | 7 days | none | +| 7996 | Amusement Parks, Carnivals, Circuses, Fortune Tellers | 7 days | none | +| 5599 | Miscellaneous Automotive, Aircraft, and Farm Equipment Dealers | 7 days | none | +| 4457 | Boat Rentals and Leasing | 7 days | none | +| 5571 | Motorcycle Shops and Dealers | 7 days | none | +| 4111 | Local and Suburban Commuter, Passenger Transportation, including Ferries | 7 days | 25 USD (or equivalent amount in local currency) | +| 4112 | Passenger Railways | 7 days | 25 USD (or equivalent amount in local currency) | +| 4131 | Bus Lines | 7 days | 25 USD (or equivalent amount in local currency) | +| 5812 | Eating Places and Restaurants | Same day | 20% | +| 5813 | Drinking Places, Bars, Taverns, Cocktail Lounges, Nightclubs, Discotheques | Same day | 20% | +| 4121 | Taxicabs and Limousines (Card-Absent Environment only) | Same day | 20% | + +**MASTERCARD rules** + +| MCC | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- | +| All MCCs | 30 days | 20% | + +**Maestro rules** + +| MCC | Segment | Authorization timeframe | Amount tolerance (captured amount above pre-authorized amount) | +| ----------- | ----------- | ----------- |----------- | +| 5812 | Eating Places and Restaurants | 7 days | 20% | +| 5814 | Fast Food Restaurants | 7 days | 20% | + + +**AMEX rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| All MCCs | 7 days | +Note: Pre-Auth with AMEX is only available in the United States/Canada with the processor TSYS. + + + +**Discover rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | 10 days | + +**Diners rules** + +| MCC | Debit/credit | Authorization timeframe | +| ----------- | ----------- | ----------- | +| Car Rental, Hotel/Lodging MCCs | All | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Credit | 30 days | +| All MCCs except Car Rental and Hotel/Lodging | Debit | 7 days | + + +**JCB rules** + +| MCC | Authorization timeframe | +| ----------- | ----------- | +| Hotel and Car rental | Time of stay/rental | +| All MCCs except Hotel and Car rental | 1 year | + + + + + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `amount` Required
*BigInteger* | Amount of funds to pre-auth - in the minor unit of currency (f.ex. 1000 is 10.00 GBP)| +| `currency` Required
[*Currency*](androidobjects.md#13) | Currency of the charge| +| `originalTransactionID` Required
*String* | Transaction id of the original pre-auth transaction| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth capture for 1.00 in Great British Pounds +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +api.preAuthorizationCapture(new BigInteger("1000"),Currency.GBP,"00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + +## Pre-Auth/Capture Reversal + +`preAuthorizationReversal` + +A Pre-Auth reversal allows the user to reverse a previous pre-auth operation. This operation reverts (if possible) a specific pre-auth identified with a transaction id. +A pre-authorized reversal transaction **will release the whole pre-authorized amount**, for example when renting a car, the pre-auth reversal allows the merchant to release the funds if the car was not damaged. For partial releases, please check the [Pre-Auth Increase/Decrease](androidtransactions.md#pre-auth-increasedecrease) operation. + +A Pre-Auth reversal can be used to reverse a capture operation as well. A capture reversal transaction **will release all the funds withheld**. Reversing a capture operation can only be done before the funds are automatically settled at night, please note that not all acquirers support reversal of captured transactions. If a capture reversal is attempted after the funds have been moved, the operation will receive a decline.

When the capture is reverted it returns to the previous state ([CAPTURED](androidobjects.md#34) -> [AUTHORISED](androidobjects.md#34)). + +**Parameters** + + +| Parameter | Notes | +| ----------- | ----------- | +| `originalTransactionID` Required
*String* |Transaction id of the original pre-auth or capture GUID transaction.| +| `preauthOptions`
[*Options*](androidobjects.md#7) | An object to store merchant authentication options for pre-auth operations.| + +**Code example** + +```java +//Initiate a pre-auth reversal +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000"); + +Options preauthOptions = new Options(); +preauthOptions.setCustomerReference("CustomerReference"); + +//Initiate a pre-auth reversal with options +api.preAuthorizationReversal("00000000-0000-0000-0000-000000000000", preauthOptions); +``` + +**Events invoked** + +[**currentTransactionStatus**](androideventlisteners.md#14) + +Invoked during a transaction, it fetches statuses coming from the terminal (ex : 'waiting for card' or 'waiting for PIN entry'). +*** + +[**endOfTransaction**](androideventlisteners.md#16) + +Invoked when the terminal finishes processing the transaction. +*** + +**Returns** + +| Parameter | Notes | +| ----------- | ----------- | +| *[OperationStartResult](androidobjects.md#operation-start-result)*| Object containing information about the financial operation performed. Most specifically the `transactionReference` which **must** be saved on your end in case you do not get back the transaction result object at the end of the transaction. The `transactionReference` will allow you to query the Handpoint Gateway directly to know the outcome of the transaction in case it is not delivered as planned by the terminal at the end of the transaction.| + + +## Standalone Tokenized Payments Operations (Tokenize and Modify) + +`standaloneTokenizedPaymentsOperations` + +### Standalone Tokenized Sale + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK enables card tokenization followed by a sale transaction. It is executed through the `Hapi` Android interface. + +This operation consists of two stages: + +1. **Card Tokenization**: The SDK tokenizes the card and triggers the **`Events.CardTokenized` event**, providing the tokenized card details and control callbacks. +2. **Sale Execution**: The integrator must invoke the `resume()` method from the callback object to proceed with the sale transaction. The outcome is returned through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of two parts. The first part, performs a tokenization of the card, + * whose token is sent to the integrator through the Events.CardTokenized event. + * Once the integrator wishes to continue the operation, + * it must execute the resume method of the object sent through the event, + * with the data of the operation it wishes to perform. + * This operation will be executed and + * the result will be received through the Events.EndOfTransaction event. + * The operation supported is Sale. + * + * @param amount The transaction amount. + * @param currency The currency to be used. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if sending failed. + */ +@JvmOverloads +fun tokenizedOperation(amount: BigInteger, currency: Currency, options: Options = Options()): OperationStartResult +``` + +--- + +** Events Flow ** + +*** 1. `Events.CardTokenized` *** + +Triggered after the card is tokenized. Provides: + +- **`CardTokenizationData`**: Contains tokenized card information. +- **`ResumeCallback`**: Allows the integrator to resume, cancel, or finish the operation. + +*** 2. `Events.EndOfTransaction` *** + +Triggered after the sale transaction is completed, returning the transaction result. + +--- + +** cardTokenized Event Components ** + +*** CardTokenizationData *** + +| Field | Type | Description | +|-----------------------|-------------------|--------------------------------------------------| +| `token` | `String` | Tokenized card value. | +| `expiryDate` | `String` | Card's expiry date. | +| `tenderType` | `TenderType` | Transaction type: `CREDIT`, `DEBIT`, or `NOT_SET`.| +| `issuerCountryCode` | `CountryCode` | Country code of the issuer (defaults to `Unknown`).| +| `cardBrand` | `String` | Brand of the card (e.g., Visa, MasterCard). | +| `languagePref` | `String` | Preferred language setting. | +| `tipAmount` | `BigInteger` | Tip amount (defaults to `BigInteger.ZERO`). | + +--- + +*** ResumeCallback *** + +Interface responsible for managing the continuation or termination of the tokenization operation. + +| Method | Description | Exceptions | +|--------------------------------------|----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `fun resume(operationDto: OperationDto)` | Continues the operation with a specified `OperationDto`. Only `Sale` operations are allowed. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun finishWithoutCardOperation()` | Completes the operation without proceeding to a card transaction. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | +| `fun cancel()` | Cancels the ongoing operation. | `ResumedOperation`, `CancelledOperation`, `TimeoutOperation`, `IllegalStateException` | + +> **Note:** +> Calling any method multiple times, after timeout, or after cancellation triggers exceptions. + +--- + +*** Example Handling of `Events.CardTokenized` (Kotlin) *** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + // Access tokenized card details + val token = cardTokenizationData.token + val cardBrand = cardTokenizationData.cardBrand + + // Decide next action: proceed with sale + resumeCallback.resume( + OperationDto.Sale( + amount = BigInteger.valueOf(2000), + currency = Currency.getInstance("USD"), + options = SaleOptions(/* configuration options */) + ) + ) +} +``` + +--- + +** OperationDto ** + +A sealed class representing supported transaction types after tokenization. + +| Subclass | Fields | Description | +|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Sale` | `amount: BigInteger`, `currency: Currency`, `options: SaleOptions` | Initiates a sale transaction. | +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. *(Not allowed after tokenization)* | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. *(Not allowed after tokenization)* | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. *(Not allowed after tokenization)* | + +--- + +** Behavior and Restrictions ** + +- **Only `Sale` operations are allowed** when invoking `resume()` after receiving the `cardTokenized` event. + - Passing other operation types (`Refund`, `SaleReversal`, `RefundReversal`) will result in a transaction result with **`MessageType.FEATURE_NOT_SUPPORTED`**. + +- Proper exception handling is required when using the `ResumeCallback` methods. + +--- + +** Exceptions ** + +| Exception | Description | +|------------------------|--------------------------------------------------------------------------------| +| `ResumedOperation` | Thrown if the operation was already resumed. | +| `CancelledOperation` | Thrown if the operation was previously cancelled. | +| `TimeoutOperation` | Thrown if the operation timed out. | +| `IllegalStateException` | Thrown for any invalid operation state. | + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized SALE Sequence Diagram](/img/standalone_tokenized_SALE.png)](/img/standalone_tokenized_SALE.png) +--- + +** Summary ** + +The **`tokenizedOperation`** method securely tokenizes card data and passes control to the integrator via the **`Events.CardTokenized` event**, delivering: + +1. **`CardTokenizationData`**: Contains the tokenized card details. +2. **`ResumeCallback`**: Allows integrators to resume with a supported `Sale` operation, cancel, or finish without a transaction. + +The result of the operation is returned through the **`Events.EndOfTransaction` event**. + +> **Tip:** Always validate and handle exceptions when interacting with `ResumeCallback` to ensure smooth operation flow. + +--- + +### Standalone Tokenized Refund, Reversal and RefundReversal + +`standaloneTokenizedRefund` + +** Overview ** + +The **`tokenizedOperation`** functionality in the Handpoint Android SDK allows the execution of a card tokenization followed immediately by a specified operation (such as SaleReversal, Refund, or RefundReversal). + +In this version, the integrator provides the required operation as a parameter, and the SDK performs: + +1. Card Tokenization (with a REST API request to retrieve the card token). +2. Execution of the operation passed by the integrator. + +The result of both actions is delivered through the **`Events.EndOfTransaction` event**. + +--- + +** Method Signature ** + +```kotlin +/** + * Tokenized Operation on a specific device using regular parameters. + * This operation consists of the consecutive execution of two operations: + * Tokenization of the card and the operation passed by parameter by + * the integrator. The result of both operations will be received through + * the Events.EndOfTransaction event. + * The operations supported are: SaleReversal, Refund, RefundReversal + * + * @param currency The currency to be used. + * @param operation The operation to be executed. + * @param options An object containing configuration parameters for customer reference. + * @return True if the command was sent successfully to the device. False if the sending was not successful. + */ +fun tokenizedOperation( + currency: Currency, + operation: OperationDto, + options: Options = Options() +): OperationStartResult +``` + +--- + +** Events Flow ** + +*** Events.EndOfTransaction *** + +Triggered after both card tokenization and the specified operation are executed. The integrator receives the final transaction result in this event. + +--- + +** Supported Operations ** + +This version of `tokenizedOperation` supports the following **OperationDto** types: + +| OperationDto Subclass | Fields | Description | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------| +| `Refund` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String?`, `options: RefundOptions` | Initiates a refund transaction. | +| `SaleReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: SaleReversalOptions` | Reverses a previous sale. | +| `RefundReversal` | `amount: BigInteger`, `currency: Currency`, `originalTransactionID: String`, `options: RefundReversalOptions` | Reverses a previous refund. | + +> **Note:** +> `Sale` operation is **not supported** in this version of `tokenizedOperation`. + +--- + +** Tokenization Process ** + +Internally, the SDK performs a REST API call to retrieve the card token. Once retrieved, it immediately proceeds to execute the operation provided by the integrator. + +--- + +*** Example Usage (Kotlin) *** + +```kotlin +val refundOperation = OperationDto.Refund( + amount = BigInteger.valueOf(1500), + currency = Currency.getInstance("EUR"), + originalTransactionID = "TX123456", + options = RefundOptions(/* options */) +) + +val result = hapi.tokenizedOperation( + currency = Currency.getInstance("EUR"), + operation = refundOperation, + options = Options(/* config */) +) +``` + +--- + +** Behavior and Restrictions ** + +- The SDK will **automatically execute** both: + 1. Tokenization (via REST API). + 2. The provided operation (`Refund`, `SaleReversal`, or `RefundReversal`). + +- The integrator will receive the outcome via **`Events.EndOfTransaction`**. + +- Sale operations are **not allowed** in this mode. + +--- + +** Exceptions ** + +The method itself returns `false` if the command fails to send to the device. Other exceptions related to transaction processing will be communicated via the **`Events.EndOfTransaction`** event. + +--- + +** Sequence Diagram ** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/standalone_Tokenized_Refund_and_reversals.png)](/img/standalone_Tokenized_Refund_and_reversals.png) + +--- + +** Summary ** + +The **`tokenizedOperation`** method allows integrators to provide a specific operation upfront (Refund, SaleReversal, RefundReversal). The SDK: + +1. Retrieves the card token via REST API. +2. Immediately executes the operation. +3. Returns the result via **`Events.EndOfTransaction`**. + +> **Tip:** Use this method when you want to perform tokenization and the operation in one streamlined flow, without intermediate decision points. + +--- + +## Cloud Tokenized Payments Operations + +`cloudTokenizedPaymentsOperations` + +** Overview ** + +In Cloud mode, integrators can control the Android SDK via one of our Cloud clients, which are our [REST API](/restapi/restintroduction), [JavaScript SDK](/javascript/javascriptintroduction) and [Windows SDK](/windows/windowsintroduction). + +There are two possible types of Cloud integrations: + +- **Integration with a callback URL** +- **Integration with Polling** + +--- + +**Integration with a callback URL** + +If a `callbackUrl` and a `token` are included in the request, the terminal sends a POST with the transaction result to the specified URL. The token will be included in the HTTP header as `AUTH-TOKEN` and can be used on the callback URL side to identify or authenticate the call. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true, "callbackUrl": "https://results.example.com/callback", "token": "auth-token-1" }' \ +https://cloud.handpoint.io/transactions +``` +*Response:* +```json +{"statusMessage":"Operation Accepted"} +``` + +*Callback:* + +The following is an example of the transaction result sent to the specified `callbackUrl`: +```json +{ + "accountType": "", + "aid": "A0000000041010", + "arc": "0000", + "authorisationCode": "010119", + "balance": null, + "budgetNumber": "", + "cardEntryType": "ICC", + "cardHolderName": "", + "cardLanguagePreference": "", + "cardSchemeName": "VISA", + "cardToken": "535120cMXnuK6046", + "cardTypeId": "************6046", + "chipTransactionReport": "", + "currency": "EUR", + "customData": "...", + "customerReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/customer.html", + "customerReference": "", + "deviceStatus": { + "applicationName": "Atom", + "applicationVersion": "20.4.9.2-RC.5", + "batteryCharging": "Full", + "batteryStatus": "100", + "batterymV": "8154", + "bluetoothName": "PAXA910S", + "externalPower": "USB", + "serialNumber": "2840011110", + "statusMessage": "" + }, + "dueAmount": 0, + "errorMessage": "", + "expiryDateMMYY": "0129", + "finStatus": "AUTHORISED", + "iad": "0210A04003240000000000000000000000FF", + "issuerResponseCode": "00", + "maskedCardNumber": "************6046", + "merchantAddress": "Random Street, Some City", + "merchantName": "Random Merchant", + "merchantReceipt": "https://receipts.handpoint.io/receipts/f6059a10-c1fe-11ef-9cf2-8b8a2cdbabca/merchant.html", + "metadata": null, + "mid": "12S001", + "moneyRemittanceOptions": null, + "multiLanguageErrorMessages": {}, + "multiLanguageStatusMessages": { + "en_CA": "Approved or completed successfully", + "fr_FR": "Transaction approuvée" + }, + "originalEFTTransactionID": "", + "paymentScenario": "CHIPCONTACTLESS", + "requestedAmount": 524, + "rrn": "513815902180", + "signatureUrl": "", + "statusMessage": "Approved or completed successfully", + "tenderType": "CREDIT", + "tid": "123123", + "tipAmount": 0, + "totalAmount": 524, + "transactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "transactionOrigin": "CLOUD", + "transactionReference": "b45ff306-78f2-4d3b-970c-e47c8d9b9f83", + "tsi": "0000", + "tvr": "0000008001", + "type": "SALE", + "unMaskedPan": "", + "verificationMethod": "NOT_REQUIRED", + "efttimestamp": 1735048275000, + "efttransactionID": "16059a10-c1fe-11ef-9cf2-8b8a2cdbabca", + "tipPercentage": 0.0, + "recoveredTransaction": false +} +``` + +**Integration using Polling** + +If the request does not include a `callbackUrl` and a `token`, then polling can be used to retrieve the transaction result from Handpoint's transaction-result endpoint. + +***Example:*** + +*Request:* + +```bash +curl -X POST -H"ApiKeyCloud: XXXXXXX-KXDMZV1-HW8MXBG-XXXXXXX" -H"Content-Type: application/json" \ +-d '{"operation": "sale", "terminal_type":"PAXA910S", "serial_number": "2840011110", "amount": "1034", "currency": "EUR", "tokenize": true }' \ +https://cloud.handpoint.io/transactions +``` + +*Response:* + +Using the `transactionResultId`, integrators can poll the transaction-result endpoint to retrieve the result: + +```json +{ + "statusMessage": "Operation Accepted", + "transactionResultId": "1840011114-1735048331833" +} +``` + +*Polling request:* + +```bash +curl -i -X GET -H"ApiKeyCloud: XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX" -H"Content-Type: application/json" \ +https://cloud.handpoint.io/transaction-result/1840011114-1735048331833 +``` + +*Possible responses from polling:* + +- 204: Transaction still in process. +- 200: Transaction result is available. + + +--- + +### Cloud Tokenized Sale + +**Overview** + +The **Cloud Tokenized Operation** enables remote-triggered financial operations, where a cloud-based system initiates a request to tokenize a card and perform a **Sale** transaction using the Android SDK. + +This operation is initiated by sending a **`CloudFinancialRequest`** object. The SDK handles the following workflow: + +1. Parses and validates the `CloudFinancialRequest`. +2. Tokenizes the card (if `tokenize` is `true` and `operation` is `Sale`). +3. Triggers the **`Events.CardTokenized`** event with token and callback. +4. Proceeds with the Sale operation upon `resume()` call. +5. Emits the final result via **`Events.EndOfTransaction`**. + +--- + +**CloudFinancialRequest** + +**Description** + +A data object that represents the request payload for initiating cloud-based financial operations including tokenized sales. + +**Key Fields** + +| Field | Type | Description | +|--------------------------|-----------------------------------|-------------| +| `operation` | `Operations` | Must be set to `Operations.Sale` for this flow. | +| `tokenize` | `Boolean` | Must be set to `true` to trigger card tokenization. | +| `amount` | `String?` | Transaction amount as string. | +| `currency` | `String?` | Currency code. | +| `callbackUrl` | `String?` | If present, indicates REST API request. | +| `originalTransactionId` | `String` | Identifier of original transaction (if any). | +| `uuid` | `String` | Event UUID, auto-formatted as 6-digit string. | +| `transactionReference` | `String` | Reference for idempotency; auto-generated if blank. | +| `receipt` | `String?` | Raw or URL-based receipt data. | +| `metadata` | `Metadata?` | Optional metadata for the operation. | +| `merchantAuth` | `MerchantAuth?` | Merchant authentication object. | +| `duplicateCheck` | `Boolean` | Enables duplicate request validation. | +| `duplicateCheckEndpoint`| `String` | Optional custom endpoint for duplicate checks. | + +> **Note:** Other fields may be present but are not required for the tokenized Sale flow. + +--- + +**Internal Behavior** + +- The SDK uses `getParsedAmount()` and `getParsedCurrency()` to convert string values into typed `BigInteger` and `Currency`. +- If `callbackUrl` is present, the request is treated as a REST API request. +- If `tokenize` is `true` and `operation == Sale`, the card is tokenized, and the **`Events.CardTokenized`** event is emitted. +- After receiving the `resume()` call, the SDK performs the Sale operation. + +--- + +**Events Flow** + +1. `Events.CardTokenized` + +Emitted after card tokenization. Provides: +- `CardTokenizationData`: Includes card token and card info. +- `ResumeCallback`: To resume with the `Sale` operation. + +2. `Events.EndOfTransaction` + +Emitted after the sale is completed. + +--- + +**Behavior and Restrictions** + +- The only supported operation for this flow is **Sale**. +- Must set: + - `operation = Operations.Sale` + - `tokenize = true` +- Invoking `resume()` with any operation other than `Sale` will result in `MessageType.FEATURE_NOT_SUPPORTED`. + +--- + +**Example CloudFinancialRequest JSON** + +```json +{ + "operation": "Sale", + "tokenize": true, + "amount": "1000", + "currency": "EUR", + "transactionReference": "a1b2c3d4", + "callbackUrl": "https://merchant.com/callback" +} +``` + +--- + +**Example Kotlin Flow** + +```kotlin +override fun onCardTokenized( + cardTokenizationData: CardTokenizationData, + resumeCallback: ResumeCallback +) { + val sale = OperationDto.Sale( + amount = cardTokenizationData.tipAmount, + currency = Currency.getInstance("EUR"), + options = SaleOptions(/* additional config */) + ) + resumeCallback.resume(sale) +} +``` + +--- + +**Sequence Diagram** + +[![Cloud Tokenized SALE](/img/cloud_tokenized_Sale.png)](/img/cloud_tokenized_Sale.png) + +--- + +**Summary** + +The **Cloud Tokenized Operation** enables external services to initiate tokenized Sale transactions through a structured `CloudFinancialRequest`. The SDK handles card tokenization and executes the Sale transaction if the correct flags are set. + +> **Tip:** This is ideal for headless or server-triggered flows that require secure card tokenization and transaction execution in a single interaction. + + +### Cloud Tokenized Sale Reversal + +**Overview** + +The **Sale Reversal Tokenized Operation** is a cloud-initiated process that tokenizes a card and performs a **Sale Reversal** transaction. This operation is triggered via a `CloudFinancialRequest` object and follows the same interaction pattern as other dependant tokenized operations. + +It is identified by: + +- `operation = Operations.SaleReversal` +- `tokenize = true` + +Upon receiving this request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator is then responsible for controlling the transaction flow using the `ResumeDependantOperationExecutor` interface. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|----------------------------------|---------------------------------------------| +| `operation` | `Operations.SaleReversal` | Identifies a Sale Reversal request. | +| `tokenize` | `true` | Triggers tokenization before the operation. | + +Other fields such as `originalTransactionId`, `currency`, `amount`, and `transactionReference` must also be set as needed. + +--- + +**Event: `Events.DependantReversalReceived`** + +Emitted when the SDK receives a cloud request for a **Sale Reversal** with tokenization enabled. The integrator handles this event via the `DependantOperationEvent` interface: + +```kotlin +interface DependantOperationEvent { + fun dependantRefundReceived( + amount: BigInteger, + currency: Currency, + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) + + fun dependantReversalReceived( + originalTransactionId: String, + resumeDependantOperation: ResumeDependantOperation + ) +} +``` + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) + fun finishWithoutCardOperation() + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantSaleReversalExecutorImpl** + +```kotlin +class ResumeDependantSaleReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalSaleReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.SaleReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_SALE + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Executes the `SaleReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Returns an `AUTHORISED` transaction result without financial movement. | +| `cancel()` | Sends a `CANCELLED` transaction result indicating cancellation. | + +--- + +**Sequence Diagram** + +[![Standalone Tokenized Refund, Reversal and RefundReversal Sequence Diagram](/img/cloud_tokenized_SaleReversal.png)](/img/cloud_tokenized_SaleReversal.png) +--- + +**Summary** + +The **Sale Reversal Tokenized Operation** is a secure, cloud-triggered flow for performing a **Sale Reversal** using a tokenized card. The operation is handled through the `DependantReversalReceived` event and executed with a `ResumeDependantOperationExecutor` implementation. + +> **Tip:** Use `finishWithoutCardOperation()` when the sale reversal is already completed outside the SDK but you want to report it as authorised for consistency. + + +### Cloud Tokenized Refund + +**Overview** + +The **Refund Tokenized Operation** is a cloud-based flow that allows merchants to initiate a tokenized refund from a remote system. It uses the same `CloudFinancialRequest` object as other cloud operations. + +This operation is identified by: +- `operation = Operations.Refund` +- `tokenize = true` + +Upon receiving the request, the SDK emits the **`Events.DependantRefundReceived`** event. The integrator must handle this event by using the **`ResumeDependantOperationExecutor`** interface to define the next step. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|------------------------------|-----------------------------------------| +| `operation` | `Operations.Refund` | Indicates the refund operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should be populated according to the use case. + +--- + +**Event: `Events.DependantRefundReceived`** + +Triggered when a tokenized refund request is received from the cloud. The integrator must respond using a `ResumeDependantOperationExecutor` implementation. + +--- + +**Interface: ResumeDependantOperationExecutor** + +Defines the actions the integrator must take after receiving the refund request. + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundExecutorImpl** + +This implementation manages the refund operation execution and fallback flows. + +```kotlin +class ResumeDependantRefundExecutorImpl( + private val currency: Currency, + private val options: InternalRefundOptions, + private val originalTransactionId: String, + private val delegate: Hapi +) : ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.Refund( + amount, + currency, + originalTransactionId.ifBlank { null }, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.originalEFTTransactionID = originalTransactionId + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Triggers the refund transaction using the provided amount, currency, and original transaction ID. | +| `finishWithoutCardOperation()` | Sends a transaction result with `AUTHORISED` status but **without processing a refund** — used when the refund was completed outside the SDK. | +| `cancel()` | Sends a transaction result with `CANCELLED` status — used when the integrator cancels the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Sequence Diagram](/img/cloud_tokenized_Refund.png)](/img/cloud_tokenized_Refund.png) + +--- + +**Summary** + +The **Refund Tokenized Operation** is a controlled cloud-based refund workflow that tokenizes the card and delegates control to the integrator for determining the refund outcome. + +- Triggered via `CloudFinancialRequest` with `operation = Refund` and `tokenize = true`. +- Uses the `ResumeDependantOperationExecutor` interface to define the refund behavior. +- Provides flexibility to execute, authorize without refund, or cancel the transaction. + +> **Tip:** Use `finishWithoutCardOperation()` when refund logic is handled outside the SDK and you only need to notify the POS system. + + +### Cloud Tokenized Refund Reversal + +**Overview** + +The **Refund Reversal Tokenized Operation** is a cloud-triggered operation that securely tokenizes a card and performs a **Refund Reversal**. This operation is initiated via a `CloudFinancialRequest` object with: + +- `operation = Operations.RefundReversal` +- `tokenize = true` + +After receiving the request, the SDK emits the **`Events.DependantReversalReceived`** event. The integrator must respond by using the **`ResumeDependantOperationExecutor`** interface to control how the operation proceeds. + +--- + +**CloudFinancialRequest Configuration** + +**Required Fields** + +| Field | Value | Description | +|------------------|-----------------------------------|----------------------------------------------| +| `operation` | `Operations.RefundReversal` | Indicates the refund reversal operation. | +| `tokenize` | `true` | Enables card tokenization. | + +Other standard fields such as `amount`, `currency`, `originalTransactionId`, and `transactionReference` should also be included. + +--- + +**Event: `Events.DependantReversalReceived`** + +This event is emitted after receiving a valid cloud request for a refund reversal. The integrator must implement `ResumeDependantOperationExecutor` to define the next action. + +--- + +**Interface: ResumeDependantOperationExecutor** + +```kotlin +interface ResumeDependantOperationExecutor { + + fun executeDependantOperation( + amount: BigInteger, + currency: Currency, + originalTransactionId: String + ) + + fun finishWithoutCardOperation() + + fun cancel() +} +``` + +--- + +**Implementation: ResumeDependantRefundReversalExecutorImpl** + +```kotlin +class ResumeDependantRefundReversalExecutorImpl( + private val currency: Currency, + private val originalTransactionId: String, + private val options: InternalRefundReversalOptions, + private val delegate: Hapi +): ResumeDependantOperationExecutor { + + override fun executeDependantOperation(amount: BigInteger, currency: Currency, originalTransactionId: String) { + val refundOperationDto = OperationDto.RefundReversal( + amount, + currency, + originalTransactionId, + options + ) + val result = delegate.tokenizedOperation(currency, refundOperationDto, options).operationStarted + if (!result) { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.FAILED + sendTransactionResult(transactionResult) + } + } + + override fun finishWithoutCardOperation() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.AUTHORISED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = currency + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.transactionID = UUID.randomUUID().toString() + transactionResult.eFTTransactionID = transactionResult.transactionID + transactionResult.originalEFTTransactionID = originalTransactionId + + InstancesManager.cardReader.isCardPresent = true + sendTransactionResult(transactionResult) + } + + override fun cancel() { + val transactionResult = InstancesManager.transactionData.generateTransactionResultWithoutResponse() + transactionResult.finStatus = FinancialStatus.CANCELLED + transactionResult.type = TransactionType.VOID_REFUND + transactionResult.currency = Currency.Unknown + transactionResult.totalAmount = BigInteger.ZERO + transactionResult.transactionOrigin = TransactionOrigin.CLOUD + transactionResult.originalEFTTransactionID = originalTransactionId + sendTransactionResult(transactionResult) + } + + internal fun sendTransactionResult(transactionResult: TransactionResult) { + TransactionResultHandler.transactionFinished(transactionResult) + } +} +``` + +--- + +**Behavior and Flow** + +| Method | Description | +|----------------------------------|-------------| +| `executeDependantOperation(...)` | Launches the `RefundReversal` operation after tokenization. | +| `finishWithoutCardOperation()` | Sends an `AUTHORISED` transaction result without moving funds — used when reversal is handled externally. | +| `cancel()` | Sends a `CANCELLED` result indicating the integrator aborted the operation. | + +--- + +**Sequence Diagram** + +[![Cloud Tokenized Refund Reversal Sequence Diagram](/img/cloud_tokenized_refund_Reversal.png)](/img/cloud_tokenized_refund_Reversal.png) + +--- + +**Summary** + +The **Refund Reversal Tokenized Operation** is a cloud-driven flow designed to securely tokenize a card and optionally reverse a refund. It follows the same interaction pattern as other dependant cloud operations, with three possible paths controlled by the integrator: + +- Execute the refund reversal. +- Acknowledge the transaction without refund movement. +- Cancel the operation entirely. + +> **Tip:** Use this operation in cloud or headless setups where refunds need to be securely reversed with authorization logging. diff --git a/android_versioned_sidebars/version-Android SDK 7.1010.8-sidebars.json b/android_versioned_sidebars/version-Android SDK 7.1010.8-sidebars.json new file mode 100644 index 0000000..caea0c0 --- /dev/null +++ b/android_versioned_sidebars/version-Android SDK 7.1010.8-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/android_versions.json b/android_versions.json index 3761e1e..abee6ad 100644 --- a/android_versions.json +++ b/android_versions.json @@ -1,4 +1,5 @@ [ + "Android SDK 7.1010.8", "Android SDK 7.1010.7", "Android SDK 7.1010.6", "Android SDK 7.1010.5",