@payos-inc/payos-js
v1.0.7
Published
PayOS JavaScript SDK for browser-based checkout and wallet onboarding
Maintainers
Readme
@payos-inc/payos-js
JavaScript SDK for PayOS integration, providing checkout and wallet onboarding functionality.
Installation
npm install @payos-inc/payos-jsCDN:
<script src="https://unpkg.com/@payos-inc/payos-js@latest/dist/payos-js.min.js"></script>Quick Start
import { PayOS } from '@payos-inc/payos-js';
const payos = new PayOS();
// Wallet Onboarding - Add payment methods
payos.walletOnboard.open({
token: 'YOUR_TOKEN', // Get from your backend
mode: 'popup', // or 'redirect'
environment: 'sandbox', // or 'production'
onComplete: (result) => {
console.log('Wallet User ID:', result.walletUserId);
console.log('Cards added:', result.linkedCardIds);
},
onError: (error) => {
console.error('Error:', error);
}
});
// Checkout - Process payments
payos.checkout.open({
token: 'YOUR_TOKEN', // Get from your backend
mode: 'popup', // or 'redirect'
environment: 'sandbox', // or 'production'
onComplete: (result) => {
console.log('Payment Intent ID:', result.paymentIntentId);
console.log('Auth completed:', result.authCompleted);
console.log('Credentials generated:', result.credentialsGenerated);
},
onError: (error) => {
console.error('Error:', error);
}
});
// Card Element - Embed secure card capture
const cardElement = PayOS.cardElement.init('#card-container', {
token: 'YOUR_TOKEN',
environment: 'sandbox',
styles: {
layout: { preset: 'two-row' },
base: { fontSize: '16px' }
},
onTokenized: (result) => {
console.log('Card tokenized:', result.card);
}
});API Reference
Constructor
const payos = new PayOS();Methods
payos.walletOnboard.open(options)
Opens the wallet onboarding flow to add payment methods.
payos.walletOnboard.close()
Closes the current wallet onboarding session.
payos.walletOnboard.isActive()
Returns true if wallet onboarding is currently active.
payos.checkout.open(options)
Opens the checkout flow to process payments.
payos.checkout.close()
Closes the current checkout session.
payos.checkout.isActive()
Returns true if checkout is currently active.
payos.cardElement.init(container, options)
Creates and mounts a secure card capture element in the specified container.
Returns: CardElementInstance with methods:
mount()- Mount the element to DOMunmount()- Remove from DOMdestroy()- Clean up completelysubmit()- Trigger form submissionconfigure(config)- Update configurationupdateStyles(styles)- Update styles dynamically
Options
Wallet Onboarding Options
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| token | string | Yes | Session token from your backend |
| mode | string | No | 'popup' or 'redirect' (default: 'popup') |
| environment | string | No | 'sandbox' or 'production' (default: 'sandbox') |
| merchantName | string | No | Your merchant name to display |
| returnUrl | string | No | URL for redirect mode |
| onComplete | function | No | Called with {walletUserId, linkedCardIds} |
| onError | function | No | Called on error |
| onCancel | function | No | Called when user cancels |
| onReady | function | No | Called when UI is ready |
Checkout Options
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| token | string | Yes | Checkout token from your backend |
| mode | string | No | 'popup' or 'redirect' (default: 'popup') |
| environment | string | No | 'sandbox' or 'production' (default: 'sandbox') |
| returnUrl | string | No | URL for redirect mode |
| onComplete | function | No | Called when checkout completes |
| onError | function | No | Called on error |
| onCancel | function | No | Called when user cancels |
| onReady | function | No | Called when UI is ready |
Card Element Options
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| token | string | Yes | Session token from your backend |
| environment | string | No | 'sandbox' or 'production' (default: 'sandbox') |
| styles | object | No | Custom styles for the card fields (see Styling section) |
| height | string | No | Container height (default: '720px') |
| onReady | function | No | Called when card element is ready |
| onTokenized | function | No | Called with tokenized card data |
| onChange | function | No | Called when field validation changes |
| onError | function | No | Called on error |
| onCancel | function | No | Called when user cancels |
Display Modes
Popup Mode (Default)
Opens in a new window:
payos.walletOnboard.open({
token: 'token',
mode: 'popup',
environment: 'sandbox'
});Redirect Mode
Redirects the current page:
payos.walletOnboard.open({
token: 'token',
mode: 'redirect',
environment: 'sandbox',
returnUrl: 'https://yourapp.com/complete'
});Handling Redirect Returns
PayOS returns parameters prefixed with payos_:
// In your return URL handler
const params = new URLSearchParams(window.location.search);
const status = params.get('payos_status'); // 'success', 'cancel', or 'error'
const encodedData = params.get('payos_data'); // URL-encoded JSON
const timestamp = params.get('payos_timestamp');
if (status === 'success' && encodedData) {
// Decode the data
const data = JSON.parse(decodeURIComponent(encodedData));
// For wallet onboarding:
if (data.walletUserId) {
console.log('Wallet User ID:', data.walletUserId);
console.log('Cards Added:', data.linkedCardIds);
}
// For checkout:
if (data.paymentIntentId) {
console.log('Payment Intent ID:', data.paymentIntentId);
console.log('Auth Completed:', data.authCompleted);
}
}Card Element
Embedding Secure Card Capture
The Card Element provides a secure, PCI-compliant way to capture card details directly in your application. Card data never touches your servers - it's tokenized through secure iframes.
// Basic setup
const cardElement = PayOS.cardElement.init('#card-container', {
token: 'YOUR_TOKEN',
environment: 'sandbox',
onTokenized: (result) => {
console.log('Card tokenized:', result.card);
// Submit to your backend
}
});
// With custom styling
const cardElement = PayOS.cardElement.init('#card-container', {
token: 'YOUR_TOKEN',
environment: 'sandbox',
styles: {
layout: {
preset: 'two-row', // Layout preset
showLabels: true, // Show field labels
gap: '16px' // Space between fields
},
base: {
fontSize: '16px',
color: '#333',
padding: '12px',
borderRadius: '8px',
border: '1px solid #ddd',
'&:focus': {
borderColor: '#007bff',
outline: 'none'
}
},
cardNumber: {
paddingRight: '50px' // Space for card icon
}
},
onTokenized: (result) => {
console.log('Card:', result.card);
console.log('Billing:', result.billingAddress);
}
});Card Element Styling
The Card Element supports extensive styling through the styles option:
Layout Styles
Controls the overall form layout:
styles: {
layout: {
preset: 'two-row', // 'single-row' | 'two-row' | 'compact' | 'stacked'
showLabels: true, // Show/hide field labels
showErrorMessages: true, // Show validation errors
gap: '16px', // Space between fields
padding: '20px', // Container padding
backgroundColor: '#f5f5f5', // Background color
labels: {
cardNumber: 'Card Number', // Custom label text
expiry: 'Expiration', // or false to hide
cvv: 'Security Code'
}
}
}Layout Presets:
two-row(default): Card number on first row, expiry/CVV on secondsingle-row: All fields in one horizontal rowcompact: Minimal spacing for tight layoutsstacked: All fields vertically stacked (mobile-friendly)
Field Styles
Customize individual field appearance:
styles: {
// Base styles apply to all fields
base: {
fontSize: '16px',
fontFamily: 'system-ui, sans-serif',
color: '#333',
padding: '12px',
height: '48px',
border: '1px solid #e0e0e0',
borderRadius: '8px',
backgroundColor: 'white',
'&:focus': {
borderColor: '#007bff',
boxShadow: '0 0 0 3px rgba(0,123,255,0.1)'
},
'&::placeholder': {
color: '#999'
}
},
// Override for specific fields
cardNumber: {
fontSize: '18px'
},
expiry: {
width: '140px'
},
cvc: {
width: '100px'
}
}Card Element Events
Handle card element events for better UX:
const cardElement = PayOS.cardElement.init('#card-container', {
token: 'YOUR_TOKEN',
onReady: () => {
console.log('Card element ready');
// Enable submit button
},
onChange: (event) => {
console.log('Validation:', {
complete: event.complete, // All fields valid
empty: event.empty, // All fields empty
error: event.error // Validation error message
});
// Update UI based on validation
},
onTokenized: (result) => {
console.log('Success:', {
card: result.card, // Card details
billingAddress: result.billingAddress,
walletUserId: result.walletUserId
});
// Submit to your backend
},
onError: (error) => {
console.error('Error:', error);
// Show error to user
}
});Programmatic Control
Control the card element after initialization:
// Submit the form programmatically
document.getElementById('submit-btn').onclick = () => {
cardElement.submit();
};
// Configure with user data
cardElement.configure({
walletUserId: 'user_123',
cardholderName: 'John Doe',
billingAddress: {
line1: '123 Main St',
city: 'San Francisco',
state: 'CA',
postalCode: '94105',
country: 'US'
}
});
// Update styles dynamically
cardElement.updateStyles({
base: {
fontSize: '18px',
color: '#000'
}
});
// Clean up
cardElement.unmount(); // Remove from DOM
cardElement.destroy(); // Complete cleanupComplete Example
<!DOCTYPE html>
<html>
<head>
<script src="https://unpkg.com/@payos-inc/payos-js@latest/dist/payos-js.min.js"></script>
</head>
<body>
<div id="card-element"></div>
<button id="pay-button">Pay</button>
<script>
const payos = new PayOS();
// Initialize card element
const cardElement = PayOS.cardElement.init('#card-element', {
token: 'YOUR_TOKEN_HERE',
environment: 'sandbox',
styles: {
layout: {
preset: 'two-row',
showLabels: true
},
base: {
fontSize: '16px',
padding: '12px',
borderRadius: '8px'
}
},
onChange: (event) => {
// Enable/disable pay button based on validation
document.getElementById('pay-button').disabled = !event.complete;
},
onTokenized: async (result) => {
// Send to your backend
const response = await fetch('/api/process-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
cardId: result.card.id,
walletUserId: result.walletUserId
})
});
if (response.ok) {
alert('Payment successful!');
}
},
onError: (error) => {
alert('Error: ' + error.message);
}
});
// Handle pay button click
document.getElementById('pay-button').onclick = () => {
cardElement.submit();
};
</script>
</body>
</html>TypeScript
import { PayOS, CardElementStyles, CardElementTokenizedEvent } from '@payos-inc/payos-js';
const payos = new PayOS();
// Wallet Onboarding with types
payos.walletOnboard.open({
token: 'token',
mode: 'popup',
environment: 'sandbox',
onComplete: (result) => {
// TypeScript support included
console.log(result.walletUserId); // string
console.log(result.linkedCardIds); // string[]
}
});
// Card Element with typed styles
const styles: CardElementStyles = {
layout: {
preset: 'two-row',
showLabels: true,
labels: {
cardNumber: 'Card Number',
expiry: 'Exp Date',
cvv: 'CVV'
}
},
base: {
fontSize: '16px',
color: '#333',
padding: '12px',
'&:focus': {
borderColor: '#007bff'
}
}
};
const cardElement = PayOS.cardElement.init('#card-container', {
token: 'token',
environment: 'sandbox',
styles,
onTokenized: (event: CardElementTokenizedEvent) => {
console.log(event.card?.id); // string | undefined
console.log(event.card?.last4); // string | undefined
console.log(event.walletUserId); // string | undefined
}
});Browser Support
- Chrome 89+
- Firefox 87+
- Safari 14+
- Edge 89+
License
MIT
Support
Contact: [email protected]
Documentation: https://docs.payos.ai
