The SDK manages communication with the payment device and gateway but does not store merchant credentials. Set these at runtime:
import java.math.BigDecimal;
import com.heartlandpaymentsystems.library.entities.Card;
import com.heartlandpaymentsystems.library.terminals.ConnectionConfig;
import com.heartlandpaymentsystems.library.terminals.c2x.C2XDevice;
import com.heartlandpaymentsystems.library.terminals.moby.MobyDevice;
import com.heartlandpaymentsystems.library.terminals.enums.Environment;ConnectionConfig connectionConfig = new ConnectionConfig();
connectionConfig.setUsername("your_username");
connectionConfig.setPassword("your_password");
connectionConfig.setSiteId("your_site_id");
connectionConfig.setDeviceId("your_device_id");
connectionConfig.setLicenseId("your_license_id");
connectionConfig.setConnectionMode(ConnectionMode.BLUETOOTH);
connectionConfig.setEnvironment(Environment.TEST);C2X Device:
C2XDevice device = new C2XDevice(this.getApplicationContext(), connectionConfig);Moby 5500:
MobyDevice device = new MobyDevice(this.getApplicationContext(), connectionConfig);To pair via Bluetooth, use a device listener:
device.setDeviceListener(new DeviceListener() {
@Override
public void onBluetoothDeviceFound(BluetoothDevice bluetoothDevice) {
// Device found
}
@Override
public void onBluetoothDeviceList(HashSet<BluetoothDevice> deviceList) {
if (deviceList.isEmpty()) return;
device.connect(deviceList.iterator().next());
}
@Override
public void onConnected(TerminalInfo terminalInfo) {
// Device connected
}
@Override
public void onDisconnected() {
Start transactions with the correct builder:
CreditSaleBuilder builder = new CreditSaleBuilder(device);
builder.setAmount(new BigDecimal("10.00"));
builder.execute();Card card = new Card();
card.setNumber("424242******4242");
card.setExpMonth(12);
card.setExpYear(2025);
card.setCvv("123");
CreditSaleBuilder builder = new CreditSaleBuilder(device);
builder.setAmount(new BigDecimal("10.00"));
builder.setCreditCard(card);
builder.execute();Handle transaction responses effectively:
device.setTransactionListener(new TransactionListener() {
@Override
public void onStatusUpdate(TransactionStatus transactionStatus) {
// Status updates
}
@Override
public boolean onCardholderInteractionRequested(CardholderInteractionRequest request) {
// Handle interactions such as EMV app selection or amount confirmation
return true;
}
@Override
public void onTransactionComplete(TerminalResponse response) {
// Transaction completion logic
}
@Override
public void onError(Error error, ErrorType errorType) {
// Error handling
}
To pair via Bluetooth, set up a device listener using the following methods and examples:
device.setDeviceListener(new DeviceListener() {
@Override
public void onBluetoothDeviceFound(BluetoothDevice bluetoothDevice) {
// Called when a Bluetooth device is found
}
@Override
public void onBluetoothDeviceList(HashSet<BluetoothDevice> deviceList) {
// Called after scanning completes with a list of available devices
if (deviceList.isEmpty()) return;
device.connect(deviceList.iterator().next()); // Connect to selected device
}
@Override
public void onConnected(TerminalInfo terminalInfo) {
// Called when Bluetooth connection is successfully established
}
@
Use the following methods to handle various transaction types with the SDK:
To perform a Credit Sale transaction via card tap, insert, or swipe:
CreditSaleBuilder builder = new CreditSaleBuilder(device);
builder.setAmount(new BigDecimal("10.00"));
builder.execute();To manually enter card information for a transaction:
Card card = new Card();
card.setNumber("424242******4242");
card.setExpMonth(12);
card.setExpYear(2025);
card.setCvv("123");
CreditSaleBuilder builder = new CreditSaleBuilder(device);
builder.setAmount(new BigDecimal("10.00"));
builder.setCreditCard(card);
builder.execute();To handle transaction responses, set up a transaction listener:
device.setTransactionListener(new TransactionListener() {
@Override
public void onStatusUpdate(TransactionStatus transactionStatus) {
// Provide updates during transaction processing
}
@Override
public boolean onCardholderInteractionRequested(CardholderInteractionRequest request) {
// Manage interactions required from the cardholder
return true;
}
@Override
public void onTransactionComplete(TerminalResponse response) {
// Handle transaction completion logic
}
@Override
public void onError(Error error, ErrorType errorType) {
// Handle errors during transaction processing
The Transaction Listener handles key events during the lifecycle of a transaction. You must set up a listener to manage status updates, cardholder actions, and completion events.
device.setTransactionListener(new TransactionListener() {
@Override
public void onStatusUpdate(TransactionStatus transactionStatus) {
// Update the user with the current transaction status
}
@Override
public boolean onCardholderInteractionRequested(CardholderInteractionRequest request) {
// Respond to cardholder prompts like app selection or surcharge approval
CardholderInteractionResult result;
switch (request.getCardholderInteractionType()) {
case EMV_APPLICATION_SELECTION:
// Select the first available application
result = new CardholderInteractionResult(request.getCardholderInteractionType());
result.setSelectedAidIndex(0);
device.sendCardholderInteractionResult(result);
true from onCardholderInteractionRequested if you’ve handled the request.onTransactionComplete to capture transaction results and process receipts.If you're using a Moby 5500 reader, you can retrieve the PAN (Primary Account Number) from a gift card using the doSvaStartCard() method. This starts the card reading process.
Once the card is read, the PAN will be available in the callback for onTransactionComplete().
// Start the SVA gift card reading process
device.doSvaStartCard();
// Retrieve PAN in the transaction complete listener
@Override
public void onTransactionComplete(TerminalResponse response) {
// Access the gift card data from the response
String giftCardPan = response.getCard().getNumber();
// Use the PAN as needed
}Note: This functionality is specific to gift cards on Moby 5500 devices.
You can assign your own client-side transaction identifier using the setReferenceNumber() method. This ID will appear in the transaction response and can be used for tracking and reconciliation.
builder.setReferenceNumber("yourClientTxnId");@Override
public void onTransactionComplete(TerminalResponse response) {
String transactionId = response.getTransactionId();
// You can now match this to your original clientTxnId
}Note: If you don't set a reference number, the SDK will generate one automatically.
Auto-substantiation is commonly used in the healthcare industry to support FSA and HRA debit card transactions. It ensures qualified healthcare expenses are approved at the point of sale.
To implement this, merchants must use an IIAS (Inventory Information Approval System) that identifies eligible products.
Set the subtotal values per healthcare category before executing a transaction. These subtotals must not exceed the overall transaction amount.
creditSaleBuilder.setClinicSubTotal(new BigDecimal(5));
creditSaleBuilder.setDentalSubTotal(new BigDecimal(5));
creditSaleBuilder.setPrescriptionSubTotal(new BigDecimal(5));
creditSaleBuilder.setVisionSubTotal(new BigDecimal(5));The SDK supports over-the-air (OTA) firmware and configuration updates for C2X/C3X and Moby 5500 devices. These updates improve device functionality without requiring manual installation.
First, set a listener to retrieve available firmware or config versions:
device.setAvailableTerminalVersionsListener(new AvailableTerminalVersionsListener() {
@Override
public void onAvailableTerminalVersionsReceived(TerminalUpdateType type, List<String> versions) {
// Display or select a version to install
}
@Override
public void onTerminalVersionInfoError(Error error) {
// Handle version lookup errors
}
});
// Request firmware or config versions
device.getAvailableTerminalVersions(TerminalUpdateType.FIRMWARE);
device.getAvailableTerminalVersions(TerminalUpdateType.CONFIG);Note: Moby 5500 only returns "Update available" without specific version details.
Set a listener for the update process:
device.setUpdateTerminalListener(new UpdateTerminalListener() {
@Override
public void onProgress(Double completionPercentage, String progressMessage) {
// Show update progress to the user
}
@Override
public void onTerminalUpdateSuccess() {
// Notify that the update was successful
}
@Override
public void onTerminalUpdateError(Error error) {
// Handle update errors
}
});Initiate the update using the chosen version string:
device.updateTerminal(TerminalUpdateType.FIRMWARE, versions.get(0));Note: For Moby 5500, the version string can be null or any placeholder value.
After a successful update, the device will reboot. Watch for blinking lights as it completes the final steps. Once finished, reconnect the device to resume normal operations.
The SDK requires the following Android permissions:
INTERNET – for network communicationBLUETOOTH – to connect to card readersACCESS_FINE_LOCATION – required for Bluetooth scanning on Android 11 and belowThe SDK provides a helper class to request permissions easily:
PermissionHelper.requestPermissions(Activity activity);Refer to the example app included in the SDK package for a complete usage guide.
Store and Forward (SAF) enables offline transaction storage when internet or server connections are unavailable. These transactions can be uploaded later.
connectionConfig.setSafEnabled(true);
connectionConfig.setSafExpirationInDays(5); // Max days to store a transactiondevice.setSafListener(new SafListener() {
@Override
public void onProcessingComplete(List<TransactionResponse> responses) {
// All stored transactions attempted
}
@Override
public void onAllSafTransactionsRetrieved(List<SafTransaction> safTransactions) {
// All stored SAF transactions retrieved
}
@Override
public void onError(Error error) {
// Error encountered
}
@Override
public void onTransactionStored(String id, int totalCount, BigDecimal totalAmount) {
// A transaction was stored offline
}
device.uploadSAF();device.acknowledgeSAFTransaction(id);device.setForcedSafEnabled(true);Note: When handling follow-up actions (like refunds or voids), use the SAF ID if the original transaction hasn’t been uploaded yet. Once uploaded, it will use the new transaction ID.
Surcharge functionality allows merchants to apply a 3% fee on credit card transactions. No fee is applied if the card type cannot be determined.
Enable this feature using the connection config:
connectionConfig.setSurchargeEnabled(true);When surcharge is enabled, the SDK will prompt the cardholder to approve or decline the additional fee using the SURCHARGE_REQUESTED interaction type.
case SURCHARGE_REQUESTED:
// Prompt the user and confirm approval
CardholderInteractionResult result = new CardholderInteractionResult(CardholderInteractionType.CARDHOLDER_SURCHARGE_CONFIRMATION);
result.setFinalAmountConfirmed(true); // Or false if declined
device.sendCardholderInteractionResult(result);
return true;By default, the surcharge is calculated on the total amount including tax. To calculate pre-tax surcharge:
connectionConfig.setSurchargePreTax(true);
creditSaleBuilder.setTaxAmount(new BigDecimal("1.00"));Important:
This ensures compliance with state-specific tax and surcharge laws.