# Customisation

Learn about customisation options for the Apple Pay component for Web.

## Overview

The Apple Pay component comes with responsive and accessible default styling that follows Apple's design guidelines, but is designed to be customisable to match your brand and website requirements.

You can find Apple's official recommendations around button styling in their Apple Pay button CSS guide and Apple Pay JS API reference.

## Default styling

The default implementation uses Apple's official JavaScript SDK with the `<apple-pay-button>` web component:


```typescript
const config = {
  usingCss: false, // Default - uses official Apple Pay SDK
  style: {
    type: 'buy',
    buttonstyle: 'black',
    height: '44px',
    borderRadius: '4px'
  }
};
```

You can try out the default button types and styles with Apple's Apple Pay on the Web interactive demo.

### Default button types

| Type | Description | Use case |
|  --- | --- | --- |
| `buy` | Standard purchase button. | E-commerceRetail |
| `pay` | Payment button. | CheckoutBilling |
| `donate` | Donation button. | CharitiesCrowdfunding |
| `book` | Booking button. | TravelReservations |
| `check-out` | Checkout button | Shopping cart |
| `continue` | Continue button | Multi-step processes |
| `contribute` | Contribution button | SubscriptionsMemberships |
| `order` | Order button | Food deliveryServices |
| `reload` | Reload button | Gift cardsPrepaid |
| `rent` | Rent button | RentalsSubscriptions |
| `set-up` | Setup button | Account setupConfiguration |
| `subscribe` | Subscribe button | NewslettersServices |
| `support` | Support button | SupportHelp |
| `tip` | Tip button | GratuitiesTips |
| `top-up` | Top-up button | PrepaidCredits |


### Default button styles

| Style | Description |
|  --- | --- |
| `black` | Black background with white text. |
| `white` | White background with black text. |
| `white-outline` | White background with a black border and black text. |


## CSS method styling

When using `usingCss: true`, you have complete control over the button's appearance:


```typescript
const config = {
  usingCss: true,
  style: {
    type: 'buy',
    buttonstyle: 'black',
    template: '<button class="apple-pay-button">Pay with Apple Pay</button>',
    templateCSS: `
      .apple-pay-button {
        background-color: #000;
        color: #fff;
        border: none;
        border-radius: 4px;
        height: 44px;
        width: 100%;
        font-size: 16px;
        font-weight: 500;
        cursor: pointer;
      }
    `
  }
};
```

Here's a full example of a CSS method implementation.


```typescript
```typescript
const config = {
  merchantDisplayName: 'Urban Fashion Boutique',
  paymentDescription: 'Designer Jacket Purchase',
  usingCss: true, // Enable CSS method
  style: {
    type: 'buy',
    buttonstyle: 'black',
    locale: 'en-US',
    template: `
      <button class="custom-apple-pay-button">
        <svg class="apple-pay-icon" viewBox="0 0 102 26" width="102" height="26">
          <path fill="currentColor" d="M28.94 11.26c.09-4.21 3.48-6.26 3.64-6.37-1.98-2.9-5.06-3.3-6.16-3.34-2.62-.27-5.11 1.54-6.44 1.54-1.34 0-3.41-1.5-5.6-1.46-2.88.04-5.53 1.67-7.02 4.25-2.99 5.18-.77 12.85 2.15 17.06 1.43 2.06 3.14 4.38 5.38 4.3 2.18-.09 3-1.41 5.63-1.41 2.62 0 3.37 1.41 5.64 1.37 2.33-.04 3.83-2.11 5.26-4.18 1.66-2.39 2.34-4.7 2.38-4.82-.05-.02-4.57-1.75-4.66-6.94zM25.13 8.12c1.19-1.44 1.99-3.44 1.77-5.43-1.71.07-3.78.89-5.01 2.01-1.1 1.27-2.06 3.31-1.8 5.26 1.9.15 3.85-.97 5.04-1.84z"/>
          <path fill="currentColor" d="M45.34 21.85h-4.8l-1.15-3.61h-5.02l-1.1 3.61h-4.66l5.05-15.73h5.58l5.1 15.73zm-6.47-6.82l-1.42-4.39c-.14-.44-.42-1.58-.83-3.42h-.05c-.19.95-.47 2.09-.84 3.42l-1.37 4.39h4.51z"/>
          <path fill="currentColor" d="M61.11 15.23c0 2.19-.59 3.93-1.76 5.22-1.05 1.16-2.37 1.74-3.96 1.74-1.67 0-2.88-.61-3.61-1.83h-.05v6.87h-4.5V12.5c0-1.55-.04-3.14-.12-4.78h3.95l.25 2.32h.1c.94-1.75 2.48-2.62 4.62-2.62 1.54 0 2.83.61 3.86 1.83 1.03 1.22 1.55 2.85 1.55 4.9v.08zm-4.55-.13c0-1.3-.32-2.37-.95-3.21-.68-.89-1.6-1.34-2.75-1.34-.77 0-1.47.25-2.1.74-.63.49-1.06 1.15-1.29 1.97-.12.41-.18.76-.18 1.05v2.58c0 1.13.36 2.07 1.08 2.82.72.75 1.64 1.12 2.76 1.12 1.18 0 2.1-.46 2.76-1.39.66-.93.99-2.18.99-3.75v-.59z"/>
          <path fill="currentColor" d="M76.47 15.23c0 2.19-.59 3.93-1.76 5.22-1.05 1.16-2.37 1.74-3.96 1.74-1.67 0-2.88-.61-3.61-1.83h-.05v6.87h-4.5V12.5c0-1.55-.04-3.14-.12-4.78h3.95l.25 2.32h.1c.94-1.75 2.48-2.62 4.62-2.62 1.54 0 2.83.61 3.86 1.83 1.03 1.22 1.55 2.85 1.55 4.9v.08zm-4.55-.13c0-1.3-.32-2.37-.95-3.21-.68-.89-1.6-1.34-2.75-1.34-.77 0-1.47.25-2.1.74-.63.49-1.06 1.15-1.29 1.97-.12.41-.18.76-.18 1.05v2.58c0 1.13.36 2.07 1.08 2.82.72.75 1.64 1.12 2.76 1.12 1.18 0 2.1-.46 2.76-1.39.66-.93.99-2.18.99-3.75v-.59z"/>
          <path fill="currentColor" d="M85.44 21.85h-4.5V7.75h4.5v14.1z"/>
          <path fill="currentColor" d="M96.66 18.43c0 1.14-.41 2.08-1.23 2.82-.9.82-2.19 1.23-3.87 1.23-1.55 0-2.79-.37-3.72-1.11l.53-3.53c1.04.74 2.06 1.11 3.06 1.11.64 0 1.14-.16 1.5-.47.36-.31.54-.73.54-1.26 0-.47-.18-.87-.54-1.21-.36-.34-.95-.68-1.77-1.03-2.66-1.14-3.99-2.81-3.99-5.01 0-1.14.43-2.08 1.29-2.82.86-.74 2.01-1.11 3.45-1.11 1.3 0 2.38.22 3.24.67l-.64 3.46c-.77-.45-1.54-.67-2.31-.67-.59 0-1.05.15-1.38.46-.27.25-.41.58-.41.99 0 .47.2.86.59 1.17.32.25.86.54 1.62.87 1.57.67 2.69 1.35 3.36 2.04.67.69 1.01 1.54 1.01 2.55v.01z"/>
        </svg>
        <span class="apple-pay-text">Buy with Apple Pay</span>
      </button>
    `,
    templateCSS: `
      .custom-apple-pay-button {
        background: linear-gradient(135deg, #1a1a1a 0%, #333 100%);
        border: none;
        border-radius: 12px;
        height: 52px;
        width: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        transition: all 0.3s ease;
        font-family: -apple-system, BlinkMacSystemFont, sans-serif;
        color: white;
        font-size: 16px;
        font-weight: 600;
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
      }
      
      .custom-apple-pay-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
        background: linear-gradient(135deg, #333 0%, #555 100%);
      }
      
      .custom-apple-pay-button:active {
        transform: translateY(0);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
      }
      
      .apple-pay-icon {
        margin-right: 10px;
        filter: brightness(1.1);
      }
      
      .apple-pay-text {
        font-weight: 600;
        letter-spacing: 0.5px;
      }
      
      @media (max-width: 480px) {
        .custom-apple-pay-button {
          height: 48px;
          font-size: 15px;
        }
      }
    `
  },
  paymentRequest: {
    countryCode: 'US',
    currencyCode: 'USD',
    merchantCapabilities: ['supports3DS', 'supportsEMV'],
    supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
    total: {
      label: 'Total',
      amount: '299.99'
    },
    lineItems: [
      {
        label: 'Designer Leather Jacket',
        amount: '279.99'
      },
      {
        label: 'Tax',
        amount: '20.00'
      }
    ]
  }
};
```

## Configuration options

The Apple Pay component accepts two main configuration interfaces that control its appearance and behaviour:

- `ApplePayButtonComponentConfig`, which is the main configuration class that contains all the settings needed for an Apple Pay button component, including payment details (amount, currency, merchant info), payment processing options (supported networks, billing/shipping requirements), and button appearance settings.
- `ApplePayButtonStyle`, which is is a nested configuration object within `ApplePayButtonComponentConfig` that specifically controls the visual appearance of the Apple Pay button, including the button type, style, and dimensions.


### ApplePayButtonComponentConfig


```typescript Definition
interface ApplePayButtonComponentConfig extends BaseComponentConfig {
  merchantDisplayName: string;
  paymentDescription: string;
  paymentRequest: ApplePayPaymentRequest;
  usingCss?: boolean;
  style?: ApplePayButtonStyle;
  applePayConsentComponent?: ApplePayConsentComponent;
  onGetConsent?: () => boolean;
  onPreAuthorisation?: () => Promise<ApplePayTransactionInitData | null>;
  onPostAuthorisation?: (submitResult: BaseSubmitResult, applePayResult: ApplePayResult) => void;
  onShippingContactSelected?: (contact: ApplePayContact) => Promise<ApplePayShippingContactUpdate>;
  onShippingMethodSelected?: (method: ApplePayShippingMethod) => Promise<ApplePayShippingMethodUpdate>;
  onPaymentMethodSelected?: (paymentMethod: ApplePayPaymentMethod) => Promise<ApplePayPaymentMethodUpdate>;
  onCouponCodeChanged?: (couponCode: string) => Promise<ApplePayCouponCodeUpdate>;
  onError?: (error: Error) => void;
  onCancel?: (error: Error) => void;
}
```


```typescript Example
const config: ApplePayButtonComponentConfig = {
  // Required fields
  merchantDisplayName: 'Acme Store',
  paymentDescription: 'Product Purchase',
  paymentRequest: {
    countryCode: 'US',
    currencyCode: 'USD',
    merchantCapabilities: ['supports3DS', 'supportsEMV'],
    supportedNetworks: ['visa', 'masterCard', 'amex'],
    total: {
      label: 'Total',
      amount: '99.99'
    },
    lineItems: [
      {
        label: 'Product',
        amount: '89.99'
      },
      {
        label: 'Tax',
        amount: '10.00'
      }
    ]
  },
  
  // Rendering method
  usingCss: false,
  
  // Styling configuration
  style: {
    type: 'buy',
    buttonstyle: 'black',
    height: '48px',
    borderRadius: '8px'
  },
  
  // Apple Pay consent component
  applePayConsentComponent: consentComponentInstance,
  
  // Event handlers
  onGetConsent: () => {
    return userHasGivenConsent();
  },
  
  onPreAuthorisation: async () => {
    return {
      riskScreeningData: {
        deviceSessionId: 'session-123',
        performRiskScreening: true,
        userIp: "192.168.1.100",
        account: {
          id: "user_12345678",
          creationDateTime: "2024-01-15T10:30:00.000Z"
        },
        fulfillments: [{
          type: "Shipped",
          recipientPerson: {
            phoneNumber: "+1234567890"
          }
        }]
      }
    };
  },
  
  onPostAuthorisation: (result, applePayResult) => {
    if (result instanceof AuthorisedSubmitResult) {
      console.log('Payment successful:', result.transactionId);
    } else {
      console.error('Payment failed:', result.errorReason);
    }
  },
  
  onShippingContactSelected: async (contact) => {
    return {
      newTotal: {
        label: 'Total',
        amount: '109.99'
      },
      newLineItems: [
        { label: 'Product', amount: '89.99' },
        { label: 'Shipping', amount: '10.00' },
        { label: 'Tax', amount: '10.00' }
      ]
    };
  },
  
  onShippingMethodSelected: async (method) => {
    return {
      newTotal: {
        label: 'Total',
        amount: '104.99'
      },
      newLineItems: [
        { label: 'Product', amount: '89.99' },
        { label: method.label, amount: method.amount },
        { label: 'Tax', amount: '10.00' }
      ]
    };
  },
  
  onPaymentMethodSelected: async (paymentMethod) => {
    return {
      newTotal: {
        label: 'Total',
        amount: '99.99'
      }
    };
  },
  
  onCouponCodeChanged: async (couponCode) => {
    const discount = calculateDiscount(couponCode);
    return {
      newTotal: {
        label: 'Total',
        amount: (99.99 - discount).toFixed(2)
      },
      newLineItems: [
        { label: 'Product', amount: '89.99' },
        { label: 'Discount', amount: `-${discount.toFixed(2)}` },
        { label: 'Tax', amount: '10.00' }
      ]
    };
  },
  
  onError: (error) => {
    console.error('Apple Pay error:', error);
    showErrorMessage('Payment failed. Please try again.');
  },
  
  onCancel: (error) => {
    console.log('Payment cancelled by user');
    trackEvent('apple_pay_cancelled');
  }
};
```

| Property | Description |
|  --- | --- |
| `merchantDisplayName`string | The display name for your business. |
| `paymentDescription`string | A description of what the payment is for. |
| `paymentRequest`ApplePayPaymentRequest | The Apple Pay payment configuration. |
| `usingCss`boolean | Whether to use CSS method instead of official SDK. Defaults to `false`. |
| `style`ApplePayButtonStyle | Button styling configuration. |
| `applePayConsentComponent`ApplePayConsentComponent | Consent component for data processing. |
| `onGetConsent`() => boolean | Event handler to check if a user has given consent. |
| `onPreAuthorisation`() => Promise<ApplePayTransactionInitData | null> | Event handler for before payment authorisation. |
| `onPostAuthorisation`(result, applePayResult) => void | Event handler for after payment authorisation. |
| `onShippingContactSelected`(contact) => Promise<ApplePayShippingContactUpdate> | Event handler for when the shipping address changes. |
| `onShippingMethodSelected`(method) => Promise<ApplePayShippingMethodUpdate> | Event handler for when the shipping method changes. |
| `onPaymentMethodSelected`(paymentMethod) => Promise<ApplePayPaymentMethodUpdate> | Event handler for when the payment method changes. |
| `onCouponCodeChanged`(couponCode) => Promise<ApplePayCouponCodeUpdate> | Event handler for when a coupon code is entered. |
| `onError`(error) => void | Event handler for when an error occurs. |
| `onCancel`(error) => void | Event handler for when a user cancels their payment. |


### ApplePayButtonStyle


```typescript Definition
interface ApplePayButtonStyle {
  type?: string;
  buttonstyle?: string;
  height?: string;
  width?: string;
  borderRadius?: string;
  padding?: string;
  boxSizing?: string;
  fontSize?: string;
  fontWeight?: string;
  fontFamily?: string;
  letterSpacing?: string;
  textTransform?: string;
  backgroundColor?: string;
  color?: string;
  borderColor?: string;
  borderWidth?: string;
  borderStyle?: string;
  boxShadow?: string;
  textShadow?: string;
  opacity?: string;
  transition?: string;
  position?: string;
  top?: string;
  right?: string;
  bottom?: string;
  left?: string;
  zIndex?: string;
  display?: string;
  alignItems?: string;
  justifyContent?: string;
  flexDirection?: string;
  gap?: string;
  customCSS?: string;
  template?: string;
  templateCSS?: string;
  locale?: string;
}
```


```typescript Example
const style: ApplePayButtonStyle = {
  // Button type and style
  type: 'buy',
  buttonstyle: 'black',
  
  // Dimensions
  height: '48px',
  width: '100%',
  borderRadius: '8px',
  padding: '12px 16px',
  boxSizing: 'border-box',
  
  // Typography
  fontSize: '16px',
  fontWeight: '600',
  fontFamily: '-apple-system, BlinkMacSystemFont, sans-serif',
  letterSpacing: '0.5px',
  textTransform: 'none',
  
  // Colours
  backgroundColor: '#000000',
  color: '#ffffff',
  borderColor: '#333333',
  borderWidth: '1px',
  borderStyle: 'solid',
  
  // Effects
  boxShadow: '0 2px 8px rgba(0, 0, 0, 0.15)',
  textShadow: '0 1px 2px rgba(0, 0, 0, 0.5)',
  opacity: '1',
  
  // Transitions
  transition: 'all 0.3s ease',
  
  // Positioning
  position: 'relative',
  top: '0',
  right: '0',
  bottom: '0',
  left: '0',
  zIndex: '1',
  
  // Layout
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  flexDirection: 'row',
  gap: '8px',
  
  // Custom CSS (for official SDK method)
  customCSS: `
    apple-pay-button:hover {
      transform: translateY(-2px);
    }
  `,
  
  // Template (for CSS method)
  template: '<button class="apple-pay-button">Pay with Apple Pay</button>',
  templateCSS: `
    .apple-pay-button {
      background-color: #000;
      color: #fff;
      border: none;
      border-radius: 8px;
      padding: 12px 16px;
      cursor: pointer;
    }
  `,
  
  // Locale
  locale: 'en-US'
};
```

| Property | Description |
|  --- | --- |
| `type`string | The button type. Defaults to `buy`.Possible values:`add-money``book``buy``check-out``continue``contribute``donate``order``pay``plain``reload``rent``set-up``subscribe``support``tip``top-up` |
| `buttonstyle`string | The button style variant. Defaults to `black`.Possible values:`black``white``white-outline` |
| `height`string | The button height. Defaults to `44px`. |
| `width`string | The button width. Defaults to `100%`. |
| `borderRadius`string | The border radius for rounded corners. Defaults to `4px`. |
| `padding`string | The internal spacing. |
| `boxSizing`string | The CSS box-sizing property. Defaults to `border-box`.Possible values:`border-box``content-box` |
| `fontSize`string | The font size. |
| `fontWeight`string | The font weight. |
| `fontFamily`string | The font family. |
| `letterSpacing`string | The character spacing. |
| `textTransform`string | The text transformation to apply.Possible values:`none``uppercase``lowercase``capitalize` |
| `backgroundColor`string | The background colour. |
| `color`string | The text colour. |
| `borderColor`string | The border colour. |
| `borderWidth`string | The border thickness. |
| `borderStyle`string | The border style.Possible values:`solid``dashed``dotted``none` |
| `boxShadow`string | The drop shadow effect. |
| `textShadow`string | The text shadow effect. |
| `opacity`string | The transparency level (`0-1`). |
| `transition`string | The animation transitions. |
| `position`string | The CSS positioning.Possible values:`static``relative``absolute``fixed``sticky` |
| `top`string | The top position offset. |
| `right`string | The right position offset. |
| `bottom`string | The bottom position offset. |
| `left`string | The left position offset. |
| `zIndex`string | The stacking order. |
| `display`string | The display type. |
| `alignItems`string | The vertical flex alignment. |
| `justifyContent`string | The horizontal flex alignment. |
| `flexDirection`string | The flex direction.Possible values:`row``column``row-reverse``column-reverse` |
| `gap`string | The flex gap spacing. |
| `customCSS`string | Additional CSS rules (official SDK only). |
| `template`string | HTML template (CSS method only). |
| `templateCSS`string | CSS styles (CSS method only). |
| `locale`string | The language/region code. Defaults to `en-US`. |


## Examples


```typescript Official SDK
const applePayComponent = pxpSdk.create('apple-pay-button', {
  merchantDisplayName: 'Acme Electronics Store',
  paymentDescription: 'Wireless Headphones Purchase',
  usingCss: false, // Use official Apple Pay SDK
  style: {
    type: 'buy',
    buttonstyle: 'black',
    height: '50px',
    borderRadius: '8px',
    locale: 'en-US',
    customCSS: `
      apple-pay-button {
        --apple-pay-button-width: 100%;
        --apple-pay-button-height: 50px;
        --apple-pay-button-border-radius: 8px;
        --apple-pay-button-padding: 0 16px;
        margin: 10px 0;
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
        transition: all 0.3s ease;
        font-family: -apple-system, BlinkMacSystemFont, sans-serif;
      }
      
      apple-pay-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
      }
      
      apple-pay-button:active {
        transform: translateY(0);
        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
      }
    `
  },
  paymentRequest: {
    countryCode: 'US',
    currencyCode: 'USD',
    merchantCapabilities: ['supports3DS', 'supportsEMV'],
    supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
    total: {
      label: 'Total',
      amount: '129.99'
    },
    lineItems: [
      {
        label: 'Wireless Headphones',
        amount: '119.99'
      },
      {
        label: 'Tax',
        amount: '10.00'
      }
    ],
    requiredBillingContactFields: ['postalAddress', 'name', 'email'],
    requiredShippingContactFields: ['postalAddress', 'name', 'phone']
  },
  onError: (error) => {
    console.error('Apple Pay Error:', error);
    showErrorMessage('Payment failed. Please try again.');
  },
  onPostAuthorisation: (result, applePayResult) => {
    if (result instanceof AuthorisedSubmitResult) {
      console.log('Payment successful:', result.transactionId);
      window.location.href = `/order-confirmation/${result.transactionId}`;
    } else {
      console.error('Payment failed:', result.errorReason);
      showErrorMessage('Payment was declined. Please try a different payment method.');
    }
  },
  onCancel: () => {
    console.log('User cancelled Apple Pay');
    trackEvent('apple_pay_cancelled', { amount: '129.99' });
  }
});

applePayComponent.mount('apple-pay-container');
```


```typescript Custom CSS with shipping
const applePayComponent = pxpSdk.create('apple-pay-button', {
  merchantDisplayName: 'Outdoor Adventure Gear',
  paymentDescription: 'Camping Equipment Order',
  usingCss: true, // Use custom CSS method
  style: {
    type: 'buy',
    buttonstyle: 'black',
    locale: 'en-US',
    template: `
      <button class="custom-apple-pay-button" type="button">
        <div class="apple-pay-content">
          <svg class="apple-pay-icon" viewBox="0 0 102 26" width="51" height="13">
            <path fill="currentColor" d="M28.94 11.26c.09-4.21 3.48-6.26 3.64-6.37-1.98-2.9-5.06-3.3-6.16-3.34-2.62-.27-5.11 1.54-6.44 1.54-1.34 0-3.41-1.5-5.6-1.46-2.88.04-5.53 1.67-7.02 4.25-2.99 5.18-.77 12.85 2.15 17.06 1.43 2.06 3.14 4.38 5.38 4.3 2.18-.09 3-1.41 5.63-1.41 2.62 0 3.37 1.41 5.64 1.37 2.33-.04 3.83-2.11 5.26-4.18 1.66-2.39 2.34-4.7 2.38-4.82-.05-.02-4.57-1.75-4.66-6.94zM25.13 8.12c1.19-1.44 1.99-3.44 1.77-5.43-1.71.07-3.78.89-5.01 2.01-1.1 1.27-2.06 3.31-1.8 5.26 1.9.15 3.85-.97 5.04-1.84z"/>
            <path fill="currentColor" d="M61.11 15.23c0 2.19-.59 3.93-1.76 5.22-1.05 1.16-2.37 1.74-3.96 1.74-1.67 0-2.88-.61-3.61-1.83h-.05v6.87h-4.5V12.5c0-1.55-.04-3.14-.12-4.78h3.95l.25 2.32h.1c.94-1.75 2.48-2.62 4.62-2.62 1.54 0 2.83.61 3.86 1.83 1.03 1.22 1.55 2.85 1.55 4.9v.08zm-4.55-.13c0-1.3-.32-2.37-.95-3.21-.68-.89-1.6-1.34-2.75-1.34-.77 0-1.47.25-2.1.74-.63.49-1.06 1.15-1.29 1.97-.12.41-.18.76-.18 1.05v2.58c0 1.13.36 2.07 1.08 2.82.72.75 1.64 1.12 2.76 1.12 1.18 0 2.1-.46 2.76-1.39.66-.93.99-2.18.99-3.75v-.59z"/>
            <path fill="currentColor" d="M85.44 21.85h-4.5V7.75h4.5v14.1z"/>
          </svg>
          <span class="apple-pay-text">Buy Now</span>
        </div>
      </button>
    `,
    templateCSS: `
      .custom-apple-pay-button {
        width: 100%;
        height: 52px;
        background: linear-gradient(135deg, #1a1a1a 0%, #333 100%);
        border: none;
        border-radius: 12px;
        color: white;
        font-size: 16px;
        font-weight: 600;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
        position: relative;
        overflow: hidden;
      }
      
      .custom-apple-pay-button::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(255,255,255,0.1), transparent);
        transition: left 0.5s;
      }
      
      .custom-apple-pay-button:hover::before {
        left: 100%;
      }
      
      .custom-apple-pay-button:hover {
        transform: translateY(-2px);
        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
        background: linear-gradient(135deg, #333 0%, #555 100%);
      }
      
      .custom-apple-pay-button:active {
        transform: translateY(0);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
      }
      
      .custom-apple-pay-button:disabled {
        opacity: 0.6;
        cursor: not-allowed;
        transform: none;
      }
      
      .apple-pay-content {
        display: flex;
        align-items: center;
        gap: 10px;
        z-index: 1;
        position: relative;
      }
      
      .apple-pay-icon {
        flex-shrink: 0;
        filter: brightness(1.1);
      }
      
      .apple-pay-text {
        font-weight: 600;
        letter-spacing: 0.5px;
      }
      
      @media (max-width: 768px) {
        .custom-apple-pay-button {
          height: 48px;
          font-size: 15px;
          border-radius: 10px;
        }
      }
      
      @media (max-width: 480px) {
        .custom-apple-pay-button {
          height: 44px;
          font-size: 14px;
          border-radius: 8px;
        }
        
        .apple-pay-icon {
          width: 45px;
          height: 11px;
        }
        
        .apple-pay-text {
          display: none;
        }
      }
    `
  },
  paymentRequest: {
    countryCode: 'US',
    currencyCode: 'USD',
    merchantCapabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit'],
    supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
    total: {
      label: 'Total',
      amount: '89.97'
    },
    lineItems: [
      {
        label: 'Camping Tent',
        amount: '69.99'
      },
      {
        label: 'Sleeping Bag',
        amount: '14.99'
      },
      {
        label: 'Tax',
        amount: '4.99'
      }
    ],
    requiredBillingContactFields: ['postalAddress', 'name', 'email'],
    requiredShippingContactFields: ['postalAddress', 'name', 'phone'],
    shippingMethods: [
      {
        label: 'Standard Shipping',
        detail: '5-7 business days',
        amount: '0.00',
        identifier: 'standard'
      },
      {
        label: 'Express Shipping',
        detail: '2-3 business days',
        amount: '12.99',
        identifier: 'express'
      }
    ]
  },
  onShippingMethodSelected: async (method) => {
    const baseAmount = 84.98; // Subtotal + tax
    const shippingCost = parseFloat(method.amount);
    const newTotal = baseAmount + shippingCost;
    
    return {
      newTotal: {
        label: 'Total',
        amount: newTotal.toFixed(2)
      },
      newLineItems: [
        { label: 'Camping Tent', amount: '69.99' },
        { label: 'Sleeping Bag', amount: '14.99' },
        { label: 'Tax', amount: '4.99' },
        { label: `Shipping (${method.label})`, amount: method.amount }
      ]
    };
  },
  onPostAuthorisation: (result, applePayResult) => {
    if (result instanceof AuthorisedSubmitResult) {
      console.log('Order successful:', result.transactionId);
      
      // Send order confirmation email
      sendOrderConfirmation({
        transactionId: result.transactionId,
        email: applePayResult.billingContact?.emailAddress,
        shippingAddress: applePayResult.shippingContact?.postalAddress
      });
      
      // Redirect to order tracking page
      window.location.href = `/order-tracking/${result.transactionId}`;
    } else {
      console.error('Order failed:', result.errorReason);
      showErrorNotification('Order failed. Please try again or contact support.');
    }
  },
  onError: (error) => {
    console.error('Apple Pay Error:', error);
    trackEvent('apple_pay_error', { error: error.message });
    showErrorNotification('Payment system error. Please try again.');
  }
});

applePayComponent.mount('apple-pay-container');
```


```typescript Dynamic state management
class ApplePayButtonManager {
  private component: any = null;
  private container: string;
  private state: 'idle' | 'loading' | 'success' | 'error' = 'idle';
  
  constructor(container: string) {
    this.container = container;
  }
  
  create(theme: 'light' | 'dark' = 'light') {
    const config = {
      merchantDisplayName: 'TechGadget Pro Store',
      paymentDescription: 'Wireless Gaming Headset Purchase',
      usingCss: true,
      style: {
        type: 'buy',
        buttonstyle: 'black',
        locale: 'en-US',
        template: this.getTemplate(),
        templateCSS: this.getCSS(theme)
      },
      paymentRequest: {
        countryCode: 'US',
        currencyCode: 'USD',
        merchantCapabilities: ['supports3DS', 'supportsEMV', 'supportsCredit', 'supportsDebit'],
        supportedNetworks: ['visa', 'masterCard', 'amex', 'discover'],
        total: {
          label: 'Total',
          amount: '189.99'
        },
        lineItems: [
          {
            label: 'Gaming Headset Pro X',
            amount: '169.99'
          },
          {
            label: 'Extended Warranty',
            amount: '12.99'
          },
          {
            label: 'Tax',
            amount: '7.01'
          }
        ],
        requiredBillingContactFields: ['postalAddress', 'name', 'email']
      },
      onPostAuthorisation: (result, applePayResult) => {
        if (result instanceof AuthorisedSubmitResult) {
          this.setState('success');
          setTimeout(() => {
            window.location.href = '/payment-success';
          }, 1500);
        } else {
          this.setState('error');
          setTimeout(() => this.setState('idle'), 3000);
        }
      },
      onError: (error) => {
        this.setState('error');
        setTimeout(() => this.setState('idle'), 3000);
      }
    };
    
    this.component = pxpSdk.create('apple-pay-button', config);
    return this;
  }
  
  mount() {
    if (this.component) {
      this.component.mount(this.container);
      this.setupEventListeners();
    }
    return this;
  }
  
  setState(newState: 'idle' | 'loading' | 'success' | 'error') {
    this.state = newState;
    this.updateButtonAppearance();
  }
  
  private getTemplate() {
    return `
      <button class="dynamic-apple-pay-button" type="button">
        <div class="button-content">
          <svg class="apple-pay-icon" viewBox="0 0 102 26" width="51" height="13">
            <path fill="currentColor" d="M28.94 11.26c.09-4.21 3.48-6.26 3.64-6.37-1.98-2.9-5.06-3.3-6.16-3.34-2.62-.27-5.11 1.54-6.44 1.54-1.34 0-3.41-1.5-5.6-1.46-2.88.04-5.53 1.67-7.02 4.25-2.99 5.18-.77 12.85 2.15 17.06 1.43 2.06 3.14 4.38 5.38 4.3 2.18-.09 3-1.41 5.63-1.41 2.62 0 3.37 1.41 5.64 1.37 2.33-.04 3.83-2.11 5.26-4.18 1.66-2.39 2.34-4.7 2.38-4.82-.05-.02-4.57-1.75-4.66-6.94zM25.13 8.12c1.19-1.44 1.99-3.44 1.77-5.43-1.71.07-3.78.89-5.01 2.01-1.1 1.27-2.06 3.31-1.8 5.26 1.9.15 3.85-.97 5.04-1.84z"/>
          </svg>
          <span class="button-text">Pay</span>
          <div class="status-indicator">
            <div class="spinner"></div>
            <div class="checkmark">✓</div>
            <div class="error-mark">✗</div>
          </div>
        </div>
      </button>
    `;
  }
  
  private getCSS(theme: 'light' | 'dark') {
    const colors = theme === 'dark' ? {
      bg: '#1c1c1e',
      text: '#ffffff',
      hover: '#2c2c2e',
      success: '#30d158',
      error: '#ff453a'
    } : {
      bg: '#000000',
      text: '#ffffff',
      hover: '#333333',
      success: '#34c759',
      error: '#ff3b30'
    };
    
    return `
      .dynamic-apple-pay-button {
        width: 100%;
        height: 52px;
        background: ${colors.bg};
        color: ${colors.text};
        border: none;
        border-radius: 8px;
        font-size: 16px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.3s ease;
        font-family: -apple-system, BlinkMacSystemFont, sans-serif;
        position: relative;
        overflow: hidden;
      }
      
      .button-content {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;
        gap: 8px;
        transition: all 0.3s ease;
      }
      
      .dynamic-apple-pay-button:hover {
        background: ${colors.hover};
        transform: translateY(-1px);
      }
      
      .status-indicator {
        position: absolute;
        right: 16px;
        top: 50%;
        transform: translateY(-50%);
        width: 20px;
        height: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
      }
      
      .spinner, .checkmark, .error-mark {
        display: none;
        position: absolute;
      }
      
      .spinner {
        width: 16px;
        height: 16px;
        border: 2px solid rgba(255, 255, 255, 0.3);
        border-top: 2px solid white;
        border-radius: 50%;
        animation: spin 1s linear infinite;
      }
      
      .checkmark {
        color: ${colors.success};
        font-size: 18px;
        font-weight: bold;
      }
      
      .error-mark {
        color: ${colors.error};
        font-size: 18px;
        font-weight: bold;
      }
      
      @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
      }
      
      /* State classes */
      .dynamic-apple-pay-button.loading .spinner { display: block; }
      .dynamic-apple-pay-button.success .checkmark { display: block; }
      .dynamic-apple-pay-button.error .error-mark { display: block; }
      
      .dynamic-apple-pay-button.loading {
        cursor: not-allowed;
        opacity: 0.8;
      }
      
      .dynamic-apple-pay-button.success {
        background: ${colors.success};
      }
      
      .dynamic-apple-pay-button.error {
        background: ${colors.error};
      }
    `;
  }
  
  private setupEventListeners() {
    const button = document.querySelector('.dynamic-apple-pay-button');
    if (button) {
      button.addEventListener('click', () => {
        if (this.state === 'idle') {
          this.setState('loading');
        }
      });
    }
  }
  
  private updateButtonAppearance() {
    const button = document.querySelector('.dynamic-apple-pay-button');
    if (button) {
      button.className = `dynamic-apple-pay-button ${this.state}`;
    }
  }
}

// Usage
const applePayManager = new ApplePayButtonManager('apple-pay-container');
applePayManager.create('dark').mount();
```