Skip to content

Receiver component

Learn how to configure the PayPal payout receiver component for iOS.

Overview

The PayPalPayoutReceiverComponent displays the recipient's PayPal email address with optional masking for privacy. This component shows users which PayPal account will receive their payout. Use this component alongside the PayoutAmountComponent and PayoutSubmissionComponent for returning users who have already linked their PayPal accounts.

This component is for users with stored PayPal credentials provided by your backend.

Pre-requisites

Before using the payout receiver component, ensure you have:

  1. Initialised the SDK with stored PayPal credentials:
let paypalConfig = PayPalConfig(
    payout: PayPalPayoutConfig(
        paypalWallet: PayPalWallet(
            email: "user@example.com",        // This email will be displayed
            payerId: "PAYERID123ABC",         // Credentials from backend
            proceedPayoutWithSdk: true
        )
    )
)

let checkoutConfig = CheckoutConfig(
    environment: .test,
    session: sessionData,
    transactionData: transactionData,
    merchantShopperId: "user-123",
    ownerId: "merchant-456",
    paypalConfig: paypalConfig
)

let pxpCheckout = try PxpCheckout.initialize(config: checkoutConfig)
  1. Retrieved the user's PayPal credentials from your backend:
// Fetch stored PayPal credentials from your backend
let credentials = try await fetchPayPalCredentials(userId: currentUser.id)
// Use credentials.paypalAccountId and credentials.paypalEmail in SDK initialisation

Basic usage

Minimal configuration

At minimum, the payout receiver component requires no mandatory configuration:

let config = PayPalPayoutReceiverComponentConfig()
let component = try pxpCheckout.create(.paypalPayoutReceiver, componentConfig: config)

With masking

Enable email masking for privacy (e.g., j***@****.com):

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    accessibilityLabel: "PayPal account email",
    applyMask: true,
    showMaskToggle: true
)
let component = try pxpCheckout.create(.paypalPayoutReceiver, componentConfig: config)
PropertyDescription
label
String?
The label text displayed above the email field.
accessibilityLabel
String?
The accessibility label for screen readers.
applyMask
Bool
Whether to mask the email address. Defaults to true.
showMaskToggle
Bool
Whether to show a toggle button to reveal/hide the email. Defaults to true.

Advanced configuration

For more complex implementations, configure styling, validation messages, and receiver type:

let config = PayPalPayoutReceiverComponentConfig(
    label: "Receiving PayPal Account",
    placeholder: "PayPal email",
    guideText: "Funds will be sent to this account",
    accessibilityLabel: "PayPal account receiving the payout",
    applyMask: true,
    showMaskToggle: true,
    receiverType: .email,
    
    // Custom container styling
    styles: FieldStyle(
        backgroundColor: Color(.systemGray6),
        borderColor: Color(.systemGray4),
        borderWidth: 1,
        cornerRadius: 8,
        padding: EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)
    ),
    
    // Custom input text styling
    inputStyles: FieldInputStateStyles(
        base: FieldStyle(
            color: Color(.label),
            fontSize: 16,
            fontWeight: .regular
        )
    ),
    
    // Custom label styling
    labelStyles: FieldLabelStateStyles(
        base: FieldStyle(
            color: Color(.secondaryLabel),
            fontSize: 14,
            fontWeight: .medium
        )
    ),
    
    // Custom validation messages
    validations: PayPalPayoutReceiverValidationResource(
        PPE01: "PayPal email is required",
        PPE02: "Please enter a valid email address"
    )
)
PropertyDescription
label
String?
The label text displayed above the email field.
placeholder
String?
The placeholder text shown when the field is empty.
guideText
String?
The helper text displayed below the email field.
accessibilityLabel
String?
The accessibility label for screen readers.
applyMask
Bool
Whether to mask the email address. Defaults to true.
showMaskToggle
Bool
Whether to show a toggle to reveal/hide email. Defaults to true.
receiverType
PayoutRecipientType
The recipient type. Defaults to .email.
styles
FieldStyle?
Custom styling for the container.
inputStyles
FieldInputStateStyles?
Custom styling for the email text.
labelStyles
FieldLabelStateStyles?
Custom styling for the label text.
validations
PayPalPayoutReceiverValidationResource?
Custom validation error messages.

Email masking

The receiver component supports email masking for user privacy. When masking is enabled, emails are displayed in a protected format.

For john.doe@example.com:

  • If applyMask: false, then john.doe@example.com is displayed.
  • If applyMask: true, then j***@****.com is displayed.

Email masking displays:

  • The first character of the local part (before @)
  • Three asterisks replacing the remaining local part characters
  • The @ symbol
  • Four asterisks the replacing domain name
  • .com (or the actual TLD)

Mask toggle

When showMaskToggle is enabled, users can tap to reveal or hide their email:

let config = PayPalPayoutReceiverComponentConfig(
    applyMask: true,        // Start with masked email
    showMaskToggle: true    // Allow user to reveal/hide
)

Privacy-focused configuration

For maximum privacy, hide the toggle so users can't reveal the full email:

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    applyMask: true,
    showMaskToggle: false
)

Full display configuration

For contexts where privacy is less of a concern:

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    applyMask: false,       
    showMaskToggle: false   
)

Styling

Default styling

The payout receiver component renders with default styling suitable for most applications:

// Default container style
FieldStyle(
    color: Color(red: 0.035, green: 0.035, blue: 0.047),
    font: .system(size: 16, weight: .regular),
    backgroundColor: Color(red: 0.929, green: 0.933, blue: 0.937),
    borderColor: Color(red: 0.725, green: 0.741, blue: 0.753),
    borderWidth: 1,
    cornerRadius: 4,
    padding: EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)
)

// Default label style
FieldStyle(
    color: Color.primary,
    font: .system(size: 14, weight: .bold)
)

Custom styling

Customise the appearance to match your app's design:

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    applyMask: true,
    showMaskToggle: true,
    
    // Container styling
    styles: FieldStyle(
        backgroundColor: Color(red: 0.0, green: 0.44, blue: 0.73).opacity(0.1),  // Light PayPal blue
        borderColor: Color(red: 0.0, green: 0.44, blue: 0.73),
        borderWidth: 1,
        cornerRadius: 8,
        padding: EdgeInsets(top: 14, leading: 16, bottom: 14, trailing: 16)
    ),
    
    // Email text styling
    inputStyles: FieldInputStateStyles(
        base: FieldStyle(
            color: Color(red: 0.0, green: 0.44, blue: 0.73),  // PayPal blue
            fontSize: 16,
            fontWeight: .medium
        )
    ),
    
    // Label styling
    labelStyles: FieldLabelStateStyles(
        base: FieldStyle(
            color: Color(.secondaryLabel),
            fontSize: 12,
            fontWeight: .semibold
        )
    )
)

PayPal branded styling

Apply PayPal's brand colours:

struct PayPalBrand {
    static let blue = Color(red: 0.0, green: 0.44, blue: 0.73)
    static let darkBlue = Color(red: 0.0, green: 0.18, blue: 0.38)
    static let lightBlue = Color(red: 0.0, green: 0.44, blue: 0.73).opacity(0.1)
}

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    applyMask: true,
    showMaskToggle: true,
    
    styles: FieldStyle(
        backgroundColor: PayPalBrand.lightBlue,
        borderColor: PayPalBrand.blue,
        borderWidth: 2,
        cornerRadius: 8,
        padding: EdgeInsets(top: 16, leading: 20, bottom: 16, trailing: 20)
    ),
    
    inputStyles: FieldInputStateStyles(
        base: FieldStyle(
            color: PayPalBrand.darkBlue,
            fontSize: 16,
            fontWeight: .semibold
        )
    ),
    
    labelStyles: FieldLabelStateStyles(
        base: FieldStyle(
            color: PayPalBrand.blue,
            fontSize: 13,
            fontWeight: .bold
        )
    )
)

FieldStyle properties

Each FieldStyle object supports the following SwiftUI-based properties:

PropertyTypeDescriptionExample
colorColor?The text/foreground colour..label
fontFont?The SwiftUI font for the text..body
fontWeightFont.Weight?The font weight..semibold, .bold
fontSizeCGFloat?The font size in points.16
labelFontFont?The SwiftUI font for labels..caption
labelColorColor?The colour for labels..secondary
valueFontFont?The SwiftUI font for values..body
valueColorColor?The colour for values..primary
backgroundColorColor?The background colour.Color(.systemGray6)
borderColorColor?The border colour..gray
borderWidthCGFloat?The border width in points.1
cornerRadiusCGFloat?The corner radius in points.8
paddingEdgeInsets?The padding around the content.EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)
marginEdgeInsets?The margin around the component.EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0)
textAlignmentTextAlignment?The text alignment..leading
opacityDouble?The opacity (0.0 - 1.0).1.0
shadowShadowStyle?Shadow styling.ShadowStyle(color: .black.opacity(0.2), radius: 4, x: 0, y: 2)
iconIconStyle?Icon styling with size and tint colour.IconStyle(size: CGSize(width: 24, height: 24), tintColor: .white)

Validation

Custom validation messages

Provide custom error messages for validation scenarios:

let config = PayPalPayoutReceiverComponentConfig(
    label: "PayPal Account",
    validations: PayPalPayoutReceiverValidationResource(
        PPE01: "Please provide a PayPal email address",
        PPE02: "The email address format is invalid"
    )
)
ValidationDescription
PPE01Message shown when the receiver email is missing.
PPE02Message shown when the email format is invalid.

receiverType

Currently, only .email is supported:

receiverType: .email  // Only supported value

Methods

buildContent()

Renders the receiver display as a SwiftUI view:

func buildContent() -> AnyView

Returns the component as a SwiftUI AnyView. The returned view is a read-only display showing the PayPal email from SDK configuration.

struct PayoutView: View {
    @State private var receiverComponent: BaseComponent?
    
    var body: some View {
        VStack {
            if let component = receiverComponent {
                component.buildContent()
                    .frame(maxWidth: .infinity)
            }
        }
        .onAppear {
            createReceiverComponent()
        }
    }
    
    private func createReceiverComponent() {
        Task {
            let config = PayPalPayoutReceiverComponentConfig(
                label: "PayPal Account",
                applyMask: true,
                showMaskToggle: true
            )
            
            let component = try pxpCheckout.create(.paypalPayoutReceiver, componentConfig: config)
            
            await MainActor.run {
                self.receiverComponent = component
            }
        }
    }
}

The PayPalPayoutReceiverComponent is primarily a display component. The email address displayed is determined by the paypalConfig.payout.paypalWallet.email configured during the SDK initialisation.

Important: Display-only component

The PayPalPayoutReceiverComponent is a read-only display component:

  • The email address is sourced from PayPalWallet.email in the SDK configuration.
  • Users can't edit the email through this component.
  • To change the displayed email, you must reinitialise SDK with a different PayPalWallet configuration.
  • The component has no getValue() method (display-only, no input collection).
// To change the displayed email, update SDK configuration
let updatedPaypalWallet = PayPalWallet(
    email: "newemail@example.com",  // New email to display
    payerId: "PAYERID123ABC",
    proceedPayoutWithSdk: true
)

// Reinitialise SDK with new configuration
let checkoutConfig = CheckoutConfig(
    // ... other config
    paypalConfig: PayPalConfig(
        payout: PayPalPayoutConfig(
            paypalWallet: updatedPaypalWallet
        )
    )
)

Examples

Basic receiver display

A simple implementation showing the PayPal email:

import SwiftUI
import PXPCheckoutSDK

struct BasicReceiverView: View {
    @State private var receiverComponent: BaseComponent?
    
    var body: some View {
        VStack(spacing: 16) {
            Text("Payout Destination")
                .font(.title)
            
            if let component = receiverComponent {
                component.buildContent()
                    .frame(maxWidth: .infinity)
            }
        }
        .padding()
        .onAppear {
            createComponent()
        }
    }
    
    private func createComponent() {
        Task {
            let config = PayPalPayoutReceiverComponentConfig(
                label: "PayPal Account",
                accessibilityLabel: "PayPal account for receiving payout",
                applyMask: true,
                showMaskToggle: true
            )
            
            let component = try pxpCheckout.create(.paypalPayoutReceiver, componentConfig: config)
            
            await MainActor.run {
                self.receiverComponent = component
            }
        }
    }
}

Privacy-focused display

Implementation with masked email and no reveal option:

let config = PayPalPayoutReceiverComponentConfig(
    label: "Linked PayPal Account",
    guideText: "Your email is hidden for security",
    accessibilityLabel: "Linked PayPal account",
    applyMask: true,
    showMaskToggle: false,  // Cannot reveal email
    
    styles: FieldStyle(
        backgroundColor: Color(.systemGray6),
        borderColor: Color(.systemGray4),
        borderWidth: 1,
        cornerRadius: 8,
        padding: EdgeInsets(top: 14, leading: 16, bottom: 14, trailing: 16)
    ),
    
    inputStyles: FieldInputStateStyles(
        base: FieldStyle(
            color: Color(.label),
            fontSize: 16,
            fontWeight: .medium,
            // Add a lock icon style if supported
        )
    )
)

Combined with other payout components

Use the receiver component alongside the amount and submission components:

struct DirectPayoutView: View {
    @State private var amountComponent: BaseComponent?
    @State private var receiverComponent: BaseComponent?
    @State private var submissionComponent: BaseComponent?
    
    var body: some View {
        VStack(spacing: 20) {
            Text("Withdraw to PayPal")
                .font(.title)
            
            // Amount display
            if let amount = amountComponent {
                amount.buildContent()
                    .frame(maxWidth: .infinity)
            }
            
            // Receiver display
            if let receiver = receiverComponent {
                receiver.buildContent()
                    .frame(maxWidth: .infinity)
            }
            
            Divider()
                .padding(.vertical, 8)
            
            // Submit button
            if let submit = submissionComponent {
                submit.buildContent()
                    .frame(maxWidth: .infinity)
            }
        }
        .padding()
        .onAppear {
            createComponents()
        }
    }
    
    private func createComponents() {
        Task {
            // Create amount component
            let amountConfig = PayoutAmountComponentConfig(
                label: "Payout Amount"
            )
            let amount = try pxpCheckout.create(.payoutAmount, componentConfig: amountConfig)
            
            // Create receiver component with PayPal branding
            let receiverConfig = PayPalPayoutReceiverComponentConfig(
                label: "PayPal Account",
                applyMask: true,
                showMaskToggle: true,
                
                styles: FieldStyle(
                    backgroundColor: Color(red: 0.0, green: 0.44, blue: 0.73).opacity(0.05),
                    borderColor: Color(red: 0.0, green: 0.44, blue: 0.73).opacity(0.3),
                    borderWidth: 1,
                    cornerRadius: 8
                )
            )
            let receiver = try pxpCheckout.create(.paypalPayoutReceiver, componentConfig: receiverConfig)
            
            // Create submission component
            let submissionConfig = PayoutSubmissionComponentConfig(
                submitText: "Withdraw Now",
                onPostPayout: { result in
                    print("Payout completed: \(result.merchantTransactionId)")
                }
            )
            let submission = try pxpCheckout.create(.payoutSubmission, componentConfig: submissionConfig)
            
            await MainActor.run {
                self.amountComponent = amount
                self.receiverComponent = receiver
                self.submissionComponent = submission
            }
        }
    }
}

Error handling

The receiver component can generate validation errors. Handle these errors through the PayoutSubmissionComponent's onError callback:

Error codeExceptionDescription
SDK0803PaypalPayoutReceiverRequiredExceptionThe receiver is required.
SDK0804PayoutReceiverTypeInvalidExceptionInvalid receiver type.
SDK0805PaypalPayoutReceiverTypeEmailOnlyExceptionThe receiver type must be Email.
SDK0808PaypalPayoutEmailInvalidExceptionInvalid email format.

While the receiver component displays the PayPal email, validation errors are triggered by the PayoutSubmissionComponent when attempting to execute a payout. Handle these errors through the submission component's onError callback:

let submissionConfig = PayoutSubmissionComponentConfig(
    onError: { error in
        // Handle receiver-related validation errors here
        switch error.errorCode {
        case "SDK0803", "SDK0804", "SDK0805", "SDK0808":
            // Receiver validation errors
            print("Receiver error: \(error.errorMessage)")
        default:
            break
        }
    }
)

For a complete list of error codes, see Data validation.