Skip to content
Last updated

Apple Pay

Overview

It is considered best practice to offer Apple Pay as a payment method as early as possible in the checkout process, as it can significantly streamline the payment experience for users on Apple devices.

By providing Apple Pay as an option in the Drop-In UI, you can enhance user convenience and potentially increase conversion rates.

Enabling Apple Pay

There are two ways to initialise the Drop-In with Apple Pay support:

  1. Via RyftApplePayComponentConfig.auto, which will let Ryft construct and populate the information on the Apple Pay sheet automatically.
  2. Via RyftApplePayComponentConfig.manual, which allows you to manually construct the Apple's PKPaymentRequest object, giving you more control over the payment request details.

We recommend using the auto configuration for most use cases. This approach ensures that the financial details displayed to the customer are consistent with Ryft's expectations and reduces the risk of discrepancies during payment processing.

Here's an example of how to enable Apple Pay in the Drop-In configuration:

Enabling Apple Pay - Single Payment
@objc private func applePayButtonClicked() {
    let config = RyftApplePayConfig(
        merchantIdentifier: "{{your Apple merchant ID}}",
        merchantCountryCode: "{{The country code of your business}}",
        merchantName: "{{your merchant name to display on the Apple Pay sheet}}"
    )
    // assign a fresh instance each time you want to display the ApplePay sheet
    // note: store the instance at the class level
    self.applePayComponent = RyftApplePayComponent(
        publicApiKey: "{{your public API key}}",
        clientSecret: config.clientSecret,
        config: .auto(config: config),
        delegate: self
    )
    self.applePayComponent?.present { presented in
        if !presented {
            /*
            * something went wrong with presenting the ApplePay sheet
            * show an alert or retry
            */
            self.applePayButton.isEnabled = true
        }
    }
}

Handle Payment Result

Once Apple Pay has been presented and the user has completed the payment, the drop-in will dismiss.

To handle the payment result, you need to implement the RyftDropInPaymentDelegate protocol in your view controller:

Implementing RyftDropInPaymentDelegate
func applePayPayment(
    finishedWith status: RyftApplePayComponent.RyftApplePayPaymentStatus
)

This method is invoked with one of the following states:

RyftApplePayPaymentStatus
// user dismissed/cancelled the Apple Pay sheet
case cancelled
// either an unexpected error occurred or the payment failed to authorize
case error(error: Error?, paymentError: RyftPaymentError?)
// payment successful, show a receipt view
case success(paymentSession: PaymentSession)

Example

Handling Apple Pay Payment Result
public func applePayPayment(
    finishedWith status: RyftApplePayComponent.RyftApplePayPaymentStatus
) {
    applePayButton.isEnabled = true
    
    switch status {
    case .cancelled:
        break
        
    case .success(let paymentSession):
        /*
         * Display your receipt/success view.
         * The Ryft payment session is returned should you want to use
         * any of the values on it.
         */
        showSuccessView()
        
    case .error(_, let paymentError):
        // Payment failed, show an alert to the customer.
        // `paymentError.displayError` provides a human-friendly message you can display.
        let alert = UIAlertController(
            title: "Error taking payment",
            message: paymentError.displayError, // Note: Changed 'error.displayError' to 'paymentError.displayError' based on declaration
            preferredStyle: .alert
        )
        
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        
        alert.addAction(UIAlertAction(title: "Try again", style: .default) { [weak self] _ in
            // Use [weak self] to prevent retain cycles in closure
            self?.applePayClicked()
        })
        
        present(alert, animated: true, completion: nil)
    }
}