Learn how to fix common issues with the payout components.
| Issue | Description | Next steps |
|---|---|---|
| Payout button not rendering. | The submission button doesn't appear in the container. |
|
| "PayPal configuration is required" error. | SDK throws SDK1000 error on component creation. |
|
| "Payer ID required" error. | SDK throws SDK0809 error during payout submission. |
|
| Venmo payout fails with currency error. | SDK throws SDK0905 error. |
|
| Invalid email format error. | SDK throws SDK0808 error. |
|
| Invalid phone format error. | SDK throws SDK0904 for Venmo phone payouts. |
|
| Amount validation errors. | SDK throws SDK0810, SDK0811, or SDK0812. |
|
| Receiver masking not working. | Email/phone always shows masked or unmasked. |
|
| Payout note too long warning. | SDK logs a console warning about note length. |
|
| onPostPayout not being called. | Payout completes but callback doesn't fire. |
|
| Component styles not applying. | Custom styles are ignored. |
|
Ensure your SDK initialisation includes all required payout configuration:
const pxpCheckoutSdk = PxpCheckout.initialize({
environment: "test", // or "production"
session: sessionData,
ownerId: "Unity",
ownerType: "MerchantGroup",
transactionData: {
amount: 100, // Required: must be > 0
currency: "USD", // Required: 3-letter ISO code
entryType: "Ecom",
intent: {
paypal: IntentType.Payout // Required for payouts
},
merchantTransactionId: crypto.randomUUID(),
merchantTransactionDate: () => new Date().toISOString()
},
paypalConfig: { // Required for payout components
payoutConfig: {
proceedPayoutWithSdk: true, // or false for merchant-initiated
// For returning customers:
paypalWallet: {
email: "customer@example.com",
payerId: "PAYER_ID_XXX" // Optional but recommended
}
// OR for Venmo:
// venmoWallet: {
// receiver: "+14155551234",
// recipientType: "Phone"
// }
}
}
});Ensure your environment setting matches your credentials:
test: Development and testing with sandbox credentials.production: Live transactions with production credentials.
// For development
environment: "test"
// For production
environment: "production"Understand the difference between payout modes:
| Mode | proceedPayoutWithSdk | Behaviour |
|---|---|---|
| SDK-initiated | true | SDK executes payout after user approval. onPostPayout is called. |
| Merchant-initiated | false | SDK collects data only. Your backend must call the payout API. |
// SDK-initiated: SDK handles everything
payoutConfig: {
proceedPayoutWithSdk: true,
paypalWallet: { email: "customer@example.com" }
}
// Merchant-initiated: You control payout execution
payoutConfig: {
proceedPayoutWithSdk: false,
paypalWallet: { email: "customer@example.com" }
}If onPrePayoutSubmit isn't being called or payout proceeds without approval:
onPrePayoutSubmit: async () => {
console.log("onPrePayoutSubmit called"); // Debug log
// Show confirmation dialog
const approved = await showConfirmationDialog();
console.log("User approved:", approved); // Debug log
// Must return an object with isApproved
return {
isApproved: approved,
note: "Optional note"
};
}Always return an object with isApproved from onPrePayoutSubmit. Returning undefined or not returning anything may cause unexpected behaviour.
If the PayPal receiver component shows no email:
- Verify
paypalConfig.payoutConfig.paypalWallet.emailis provided. - Check that the email value is a non-empty string.
- Ensure the component is mounted after SDK initialisation completes.
Ensure the recipientType matches the receiver format:
| Receiver format | Required recipientType |
|---|---|
user@example.com | "Email" |
+14155551234 | "Phone" |
@username | "UserHandle" |
// Email example
venmoWallet: {
receiver: "user@example.com",
recipientType: "Email"
}
// Phone example
venmoWallet: {
receiver: "14155551234", // Numbers only
recipientType: "Phone"
}
// Handle example
venmoWallet: {
receiver: "@john-doe",
recipientType: "UserHandle"
}Add logging to track the payout flow:
const payoutConfig = {
onClick: (event) => {
console.log("[Payout] Button clicked");
},
onPrePayoutSubmit: async () => {
console.log("[Payout] Pre-submit validation");
return { isApproved: true };
},
onPostPayout: (result) => {
console.log("[Payout] Success:", result);
},
onError: (error) => {
console.error("[Payout] Error:", error.ErrorCode, error.message);
}
};Ensure session data is valid and not expired:
async function initializePayoutSdk() {
const sessionData = await getSessionDataFromBackend();
// Debug: Log session data
console.log("Session data:", {
sessionId: sessionData.sessionId,
expiry: sessionData.sessionExpiry,
hasHmacKey: !!sessionData.hmacKey,
hasEncryptionKey: !!sessionData.encryptionKey
});
// Check if session is expired
if (new Date(sessionData.sessionExpiry) < new Date()) {
console.error("Session has expired!");
// Request a new session
return;
}
// Proceed with SDK initialisation
const sdk = PxpCheckout.initialize({
session: sessionData,
// ... rest of config
});
}