Skip to content

Submission component

Learn how to configure the payout submission component for Web.

Basic usage

Minimal configuration

The payout submission component renders a "Withdraw with PayPal" or "Withdraw with Venmo" button that executes the payout. At minimum, you must specify the recipient wallet type.

const submitComponent = pxpCheckoutSdk.create('payout-submission', {
  recipientWallet: "Paypal"
});
submitComponent.mount('payout-submit-container');
PropertyDescription
recipientWallet
string (enum)
required
The wallet type for the payout. Determines button styling and payout destination.

Possible values:
  • PayPal
  • Venmo

Advanced configuration

For more control over the button's appearance and behaviour, you can configure custom options:

const submitConfig = {
  recipientWallet: "Paypal",
  submitText: "Confirm withdrawal",
  class: "custom-payout-button",
  
  styles: {
    base: {
      backgroundColor: "#FFC438",
      color: "#09090C",
      borderRadius: "8px",
      padding: "14px 28px",
      fontSize: "16px",
      fontWeight: "600"
    },
    hover: {
      backgroundColor: "#F7B731"
    },
    active: {
      opacity: "0.7"
    },
    focus: {
      outline: "2px solid #0070CC",
      outlineOffset: "2px"
    },
    disabled: {
      opacity: "0.5",
      cursor: "not-allowed"
    },
    loading: {
      opacity: "0.8"
    }
  },
  
  brandingImageConfig: {
    width: "60px",
    height: "auto"
  },
  
  onClick: (event) => {
    console.log("Withdraw button clicked");
  },
  
  onPrePayoutSubmit: async () => {
    const approved = await showConfirmationModal();
    return { isApproved: approved, note: "Withdrawal request" };
  },
  
  onPostPayout: (result) => {
    console.log("Payout successful:", result);
    showSuccessMessage("Withdrawal completed!");
  },
  
  onError: (error) => {
    console.error("Payout failed:", error);
    showErrorMessage("Withdrawal failed. Please try again.");
  }
};

const submitComponent = pxpCheckoutSdk.create('payout-submission', submitConfig);
submitComponent.mount('payout-submit-container');
PropertyDescription
recipientWallet
string (enum)
required
The wallet type for the payout.

Possible values:
  • PayPal
  • Venmo
submitText
string
Custom button text. Defaults to "Withdraw with {recipientWallet}".
class
string
Custom CSS class for the button.
styles
object
Button styles for different states.
brandingImageConfig
object
Configuration for the wallet logo dimensions.

The payout execution mode (SDK-managed vs merchant-managed) is configured at SDK initialisation via paypalConfig.payoutConfig.proceedPayoutWithSdk, not at component level.

Styling

Default styling

The submission component renders with PayPal or Venmo branded styling by default.

{
  base: { 
    borderRadius: '3px',
    backgroundColor: '#FFC438', 
    padding: '12px 24px',
    color: '#09090C', 
    border: 'none',
    fontFamily: 'Roboto, sans-serif',
    fontSize: '16px', 
    lineHeight: '18px', 
    fontWeight: '500' 
  },
  hover: { backgroundColor: '#F7B731' },
  disabled: { opacity: '0.5', cursor: 'not-allowed' },
  loading: { }
}

The component doesn't apply default active or focus styles. If you need these states styled, provide custom values in the styles configuration.

Custom styling

You can override the default appearance by providing custom styles for each button state:

const submitConfig = {
  recipientWallet: "Paypal",
  styles: {
    base: {
      backgroundColor: "#003087",
      color: "#ffffff",
      borderRadius: "12px",
      padding: "16px 32px",
      fontSize: "18px",
      fontWeight: "bold",
      border: "none",
      cursor: "pointer",
      transition: "all 0.2s ease"
    },
    hover: {
      backgroundColor: "#001f5c",
      transform: "translateY(-1px)",
      boxShadow: "0 4px 12px rgba(0, 48, 135, 0.3)"
    },
    active: {
      transform: "translateY(0)",
      boxShadow: "0 2px 6px rgba(0, 48, 135, 0.2)"
    },
    focus: {
      outline: "3px solid #0070CC",
      outlineOffset: "3px"
    },
    disabled: {
      backgroundColor: "#cccccc",
      color: "#666666",
      cursor: "not-allowed",
      opacity: "0.7"
    },
    loading: {
      backgroundColor: "#001f5c",
      opacity: "0.9"
    }
  }
};
PropertyDescription
styles.base
CSSProperties
The normal interactive state. Applied when the button is ready to be clicked.
styles.hover
CSSProperties
The hover state. Applied when the cursor is over the button.
styles.active
CSSProperties
The active state. Applied when the button is pressed.
styles.focus
CSSProperties
The focus state. Applied when the button receives keyboard focus.
styles.disabled
CSSProperties
The disabled state. Applied during initialisation or when payout isn't available.
styles.loading
CSSProperties
The loading state. Applied during payout processing.

Branding image configuration

Customise the wallet logo dimensions:

const submitConfig = {
  recipientWallet: "Paypal",
  brandingImageConfig: {
    width: "80px",
    height: "auto"
  }
};
PropertyDescription
brandingImageConfig.width
string
The width of the wallet logo.
brandingImageConfig.height
string
The height of the wallet logo.

Event handling

The submission component provides event handlers to manage the payout flow:

const submitConfig = {
  recipientWallet: "Paypal",
  
  onClick: (event) => { },
  onPrePayoutSubmit: async () => { },
  onPostPayout: (result) => { },
  onError: (error) => { }
};
CallbackDescription
onClick
(event: Event) => void
Called when the button is clicked, before validation.
onPrePayoutSubmit
() => Promise<{ isApproved: boolean; note?: string }>
Called after validation, before payout execution. Return { isApproved: false } to cancel.
onPostPayout
(result: any) => void
Called when the payout completes successfully.
onError
(error: any) => void
Called when an error occurs during payout.

onPrePayoutSubmit

This callback allows you to show a confirmation dialog and optionally include a note with the payout:

onPrePayoutSubmit: async () => {
  // Show custom confirmation modal
  const userConfirmed = await showConfirmationModal({
    title: "Confirm Withdrawal",
    message: `Withdraw $${amount} to your PayPal account?`,
    confirmText: "Confirm",
    cancelText: "Cancel"
  });
  
  if (!userConfirmed) {
    return { isApproved: false };
  }
  
  return { 
    isApproved: true,
    note: "Withdrawal initiated by customer"  // Optional note (max 4000 chars)
  };
}

The note field is optional and has a maximum length of 4000 characters. It will be included with the payout transaction for reference.

Methods

mount(containerId)

Renders the submission button in the specified container:

const submitComponent = pxpCheckoutSdk.create('payout-submission', submitConfig);
submitComponent.mount('payout-submit-container');

unmount()

Removes the component from the DOM:

submitComponent.unmount();

Examples

Basic PayPal submission

A simple implementation for PayPal payouts:

const submitComponent = pxpCheckoutSdk.create('payout-submission', {
  recipientWallet: "Paypal",
  onPostPayout: (result) => {
    window.location.href = `/success?txn=${result.transactionId}`;
  },
  onError: (error) => {
    alert("Withdrawal failed. Please try again.");
  }
});
submitComponent.mount('payout-submit-container');

Venmo submission with custom styling

An implementation styled to match Venmo branding:

const submitConfig = {
  recipientWallet: "Venmo",
  submitText: "Get paid with Venmo",
  styles: {
    base: {
      backgroundColor: "#008CFF",
      color: "#ffffff",
      borderRadius: "24px",
      padding: "14px 28px",
      fontSize: "16px",
      fontWeight: "600",
      border: "none"
    },
    hover: {
      backgroundColor: "#0070CC"
    }
  },
  onPostPayout: (result) => {
    showSuccessMessage("Venmo payout successful!");
  }
};

const submitComponent = pxpCheckoutSdk.create('payout-submission', submitConfig);
submitComponent.mount('payout-submit-container');

Submission with confirmation dialog

An implementation with a custom approval flow:

const submitConfig = {
  recipientWallet: "Paypal",
  submitText: "Withdraw Funds",
  
  onClick: (event) => {
    console.log("User clicked withdraw button");
    trackEvent("payout_button_clicked");
  },
  
  onPrePayoutSubmit: async () => {
    // Perform validation
    const balance = await checkUserBalance();
    if (balance < payoutAmount) {
      showError("Insufficient balance");
      return { isApproved: false };
    }
    
    // Show confirmation dialog
    const confirmed = await showModal({
      title: "Confirm Withdrawal",
      body: `
        Amount: $${payoutAmount}
        Destination: ${userPaypalEmail}
        Processing time: 1-2 business days
      `,
      confirmButton: "Confirm Withdrawal",
      cancelButton: "Cancel"
    });
    
    if (!confirmed) {
      return { isApproved: false };
    }
    
    return { 
      isApproved: true,
      note: `Withdrawal request for user ${userId}`
    };
  },
  
  onPostPayout: (result) => {
    // Update UI
    showSuccessMessage("Withdrawal successful!");
    
    // Track analytics
    trackEvent("payout_completed", {
      transactionId: result.transactionId,
      amount: payoutAmount
    });
    
    // Redirect after delay
    setTimeout(() => {
      window.location.href = `/account/transactions`;
    }, 2000);
  },
  
  onError: (error) => {
    console.error("Payout error:", error);
    showErrorMessage("Withdrawal failed. Please try again.");
    trackEvent("payout_failed", { error: error.message });
  }
};

const submitComponent = pxpCheckoutSdk.create('payout-submission', submitConfig);
submitComponent.mount('payout-submit-container');

Complete payout page

A full example showing the submission component in context:

import { PxpCheckout, IntentType, CurrencyType } from "@pxpio/web-components-sdk";

async function initializePayoutPage() {
  const sessionData = await getSessionDataFromBackend();
  const customerWallet = await getStoredCustomerWallet();
  const payoutAmount = 150.00;
  
  const pxpCheckoutSdk = PxpCheckout.initialize({
    environment: "test",
    session: sessionData,
    ownerId: "Unity",
    ownerType: "MerchantGroup",
    transactionData: {
      amount: payoutAmount,
      currency: "USD" as CurrencyType,
      entryType: "Ecom",
      intent: { paypal: IntentType.Payout },
      merchantTransactionId: crypto.randomUUID(),
      merchantTransactionDate: () => new Date().toISOString()
    },
    paypalConfig: {
      payoutConfig: {
        proceedPayoutWithSdk: true,
        paypalWallet: {
          email: customerWallet.email,
          payerId: customerWallet.payerId
        }
      }
    }
  });

  // Create components
  const amountComponent = pxpCheckoutSdk.create('payout-amount', {
    label: "Withdrawal Amount"
  });

  const receiverComponent = pxpCheckoutSdk.create('paypal-payout-receiver', {
    label: "PayPal Account",
    showMaskToggle: true
  });

  const submitComponent = pxpCheckoutSdk.create('payout-submission', {
    recipientWallet: "Paypal",
    submitText: "Withdraw to PayPal",
    
    styles: {
      base: {
        backgroundColor: "#FFC438",
        color: "#09090C",
        borderRadius: "8px",
        padding: "16px 32px",
        fontSize: "18px",
        fontWeight: "bold",
        width: "100%"
      }
    },
    
    onPrePayoutSubmit: async () => {
      const confirmed = await showConfirmationDialog(payoutAmount);
      return { isApproved: confirmed };
    },
    
    onPostPayout: (result) => {
      showSuccessAnimation();
      setTimeout(() => {
        window.location.href = `/success?txn=${result.transactionId}`;
      }, 1500);
    },
    
    onError: (error) => {
      showErrorToast(error.message);
    }
  });

  // Mount all components
  amountComponent.mount('payout-amount-container');
  receiverComponent.mount('payout-receiver-container');
  submitComponent.mount('payout-submit-container');
}

initializePayoutPage();
<div class="payout-page">
  <h1>Withdraw Funds</h1>
  <div class="payout-card">
    <div id="payout-amount-container"></div>
    <div id="payout-receiver-container"></div>
    <div id="payout-submit-container"></div>
  </div>
</div>

Error handling

The component handles validation errors and payout failures through the onError callback:

onError: (error) => {
  console.error("Payout error:", error);
  
  // Handle specific error types
  switch (error.ErrorCode) {
    case "SDK0809":
      showError("PayPal account information is missing.");
      break;
    case "SDK0810":
    case "SDK0811":
    case "SDK0812":
      showError("Invalid payout amount.");
      break;
    case "SDK0813":
    case "SDK0814":
    case "SDK0815":
      showError("Invalid currency.");
      break;
    case "SDK1001":
      showError("Recipient wallet is required.");
      break;
    case "SDK1003":
      showError("Unsupported wallet type.");
      break;
    default:
      showError("An error occurred. Please try again or contact support.");
  }
}

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