# 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](/api/authentication) · [Set up the SDK](/guides/payments/tap-to-pay-on-iphone/set-up-the-sdk) · [Configure the processing terminal](/guides/payments/tap-to-pay-on-iphone/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.

<a id="integration-steps"></a>
## Integration steps

1. Register your listeners.
2. Initialize the device.
3. Process the sale.

<a id="step-1-register-your-listeners"></a>
## 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];
  ```

<a id="step-2-initialize-the-device"></a>
## 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](/guides/payments/tap-to-pay-on-iphone/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);
   }
   ```

<a id="accept-the-terms-and-conditions"></a>
### 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.

<a id="step-3-process-the-sale"></a>
## 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.

<a id="time-limit-for-the-tap-screen"></a>
### 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.

<a id="messages-during-the-sale"></a>
### 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](#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
}
```

<a id="sale-response"></a>
### 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:

| **Field** | **Description** |
| --- | --- |
| `code` | Indicator for the sale response. `A` indicates that we approved the sale. Any other value indicates that we declined the sale. |
| `uniqueRef` | Unique 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. |
| `status` | Status of the sale. |
| `descriptionCode` | Description of the transaction result. |
| `approvalCode` | Approval code for the sale. Our gateway returns a value for `approvalCode` only if the value of `code` is `A`. |
| `authorizedAmount` | Amount that we authorized. This amount can differ from the amount that you requested if you add a tip, a tax, or a surcharge. |
| `currency` | Currency of the sale. |
| `cardNumber` | Masked card number. |
| `cardType` | Card scheme. |
| `cardHolderName` | Cardholder's name. |
| `expiryDate` | Card's expiry date. |
| `dateTime` | Date and time that we processed the sale. |
| `orderNumber` | Order number for the sale. |
| `surcharge` | Surcharge 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);
    }
}
```

<a id="alternative-payment-methods"></a>
### 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](/guides/payments/payment-links) to your integration.

<a id="next-steps"></a>
## Next steps

- [Handle errors](/guides/payments/tap-to-pay-on-iphone/handle-errors).
- [Retrieve transactions](/guides/payments/tap-to-pay-on-iphone/retrieve-transactions).
- [Add a tip](/guides/payments/tap-to-pay-on-iphone/add-a-tip), [add a tax](/guides/payments/tap-to-pay-on-iphone/add-a-tax), or [add a line item](/guides/payments/tap-to-pay-on-iphone/add-a-line-item) to your sales.
- [Handle surcharges](/guides/payments/tap-to-pay-on-iphone/handle-surcharges).
- [Run a refund](/guides/payments/tap-to-pay-on-iphone/run-a-refund).
