Learn about built-in validation and error handling for payout components.
The payout components include comprehensive validation to ensure data integrity and compliance with PayPal and Venmo requirements. All built-in validation is performed before executing payouts. If validation fails, the SDK will throw a specific exception with detailed error information.
You can handle these errors through the onError callback and display appropriate messages to your customers.
By default, the payout components validate that:
- Required fields are provided (amount, currency, recipient wallet details).
- Amount is a valid positive number greater than zero.
- Currency codes are valid 3-letter ISO 4217 codes.
- Email addresses are properly formatted.
- Phone numbers contain only numeric characters (Venmo).
- Recipient types match the provided receiver format.
- Field lengths don't exceed maximum limits.
- Venmo payouts use USD currency (the only supported currency for Venmo).
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK1000 | PaypalConfigRequiredException | PayPal configuration is required. | Ensure paypalConfig is provided in SDK initialisation. |
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK0810 | PaypalPayoutAmountInvalidException | Amount must be a valid number. | Provide a valid numeric amount. |
| SDK0811 | PaypalPayoutAmountNotPositiveException | Amount must be a positive number greater than 0. | Ensure amount is greater than zero. |
| SDK0812 | PaypalPayoutAmountRequiredException | Amount is required. | Provide an amount in transactionData.amount. |
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK0813 | PaypalPayoutCurrencyRequiredException | Currency code must be a non-empty string. | Provide a currency code in transactionData.currency. |
| SDK0814 | PaypalPayoutCurrencyLengthInvalidException | Currency code must be a 3-letter ISO 4217 code. | Use a valid 3-letter code like USD, EUR, GBP. |
| SDK0815 | PaypalPayoutCurrencyCodeInvalidException | Invalid currency code. | Use a valid ISO 4217 currency code. |
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK0803 | PaypalPayoutReceiverRequiredException | Receiver value is required. | Provide a PayPal email or Payer ID. |
| SDK0804 | PaypalPayoutReceiverTypeInvalidException | Invalid receiver type. | Use Email, Phone, PaypalId, or UserHandle. |
| SDK0805 | PaypalPayoutReceiverTypeEmailOnlyException | Receiver type must be Email. | PayPal wallet requires Email as receiver type. |
| SDK0806 | PaypalPayoutWalletInvalidException | Invalid wallet value. | Use Paypal for PayPal payouts. |
| SDK0807 | PaypalPayoutWalletRequiresEmailException | Receiver type must be Email when wallet is Paypal. | Ensure receiver type is Email. |
| SDK0808 | PaypalPayoutEmailInvalidException | Invalid email format. | Provide a valid email address. |
| SDK0809 | PaypalPayoutPayerIdRequiredException | PayPal Payer ID is required. | Provide a PayPal Payer ID or email. |
| SDK0816 | PaypalPayoutReceiverTypeRequiredException | Receiver type is required. | Specify the receiver type (e.g., Email, PaypalId). |
| SDK0818 | PaypalPayoutFieldLengthExceededException | Field exceeds maximum length. | Reduce the field length to within limits. |
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK0900 | VenmoPayoutWalletInvalidException | Venmo wallet is required. | Provide venmoWallet configuration. |
| SDK0901 | VenmoPayoutReceiverRequiredException | Receiver value is required. | Provide a Venmo receiver (email, phone, or handle). |
| SDK0902 | VenmoPayoutRecipientTypeRequiredException | Venmo recipient type is required. | Specify recipientType as Email, Phone, or UserHandle. |
| SDK0903 | VenmoPayoutRecipientTypeInvalidException | Invalid recipient type. | Use Email, Phone, or UserHandle. |
| SDK0904 | VenmoPayoutPhoneInvalidException | Invalid phone format. | Phone number must contain only numeric characters. |
| SDK0905 | VenmoPayoutCurrencyInvalidException | Venmo only supports USD currency. | Use USD for Venmo payouts. |
| Error code | Exception | Description | Resolution |
|---|---|---|---|
| SDK1001 | PayoutRecipientWalletRequiredException | Recipient wallet is required. | Specify recipientWallet as Paypal or Venmo. |
| SDK1002 | PayoutReceiverAndRecipientTypeRequiredException | Receiver and recipient type are required. | Provide both receiver value and recipient type. |
| SDK1003 | UnsupportedPayoutRecipientWalletException | Unsupported recipient wallet. | Use Paypal or Venmo. |
| SDK1004 | PayoutNoteTooLongException | Payout note exceeds maximum length. | Notes longer than 4000 characters will be automatically truncated with a console warning. |
Handle validation errors through the onError callback:
const submitConfig = {
recipientWallet: "Paypal",
onError: (error) => {
console.error("Payout error:", error.ErrorCode, error.message);
// Display user-friendly message
showErrorMessage(error.message);
}
};Implement detailed error handling based on error codes:
const submitConfig = {
recipientWallet: "Paypal",
onError: (error) => {
console.error("Payout error:", error);
let userMessage: string;
let action: string = "";
switch (error.ErrorCode) {
// Amount errors
case "SDK0810":
userMessage = "Invalid withdrawal amount.";
action = "Please enter a valid number.";
break;
case "SDK0811":
userMessage = "Withdrawal amount must be greater than zero.";
action = "Please enter a positive amount.";
break;
case "SDK0812":
userMessage = "Withdrawal amount is missing.";
action = "Please contact support.";
break;
// Currency errors
case "SDK0813":
case "SDK0814":
case "SDK0815":
userMessage = "Invalid currency configuration.";
action = "Please contact support.";
break;
// PayPal receiver errors
case "SDK0803":
case "SDK0809":
userMessage = "PayPal account information is missing.";
action = "Please link your PayPal account.";
break;
case "SDK0808":
userMessage = "Invalid PayPal email address.";
action = "Please update your PayPal email.";
break;
case "SDK0818":
userMessage = "Account information exceeds maximum length.";
action = "Please contact support.";
break;
// Venmo receiver errors
case "SDK0901":
userMessage = "Venmo account information is missing.";
action = "Please link your Venmo account.";
break;
case "SDK0903":
userMessage = "Invalid Venmo recipient type.";
action = "Please contact support.";
break;
case "SDK0904":
userMessage = "Invalid phone number format.";
action = "Please update your Venmo phone number.";
break;
case "SDK0905":
userMessage = "Venmo only supports USD withdrawals.";
action = "Please select a different payout method.";
break;
// Payout submission errors
case "SDK1001":
case "SDK1002":
case "SDK1003":
userMessage = "Invalid payout configuration.";
action = "Please contact support.";
break;
case "SDK1004":
userMessage = "Payout note is too long.";
action = "Notes longer than 4000 characters will be truncated.";
break;
// Configuration errors
case "SDK1000":
userMessage = "Payout is not configured correctly.";
action = "Please contact support.";
break;
default:
userMessage = "An error occurred during withdrawal.";
action = "Please try again or contact support.";
}
// Display error to user
showErrorDialog({
title: "Withdrawal Error",
message: userMessage,
action: action,
errorCode: error.ErrorCode
});
// Log for debugging
logError("payout_validation_error", {
errorCode: error.ErrorCode,
errorMessage: error.message,
timestamp: new Date().toISOString()
});
}
};Run validation before the payout is executed to catch issues early:
const submitConfig = {
recipientWallet: "Paypal",
onPrePayoutSubmit: async () => {
try {
// 1. Validate withdrawal limits
const limitsCheck = await validateWithdrawalLimits({
userId: getCurrentUserId(),
amount: getPayoutAmount(),
currency: getPayoutCurrency()
});
if (!limitsCheck.valid) {
showError(`Withdrawal limit exceeded. Maximum: ${limitsCheck.maxAmount}`);
return { isApproved: false };
}
// 2. Verify sufficient balance
const balanceCheck = await verifyBalance({
userId: getCurrentUserId(),
amount: getPayoutAmount()
});
if (!balanceCheck.sufficient) {
showError("Insufficient balance for this withdrawal.");
return { isApproved: false };
}
// 3. Compliance check
const complianceCheck = await performComplianceCheck({
userId: getCurrentUserId(),
amount: getPayoutAmount(),
recipientType: getRecipientType()
});
if (!complianceCheck.passed) {
showError("This withdrawal requires additional verification.");
return { isApproved: false };
}
// 4. Fraud prevention
const fraudCheck = await checkFraudIndicators({
userId: getCurrentUserId(),
amount: getPayoutAmount(),
ipAddress: getClientIP(),
deviceFingerprint: getDeviceFingerprint()
});
if (fraudCheck.riskLevel === "HIGH") {
showError("This withdrawal has been flagged for review.");
return { isApproved: false };
}
// All validations passed
return { isApproved: true };
} catch (error) {
console.error("Pre-payout validation failed:", error);
showError("Unable to validate withdrawal. Please try again.");
return { isApproved: false };
}
}
};Check if the payout amount is within allowed limits:
async function validateWithdrawalLimits(userId: string, amount: number, currency: string) {
// Get user's withdrawal limits
const limits = await getUserWithdrawalLimits(userId);
// Check daily limit
const todayWithdrawals = await getTodayWithdrawals(userId);
const dailyTotal = todayWithdrawals.reduce((sum, w) => sum + w.amount, 0);
if (dailyTotal + amount > limits.dailyLimit) {
return {
valid: false,
reason: "daily_limit_exceeded",
remaining: limits.dailyLimit - dailyTotal
};
}
// Check monthly limit
const monthlyWithdrawals = await getMonthlyWithdrawals(userId);
const monthlyTotal = monthlyWithdrawals.reduce((sum, w) => sum + w.amount, 0);
if (monthlyTotal + amount > limits.monthlyLimit) {
return {
valid: false,
reason: "monthly_limit_exceeded",
remaining: limits.monthlyLimit - monthlyTotal
};
}
// Check minimum withdrawal amount
if (amount < limits.minimumWithdrawal) {
return {
valid: false,
reason: "below_minimum",
minimum: limits.minimumWithdrawal
};
}
// Check maximum single withdrawal
if (amount > limits.maximumSingleWithdrawal) {
return {
valid: false,
reason: "exceeds_maximum",
maximum: limits.maximumSingleWithdrawal
};
}
return { valid: true };
}Verify the recipient account is valid and active:
async function validateRecipientAccount(walletType: string, receiver: string) {
if (walletType === "Paypal") {
// Validate PayPal email format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(receiver)) {
return {
valid: false,
reason: "invalid_email_format"
};
}
// Check if account is verified (if you have this capability)
const accountStatus = await checkPayPalAccountStatus(receiver);
if (accountStatus.restricted) {
return {
valid: false,
reason: "account_restricted"
};
}
}
if (walletType === "Venmo") {
// Validate based on recipient type
const recipientType = getVenmoRecipientType();
if (recipientType === "Phone") {
// Phone must be numeric
const phoneRegex = /^\+?[0-9]+$/;
if (!phoneRegex.test(receiver)) {
return {
valid: false,
reason: "invalid_phone_format"
};
}
}
if (recipientType === "Email") {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(receiver)) {
return {
valid: false,
reason: "invalid_email_format"
};
}
}
}
return { valid: true };
}Assess the risk level of a payout request:
async function calculatePayoutRiskScore(payoutData: PayoutData) {
const factors = {
// Check velocity - multiple payouts in short time
velocityScore: await checkPayoutVelocity(payoutData.userId),
// Check if payout destination is new
destinationScore: await checkDestinationHistory(payoutData.userId, payoutData.receiver),
// Check amount patterns
amountScore: await analyzeAmountPatterns(payoutData.userId, payoutData.amount),
// Check device/location consistency
deviceScore: await checkDeviceConsistency(payoutData.userId, payoutData.deviceData),
// Check time patterns
timeScore: await checkTimePatterns(payoutData.userId)
};
// Calculate weighted average
const weights = {
velocityScore: 0.25,
destinationScore: 0.20,
amountScore: 0.20,
deviceScore: 0.20,
timeScore: 0.15
};
const totalScore = Object.entries(factors).reduce((sum, [key, score]) => {
return sum + (score * weights[key as keyof typeof weights]);
}, 0);
return {
score: totalScore,
riskLevel: totalScore > 0.8 ? "HIGH" : totalScore > 0.5 ? "MEDIUM" : "LOW",
factors: factors,
requiresReview: totalScore > 0.7
};
}Always validate on the client side before submission:
function validatePayoutBeforeSubmit() {
const errors: string[] = [];
// Validate amount
const amount = getPayoutAmount();
if (!amount || amount <= 0) {
errors.push("Please enter a valid withdrawal amount.");
}
// Validate recipient is selected
const recipientWallet = getSelectedWallet();
if (!recipientWallet) {
errors.push("Please select a payout method.");
}
// Validate wallet-specific requirements
if (recipientWallet === "Venmo" && getCurrency() !== "USD") {
errors.push("Venmo only supports USD withdrawals.");
}
if (errors.length > 0) {
showValidationErrors(errors);
return false;
}
return true;
}Map technical errors to user-friendly messages:
const errorMessages: Record<string, { title: string; message: string; action: string }> = {
"SDK0810": {
title: "Invalid Amount",
message: "The withdrawal amount is not valid.",
action: "Please enter a valid number."
},
"SDK0811": {
title: "Invalid Amount",
message: "The withdrawal amount must be greater than zero.",
action: "Please enter a positive amount."
},
"SDK0808": {
title: "Invalid Email",
message: "The PayPal email address is not valid.",
action: "Please check your PayPal email and try again."
},
"SDK0904": {
title: "Invalid Phone",
message: "The phone number format is not valid.",
action: "Please enter a valid phone number with only digits."
},
"SDK0905": {
title: "Currency Not Supported",
message: "Venmo only supports USD withdrawals.",
action: "Please use PayPal for non-USD withdrawals."
},
"SDK1004": {
title: "Note Too Long",
message: "The payout note exceeds the maximum length.",
action: "Notes longer than 4000 characters will be truncated."
}
};
function getErrorMessage(errorCode: string) {
return errorMessages[errorCode] || {
title: "Error",
message: "An unexpected error occurred.",
action: "Please try again or contact support."
};
}Always log errors for troubleshooting:
function logPayoutError(error: any, context: Record<string, any>) {
const errorLog = {
timestamp: new Date().toISOString(),
errorCode: error.ErrorCode,
errorMessage: error.message,
userId: context.userId,
payoutAmount: context.amount,
payoutCurrency: context.currency,
recipientWallet: context.recipientWallet,
userAgent: navigator.userAgent,
url: window.location.href
};
// Send to logging service
sendToLoggingService("payout_error", errorLog);
// Console log for development
console.error("Payout error:", errorLog);
}