Apple Pay in your native app

This document is intented for Apple Pay in your iOS native application. For Apple Pay in your web application please see the web guide.

Setup Apple's Developer Account

Enabe Apple Pay

1. Accept Apple Pay in App

Obtain an Apple Merchant ID by registering for a new identifier in the Apple Developer portal.

Complete the form by providing a description and an identifier. The description is for your reference and can be updated later. It is recommended to use your app's name as the identifier for example merchant.{{YOUR_APP_NAME}}).

2. Create an Apple Pay Certificate

To enable your app to encrypt payment data using Apple Pay, follow these steps:

  1. Navigate to the Merchant settings in the PE Partner Portal.

  2. Scroll to the Apple Pay section and follow the provided instructions.

  3. Enter your Apple Merchant ID and download the Certificate Signing Request (CSR) file.

  4. Use the CSR file to obtain a secure certificate from Apple, enabling the use of Apple Pay.

3. Upload Apple Pay Processing Certificate

Navigate to the Apple Merchant ID that you registered earlier on the Apple Developer website. Upload the CSR file to generate an Apple Pay Processing Certificate. Once the certificate is active, download it. The certificate file should be named apple_pay.cer.

Upload the cer file back to PayEngine as described in the Apple Pay settings.

4. Integrate with Xcode

To enable Apple Pay in your app:

  1. Open your project in Xcode.

  2. Go to the Signing & Capabilities tab within your project settings.

  3. Add the Apple Pay capability.

  4. If prompted, log in to your Apple Developer account.

  5. Select the Merchant ID you previously created.

Your app is now ready to accept Apple Pay.

API Integration (iOS SDK)

// Example Swift code for integrating the API
import PayEngine

class ApplePayViewController: UIViewController, PEApplePayDelegate {
    let amount = 1.00
    
    let config = PEConfig(publicKey: "<API Public key")
    let payengine = PayEngine(config: config)
    
    func paymentSheetDidMDismiss() {
        //Handle Payment Sheet dismiss 
    }
    
    func paymentTokenDidReturn(token: String, completion: @escaping (PEApplePayResult) -> Void) {
        print("paymentTokenDidReturn \(token)")
        makePaymentWithToken(token: token, completion: completion)
    }
    
    func paymentTokenNotAvailable() {
        //Handle Payment token not available 
        print("paymentTokenNotAvailable")
    }
    
    //This is just an example of you calling your backend to complete the transaction.
    //Call completion(.success) or completion(.failure) to close the payment sheet
    private func makePaymentWithToken(token: String, completion: @escaping (PEApplePayResult) -> Void) {
        let json: [String: Any] = [
            "merchant_id": MERCHANT_ID,
            "data": [
                "cardToken": token,
                "transactionAmount": amount
            ]
        ]

        let jsonData = try? JSONSerialization.data(withJSONObject: json)

        let url = URL(string: <your-backend-url>)!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("Basic " + <your-api-key>, forHTTPHeaderField: "Authorization")
        request.setValue("\(String(describing: jsonData?.count))", forHTTPHeaderField: "Content-Length")
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
         request.httpBody = jsonData

        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data, error == nil else {
                print(error?.localizedDescription ?? "No data")
                return
            }
            let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
            if let responseJSON = responseJSON as? [String: Any] {
                print(responseJSON) //Code after Successfull POST Request
                if let responseData = responseJSON["data"] as? [String: Any] {
                    print("responseData: \(responseData)")
                    completion(.success)
                    return
                }
            }
            
            completion(.failure)
        }

        task.resume()
    }
    
    // Sample UI code
    @IBOutlet weak var stackView: UIStackView!
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    override func viewDidLoad() {
        payengine.applePay(merchantId: <merchant-id>) { result in
            switch result {
                
            case .success(let applePay):
                // register callbacks to this view controller
                applePay.delegate = self
                
                let request = ApplePayPaymentRequest()
                request.build(paymentItems: [
                    // leave empty or list of PKPaymentSummaryItem
                ], paymentAmount: self.amount, currencyCode: "USD")
                DispatchQueue.main.async {
                    if let button = applePay.setupApplePayButton(for: request, type: .checkout) {
                        /// apple pay is available, add the button to your UI
                        self.stackView.addSubview(button)
                    }
                }
            case .failure(let error):
                print("Unable to setup apple pay: \(error)")
            }
        }
        
    }
}

Handling Multiple Merchant IDs (MIDs)

Manage various merchant IDs in your app by following Apple's guidelines and ensure your app can switch between MIDs based on the transaction context.

Last updated