Learn how to configure the payout submission component for Web.
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');| Property | Description |
|---|---|
recipientWalletstring (enum) required | The wallet type for the payout. Determines button styling and payout destination. Possible values:
|
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');| Property | Description |
|---|---|
recipientWalletstring (enum) required | The wallet type for the payout. Possible values:
|
submitTextstring | Custom button text. Defaults to "Withdraw with {recipientWallet}". |
classstring | Custom CSS class for the button. |
stylesobject | Button styles for different states. |
brandingImageConfigobject | 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.
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.
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"
}
}
};| Property | Description |
|---|---|
styles.baseCSSProperties | The normal interactive state. Applied when the button is ready to be clicked. |
styles.hoverCSSProperties | The hover state. Applied when the cursor is over the button. |
styles.activeCSSProperties | The active state. Applied when the button is pressed. |
styles.focusCSSProperties | The focus state. Applied when the button receives keyboard focus. |
styles.disabledCSSProperties | The disabled state. Applied during initialisation or when payout isn't available. |
styles.loadingCSSProperties | The loading state. Applied during payout processing. |
Customise the wallet logo dimensions:
const submitConfig = {
recipientWallet: "Paypal",
brandingImageConfig: {
width: "80px",
height: "auto"
}
};| Property | Description |
|---|---|
brandingImageConfig.widthstring | The width of the wallet logo. |
brandingImageConfig.heightstring | The height of the wallet logo. |
The submission component provides event handlers to manage the payout flow:
const submitConfig = {
recipientWallet: "Paypal",
onClick: (event) => { },
onPrePayoutSubmit: async () => { },
onPostPayout: (result) => { },
onError: (error) => { }
};| Callback | Description |
|---|---|
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. |
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.
Renders the submission button in the specified container:
const submitComponent = pxpCheckoutSdk.create('payout-submission', submitConfig);
submitComponent.mount('payout-submit-container');Removes the component from the DOM:
submitComponent.unmount();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');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');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');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>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.