Skip to content
developers

Handle errors

Handle transaction, communication, and device errors in your Tap to Pay on iPhone integration, and resolve a sale with an unknown outcome after a communication failure.

Prerequisites: Authentication · Run a sale

The SDK reports errors through different callbacks depending on the context. There are three main types of error that the SDK can return:

TypeCallbackListener
Transaction errorsonError:withDescription:CoreAPISaleListener
Communication errorsonTransactionCommError:withError:withMessage:CoreAPISaleListener
Device errorsonDeviceError:withDescription:CoreAPIDeviceListener

Note: The examples on this page show only the method for this task. Each listener requires you to implement all of its methods. For a complete implementation, go to the sample apps.

Transaction errors

The SDK returns transaction processing failures, such as network problems, to onError:withDescription: on CoreAPISaleListener. The CoreError enumeration identifies the type of failure.

Swift

swift
func onError(_ error: CoreError, withDescription message: String!) {
    print("Sale error \(error.rawValue): \(message ?? "")")
}

Objective-C

objectivec
- (void)onError:(CoreError)error withDescription:(NSString *)message {
    NSLog(@"Sale error %d: %@", (int)error, message);
}

Note: CoreAPIRefundListener uses the same parameters for refund errors.

For the full list of CoreError values, go to the CoreError page in the SDK reference.

Communication errors

Important: If you receive a communication error, treat the sale as unresolved. If we authorized the sale, we recommend that you reverse the sale.

A communication error happens when the device reads the card successfully but the transaction request doesn't reach our gateway. Because the customer has already tapped their card, you don't know the outcome on our gateway.

The SDK returns communication errors to onTransactionCommError:withError:withMessage: on CoreAPISaleListener, and passes back the original CoreSale object.

Note: Referenced refunds don't have a dedicated communication error callback. If a referenced refund fails to reach our gateway, the SDK reports it through onError:withDescription: on CoreAPIRefundListener instead.

We recommend that you use the following recovery process for sales:

  1. Store the CoreSale object on the device.

  2. When the device is back online, use RestConnector.requestTransactionList to search for the transaction by orderId or by the last four digits of the card.

  3. Check the result:

    • code is A: we authorized the transaction.
    • code not A: we declined the transaction. There's nothing to reverse.
    • No transaction: the transaction didn't reach our gateway. There's nothing to resolve, and you can run the sale again.
  4. If we authorized the sale, we recommend that you reverse it. Create a CoreReversal with the uniqueRef of the transaction, and then send it to RestConnector.request with isRefund set to NO.

  5. (Optional) Run the sale again.

The following example checks the status of the sale and resolves it when the device is back online:

Swift

swift
func onTransactionCommError(_ sale: CoreSale!, withError error: CoreError, withMessage message: String!) {
    // Persist the sale locally for later reversal
    saveSaleOffline(sale)
}

// When connectivity is restored:
func syncPendingReversal(orderId: String, amount: NSDecimalNumber, maskedPan: String) {
    let filter = CoreTransactionFilter()
    filter.orderId = orderId

    guard let result = try? RestConnector.requestTransactionList(filter, withTerminal: terminal),
            let match = result.transactionSummary?.first as? CoreTransactionSummary else { return }

    guard match.amount == amount as NSNumber,
            let cardNumber = match.cardNumber,
            cardNumber.hasSuffix(maskedPan) else { return }

    let reversal = CoreReversal()
    reversal.deviceType = "AppleTTP"
    reversal.uniqueRef = match.uniqueRef
    _ = try? RestConnector.requestReversal(reversal, isRefund: NSNumber(value: false), withTerminal: terminal)
}

Objective-C

objectivec
- (void)onTransactionCommError:(CoreSale *)sale
                        withError:(CoreError)error
                    withMessage:(NSString *)message {
    // Persist the sale locally for later reversal
    [self saveSaleOffline:sale];
}

// When connectivity is restored:
- (void)syncPendingReversal:(NSString *)orderId amount:(NSNumber *)amount maskedPan:(NSString *)maskedPan {
    NSError *error = nil;
    CoreTransactionFilter *filter = [[CoreTransactionFilter alloc] init];
    filter.orderId = orderId;

    CoreTransactions *result = [RestConnector requestTransactionList:filter
                                                        withTerminal:self.terminal
                                                                error:&error];
    if (error || result.transactionSummary.count == 0) { return; }

    CoreTransactionSummary *match = result.transactionSummary.firstObject;
    if (![match.amount isEqualToNumber:amount]) { return; }
    if (match.cardNumber.length < 4 ||
        ![[match.cardNumber substringFromIndex:match.cardNumber.length - 4] isEqualToString:maskedPan]) { return; }

    CoreReversal *reversal = [[CoreReversal alloc] init];
    reversal.deviceType = @"AppleTTP";
    reversal.uniqueRef = match.uniqueRef;
    [RestConnector requestReversal:reversal
                            isRefund:[NSNumber numberWithBool:NO]
                        withTerminal:self.terminal
                                error:&error];
}

Device errors

The SDK returns device errors to onDeviceError:withDescription: on CoreAPIDeviceListener. The CoreDeviceError enumeration covers device failures, entitlement problems, and hardware faults.

Swift

swift
func onDeviceError(_ deviceError: CoreDeviceError, withDescription message: String!) {
    print("Device error \(deviceError.rawValue): \(message ?? "")")
}

Objective-C

objectivec
- (void)onDeviceError:(CoreDeviceError)deviceError withDescription:(NSString *)message {
    NSLog(@"Device error %d: %@", (int)deviceError, message);
}

The SDK includes a set of CoreDeviceError values that are specific to Apple Tap to Pay, and they all start with APPLE_TTP_. They cover problems such as an unsupported iPhone model, an unsupported iOS version, a disabled passcode, a blocked merchant, and account-linking failures. For the full list, go to the CoreDeviceError page in the SDK reference.

If the device encounters an error and becomes unavailable, onDeviceDisconnected: fires.

Swift

swift
func onDeviceConnected(_ type: DeviceEnum, withDeviceInfo deviceInfo: [AnyHashable: Any]!) {
    // The device is active and ready
}

func onDeviceDisconnected(_ type: DeviceEnum) {
    // The reader is unavailable. Disable your payment button.
}

Objective-C

objectivec
- (void)onDeviceConnected:(DeviceEnum)type withDeviceInfo:(NSDictionary *)deviceInfo {
    // The device is active and ready
}

- (void)onDeviceDisconnected:(DeviceEnum)type {
    // The reader is unavailable. Disable your payment button.
}

Browse guides

Search documentation

API reference169
Guides118
Knowledge38
legal1
Solutions32
Workflows74
↑↓highlight↵openView all search results

Menu

Theme

Sign out

Your saved plans remain in your organization. This browser’s private draft and account view will be cleared.

Talk to an engineer