Skip to content
payrocdevelopers

Run a sale

Run a sale with Tap to Pay on iPhone by registering your listeners, initializing the contactless reader, and processing a CoreSale object.

Prerequisites: Authentication · Set up the SDK · Configure the processing terminal

Register your listeners, initialize the AppleTTP plugin on the device, and then create a CoreSale object. The SDK presents Apple's ProximityReader interface for you, so you don't need to build a card-capture screen.

Integration steps

  1. Register your listeners.

  2. Initialize the device.

  3. Process the sale.

Step 1. Register your listeners

Register your listeners before you use them, and unregister them when your view controller disappears. If you don't unregister your listeners, your app can receive callbacks that are no longer relevant.

  • Add the following code to register and unregister your listeners:

    Swift

    swift
    // viewWillAppear:
    terminal.register(self as CoreAPISaleListener)
    terminal.register(self as CoreAPIRefundListener)
    terminal.register(self as CoreAPIDeviceListener)
    terminal.register(self as CoreAPIMessageListener)
    
    // viewWillDisappear:
    terminal.unRegister(self as CoreAPISaleListener)
    terminal.unRegister(self as CoreAPIRefundListener)
    terminal.unRegister(self as CoreAPIDeviceListener)
    terminal.unRegister(self as CoreAPIMessageListener)
    

    Objective-C

    objectivec
    // viewWillAppear:
    [[WTPSTerminal singleton] registerCoreAPISaleListener:self];
    [[WTPSTerminal singleton] registerCoreAPIRefundListener:self];
    [[WTPSTerminal singleton] registerCoreAPIDeviceListener:self];
    [[WTPSTerminal singleton] registerCoreAPIMessageListener:self];
    
    // viewWillDisappear:
    [[WTPSTerminal singleton] unRegisterCoreAPISaleListener:self];
    [[WTPSTerminal singleton] unRegisterCoreAPIRefundListener:self];
    [[WTPSTerminal singleton] unRegisterCoreAPIDeviceListener:self];
    [[WTPSTerminal singleton] unRegisterCoreAPIMessageListener:self];
    

Step 2. Initialize the device

Important: Don't call initDevice before you receive the onSettingsRetrieved: callback. The SDK needs your settings before it can connect to the reader. For more information, go to Configure the processing terminal.

  1. Add the following code to initialize the reader with DCT_INTERNAL as the connection type:

    Swift

    swift
    terminal.initDevice(APPLETTP, with: DCT_INTERNAL, withDeviceData: [:])
    

    Objective-C

    objectivec
    [[WTPSTerminal singleton] initDevice:APPLETTP
                      withConnectionType:DCT_INTERNAL withDeviceData:nil];
    
  2. Add the following code to monitor the reader's connection state with CoreAPIDeviceListener:

    Swift

    swift
    func onDeviceConnected(_ type: DeviceEnum, withDeviceInfo deviceInfo: [AnyHashable: Any]!) {
        // The device is active. You can start a transaction.
    }
    
    func onDeviceDisconnected(_ type: DeviceEnum) {
        // The reader is unavailable. Check the entitlement and the iOS version.
    }
    
    func onDeviceError(_ deviceError: CoreDeviceError, withDescription message: String!) {
        print("Device error: \(message ?? "")")
    }
    

    Objective-C

    objectivec
    - (void)onDeviceConnected:(DeviceEnum)type withDeviceInfo:(NSDictionary *)deviceInfo {
        // The device is active. You can start a transaction.
    }
    
    - (void)onDeviceDisconnected:(DeviceEnum)type {
        // The reader is unavailable. Check the entitlement and the iOS version.
    }
    
    - (void)onDeviceError:(CoreDeviceError)deviceError withDescription:(NSString *)message {
        NSLog(@"Device error: %@", message);
    }
    

Accept the terms and conditions

The first time that you connect to the AppleTTP plugin for a merchant, iOS displays the terms and conditions for Apple's Tap to Pay on iPhone. The merchant or a legal representative of the merchant must use an Apple account to accept the terms and conditions. They can use an existing Apple Account or a separate account for the business.

Step 3. Process the sale

  1. Add the following code to create a CoreSale object:

    Swift

    swift
    guard terminal.getDevice() != NODEVICE else {
        // The reader isn't connected. Prompt the merchant to connect before you continue.
        return
    }
    
    let sale = CoreSale()
    sale.amount = 42.00
    sale.transactionInputMethod = TAP
    sale.orderId = "YOUR_ORDER_REFERENCE"
    
    terminal.processSale(sale)
    

    Objective-C

    objectivec
    if ([[WTPSTerminal singleton] getDevice] == NODEVICE) {
        // The reader isn't connected. Prompt the merchant to connect before you continue.
        return;
    }
    
    CoreSale *sale = [[CoreSale alloc] init];
    sale.amount = [NSNumber numberWithDouble:42.00];
    sale.transactionInputMethod = TAP;
    sale.orderId = @"YOUR_ORDER_REFERENCE";
    
    [[WTPSTerminal singleton] processSale:sale];
    
  2. In amount, enter the amount of the sale in dollars.

  3. In orderId, enter a unique identifier for the order.

  4. Call processSale.

Note: For more information about the other parameters that you can send in a CoreSale object, go to the documentation in the SDK package.

Time limit for the tap screen

After you send a successful CoreSale request, the Tap to Pay screen prompts the customer to hold their card near the reader. The screen expires 40 seconds after it appears and the session times out.

If the session times out, iOS displays a Payment Timeout alert, and the customer can tap Try Again to reactivate the reader.

Messages during the sale

While the SDK runs a sale, it sends messages that describe the progress of the transaction. To receive the messages, use the CoreAPIMessageListener that you registered in Step 1. Register your listeners.

Apple's interface handles the card-capture screen, so you don't need to show a message while the customer taps their card. After the SDK reads the card, your app is visible again while we authorize the transaction. Use the messages to show the progress of the transaction during that time.

The SDK sends a CoreMessage value instead of a string. Map each value to your own text so that you can localize your messages and match the tone of your app. The following code handles the CoreMessage value during the sale:

Swift

swift
func onMessage(_ message: CoreMessage) {
    // Show your own text for this message value
}

Objective-C

objectivec
- (void)onMessage:(CoreMessage)message {
    // Show your own text for this message value
}

Sale response

The SDK returns the result of the sale to onSaleResponse: on your CoreAPISaleListener and contains the CoreSaleResponse object. The CoreSaleResponse object includes the following fields:

FieldDescription
codeIndicator for the sale response. A indicates that we approved the sale. Any other value indicates that we declined the sale.
uniqueRefUnique reference that we apply to the sale. You need to store this value to run follow-on actions, for example, retrieve the sale or run a refund.
statusStatus of the sale.
descriptionCodeDescription of the transaction result.
approvalCodeApproval code for the sale. Our gateway returns a value for approvalCode only if the value of code is A.
authorizedAmountAmount that we authorized. This amount can differ from the amount that you requested if you add a tip, a tax, or a surcharge.
currencyCurrency of the sale.
cardNumberMasked card number.
cardTypeCard scheme.
cardHolderNameCardholder's name.
expiryDateCard's expiry date.
dateTimeDate and time that we processed the sale.
orderNumberOrder number for the sale.
surchargeSurcharge that we applied to the sale, if any.

The following code handles the CoreSaleResponse object during the sale and checks if the sale was approved:

Swift

swift
func onSaleResponse(_ sale: CoreSaleResponse!) {
    if sale.code == "A" {
        // Approved. Store uniqueRef so that you can refund this sale later.
        store(uniqueRef: sale.uniqueRef)
    } else {
        // Declined. Show descriptionCode to the merchant.
        print("Declined: \(sale.descriptionCode ?? "")")
    }
}

Objective-C

objectivec
- (void)onSaleResponse:(CoreSaleResponse *)sale {
    if ([sale.code isEqualToString:@"A"]) {
        // Approved. Store uniqueRef so that you can refund this sale later.
        [self storeUniqueRef:sale.uniqueRef];
    } else {
        // Declined. Show descriptionCode to the merchant.
        NSLog(@"Declined: %@", sale.descriptionCode);
    }
}

Alternative payment methods

Apple requires apps that use Tap to Pay on iPhone to provide an alternative payment method so that merchants can always complete a sale with only an iPhone.

To offer an alternative payment method, add Payment Links to your integration.

Next steps

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