Learn about how to configure the PayPal payment button component for iOS.
At minimum, the PayPal button component requires the following configuration to function:
let config = PayPalButtonComponentConfig()
config.fundingSource = .paypal| Property | Description |
|---|---|
fundingSourcePayPalFundingSource | The payment method to support. Defaults to .paypal.Possible values:
|
For more complex implementations, you can configure additional settings and features:
let config = PayPalButtonComponentConfig()
// Payment details
config.fundingSource = .paypal
config.payeeEmailAddress = "merchant@example.com"
config.paymentDescription = "Premium subscription"
config.shippingPreference = .noShipping
config.userAction = .payNow
config.locale = "en_US"
// Shipping configuration
config.shippingOptions = [
PayPalShippingOption(
id: "standard",
label: "Standard Shipping",
selected: true,
amounts: PayPalShippingAmounts(
currencyCode: "USD",
shipping: "5.99"
),
type: .shipping
)
]
// Button appearance
config.style = PayPalButtonStyleConfig(
color: .blue,
label: .checkout,
size: .collapsed,
edges: .softEdges,
contentInsets: .uniform(8)
)
// Custom content (optional)
config.customContent = {
AnyView(
Text("Pay with PayPal")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
)
}| Property | Description |
|---|---|
payeeEmailAddressString? | Your merchant email address. Defaults to nil. |
paymentDescriptionString? | A description of the payment shown to the buyer. Defaults to nil. |
shippingPreferencePayPalShippingPreference? | The shipping details to use. Defaults to nil.Possible values:
|
userActionPayPalUserAction? | The next step in the payment flow. Defaults to nil.Possible values:
|
localeString? | The language and region for PayPal interface (e.g., "en_US", "fr_FR"). Defaults to nil. |
fundingSourcePayPalFundingSource | The payment method to support. Defaults to .paypal.Possible values:
|
shippingOptions[PayPalShippingOption]? | Details about the shipping options. Provide this when shippingPreference is .getFromFile. Defaults to nil. |
stylePayPalButtonStyleConfig | Styling options for the PayPal button. Defaults to .default. |
customContent(() -> AnyView)? | Optional custom SwiftUI content to replace the default PayPal button. Defaults to nil. |
paypalConsentComponentPayPalConsentComponent? | PayPal consent component for vaulting. Defaults to nil. See Consent component. |
You can find PayPal's official rules around button styling in their iOS SDK reference.
The PayPal button component renders with these default styles:
style = PayPalButtonStyleConfig(
color: .gold,
label: nil,
size: .collapsed,
edges: .softEdges,
contentInsets: nil
)You can override the default appearance by providing custom styles:
let config = PayPalButtonComponentConfig()
config.style = PayPalButtonStyleConfig(
color: .blue,
label: .buyNow,
size: .expanded,
edges: .rounded,
contentInsets: .custom(top: 12, leading: 16, bottom: 12, trailing: 16)
)| Property | Description |
|---|---|
stylePayPalButtonStyleConfig | Styling options for the PayPal button appearance. |
style.colorPayPalButtonColor | The colour of the PayPal button. Defaults to .gold.Possible values:
|
style.labelPayPalButtonLabel? | The label text of the PayPal button. Defaults to nil.Possible values:
|
style.sizePayPalButtonSize | The size of the PayPal button. Defaults to .collapsed.Possible values:
|
style.edgesPayPalButtonEdges | The corner style of the PayPal button. Defaults to .softEdges.Possible values:
|
style.contentInsetsNSDirectionalEdgeInsets? | The padding around the button content. Defaults to nil. |
The PayPal button component provides event handlers to manage the complete payment flow:
let config = PayPalButtonComponentConfig()
config.onClick = { }
config.onApprove = { approvalData in }
config.onError = { error in }
config.onCancel = { error in }
config.onOrderCreated = { submitResult in }
config.onSubmitError = { error in }
config.onPreAuthorisation = { PayPalTransactionInitData? }
config.onGetConsent = { Bool }| Callback | Description |
|---|---|
onClick: (() -> Void)? | Event handler for when the PayPal button is clicked. Called before payment flow starts. |
onApprove: ((PayPalApprovalData) -> Void)? | Event handler for when the buyer approves the transaction. Receives order and payer information. |
onError: ((BaseSdkException) -> Void)? | Event handler for when an error prevents checkout from proceeding. |
onCancel: ((BaseSdkException) -> Void)? | Event handler for when the buyer cancels the payment flow. |
onOrderCreated: ((BaseSubmitResult) -> Void)? | Event handler for when the PayPal order is successfully created. Contains transaction IDs. |
onSubmitError: ((BaseSdkException) -> Void)? | Event handler for when error occurs during order creation or submission. |
onPreAuthorisation: (() async -> PayPalTransactionInitData?)? | Event handler called before authorisation to provide additional transaction data like 3DS. |
onGetConsent: (() -> Bool)? | Event handler to get user consent status for vaulting. Return true if user consents, false otherwise. |
For detailed information about event data structures and usage patterns, see Events.
The PayPal button component provides methods for lifecycle management.
Renders the PayPal button in SwiftUI:
struct PaymentView: View {
@State private var paypalComponent: BaseComponent?
var body: some View {
VStack {
if let component = paypalComponent {
component.buildContent()
.frame(height: 50)
}
}
.onAppear {
createPayPalComponent()
}
}
}Note: The PayPal button component does not have a getValue() method. Payment data is provided through the onApprove callback.
For linked consent components:
let hasConsent = consentComponent.getValue() as? Bool ?? falseA straightforward implementation with essential configuration and error handling:
let config = PayPalButtonComponentConfig()
// Basic settings
config.fundingSource = .paypal
config.payeeEmailAddress = "merchant@example.com"
config.paymentDescription = "Order payment"
// Essential event handlers
config.onClick = {
print("PayPal button clicked")
}
config.onApprove = { approvalData in
print("Payment successful - Order ID: \(approvalData.orderID)")
// Navigate to success screen
navigateToSuccessScreen(approvalData.orderID)
}
config.onError = { error in
print("Payment failed: \(error.errorMessage)")
// Show error message
showErrorMessage("Payment failed. Please try again.")
}
config.onCancel = { error in
print("Payment cancelled")
// Show cancellation message
showMessage("Payment was cancelled.")
}A comprehensive implementation with custom styling and complete event handling:
let config = PayPalButtonComponentConfig()
// Payment details
config.fundingSource = .paypal
config.payeeEmailAddress = "enterprise@example.com"
config.paymentDescription = "Enterprise subscription"
config.shippingPreference = .getFromFile
config.userAction = .continueAction
config.locale = "en_US"
// Shipping configuration
config.shippingOptions = [
PayPalShippingOption(
id: "standard",
label: "Standard Shipping",
selected: true,
amounts: PayPalShippingAmounts(
currencyCode: "USD",
shipping: "5.99"
),
type: .shipping
),
PayPalShippingOption(
id: "express",
label: "Express Shipping",
selected: false,
amounts: PayPalShippingAmounts(
currencyCode: "USD",
shipping: "12.99"
),
type: .shipping
)
]
// Custom styling
config.style = PayPalButtonStyleConfig(
color: .blue,
label: .buyNow,
size: .expanded,
edges: .rounded,
contentInsets: .custom(top: 12, leading: 16, bottom: 12, trailing: 16)
)
// Pre-authorisation with transaction data
config.onPreAuthorisation = {
return PayPalTransactionInitData(
addressVerification: AddressVerification(
countryCode: "US",
houseNumberOrName: "123",
postalCode: "12345"
),
riskScreeningData: RiskScreeningData(
performRiskScreening: true,
excludeDeviceData: false,
deviceSessionId: "device-session-\(UUID().uuidString)",
items: [
RiskScreeningItem(
price: 25.00,
quantity: 1,
category: "electronics",
sku: "PROD-001"
)
]
)
)
}
// Complete event handling
config.onClick = {
print("PayPal button clicked")
trackAnalyticsEvent("paypal_button_clicked")
}
config.onOrderCreated = { submitResult in
print("Order created:")
if let merchantResult = submitResult as? MerchantSubmitResult {
print("- Merchant TX ID: \(merchantResult.merchantTransactionId)")
print("- System TX ID: \(merchantResult.systemTransactionId)")
trackAnalyticsEvent("paypal_order_created", params: [
"orderId": merchantResult.systemTransactionId
])
}
}
config.onApprove = { approvalData in
print("Payment approved:")
print("- Order ID: \(approvalData.orderID)")
print("- Payer ID: \(approvalData.payerID)")
trackAnalyticsEvent("paypal_payment_success", params: [
"orderId": approvalData.orderID
])
showPaymentSuccessMessage()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
navigateToSuccessScreen(approvalData.orderID)
}
}
config.onError = { error in
let errorMessage: String
switch error.errorCode {
case "SDK_ERROR":
errorMessage = "Failed to load PayPal. Please check your connection."
case "TRANSACTION_ERROR":
errorMessage = "Payment processing error. Please try again."
default:
errorMessage = "Payment error occurred: \(error.errorMessage)"
}
print("Payment error: \(error.errorMessage)")
trackAnalyticsEvent("paypal_payment_error", params: [
"error": error.errorCode
])
showErrorDialog(errorMessage)
}
config.onCancel = { error in
print("Payment cancelled")
trackAnalyticsEvent("paypal_payment_cancelled")
showMessage("Payment was cancelled.")
}
config.onSubmitError = { error in
print("Submit error: \(error.errorMessage)")
showErrorDialog("Unable to process payment: \(error.errorMessage)")
}Implementation with custom SwiftUI content instead of the default PayPal button:
let config = PayPalButtonComponentConfig()
config.fundingSource = .paypal
// Custom content that replaces default PayPal button
config.customContent = {
AnyView(
HStack {
Image(systemName: "creditcard.fill")
.foregroundColor(.white)
Text("Pay with PayPal")
.font(.headline)
.foregroundColor(.white)
}
.padding()
.frame(maxWidth: .infinity)
.background(Color.blue)
.cornerRadius(12)
)
}
// Configure callbacks
config.onApprove = { approvalData in
print("Payment successful: \(approvalData.orderID)")
handlePaymentSuccess(approvalData)
}
config.onError = { error in
print("Payment failed: \(error.errorMessage)")
handlePaymentError(error)
}Implementation with consent component for saving PayPal accounts:
// Create consent component first
let consentConfig = PayPalConsentComponentConfig(
label: "Save my PayPal account for future transactions",
checked: false
)
let consentComponent = try pxpCheckout.create(
.paypalConsent,
componentConfig: consentConfig
)
// Create PayPal button with linked consent
let paypalConfig = PayPalButtonComponentConfig()
paypalConfig.fundingSource = .paypal
paypalConfig.paypalConsentComponent = consentComponent as? PayPalConsentComponent
// Alternative: Use onGetConsent callback
paypalConfig.onGetConsent = {
let hasConsent = UserDefaults.standard.bool(forKey: "paypal_consent")
return hasConsent
}
paypalConfig.onApprove = { approvalData in
print("Payment approved with consent")
// Check consent status and handle accordingly
handlePaymentWithVaulting(approvalData)
}