Documentation Index
Fetch the complete documentation index at: https://docs.paysight.io/llms.txt
Use this file to discover all available pages before exploring further.
Troubleshooting Guide
This guide helps you diagnose and resolve common issues you might encounter when using the Paysight Widget SDK.
Common Issues
Symptoms:
- Widget container remains empty
ERROR event with initialization error
- Console errors related to script loading
Possible Causes:
- Invalid script source
- Network connectivity issues
- Invalid configuration
- DOM target element not found
Solutions:
- Check Script Loading
<!-- Ensure correct script URL -->
<script src="https://payment.paysight.io/widget-sdk.js"></script>
<!-- Add error handling -->
<script>
const script = document.createElement('script');
script.src = 'https://payment.paysight.io/widget-sdk.js';
script.onerror = (error) => {
console.error('Failed to load widget SDK:', error);
};
document.body.appendChild(script);
</script>
- Verify Configuration
// Ensure all required fields are present
const config = {
productId: 'prod_123', // Required
sessionId: 'session_123', // Required
amount: 2999, // Required
currency: 'USD' // Required
};
// Add error handling
try {
const widget = PaySightSDK.createWidget({
targetId: 'widget-container',
config,
onError: (error) => {
console.error('Widget initialization error:', error);
}
});
} catch (error) {
console.error('Failed to create widget:', error);
}
- Check DOM Target
const targetElement = document.getElementById('widget-container');
if (!targetElement) {
console.error('Widget container not found');
return;
}
// Ensure container is visible and has dimensions
if (targetElement.offsetWidth === 0 || targetElement.offsetHeight === 0) {
console.warn('Widget container has no dimensions');
}
Payment Processing
Payment Fails with 3DS Error
Symptoms:
- Payment fails during 3DS verification
PAYMENT_3DS_ERROR event
- User sees 3DS popup but verification fails
Solutions:
- Enable 3DS Debugging
const config = {
threeDSRequired: true,
debug: true,
callbacks: {
onMessage: (message) => {
if (message.type.includes('3DS')) {
console.log('3DS Event:', message);
}
}
}
};
- Handle 3DS Events Properly
function handle3DSFlow(message) {
switch (message.type) {
case 'PAYMENT_3DS_START':
showLoadingUI('Starting 3D Secure verification...');
break;
case 'PAYMENT_3DS_ERROR':
const { code, message: errorMessage } = message.payload;
if (code === '3DS_TIMEOUT') {
retryPayment();
} else if (code === '3DS_NOT_SUPPORTED') {
fallbackToNon3DS();
} else {
showError(errorMessage);
}
break;
}
}
Symptoms:
- Intermittent payment failures
- Network timeout errors
ERROR events
Solutions:
- Implement Retry Logic
class PaymentProcessor {
constructor(widget) {
this.widget = widget;
this.retryCount = 0;
this.maxRetries = 3;
}
async processPayment() {
try {
await this.widget.validate();
} catch (error) {
if (this.shouldRetry(error)) {
await this.retryPayment();
} else {
throw error;
}
}
}
shouldRetry(error) {
return (
error.type === 'NETWORK_ERROR' &&
this.retryCount < this.maxRetries
);
}
async retryPayment() {
this.retryCount++;
console.log(\`Retrying payment (attempt \${this.retryCount})\`);
await new Promise(resolve => setTimeout(resolve, 2000));
return this.processPayment();
}
}
- Check Network Status
function checkConnectivity() {
if (!navigator.onLine) {
showError('You are offline. Please check your internet connection.');
return false;
}
return true;
}
// Add network status listeners
window.addEventListener('online', () => {
hideError();
retryFailedPayments();
});
window.addEventListener('offline', () => {
showError('You are offline. Payment processing will resume when connected.');
});
Validation Issues
Symptoms:
- Fields show validation errors
ERROR events
- Form submission blocked
Solutions:
- Debug Field Values
function debugFieldValues() {
const state = widget.getState();
Object.entries(state.fields).forEach(([fieldName, field]) => {
console.log(\`Field: \${fieldName}\`, {
value: field.value,
valid: field.valid,
error: field.error
});
});
}
- Custom Validation Rules
const config = {
fields: {
email: {
validation: {
pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$',
message: 'Please enter a valid email address'
}
},
phone: {
validation: {
pattern: '^\\+?[1-9]\\d{1,14}$',
message: 'Please enter a valid phone number'
}
}
}
};
Browser Compatibility
Symptoms:
- Visual glitches
- Layout problems
- Style inconsistencies
Solutions:
- Check Browser Support
function checkBrowserSupport() {
const requirements = {
flexbox: 'flex' in document.documentElement.style,
grid: 'grid' in document.documentElement.style,
customProperties: CSS.supports('(--custom-property: value)'),
fetch: 'fetch' in window,
promise: 'Promise' in window
};
const unsupported = Object.entries(requirements)
.filter(([, supported]) => !supported)
.map(([feature]) => feature);
if (unsupported.length > 0) {
console.warn('Browser missing required features:', unsupported);
return false;
}
return true;
}
- Add Fallback Styles
const config = {
theme: {
css: {
// Modern browsers
'@supports (display: grid)': {
'.widget-container': {
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: '16px'
}
},
// Fallback for older browsers
'@supports not (display: grid)': {
'.widget-container': {
display: 'flex',
flexWrap: 'wrap'
},
'.field': {
flex: '0 0 calc(50% - 8px)',
marginRight: '16px'
}
}
}
}
};
Debug Mode
Enable debug mode to get detailed logging:
const widget = PaySightSDK.createWidget({
config: {
debug: true
},
onMessage: (message) => {
console.log('Widget Event:', {
type: message.type,
payload: message.payload,
timestamp: new Date(message.timestamp).toISOString()
});
}
});
Network Inspector
Monitor network requests:
class NetworkInspector {
constructor() {
this.requests = new Map();
}
startMonitoring() {
const originalFetch = window.fetch;
window.fetch = async (...args) => {
const requestId = Math.random().toString(36).slice(2);
const startTime = Date.now();
this.requests.set(requestId, {
url: args[0],
startTime,
status: 'pending'
});
try {
const response = await originalFetch(...args);
this.requests.set(requestId, {
...this.requests.get(requestId),
status: 'complete',
duration: Date.now() - startTime,
responseStatus: response.status
});
return response;
} catch (error) {
this.requests.set(requestId, {
...this.requests.get(requestId),
status: 'error',
duration: Date.now() - startTime,
error: error.message
});
throw error;
}
};
}
getRequestLog() {
return Array.from(this.requests.values());
}
}
State Inspector
Monitor widget state changes:
class StateInspector {
constructor(widget) {
this.widget = widget;
this.stateHistory = [];
}
startMonitoring() {
setInterval(() => {
const currentState = this.widget.getState();
this.stateHistory.push({
timestamp: Date.now(),
state: { ...currentState }
});
}, 1000);
}
getStateChanges() {
return this.stateHistory;
}
getDiff(index) {
if (index < 1) return null;
const previous = this.stateHistory[index - 1].state;
const current = this.stateHistory[index].state;
return {
timestamp: this.stateHistory[index].timestamp,
changes: this.diffObjects(previous, current)
};
}
diffObjects(obj1, obj2) {
const changes = {};
Object.keys({ ...obj1, ...obj2 }).forEach(key => {
if (JSON.stringify(obj1[key]) !== JSON.stringify(obj2[key])) {
changes[key] = {
from: obj1[key],
to: obj2[key]
};
}
});
return changes;
}
}
Next Steps