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:
| Type | Callback | Listener |
|---|---|---|
| Transaction errors | onError:withDescription: | CoreAPISaleListener |
| Communication errors | onTransactionCommError:withError:withMessage: | CoreAPISaleListener |
| Device errors | onDeviceError: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
func onError(_ error: CoreError, withDescription message: String!) {
print("Sale error \(error.rawValue): \(message ?? "")")
}
Objective-C
- (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:
Store the
CoreSaleobject on the device.When the device is back online, use
RestConnector.requestTransactionListto search for the transaction byorderIdor by the last four digits of the card.Check the result:
codeisA: we authorized the transaction.codenotA: 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.
If we authorized the sale, we recommend that you reverse it. Create a
CoreReversalwith theuniqueRefof the transaction, and then send it toRestConnector.requestwithisRefundset toNO.(Optional) Run the sale again.
The following example checks the status of the sale and resolves it when the device is back online:
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
- (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
func onDeviceError(_ deviceError: CoreDeviceError, withDescription message: String!) {
print("Device error \(deviceError.rawValue): \(message ?? "")")
}
Objective-C
- (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
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
- (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.
}