Skip to content

Installation

Install the iOS SDK library and start using components in your project.

Before you start

Make sure you have Xcode 14.0 or later with iOS deployment target 13.0 or later.

Step 1: Install the iOS SDK library

To get started, download the latest version of the iOS SDK from GitHub repository.

To install it using the Swift Package Manager:

  1. Open your Xcode project.
  2. Go to File > Add Package Dependencies.
  3. Enter the SDK repository URL.
  4. Select the version range or specific version.
  5. Click Add Package.
  6. Select your target and click Add Package.

Step 2: Get your API credentials

In order to initialise the SDK, you'll need to send authenticated requests to the PXP API.

To get your credentials:

  1. In the Unity Portal, go to Merchant setup > Merchant groups.
  2. Select a merchant group.
  3. Click the Inbound calls tab.
  4. Copy the Client ID in the top-right corner.
  5. Click New token.
  6. Choose a number of days before token expiry. For example, 30.
  7. Click Save to confirm. Your token is now created.
  8. Copy the token ID and token value. Make sure to keep these confidential to protect the integrity of your authentication process.

As best practice, we recommend regularly generating and implementing new tokens.

Step 3: Get the session data

Now that you have your credentials, you're ready to send an API request to the sessions endpoint. This allows you to retrieve the transaction session data from the back-end, so you can supply it when you initialise the SDK.

Our platform uses HMAC (Hash-based Message Authentication Code) with SHA256 for authentication to ensure secure communication and data integrity. This method involves creating a signature by hashing your request data with a secret key, which must then be included in the HTTP headers of your API request.

To create the HMAC signature, you need to prepare a string that includes four parts:

  • A timestamp, in Unix format. For example, 1754701373.
  • A unique request ID, in GUID format. For example, ce244054-b372-42c2-9102-f0d976db69f6.
  • The request path, which is api/v1/sessions.
  • The request body. For example:
    {
       "merchant": "MERCHANT-1",
       "site": "SITE-1",
       "sessionTimeout": 120,
       "merchantTransactionId": "0ce72cfd-014d-4256-a006-a56601b2ffc4",
       "amounts": {
         "currencyCode": "EUR",
         "transactionValue": 20
       }
    }
ParameterDescription
merchant
string (≤ 20 characters)
required
Your unique merchant identifier, as assigned by PXP. You can find it in the Unity Portal, by going to Merchant setup > Merchants and checking the Merchant ID column or by clicking on a merchant and checking the General information section.
site
string (≤ 20 characters)
required
Your unique site identifier, as assigned by PXP. You can find it in the Unity Portal, by going to Merchant setup > Sites and checking the Site ID column or by clicking on a site and checking the General information section.
merchantTransactionId
string (≤ 50 characters)
required
A unique identifier of your choice that represents this transaction.
sessionTimeout
number
required
The duration of the session, in minutes.
amounts
object
required
Details about the transaction amount.
amounts.currencyCode
string (3 characters)
required
The currency code associated with the transaction, in ISO 4217 format. See Supported payment currencies.
amounts.transactionValue
number
required
The transaction amount. The numbers after the decimal will be zero padded if they are less than the expected currencyCode exponent. For example, GBP 1.1 = GBP 1.10, EUR 1 = EUR 1.00, or BHD 1.3 = 1.300. The transaction will be rejected if numbers after the decimal are greater than the expected currencyCode exponent (e.g., GBP 1.234), or if a decimal is supplied when the currencyCode of the exponent does not require it (e.g., JPY 1.0).

Put these four parts together following this format: "{timestamp}{requestId}{requestPath}{requestBody}". The result should look something like this:

1754701373ce244054-b372-42c2-9102-f0d976db69f6api/v1/sessions{
  "merchant": "MERCHANT-1",
  "site": "SITE-1",
  "sessionTimeout": 120,
  "merchantTransactionId": "0ce72cfd-014d-4256-a006-a56601b2ffc4",
  "amounts": {
    "currencyCode": "EUR",
    "transactionValue": 20
  }
}

Use your token ID to encrypt this data structure by SHA256. You can find your token ID in the Unity Portal. Here's an example of an hmacSignature after you've encrypted the data:

1DE2DFC390D7CD746A972140F26846AFA81CF85F5A0BAABA95DBC95301795EA6

You can now put together your Authorization header. It follows this format: PXP-UST1 {tokenId}:{timestamp}:{hmacSignature}. For example:

"PXP-UST1 9aac6071-38d0-4545-9d2f-15b936af6d7f:1754701373:1DE2DFC390D7CD746A972140F26846AFA81CF85F5A0BAABA95DBC95301795EA6"

Lastly, send your request to the Sessions API. You'll need to add a request ID of your choice and include your client ID, which you can find in the Unity Portal.

Here's a full example of what your request might look like:

curl -i -X POST \
  'https://api-services.test.pxp.io/api/v1/sessions' \
  -H 'Authorization: "PXP-UST1 9aac6071-38d0-4545-9d2f-15b936af6d7f:1754701373:1DE2DFC390D7CD746A972140F26846AFA81CF85F5A0BAABA95DBC95301795EA6"' \
  -H 'X-Request-Id: "550e8400-e29b-41d4-a716-446655440000"' \
  -H 'X-Client-Id: "f47ac10b-58cc-4372-a567-0e02b2c3d479"' \
  -H 'Content-Type: application/json' \
  -d '{
  "merchant": "MERCHANT-1",
  "site": "SITE-1",
  "sessionTimeout": 120,
  "merchantTransactionId": "0ce72cfd-014d-4256-a006-a56601b2ffc4",
  "amounts": {
    "currencyCode": "EUR",
    "transactionValue": 20
  }
}'

If your request is successful, you'll receive a 200 response containing the session data.

{
  "sessionId": "c5f0799b-0839-43ce-abc5-5b462a98f250",
  "hmacKey": "904bc42395d4af634e2fd48ee8c2c7f52955a1da97a3aa3d82957ff12980a7bb",
  "encryptionKey": "20d175a669ad3f8c195c9c283fc86155",
  "sessionExpiry": "2025-05-19T13:39:20.3843454Z",
  "allowedFundingTypes": {
    "cards": [
      "Visa",
      "Diners",
      "Mastercard",
      "AmericanExpress"
    ],
    "wallets": {
      "paypal": {
        "allowedFundingOptions": [
          "venmo", 
          "paylater", 
          "paypal"
        ]
      },
      "applepay": {}
    }
  }
}
ParameterDescription
sessionId
string (UUID)
The unique identifier for the newly-created session.
hmacKey
string
The HMAC key generated for securing session communications.
encryptionKey
string
A key used for encrypting sensitive session data during communication.
sessionExpiry
string
The timestamp indicating when the session will expire, in ISO 8601 format.
allowedFundingTypes
object
Details about the funding types allowed for this session.

Possible values:
  • cards
  • wallets
allowedFundingTypes.cards
array of strings or null
The list of supported card schemes.
allowedFundingTypes.wallets
array of strings or null
The list of supported wallets.

Step 4: Configure your iOS project

Add required capabilities

  1. In Xcode, select your project target.
  2. Go to the Signing & Capabilities tab.
  3. Click + Capability and add:
    • Apple Pay: Required for Apple Pay functionality.

Configure Merchant IDs in Entitlements

In the Apple Pay capability section, add your Merchant IDs:

  • Click the + button under Merchant IDs.
  • Enter your merchant ID (e.g., merchant.com.yourcompany.store).
  • Ensure it matches exactly with your Apple Developer Console configuration.

Update Info.plist

Add the following entries to your Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <false/>
</dict>

Step 5: Initialise the SDK

To initialise the SDK, you then need to pass this session data back to your iOS application.

You'll also need to provide details about the environment you're using, your owner ID and type, the merchant shopper ID, and the transaction data.

import UIKit
import PXPCheckoutSDK

class ViewController: UIViewController {
    
    private var pxpCheckout: PXPCheckout?
    private var applePayComponent: ApplePayButtonComponent?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        Task {
            await initialiseTheSDK()
        }
    }
    
    private func initialiseTheSDK() async {
        do {
            // 1. Get the session data from the back-end
            let sessionData = try await getSessionDataFromBackend()
            
            // 2. Initialise the SDK
            let pxpCheckoutSdk = try PXPCheckout.initialize(
                environment: .test,
                session: sessionData,
                ownerId: "Unity",
                ownerType: .merchantGroup,
                merchantShopperId: "Shopper_01",
                transactionData: TransactionData(
                    currency: .USD,
                    amount: 25.00,
                    entryType: .ecom,
                    intent: .authorisation,
                    merchantTransactionId: UUID().uuidString,
                    merchantTransactionDate: Date()
                )
            )
            
            self.pxpCheckout = pxpCheckoutSdk
            setupApplePayComponent()
            
        } catch {
            showError("Failed to initialise SDK: \(error.localizedDescription)")
        }
    }
    
    private func setupApplePayComponent() {
        guard let pxpCheckout = pxpCheckout else { return }
        
        // Create and customise Apple Pay component
        let config = ApplePayButtonComponentConfig(
            merchantId: "merchant.com.yourcompany.store",
            countryCode: "US",
            currencyCode: "USD",
            supportedNetworks: [.visa, .masterCard, .amex, .discover],
            merchantCapabilities: .capability3DS,
            buttonStyle: ApplePaymentButtonStyle(
                type: .buy,
                style: .black
            ),
            requiredBillingContactFields: [.postalAddress, .name, .emailAddress],
            requiredShippingContactFields: [.postalAddress, .name, .phoneNumber]
        )
        
        applePayComponent = pxpCheckout.createApplePayComponent(config: config)
        
        // Set up callbacks
        applePayComponent?.onPreAuthorisation = { [weak self] in
            return self?.handlePreAuthorisation() ?? ApplePayTransactionInitData()
        }
        
        applePayComponent?.onPostAuthorisation = { [weak self] result in
            self?.handlePostAuthorisation(result: result)
        }
        
        applePayComponent?.onError = { [weak self] error in
            self?.showError("Apple Pay error: \(error.localizedDescription)")
        }
        
        applePayComponent?.onCancel = { [weak self] in
            print("Apple Pay cancelled by user")
        }
        
        // Mount the component
        applePayComponent?.mount(to: self.view)
        
    }
    
    private func handlePreAuthorisation() -> ApplePayTransactionInitData {
        return ApplePayTransactionInitData(
            riskScreeningData: RiskScreeningData(
                performRiskScreening: true,
                deviceSessionId: "device_\(UUID().uuidString)_\(Int(Date().timeIntervalSince1970))",
                items: [
                    Item(
                        name: "Product Name",
                        price: 25.00,
                        quantity: 1
                    )
                ]
            )
        )
    }
    
    private func handlePostAuthorisation(result: ApplePayResult) {
        switch result.submitResult.type {
        case .authorised:
            print("Payment authorised: \(result.submitResult.transactionId ?? "")")
            // Handle successful payment
        case .declined:
            showError("Payment declined: \(result.submitResult.responseCode ?? "")")
        case .exception:
            showError("Payment exception: \(result.submitResult.responseMessage ?? "")")
        }
    }
    
    private func getSessionDataFromBackend() async throws -> SessionData {
        // Implement your backend session request here
        // This should match the curl request shown above
        fatalError("Implement session data retrieval from your backend")
    }
    
    private func showError(_ message: String) {
        DispatchQueue.main.async {
            let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            self.present(alert, animated: true)
        }
    }
}
ParameterDescription
environment
Environment
required
The environment type.

Possible values:
  • .test
  • .live
session
SessionData
required
Details about the checkout session.
ownerId
string
required
The identifier of the owner related to the ownerType.
ownerType
OwnerType
required
The type of owner.

Possible values:
  • .merchantGroup
  • .merchant
  • .site
merchantShopperId
string
required
A unique identifier for this shopper.
transactionData
TransactionData
required
Details about the transaction.
transactionData.currency
Currency
required
The currency code associated with the transaction, in ISO 4217 format.
transactionData.amount
Double
The transaction amount.
transactionData.entryType
EntryType
required
The entry type.

Possible values:
  • .ecom
  • .moto
transactionData.intent
Intent
required
The transaction intent. Learn more about intents.

Possible values:
  • .authorisation
  • .estimatedAuthorisation
  • .purchase
  • .payout
  • .verification
transactionData.merchantTransactionId
string
required
A unique identifier for this transaction.
transactionData.merchantTransactionDate
Date
required
The date and time of the transaction.
shippingAddress
ShippingAddress
Details about the shipping address.
shippingAddress.address
string
The first line of the shipping address.
shippingAddress.addressLine2
string
The second line of the shipping address.
shippingAddress.city
string
The city of the shipping address.
shippingAddress.postalCode
string
The postal or ZIP code of the shipping address.
shippingAddress.countryCode
string (2 characters)
The country code of the shipping address, in ISO-3166-1 alpha-2 format.
analyticsEvent: AnalyticsEventHandlerHandler for analytics events.

That's it! You've got your first Apple Pay component up and running.

When you're ready to go live, make sure to update the sandbox URLs to production instead (https://api-services.pxp.io).