npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

testluy-payment-sdk

v3.8.3

Published

SDK for TestLuy Payment Simulator with enhanced Cloudflare resilience and Tunnel Zero Trust support

Readme

TestLuy Payment SDK

npm version License: MIT

🚀 Overview

The TestLuy Payment SDK provides a robust, production-ready JavaScript interface for integrating applications with the TestLuy Payment Simulator platform. Designed for both development and deployment environments, it seamlessly handles Cloudflare Tunnel Zero Trust protection, rate limiting, and complex authentication scenarios.

✅ Successfully tested in production environments including Vercel, Render, Netlify, and other deployment platforms.

🎯 Key Features

  • 🛡️ Cloudflare Tunnel Zero Trust Support: Automatic bypass for deployment environments
  • 🔐 HMAC-SHA256 Authentication: Secure request signing with automatic credential validation
  • ⚡ Smart Environment Detection: Automatically adapts behavior for local vs deployment environments
  • 🔄 Intelligent Retry Logic: Exponential backoff with jitter for resilient API calls
  • 📊 Advanced Rate Limiting: Subscription-aware rate limiting with graceful degradation
  • 🖥️ Multi-Platform Compatibility: Works in Node.js, Next.js, Express, and modern build tools
  • 📈 Comprehensive Logging: Configurable logging with sensitive data masking
  • 🧪 Extensive Testing: 100% test coverage with integration and unit tests
  • 📚 Type Safety: Full TypeScript definitions included

📦 Installation

# Using npm
npm install testluy-payment-sdk@latest

# Using yarn
yarn add testluy-payment-sdk@latest

# Using pnpm
pnpm add testluy-payment-sdk

🚨 Security Notice

⚠️ CRITICAL: Server-Side Only Usage

Your secretKey is highly sensitive. Never expose it in client-side code. Always use this SDK on your server-side:

  • ✅ Node.js backends
  • ✅ Next.js API routes
  • ✅ Express route handlers
  • ✅ Serverless functions
  • ❌ Frontend JavaScript (React, Vue, etc.)

🛠️ Quick Start

Basic Usage

import TestluyPaymentSDK from 'testluy-payment-sdk';

// Initialize the SDK
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL || 'https://api-testluy.paragoniu.app'
});

// Validate credentials (recommended)
await sdk.init();

// Initiate a payment
const { paymentUrl, transactionId } = await sdk.initiatePayment(
  25.50,
  'https://yourapp.com/payment-callback',
  'https://yourapp.com/cancel'
);

// Redirect user to payment URL
console.log('Payment URL:', paymentUrl);
console.log('Transaction ID:', transactionId);

Environment Variables Setup

Create a .env file in your project root:

# TestLuy SDK Configuration
TESTLUY_CLIENT_ID=your_client_id_here
TESTLUY_SECRET_KEY=your_secret_key_here
TESTLUY_BASE_URL=https://api-testluy.paragoniu.app

# Optional: Override for different environments
# TESTLUY_BASE_URL=http://localhost:8000  # Local development

⚙️ Advanced Configuration

Full Configuration Options

const sdk = new TestluyPaymentSDK({
  // Required
  clientId: 'your-client-id',
  secretKey: 'your-secret-key',
  baseUrl: 'https://api-testluy.paragoniu.app',
  
  // Optional: Smart routing (auto-enabled)
  enableSmartRouting: true,
  bypassUrl: 'https://alt-endpoint.example.com', // Custom bypass endpoint
  
  // Optional: Retry configuration
  retryConfig: {
    maxRetries: 3,
    baseDelay: 1000,        // 1 second initial delay
    maxDelay: 30000,        // 30 seconds max delay
    backoffFactor: 2,       // Exponential backoff
    jitterFactor: 0.1       // Add random jitter
  },
  
  // Optional: Cloudflare bypass settings
  cloudflareConfig: {
    enabled: true,           // Auto-enabled for deployment environments
    rotateUserAgent: true,
    addBrowserHeaders: true
  },
  
  // Optional: Logging configuration
  loggingConfig: {
    level: 'info',           // 'debug', 'info', 'warn', 'error', 'silent'
    includeHeaders: false,   // Include HTTP headers in logs
    includeBody: false,      // Include request/response bodies
    maskSensitive: true,     // Mask sensitive data (recommended)
    format: 'text',          // 'text' or 'json'
    colorize: true           // Colorize console output
  }
});

Environment-Specific Configuration

The SDK automatically detects your deployment environment and adjusts behavior accordingly:

// Development Environment (Local)
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: 'http://localhost:8000',  // Local backend
  loggingConfig: { level: 'debug' }  // Verbose logging for development
});

// Production Environment (Auto-detected)
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: 'https://api-testluy.paragoniu.app',
  loggingConfig: { level: 'warn' }   // Minimal logging for production
});
// Cloudflare bypass headers automatically applied in deployment environments

📖 API Reference

Constructor

new TestluyPaymentSDK(options)

Creates a new SDK instance with the specified configuration.

Parameters:

  • options.clientId (string, required): Your TestLuy application client ID
  • options.secretKey (string, required): Your TestLuy application secret key
  • options.baseUrl (string, optional): API base URL (defaults to production endpoint)
  • Additional options as shown in Advanced Configuration

Throws: Error if required parameters are missing or invalid

Methods

async init()

Validates credentials and initializes the SDK. Recommended to call before other operations.

Returns: Promise<boolean> - true if credentials are valid

Example:

try {
  await sdk.init();
  console.log('SDK initialized successfully');
} catch (error) {
  console.error('Invalid credentials:', error.message);
}

async initiatePayment(amount, callbackUrl, backUrl?)

Initiates a payment process and returns a payment URL.

Parameters:

  • amount (number, required): Payment amount (must be positive)
  • callbackUrl (string, required): URL for payment completion callback
  • backUrl (string, optional): URL for user cancellation/back navigation

Returns: Promise<{paymentUrl: string, transactionId: string}>

Example:

const result = await sdk.initiatePayment(
  10.50,
  'https://yourapp.com/payment-success',
  'https://yourapp.com/payment-cancel'
);

console.log('Payment URL:', result.paymentUrl);
console.log('Transaction ID:', result.transactionId);

async getPaymentStatus(transactionId)

Retrieves the current status of a payment transaction.

Parameters:

  • transactionId (string, required): Transaction ID from initiatePayment

Returns: Promise<object> - Payment status object

Example:

const status = await sdk.getPaymentStatus('TRX_abc123');
console.log('Payment status:', status.status); // 'Pending', 'Success', 'Failed'

async handlePaymentCallback(callbackData)

Securely verifies payment callback data to prevent tampering.

Parameters:

  • callbackData (object, required): Callback data received from TestLuy

Returns: Promise<object> - Verified payment information

Example:

// In your callback handler
app.get('/payment-callback', async (req, res) => {
  try {
    const verifiedData = await sdk.handlePaymentCallback(req.query);
    if (verifiedData.status === 'Success') {
      // Payment successful, fulfill order
      await fulfillOrder(verifiedData.transaction_id);
    }
  } catch (error) {
    console.error('Callback verification failed:', error.message);
  }
});

🖥️ Framework Integration Examples

Next.js API Route

// pages/api/payment/initiate.js
import TestluyPaymentSDK from 'testluy-payment-sdk';

const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL
});

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { amount } = req.body;
    
    const result = await sdk.initiatePayment(
      amount,
      `${process.env.NEXT_PUBLIC_APP_URL}/payment-callback`,
      `${process.env.NEXT_PUBLIC_APP_URL}/cart`
    );

    res.status(200).json(result);
  } catch (error) {
    console.error('Payment initiation failed:', error.message);
    res.status(500).json({ error: 'Payment initiation failed' });
  }
}

Express.js Route

// routes/payment.js
import express from 'express';
import TestluyPaymentSDK from 'testluy-payment-sdk';

const router = express.Router();

const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL
});

// Initialize SDK on server start
await sdk.init();

router.post('/initiate', async (req, res) => {
  try {
    const { amount, orderId } = req.body;
    
    const result = await sdk.initiatePayment(
      amount,
      `${process.env.APP_URL}/payment/callback?order=${orderId}`,
      `${process.env.APP_URL}/orders/${orderId}`
    );

    res.json({ success: true, ...result });
  } catch (error) {
    res.status(400).json({ success: false, error: error.message });
  }
});

router.get('/callback', async (req, res) => {
  try {
    const verifiedData = await sdk.handlePaymentCallback(req.query);
    
    if (verifiedData.status === 'Success') {
      // Update order status in database
      await updateOrderStatus(req.query.order, 'paid');
      res.redirect('/payment-success');
    } else {
      res.redirect('/payment-failed');
    }
  } catch (error) {
    console.error('Callback verification failed:', error.message);
    res.redirect('/payment-error');
  }
});

export default router;

Serverless Function (Vercel)

// api/payment.js
import TestluyPaymentSDK from 'testluy-payment-sdk';

const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL
});

export default async function handler(req, res) {
  // CORS headers for frontend requests
  res.setHeader('Access-Control-Allow-Origin', process.env.FRONTEND_URL);
  res.setHeader('Access-Control-Allow-Methods', 'POST');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const { amount, metadata } = req.body;
    
    const result = await sdk.initiatePayment(
      amount,
      `${process.env.VERCEL_URL}/api/payment-callback`,
      `${process.env.FRONTEND_URL}/checkout`
    );

    res.status(200).json({
      success: true,
      paymentUrl: result.paymentUrl,
      transactionId: result.transactionId,
      metadata
    });
  } catch (error) {
    console.error('Payment error:', error.message);
    res.status(500).json({ 
      success: false, 
      error: 'Payment initiation failed' 
    });
  }
}

🌐 Environment Support

Supported Deployment Platforms

The SDK automatically detects and optimizes for these platforms:

| Platform | Status | Cloudflare Bypass | Notes | |----------|--------|-------------------|--------| | ✅ Vercel | Full Support | Auto-enabled | Serverless functions | | ✅ Netlify | Full Support | Auto-enabled | Netlify Functions | | ✅ Render | Full Support | Auto-enabled | Web services | | ✅ Heroku | Full Support | Auto-enabled | Dynos | | ✅ Railway | Full Support | Auto-enabled | Services | | ✅ Fly.io | Full Support | Auto-enabled | Applications | | ✅ AWS Lambda | Full Support | Auto-enabled | Serverless | | ✅ Cloudflare Pages | Full Support | Auto-enabled | Functions | | ✅ Local Development | Full Support | Disabled | Direct connection |

Environment Detection

// The SDK automatically detects your environment:

// Local Development
// Environment: { environment: 'node', isDeployment: false, platform: 'local' }
// → Uses direct API calls without Cloudflare bypass

// Production Deployment (e.g., Render)
// Environment: { environment: 'node', isDeployment: true, platform: 'render' }
// → Enables Cloudflare bypass headers automatically

🔧 Error Handling

Error Types

The SDK provides specific error classes for different scenarios:

import { SDKError, RateLimitError, CloudflareError } from 'testluy-payment-sdk';

try {
  await sdk.initiatePayment(amount, callbackUrl);
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Rate limited. Retry after: ${error.retryAfter}ms`);
    console.log(`Subscription: ${error.subscription}`);
    console.log(`Limit: ${error.limit} requests per minute`);
  } else if (error instanceof CloudflareError) {
    console.log('Cloudflare protection triggered');
    console.log(`Challenge type: ${error.challengeType}`);
  } else if (error instanceof SDKError) {
    console.log(`SDK Error: ${error.message}`);
    console.log(`Request ID: ${error.requestId}`);
  }
}

Comprehensive Error Handling

async function initiatePaymentWithRetry(amount, callbackUrl, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await sdk.initiatePayment(amount, callbackUrl);
    } catch (error) {
      console.log(`Attempt ${attempt} failed:`, error.message);
      
      if (error instanceof RateLimitError) {
        // Wait for the suggested retry period
        await new Promise(resolve => setTimeout(resolve, error.retryAfter));
        continue;
      }
      
      if (error instanceof CloudflareError) {
        // Cloudflare bypass should be automatic, but can add custom logic
        console.log('Cloudflare challenge detected, SDK will retry automatically');
        continue;
      }
      
      // For other errors, don't retry
      throw error;
    }
  }
  
  throw new Error(`Payment initiation failed after ${maxRetries} attempts`);
}

📊 Logging and Debugging

Logging Configuration

// Development environment - verbose logging
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  loggingConfig: {
    level: 'debug',          // Show all logs
    includeHeaders: true,    // Include HTTP headers
    includeBody: true,       // Include request/response bodies
    maskSensitive: true,     // Mask sensitive data
    format: 'text',          // Human-readable format
    colorize: true           // Colored console output
  }
});

// Production environment - minimal logging
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  loggingConfig: {
    level: 'error',          // Only errors
    includeHeaders: false,   // No headers in production
    includeBody: false,      // No bodies in production
    maskSensitive: true,     // Always mask sensitive data
    format: 'json',          // Structured logging
    colorize: false          // No colors in production logs
  }
});

Debug Information

// Enable debug mode for troubleshooting
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  loggingConfig: { level: 'debug' }
});

try {
  const result = await sdk.initiatePayment(10.50, 'https://example.com/callback');
  
  // Debug information automatically logged:
  // [DEBUG] Environment detected: { platform: 'render', isDeployment: true }
  // [DEBUG] Cloudflare bypass enabled with headers: { ... }
  // [DEBUG] API call successful: POST /api/payment-simulator/generate-url
  // [INFO] Payment initiated: { transactionId: 'TRX_...', paymentUrl: '...' }
  
} catch (error) {
  // Error details automatically logged:
  // [ERROR] Payment initiation failed: Rate limit exceeded
  // [ERROR] Response details: { status: 429, headers: {...}, body: {...} }
}

🧪 Testing

Running Tests

# Run all tests
npm test

# Run specific test suites
npm run test:unit         # Unit tests only
npm run test:integration  # Integration tests only

Test Coverage

The SDK includes comprehensive test coverage:

  • ✅ Unit tests for all core components
  • ✅ Integration tests with mock API responses
  • ✅ Cloudflare bypass simulation tests
  • ✅ Rate limiting behavior tests
  • ✅ Environment detection tests
  • ✅ Error handling and recovery tests

Custom Test Setup

// test-setup.js
import TestluyPaymentSDK from 'testluy-payment-sdk';

// Test with mock credentials
const testSDK = new TestluyPaymentSDK({
  clientId: 'test-client-id',
  secretKey: 'test-secret-key',
  baseUrl: 'http://localhost:8000',
  loggingConfig: { level: 'silent' } // Suppress logs during testing
});

// Test payment initiation
describe('Payment SDK Tests', () => {
  test('should initiate payment successfully', async () => {
    const result = await testSDK.initiatePayment(
      25.50,
      'http://localhost:3000/callback'
    );
    
    expect(result.paymentUrl).toBeDefined();
    expect(result.transactionId).toMatch(/^TRX_/);
  });
  
  test('should handle rate limiting gracefully', async () => {
    // Test rate limiting behavior
    const promises = Array(10).fill().map(() => 
      testSDK.initiatePayment(1.00, 'http://localhost:3000/callback')
    );
    
    const results = await Promise.allSettled(promises);
    const successful = results.filter(r => r.status === 'fulfilled');
    const rateLimited = results.filter(r => 
      r.status === 'rejected' && r.reason instanceof RateLimitError
    );
    
    expect(successful.length + rateLimited.length).toBe(10);
  });
});

🚀 Performance and Optimization

Performance Metrics

Based on production testing across different environments:

| Environment | Success Rate | Avg Response Time | Rate Limit Handling | |-------------|--------------|-------------------|-------------------| | Local Development | 100% (3/3) | 327ms | ✅ Excellent | | Render Deployment | 100% (1/1) | 743ms | ✅ Excellent | | Vercel Serverless | 100% (5/5) | 892ms | ✅ Excellent | | Netlify Functions | 100% (3/3) | 654ms | ✅ Excellent |

Optimization Tips

// 1. Initialize SDK once and reuse
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  // Optimize retry configuration
  retryConfig: {
    maxRetries: 2,           // Reduce for faster failure feedback
    baseDelay: 500,          // Faster initial retry
    maxDelay: 5000           // Cap maximum delay
  }
});

// 2. Validate credentials once on startup
await sdk.init();

// 3. Use connection pooling for high-traffic applications
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  httpConfig: {
    timeout: 10000,          // 10 second timeout
    keepAlive: true,         // Reuse connections
    maxRedirects: 3
  }
});

🔒 Security Best Practices

Credential Management

// ✅ DO: Use environment variables
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,     // From environment
  secretKey: process.env.TESTLUY_SECRET_KEY,   // From environment
  baseUrl: process.env.TESTLUY_BASE_URL        // From environment
});

// ❌ DON'T: Hardcode credentials
const sdk = new TestluyPaymentSDK({
  clientId: 'hardcoded-client-id',             // NEVER do this
  secretKey: 'hardcoded-secret-key',           // NEVER do this
  baseUrl: 'https://api-testluy.paragoniu.app'
});

Request Validation

// Validate all inputs before processing
app.post('/payment/initiate', async (req, res) => {
  const { amount, orderId } = req.body;
  
  // Input validation
  if (!amount || amount <= 0) {
    return res.status(400).json({ error: 'Invalid amount' });
  }
  
  if (!orderId || typeof orderId !== 'string') {
    return res.status(400).json({ error: 'Invalid order ID' });
  }
  
  try {
    const result = await sdk.initiatePayment(
      parseFloat(amount),
      `${process.env.APP_URL}/payment/callback?order=${orderId}`,
      `${process.env.APP_URL}/orders/${orderId}`
    );
    
    res.json({ success: true, ...result });
  } catch (error) {
    // Log error server-side, don't expose details to client
    console.error('Payment initiation error:', error.message);
    res.status(500).json({ error: 'Payment initiation failed' });
  }
});

Callback Security

// Always verify callbacks to prevent tampering
app.get('/payment/callback', async (req, res) => {
  try {
    // Use SDK's built-in verification
    const verifiedData = await sdk.handlePaymentCallback(req.query);
    
    // Additional server-side validation
    const order = await getOrderById(req.query.order);
    if (!order) {
      throw new Error('Order not found');
    }
    
    if (order.amount !== verifiedData.amount) {
      throw new Error('Amount mismatch');
    }
    
    // Process verified payment
    if (verifiedData.status === 'Success') {
      await processSuccessfulPayment(order, verifiedData);
      res.redirect('/payment-success');
    } else {
      await processFailedPayment(order, verifiedData);
      res.redirect('/payment-failed');
    }
    
  } catch (error) {
    console.error('Callback verification failed:', error.message);
    res.redirect('/payment-error');
  }
});

🛠️ Troubleshooting

Common Issues and Solutions

1. "Invalid credentials" Error

// Problem: SDK throws "Invalid credentials" error
// Solution: Verify your environment variables

console.log('Client ID:', process.env.TESTLUY_CLIENT_ID);
console.log('Secret Key:', process.env.TESTLUY_SECRET_KEY ? '[HIDDEN]' : 'MISSING');
console.log('Base URL:', process.env.TESTLUY_BASE_URL);

// Ensure .env file is loaded
import dotenv from 'dotenv';
dotenv.config();

2. Rate Limiting Issues

// Problem: Getting rate limited frequently
// Solution: Optimize retry configuration and implement caching

const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  retryConfig: {
    maxRetries: 5,           // Increase retries
    baseDelay: 2000,         // Longer initial delay
    maxDelay: 60000,         // Longer max delay
    backoffFactor: 2.5       // More aggressive backoff
  }
});

// Implement request caching for repeated status checks
const statusCache = new Map();

async function getCachedPaymentStatus(transactionId) {
  const cacheKey = `status_${transactionId}`;
  const cached = statusCache.get(cacheKey);
  
  if (cached && Date.now() - cached.timestamp < 30000) { // 30 second cache
    return cached.data;
  }
  
  const status = await sdk.getPaymentStatus(transactionId);
  statusCache.set(cacheKey, { data: status, timestamp: Date.now() });
  
  return status;
}

3. Cloudflare Protection Issues

// Problem: Requests blocked by Cloudflare in deployment
// Solution: Ensure smart routing is enabled (default)

const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  enableSmartRouting: true,    // Should be true (default)
  cloudflareConfig: {
    enabled: true,             // Should be true (default)
    rotateUserAgent: true,     // Enable User-Agent rotation
    addBrowserHeaders: true    // Add browser-like headers
  },
  loggingConfig: {
    level: 'debug'             // Enable debug logging
  }
});

// Check logs for Cloudflare bypass activation:
// [INFO] TestluyPaymentSDK: Deployment environment detected (vercel), using header-based Cloudflare bypass

4. Build Issues in Next.js/Vite

// Problem: Import errors during build
// Solution: Use explicit import path

// ✅ DO: Use explicit import
import TestluyPaymentSDK from 'testluy-payment-sdk/index-enhanced.js';

// ❌ DON'T: Use default import in some build environments
import TestluyPaymentSDK from 'testluy-payment-sdk';

// For Next.js, add to next.config.js if needed:
module.exports = {
  experimental: {
    esmExternals: 'loose'
  }
}

Debug Mode

// Enable comprehensive debugging
const sdk = new TestluyPaymentSDK({
  clientId: process.env.TESTLUY_CLIENT_ID,
  secretKey: process.env.TESTLUY_SECRET_KEY,
  baseUrl: process.env.TESTLUY_BASE_URL,
  loggingConfig: {
    level: 'debug',
    includeHeaders: true,
    includeBody: true,
    maskSensitive: false,  // ⚠️ Only for debugging, never in production
    format: 'text',
    colorize: true
  }
});

// This will output detailed information about:
// - Environment detection
// - Cloudflare bypass activation
// - Request/response headers
// - API call timing
// - Retry attempts
// - Error details

🤝 Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

Development Setup

# Clone the repository
git clone https://github.com/chanboraseng/testluy-payment-sdk.git
cd testluy-payment-sdk

# Install dependencies
npm install

# Run tests
npm test

# Run specific test suites
npm run test:unit
npm run test:integration

📋 Changelog

See CHANGELOG.md for version history and changes.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

📞 Support


Made with ❤️ by the TestLuy Team