Appearance
Kore Payment SDK Integration Guide
Overview
The Kore Payment SDK is a JavaScript library that enables frontend applications to integrate with the Kore Payment Platform. It provides a simple, secure, and developer-friendly interface for processing payments through various payment gateways.
Key Features
- ✅ Unified Payment Flow - One integration path: the SDK handles redirect or embedded automatically based on backend response
- ✅ Payment Session Creation - Create sessions with
createEmbeddedSession; backend decides redirect vs embedded - ✅ Embedded Payment Forms - Payment forms embedded in your page when the gateway supports it
- ✅ Automatic Gateway Detection - SDK detects gateway and either redirects or initializes the correct form
- ✅ Multi-Gateway Support - Checkout.com, Adyen, and QiCard support
- ✅ Redirect Handling - Handle payment redirects with signature verification
- ✅ Status Polling - Poll payment status in real-time
- ✅ Idempotency Support - Built-in idempotency key management
- ✅ Error Handling - Comprehensive error handling with retry logic
- ✅ TypeScript Support - Full TypeScript definitions included
- ✅ Browser Compatibility - Support for modern browsers (ES6+)
Supported Environments
- Production:
https://api.kora.com - Sandbox:
https://api-sandbox.kora.com(for testing)
Installation
Download the SDK (zip) from the Download page on this documentation site. Unzip and include the script in your project.
Script tag (browser):
html
<script src="path/to/kore-sdk.js"></script>ES module (bundler):
html
<script type="module">
import Kore from './path/to/kore-sdk.esm.js';
</script>Quick Start
Unified Integration (Recommended)
Use one flow for all gateways. The backend decides whether the customer is redirected or sees an embedded form; your code stays the same.
javascript
import Kore from './path/to/kore-sdk.esm.js';
const kore = new Kore({
apiKey: 'pk_test_xxxxxxxxxxxxx',
environment: 'sandbox'
});
// 1. Create payment session (same for redirect or embedded)
const session = await kore.createEmbeddedSession({
order_id: 'order_12345',
amount: 10000,
currency: 'USD',
capture_mode: 'auto',
payer: {
email: '[email protected]',
name: 'John Doe',
phone: '+1234567890'
},
billing: {
address_line_1: '123 Main St',
city: 'New York',
state: 'NY',
postal_code: '10001',
country: 'US'
},
return_url: 'https://yourstore.com/success',
cancel_url: 'https://yourstore.com/cancel'
});
// 2. Initialize payment — SDK redirects or shows embedded form automatically
await kore.initializePayment({
session: session,
container: '#payment-form-container',
onSuccess: (result) => {
console.log('Payment successful!', result);
showSuccessMessage();
},
onError: (error) => {
console.error('Payment failed:', error);
showErrorMessage(error.message);
}
});Add a container for embedded flow (ignored when the SDK redirects):
html
<div id="payment-form-container"></div>Handling Return From Redirect
When the gateway uses redirect, the customer returns to your return_url. On that page, verify the redirect and show the result:
javascript
// On your return URL page (e.g., /success)
const urlParams = new URLSearchParams(window.location.search);
// Verify redirect (API secret should come from server-side in production)
const result = await kore.handleRedirectReturn(urlParams, apiSecret);
if (result.success) {
const { payment_id, order_id, status } = result.data;
console.log(`Payment ${payment_id} for order ${order_id} is ${status}`);
showSuccessMessage();
} else {
const { code, message } = result.error;
console.error(`Payment failed: ${code} - ${message}`);
showErrorMessage(message);
}Configuration
SDK Initialization Options
javascript
const kore = new Kore({
// Required
apiKey: 'pk_test_xxxxxxxxxxxxx',
// Optional
baseUrl: 'https://api.kora.com', // Custom API base URL
environment: 'sandbox', // 'sandbox' | 'live' (default: 'live')
timeout: 30000, // Request timeout in ms (default: 30000)
retryAttempts: 3, // Number of retry attempts (default: 3)
retryDelay: 1000, // Delay between retries in ms (default: 1000)
// Hooks
onError: (error) => { // Global error handler
console.error('SDK Error:', error);
},
onRequest: (config) => { // Request interceptor
console.log('Request:', config);
},
onResponse: (response) => { // Response interceptor
console.log('Response:', response);
},
// Logging
debug: false, // Enable debug logging (development only; do not use in production)
logger: (message) => console.log(message) // Custom logger function
});Environment Variables
For security, store your API keys in environment variables:
javascript
// .env file (never commit this)
REACT_APP_KORA_API_KEY=pk_test_xxxxxxxxxxxxx
REACT_APP_KORA_ENV=sandbox
// In your code
const kore = new Kore({
apiKey: process.env.REACT_APP_KORA_API_KEY,
environment: process.env.REACT_APP_KORA_ENV
});API Reference
Core Methods
createSession(sessionData, options)
Creates a new payment session.
Parameters:
typescript
sessionData: {
order_id: string, // Required: Unique order identifier
amount: number, // Required: Amount in minor units (e.g., 10000 = $100.00)
currency: string, // Required: ISO-4217 currency code (e.g., 'USD')
capture_mode?: 'auto' | 'manual', // Optional: Default 'auto'
payer: { // Required
email: string,
name: string,
phone?: string
},
billing: { // Required
address_line_1: string,
address_line_2?: string,
city: string,
state?: string,
postal_code: string,
country: string // ISO-3166-1 alpha-2 (e.g., 'US')
},
shipping?: { // Optional
address_line_1: string,
address_line_2?: string,
city: string,
state?: string,
postal_code: string,
country: string,
name?: string,
phone?: string
},
return_url: string, // Required: URL to redirect after payment
cancel_url: string, // Required: URL to redirect on cancellation
metadata?: object // Optional: Additional metadata
}
options: {
idempotencyKey?: string, // Optional: Custom idempotency key
timeout?: number // Optional: Request timeout in ms
}Returns:
typescript
{
session_id: string,
payment_id: string,
redirect_url: string,
expires_at: string // ISO 8601 timestamp
}Example:
javascript
const session = await kore.createSession({
order_id: 'order_12345',
amount: 10000,
currency: 'USD',
payer: {
email: '[email protected]',
name: 'John Doe'
},
billing: {
address_line_1: '123 Main St',
city: 'New York',
postal_code: '10001',
country: 'US'
},
return_url: 'https://yourstore.com/success',
cancel_url: 'https://yourstore.com/cancel'
}, {
idempotencyKey: Kore.generateIdempotencyKey()
});getSessionStatus(sessionId)
Gets the current status of a payment session.
Parameters:
typescript
sessionId: string // Session ID from createSessionReturns:
typescript
{
session_id: string,
status: 'pending' | 'requires_action' | 'redirected' | 'completed' | 'failed',
payment_id: string | null,
order_id: string,
amount: number,
currency: string,
created_at: string,
expires_at: string
}Example:
javascript
const status = await kore.getSessionStatus('session_12345');
console.log(`Session status: ${status.status}`);getTransaction(paymentId)
Gets detailed transaction information.
Parameters:
typescript
paymentId: string | number // Payment IDReturns:
typescript
{
payment_id: string,
order_id: string,
amount: number,
currency: string,
status: 'pending' | 'authorized' | 'captured' | 'failed' | 'refunded' | 'partial_refunded' | 'canceled',
gateway: {
id: number,
code: string,
name: string
} | null,
gateway_payment_id: string | null,
authorized_at: string | null,
captured_at: string | null,
failed_at: string | null,
failure_reason: string | null,
created_at: string,
updated_at: string
}Example:
javascript
const transaction = await kore.getTransaction('payment_12345');
console.log(`Transaction status: ${transaction.status}`);handleRedirectReturn(urlParams, apiSecret)
Handles redirect return from payment gateway with signature verification.
Parameters:
typescript
urlParams: URLSearchParams | Record<string, string> // URL search parameters
apiSecret: string // Merchant API secret (server-side recommended)Returns:
typescript
{
success: boolean,
data?: {
payment_id: string,
order_id: string,
status: 'captured' | 'authorized' | 'failed' | 'canceled' | 'pending',
gateway?: string
},
error?: {
code: string,
message: string,
payment_id?: string,
order_id?: string,
gateway?: string
}
}Example:
javascript
const urlParams = new URLSearchParams(window.location.search);
const result = await kore.handleRedirectReturn(urlParams, apiSecret);
if (result.success) {
// Handle success
} else {
// Handle error
console.error(result.error.code, result.error.message);
}redirectToPayment(redirectUrl, options)
Redirects the browser to the payment gateway.
Parameters:
typescript
redirectUrl: string // URL from createSession response
options: {
target?: '_self' | '_blank' // Window target (default: '_self')
}Example:
javascript
kore.redirectToPayment(session.redirect_url);
// Or open in new window
kore.redirectToPayment(session.redirect_url, { target: '_blank' });pollPaymentStatus(sessionId, options)
Polls payment status until completion or failure.
Parameters:
typescript
sessionId: string
options: {
interval?: number, // Polling interval in ms (default: 2000)
maxAttempts?: number, // Maximum polling attempts (default: 30)
onStatusChange?: (status) => void // Callback on status change
}Returns:
typescript
Promise<SessionStatus> // Final session statusExample:
javascript
const finalStatus = await kore.pollPaymentStatus('session_12345', {
interval: 2000,
maxAttempts: 30,
onStatusChange: (status) => {
console.log(`Status changed to: ${status.status}`);
}
});Utility Methods
Kore.generateIdempotencyKey()
Generates a UUID v4 string for use as an idempotency key.
Example:
javascript
const idempotencyKey = Kore.generateIdempotencyKey();Kore.formatAmount(amount, currency)
Formats amount in minor units to display format.
Example:
javascript
const formatted = Kore.formatAmount(10000, 'USD'); // Returns: '$100.00'Kore.validateCurrency(currency)
Validates ISO-4217 currency code.
Example:
javascript
Kore.validateCurrency('USD'); // Returns: true
Kore.validateCurrency('INVALID'); // Returns: falseKore.validateEmail(email)
Validates email format.
Example:
javascript
Kore.validateEmail('[email protected]'); // Returns: true
Kore.validateEmail('invalid'); // Returns: falseError Codes
Access error code constants via Kore.ErrorCodes:
javascript
// SDK Errors
Kore.ErrorCodes.AUTHENTICATION_ERROR
Kore.ErrorCodes.VALIDATION_ERROR
Kore.ErrorCodes.PAYMENT_ERROR
Kore.ErrorCodes.NETWORK_ERROR
Kore.ErrorCodes.RATE_LIMIT_ERROR
Kore.ErrorCodes.NOT_FOUND_ERROR
Kore.ErrorCodes.SERVER_ERROR
// Redirect Errors
Kore.ErrorCodes.SESSION_NOT_FOUND
Kore.ErrorCodes.PAYMENT_NOT_FOUND
Kore.ErrorCodes.GATEWAY_NOT_AVAILABLE
Kore.ErrorCodes.GATEWAY_CREDENTIALS_ERROR
Kore.ErrorCodes.GATEWAY_ADAPTER_ERROR
Kore.ErrorCodes.GATEWAY_SESSION_CREATION_FAILED
Kore.ErrorCodes.GATEWAY_VERIFICATION_FAILED
Kore.ErrorCodes.GATEWAY_TIMEOUT
Kore.ErrorCodes.NO_ACTIVE_API_KEY
Kore.ErrorCodes.RESOURCE_NOT_FOUND
Kore.ErrorCodes.BAD_REQUEST
Kore.ErrorCodes.FORBIDDEN
Kore.ErrorCodes.INTERNAL_ERROR
Kore.ErrorCodes.UNKNOWN_ERRORPayment Flow
Unified Flow (Recommended)
Use a single integration path for all gateways. You always call createEmbeddedSession and then initializePayment. The backend decides whether the gateway uses redirect or embedded; the SDK behaves accordingly.
What happens:
- Redirect: If the backend returns
gateway_config.mode === 'redirect'and aredirectUrl, the SDK redirects the customer to the gateway payment page. You handle the return on yourreturn_urlwithhandleRedirectReturn. - Embedded: If the backend returns an embedded gateway (Checkout.com, Adyen, or QiCard), the SDK loads the right form and mounts it in your container. Completion is reported via
onSuccess/onError.
1. User fills payment form on your website
2. Frontend calls createEmbeddedSession()
3. Backend returns session (redirect URL or gateway_config for embedded)
4. Frontend calls initializePayment({ session, container, onSuccess, onError })
5. SDK either redirects the user or renders the payment form in the container
6. If redirect: user completes payment on gateway page, returns to return_url; use handleRedirectReturn()
7. If embedded: user completes payment in your page; onSuccess/onError are calledComplete example (unified):
javascript
// Step 1: Create payment session (same for redirect or embedded)
const session = await kore.createEmbeddedSession({
order_id: `order_${Date.now()}`,
amount: 10000,
currency: 'USD',
capture_mode: 'auto',
payer: {
email: '[email protected]',
name: 'John Doe',
phone: '+1234567890'
},
billing: {
address_line_1: '123 Main St',
address_line_2: 'Apt 4B',
city: 'New York',
state: 'NY',
postal_code: '10001',
country: 'US'
},
return_url: 'https://yourstore.com/success',
cancel_url: 'https://yourstore.com/cancel',
processing_channel_id: 'pc_xxxxx' // Optional: Checkout.com only
});
// Step 2: Initialize payment — SDK redirects or shows embedded form
await kore.initializePayment({
session: session,
container: '#payment-form-container',
onSuccess: (result) => {
console.log('Payment successful!', result);
updateOrderStatus(result.session?.order_id, 'paid');
showSuccessMessage();
},
onError: (error) => {
console.error('Payment failed:', error);
handlePaymentError(error);
showErrorMessage(error.message);
}
});html
<div id="payment-form-container"></div>Benefits:
- One integration for all gateways
- No need to choose redirect vs embedded in your code
- Automatic gateway detection and form loading for embedded
- Automatic redirect when the backend returns a redirect URL
Legacy: Redirect-Only API
If you only need redirect and use the legacy sessions API, you can call createSession (V1) and then redirectToPayment:
javascript
const session = await kore.createSession({
order_id: `order_${Date.now()}`,
amount: 10000,
currency: 'USD',
payer: { email: '[email protected]', name: 'John Doe' },
billing: { address_line_1: '123 Main St', city: 'New York', postal_code: '10001', country: 'US' },
return_url: 'https://yourstore.com/success',
cancel_url: 'https://yourstore.com/cancel'
});
kore.redirectToPayment(session.redirect_url);On your return URL page, use handleRedirectReturn() as described in Handling Return From Redirect. For new integrations, prefer the unified flow with createEmbeddedSession + initializePayment.
Error Handling
Error Classes
The SDK provides specific error classes for different error types:
javascript
import {
KoraError,
KoreAuthenticationError,
KoreValidationError,
KorePaymentError,
KoreNetworkError,
KoreRateLimitError,
KoreNotFoundError,
KoreServerError
} from 'kora-payment-sdk';
try {
await kore.createEmbeddedSession(sessionData);
} catch (error) {
if (error instanceof KoreAuthenticationError) {
// Handle authentication error
console.error('Invalid API key');
} else if (error instanceof KoreValidationError) {
// Handle validation error
console.error('Invalid request:', error.details);
} else if (error instanceof KoreNetworkError) {
// Handle network error
console.error('Network issue, please retry');
} else {
// Handle other errors
console.error('Unexpected error:', error);
}
}Redirect Error Handling
When handling redirect returns, check the error code:
javascript
const result = await kore.handleRedirectReturn(urlParams, apiSecret);
if (!result.success) {
const { code, message } = result.error;
// Handle specific error codes
switch (code) {
case Kore.ErrorCodes.GATEWAY_SESSION_CREATION_FAILED:
case Kore.ErrorCodes.GATEWAY_TIMEOUT:
// Retryable errors - show retry button
showRetryButton();
break;
case Kore.ErrorCodes.GATEWAY_CREDENTIALS_ERROR:
case Kore.ErrorCodes.NO_ACTIVE_API_KEY:
// Configuration errors - contact support
showContactSupport();
break;
case Kore.ErrorCodes.SESSION_NOT_FOUND:
// Session expired - redirect to create new session
redirectToCreateSession();
break;
default:
// Generic error handling
showErrorMessage(message);
}
}Error Code Reference
SDK Error Codes
| Code | Description | Action |
|---|---|---|
AUTHENTICATION_ERROR | Invalid or missing API key | Check API key configuration |
VALIDATION_ERROR | Invalid request parameters | Review request data |
PAYMENT_ERROR | Payment processing error | Check payment details |
NETWORK_ERROR | Network/connection error | Retry request |
RATE_LIMIT_ERROR | Rate limit exceeded | Wait and retry |
NOT_FOUND_ERROR | Resource not found | Check resource ID |
SERVER_ERROR | Server error | Contact support |
Redirect Error Codes
| Code | Description | Action |
|---|---|---|
SESSION_NOT_FOUND | Payment session not found or expired | Create new session |
PAYMENT_NOT_FOUND | Payment record not found | Check payment ID |
GATEWAY_NOT_AVAILABLE | Gateway is not active | Contact support |
GATEWAY_CREDENTIALS_ERROR | Gateway credentials invalid | Contact support |
GATEWAY_ADAPTER_ERROR | Gateway adapter failed | Contact support |
GATEWAY_SESSION_CREATION_FAILED | Failed to create gateway session | Retry payment |
GATEWAY_VERIFICATION_FAILED | Failed to verify payment | Contact support |
GATEWAY_TIMEOUT | Gateway request timed out | Retry payment |
NO_ACTIVE_API_KEY | No active API key | Contact support |
RESOURCE_NOT_FOUND | Resource not found | Check resource ID |
BAD_REQUEST | Invalid request | Review request data |
FORBIDDEN | Access denied | Check permissions |
INTERNAL_ERROR | Server error | Contact support |
UNKNOWN_ERROR | Unknown error | Contact support |
Examples
Unified Payment Flow (React)
jsx
import { useState } from 'react';
import Kore from './path/to/kore-sdk.esm.js';
function EmbeddedPayment() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const kore = new Kore({
apiKey: process.env.REACT_APP_KORA_API_KEY,
environment: 'sandbox'
});
const handlePayment = async () => {
setLoading(true);
setError(null);
try {
// Step 1: Create embedded payment session
const session = await kore.createEmbeddedSession({
order_id: `order_${Date.now()}`,
amount: 10000,
currency: 'USD',
capture_mode: 'auto',
payer: {
email: '[email protected]',
name: 'John Doe'
},
billing: {
address_line_1: '123 Main St',
city: 'New York',
postal_code: '10001',
country: 'US'
},
return_url: window.location.origin + '/success',
cancel_url: window.location.origin + '/cancel'
});
// Step 2: Initialize payment form
await kore.initializePayment({
session: session,
container: '#payment-container',
onSuccess: (result) => {
console.log('Payment successful!', result);
setLoading(false);
// Handle success
},
onError: (err) => {
setError(err.message);
setLoading(false);
}
});
} catch (err) {
setError(err.message);
setLoading(false);
}
};
return (
<div>
<button onClick={handlePayment} disabled={loading}>
{loading ? 'Processing...' : 'Pay Now'}
</button>
{error && <div className="error">{error}</div>}
<div id="payment-container"></div>
</div>
);
}Handling Return From Redirect (React)
jsx
import { useState, useEffect } from 'react';
import { useSearchParams } from 'react-router-dom';
import Kore from './path/to/kore-sdk.esm.js';
function PaymentForm() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const kore = new Kore({
apiKey: process.env.REACT_APP_KORA_API_KEY
});
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const session = await kore.createSession({
order_id: `order_${Date.now()}`,
amount: 10000,
currency: 'USD',
payer: {
email: e.target.email.value,
name: e.target.name.value
},
billing: {
address_line_1: e.target.address.value,
city: e.target.city.value,
postal_code: e.target.zip.value,
country: e.target.country.value
},
return_url: window.location.origin + '/success',
cancel_url: window.location.origin + '/cancel'
});
kore.redirectToPayment(session.redirect_url);
} catch (err) {
setError(err.message);
setLoading(false);
}
};
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
{error && <div className="error">{error}</div>}
<button type="submit" disabled={loading}>
{loading ? 'Processing...' : 'Pay Now'}
</button>
</form>
);
}
// Payment Return Handler Component
function PaymentReturn() {
const [searchParams] = useSearchParams();
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(true);
const kore = new Kore({
apiKey: process.env.REACT_APP_KORA_API_KEY
});
useEffect(() => {
const handleReturn = async () => {
// Get API secret from server (recommended)
const apiSecret = await fetch('/api/get-secret').then(r => r.text());
try {
const result = await kore.handleRedirectReturn(searchParams, apiSecret);
setResult(result);
} catch (err) {
setResult({
success: false,
error: {
code: 'SIGNATURE_VERIFICATION_FAILED',
message: 'Failed to verify redirect signature'
}
});
} finally {
setLoading(false);
}
};
handleReturn();
}, [searchParams]);
if (loading) return <div>Processing payment...</div>;
if (result?.success) {
return (
<div className="success">
<h2>Payment Successful!</h2>
<p>Payment ID: {result.data.payment_id}</p>
<p>Order ID: {result.data.order_id}</p>
</div>
);
}
return (
<div className="error">
<h2>Payment Failed</h2>
<p>{result?.error?.message}</p>
</div>
);
}Vue.js Integration
vue
<template>
<div>
<form @submit.prevent="handleSubmit">
<!-- Form fields -->
<button type="submit" :disabled="loading">
{{ loading ? 'Processing...' : 'Pay Now' }}
</button>
</form>
</div>
</template>
<script>
import { ref } from 'vue';
import Kore from './path/to/kore-sdk.esm.js';
export default {
setup() {
const loading = ref(false);
const error = ref(null);
const kore = new Kore({
apiKey: import.meta.env.VITE_KORA_API_KEY
});
const handleSubmit = async () => {
loading.value = true;
error.value = null;
try {
const session = await kore.createSession({
order_id: `order_${Date.now()}`,
amount: 10000,
currency: 'USD',
payer: {
email: '[email protected]',
name: 'John Doe'
},
billing: {
address_line_1: '123 Main St',
city: 'New York',
postal_code: '10001',
country: 'US'
},
return_url: window.location.origin + '/success',
cancel_url: window.location.origin + '/cancel'
});
kore.redirectToPayment(session.redirect_url);
} catch (err) {
error.value = err.message;
loading.value = false;
}
};
return { loading, error, handleSubmit };
}
};
</script>Vanilla JavaScript
javascript
// Initialize SDK
const kore = new Kore({
apiKey: 'pk_test_xxxxxxxxxxxxx',
environment: 'sandbox'
});
// Handle form submission
document.getElementById('paymentForm').addEventListener('submit', async (e) => {
e.preventDefault();
try {
const session = await kore.createSession({
order_id: document.getElementById('orderId').value,
amount: parseInt(document.getElementById('amount').value),
currency: document.getElementById('currency').value,
payer: {
email: document.getElementById('email').value,
name: document.getElementById('name').value
},
billing: {
address_line_1: document.getElementById('address').value,
city: document.getElementById('city').value,
postal_code: document.getElementById('zip').value,
country: document.getElementById('country').value
},
return_url: window.location.origin + '/success',
cancel_url: window.location.origin + '/cancel'
});
kore.redirectToPayment(session.redirect_url);
} catch (error) {
alert('Error: ' + error.message);
}
});
// Handle return from payment gateway
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('status')) {
// Get API secret from server
const apiSecret = await fetch('/api/get-secret').then(r => r.text());
const result = await kore.handleRedirectReturn(urlParams, apiSecret);
if (result.success) {
document.getElementById('result').innerHTML =
`Payment successful! Payment ID: ${result.data.payment_id}`;
} else {
document.getElementById('result').innerHTML =
`Payment failed: ${result.error.message}`;
}
}Security Best Practices
1. API Key Management
❌ Never do this:
javascript
// DON'T: Hardcode API keys in frontend code
const kore = new Kore({
apiKey: 'pk_live_secret_key_12345' // Exposed in client-side code!
});✅ Do this:
javascript
// DO: Use environment variables
const kore = new Kore({
apiKey: process.env.REACT_APP_KORA_API_KEY // From .env file
});2. API Secret Handling
❌ Never do this:
javascript
// DON'T: Store API secret in frontend
const apiSecret = 'sk_live_secret_12345'; // Never expose secrets!✅ Do this:
javascript
// DO: Retrieve API secret from your backend server
const apiSecret = await fetch('/api/get-secret', {
method: 'POST',
headers: { 'Authorization': `Bearer ${userToken}` }
}).then(r => r.text());
// Or verify signature server-side
const result = await fetch('/api/verify-payment', {
method: 'POST',
body: JSON.stringify({ urlParams: Object.fromEntries(urlParams) })
}).then(r => r.json());3. Signature Verification
Always verify redirect signatures:
javascript
// Frontend: Get redirect parameters
const urlParams = new URLSearchParams(window.location.search);
// Option 1: Verify client-side (less secure, requires API secret)
const result = await kore.handleRedirectReturn(urlParams, apiSecret);
// Option 2: Verify server-side (recommended)
const result = await fetch('/api/verify-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
payment_id: urlParams.get('payment_id'),
order_id: urlParams.get('order_id'),
status: urlParams.get('status'),
signature: urlParams.get('signature')
})
}).then(r => r.json());4. HTTPS Only
Always use HTTPS in production:
javascript
// Check for HTTPS
if (window.location.protocol !== 'https:' && window.location.hostname !== 'localhost') {
console.error('SDK requires HTTPS in production');
}5. Input Validation
Validate all user inputs:
javascript
// Validate email
if (!Kore.validateEmail(formData.email)) {
throw new Error('Invalid email address');
}
// Validate currency
if (!Kore.validateCurrency(formData.currency)) {
throw new Error('Invalid currency code');
}
// Validate amount
if (formData.amount <= 0 || !Number.isInteger(formData.amount)) {
throw new Error('Invalid amount');
}6. Error Message Handling
Don't expose sensitive information:
javascript
try {
await kore.createEmbeddedSession(sessionData);
} catch (error) {
// ❌ DON'T: Expose internal error details
// console.error(error.details);
// ✅ DO: Show user-friendly messages
if (error instanceof KoreAuthenticationError) {
showError('Authentication failed. Please contact support.');
} else {
showError('Payment processing failed. Please try again.');
}
}Troubleshooting
Common Issues
1. "API key is required" Error
Problem: SDK initialization fails with API key error.
Solution:
- Ensure API key is provided in configuration
- Check that API key starts with
pk_test_orpk_live_ - Verify environment variables are loaded correctly
javascript
// Debug API key
console.log('API Key:', process.env.REACT_APP_KORA_API_KEY?.substring(0, 10) + '...');2. Signature Verification Fails
Problem: handleRedirectReturn returns SIGNATURE_VERIFICATION_FAILED.
Solution:
- Ensure API secret is correct (not API key)
- Verify signature is included in URL parameters
- Check that all required parameters are present
- Verify signature verification is done server-side when possible
javascript
// Debug redirect parameters
console.log('Redirect params:', Object.fromEntries(urlParams));3. Network Errors
Problem: Requests fail with network errors.
Solution:
- Check internet connection
- Verify API base URL is correct
- Check CORS settings if making requests from browser
- Increase timeout if needed
javascript
const kore = new Kore({
apiKey: 'pk_test_xxx',
timeout: 60000 // Increase timeout to 60 seconds
});4. Session Expired
Problem: SESSION_NOT_FOUND error when handling redirect.
Solution:
- Sessions expire after a certain time
- Create a new session if expired
- Store session ID and check expiration time
javascript
// Check session expiration
const session = await kore.createEmbeddedSession(sessionData);
const expiresAt = new Date(session.expires_at);
if (new Date() > expiresAt) {
// Session expired, create new one
const newSession = await kore.createEmbeddedSession(sessionData);
}5. CORS Issues
Problem: CORS errors when making API requests.
Solution:
- Ensure your domain is whitelisted in Kore dashboard
- Use proper CORS headers on your backend
- Consider using a backend proxy for API calls
Debug Mode
Enable debug mode to see detailed logs:
javascript
const kore = new Kore({
apiKey: 'pk_test_xxx',
debug: true,
logger: (message) => {
console.log('[Kore SDK]', message);
}
});Getting Help
If you encounter issues:
- Check Error Codes: Use
Kore.ErrorCodesto identify specific errors - Enable Debug Mode: Set
debug: trueto see detailed logs - Review Documentation: Check this guide and API reference
- Contact Support: Reach out to Kore support with:
- Error code and message
- Request/response details (with sensitive data redacted)
- Steps to reproduce
FAQ
Q: Can I use the SDK in Node.js?
A: The SDK is designed for browser environments. For Node.js, use the backend API directly or create a server-side wrapper.
Q: How do I handle webhooks?
A: Webhooks should be handled on your backend server. The SDK focuses on frontend payment flows.
Q: Can I customize the payment UI?
A: The SDK redirects to gateway-hosted payment pages. UI customization depends on the gateway provider.
Q: How do I test payments?
A: Use the sandbox environment with test API keys. Test cards are provided in the Kore dashboard.
Q: What currencies are supported?
A: Support depends on your account configuration. Check with Kora support for available currencies.
Q: How do I handle refunds?
A: Refunds are handled through the backend API, not the frontend SDK. Contact your backend team or use the Kore API directly.
Q: Is the SDK PCI compliant?
A: The SDK doesn't handle card data directly. Card data is processed by gateway-hosted pages, which are PCI compliant.
Q: Can I use multiple payment gateways?
A: Yes, Kore handles gateway routing automatically based on your configuration.
Additional Resources
- API Reference: API Reference
- Download SDK & Examples: Download
- Support: [email protected]
Changelog
Version 1.0.0
- Initial release
- Payment session creation
- Redirect handling with signature verification
- Error code system
- TypeScript support
Last Updated: SDK Version: 1.0.0