Skip to content

Validation Reference

Complete reference for input validation in @joyida/payme.

New API: Named Functions

The recommended way to use validation is with named functions:

typescript
import { validateAmount, validateCardNumber, ValidationError } from '@joyida/payme';

// Validate before API call
try {
  validateAmount(500000);
  validateCardNumber('8600069195406311');
} catch (error) {
  if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message);
  }
}

Available Validation Functions

FunctionPurpose
validateAmount(amount)Validates payment amount (positive integer in tiyin)
validateCardNumber(number)Validates card number (13-19 digits)
validateCardExpiry(expire)Validates card expiry (MMYY format)
validatePhone(phone)Validates Uzbekistan phone (998XXXXXXXXX)
validatePaymeId(id)Validates Payme transaction ID (24 characters)
validateTimestamp(timestamp)Validates Unix timestamp (13-digit ms)
validateAccount(account)Validates account object (non-empty)
validateToken(token)Validates card token (non-empty string)
validateSecretKey(secretKey)Validates merchant secret key
validateCancelReason(reason)Validates cancel reason (1,2,3,4,5,10)
validateFiscalDataType(type)Validates fiscal data type (PERFORM/CANCEL)
validateFiscalData(fiscalData)Validates fiscal data object
validateNonEmptyString(value, fieldName)Validates non-empty string
validateReceiptId(id)Validates receipt ID

Deprecated: Validator Class

Deprecation Notice

The Validator class is deprecated and will be removed in version 0.5.0. Please use the named validation functions instead.

Migration:

typescript
// ❌ Old (deprecated)
import { Validator } from '@joyida/payme';
Validator.validateAmount(500000);

// ✅ New (recommended)
import { validateAmount } from '@joyida/payme';
validateAmount(500000);

The Validator class provides static methods for validating inputs before API calls.

typescript
import { Validator, ValidationError } from '@joyida/payme';

Methods

validateAmount

Validate payment amount (must be positive integer in tiyin).

typescript
static validateAmount(amount: number): void

Rules:

  • Must be a number
  • Must be positive (> 0)
  • Must be an integer (no decimals)
  • Represents amount in tiyin (1 UZS = 100 tiyin)

Examples:

typescript
// ✅ Valid amounts
Validator.validateAmount(500000);  // 5000 UZS
Validator.validateAmount(100);     // 1 UZS
Validator.validateAmount(1);       // 0.01 UZS

// ❌ Invalid amounts
Validator.validateAmount(-100);    // Throws: negative
Validator.validateAmount(0);       // Throws: zero
Validator.validateAmount(100.5);   // Throws: decimal
Validator.validateAmount('100');   // Throws: not a number

Error Message:

"Amount must be a positive integer"

validateCardNumber

Validate card number (13-19 digits).

typescript
static validateCardNumber(cardNumber: string): void

Rules:

  • Must be a string
  • Must contain 13-19 digits
  • Spaces are allowed and will be removed
  • Only digits and spaces allowed

Examples:

typescript
// ✅ Valid card numbers
Validator.validateCardNumber('8600069195406311');
Validator.validateCardNumber('8600 0691 9540 6311');
Validator.validateCardNumber('4111111111111111');

// ❌ Invalid card numbers
Validator.validateCardNumber('123');           // Throws: too short
Validator.validateCardNumber('12345678901234567890'); // Throws: too long
Validator.validateCardNumber('abcd1234');      // Throws: contains letters
Validator.validateCardNumber('');              // Throws: empty

Error Message:

"Card number must be 13-19 digits"

validateCardExpiry

Validate card expiry date (MMYY format).

typescript
static validateCardExpiry(expire: string): void

Rules:

  • Must be a string
  • Must be exactly 4 characters
  • Format: MMYY (e.g., "0399" = March 2099)
  • Month must be 01-12
  • Must not be expired

Examples:

typescript
// ✅ Valid expiry dates
Validator.validateCardExpiry('0399');  // March 2099
Validator.validateCardExpiry('1225');  // December 2025
Validator.validateCardExpiry('0126');  // January 2026

// ❌ Invalid expiry dates
Validator.validateCardExpiry('1323');  // Throws: invalid month (13)
Validator.validateCardExpiry('0020');  // Throws: expired
Validator.validateCardExpiry('03/99'); // Throws: wrong format
Validator.validateCardExpiry('399');   // Throws: wrong length

Error Messages:

"Invalid card expiry format. Expected MMYY (e.g., 0399)"
"Invalid month in card expiry"
"Card has expired"

validatePhone

Validate phone number (Uzbekistan format).

typescript
static validatePhone(phone: string): void

Rules:

  • Must be a string
  • Must start with "998"
  • Must be exactly 12 digits
  • Format: 998XXXXXXXXX

Examples:

typescript
// ✅ Valid phone numbers
Validator.validatePhone('998901234567');
Validator.validatePhone('998971234567');
Validator.validatePhone('998331234567');

// ❌ Invalid phone numbers
Validator.validatePhone('901234567');    // Throws: missing country code
Validator.validatePhone('998901234');    // Throws: too short
Validator.validatePhone('+998901234567'); // Throws: contains +
Validator.validatePhone('998 90 123 45 67'); // Throws: contains spaces

Error Message:

"Invalid phone number format. Expected 998XXXXXXXXX"

validatePaymeId

Validate Payme transaction ID (24 characters).

typescript
static validatePaymeId(id: string): void

Rules:

  • Must be a string
  • Must be exactly 24 characters
  • Typically hexadecimal (0-9, a-f)

Examples:

typescript
// ✅ Valid Payme IDs
Validator.validatePaymeId('5305e3bab097f420a62ced0b');
Validator.validatePaymeId('61396aaed8b87a4c215ae556');

// ❌ Invalid Payme IDs
Validator.validatePaymeId('5305e3ba');           // Throws: too short
Validator.validatePaymeId('5305e3bab097f420a62ced0b123'); // Throws: too long
Validator.validatePaymeId('');                   // Throws: empty

Error Message:

"Payme ID must be 24 characters"

validateTimestamp

Validate Unix timestamp (13 digits, milliseconds).

typescript
static validateTimestamp(timestamp: number): void

Rules:

  • Must be a number
  • Must be exactly 13 digits
  • Represents Unix timestamp in milliseconds

Examples:

typescript
// ✅ Valid timestamps
Validator.validateTimestamp(Date.now());
Validator.validateTimestamp(1399114284039);
Validator.validateTimestamp(1700000000000);

// ❌ Invalid timestamps
Validator.validateTimestamp(1399114284);    // Throws: 10 digits (seconds)
Validator.validateTimestamp(139911428403);  // Throws: 12 digits
Validator.validateTimestamp('1399114284039'); // Throws: not a number

Error Message:

"Timestamp must be 13 digits (Unix timestamp in milliseconds)"

validateAccount

Validate account object.

typescript
static validateAccount(account: Record<string, string | number>): void

Rules:

  • Must be an object
  • Must not be empty
  • Keys must be strings
  • Values must be strings or numbers

Examples:

typescript
// ✅ Valid accounts
Validator.validateAccount({ order_id: 'ORD-123' });
Validator.validateAccount({ user_id: 12345 });
Validator.validateAccount({ order_id: 'ORD-123', user_id: 12345 });

// ❌ Invalid accounts
Validator.validateAccount({});              // Throws: empty
Validator.validateAccount(null);            // Throws: not an object
Validator.validateAccount('order_id');      // Throws: not an object
Validator.validateAccount({ order_id: [] }); // Throws: invalid value type

Error Message:

"Account must be a non-empty object"

validateToken

Validate card token.

typescript
static validateToken(token: string): void

Rules:

  • Must be a string
  • Must not be empty

Examples:

typescript
// ✅ Valid tokens
Validator.validateToken('card_token_here');
Validator.validateToken('abc123xyz');

// ❌ Invalid tokens
Validator.validateToken('');     // Throws: empty
Validator.validateToken(null);   // Throws: not a string

Error Message:

"Token must be a non-empty string"

Usage Examples

Validate Before API Call

typescript
import { Validator, ValidationError } from '@joyida/payme';

async function createTransaction(params) {
  try {
    // Validate all inputs
    Validator.validatePaymeId(params.id);
    Validator.validateTimestamp(params.time);
    Validator.validateAmount(params.amount);
    Validator.validateAccount(params.account);
    
    // All valid, proceed with API call
    return await payme.createTransaction(params);
    
  } catch (error) {
    if (error instanceof ValidationError) {
      console.error('Validation failed:', error.message);
      throw error;
    }
  }
}

Validate User Input

typescript
import { Validator, ValidationError } from '@joyida/payme';

function validateCardForm(cardNumber: string, cardExpiry: string) {
  const errors: string[] = [];
  
  try {
    Validator.validateCardNumber(cardNumber);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.push(error.message);
    }
  }
  
  try {
    Validator.validateCardExpiry(cardExpiry);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.push(error.message);
    }
  }
  
  return {
    valid: errors.length === 0,
    errors
  };
}

// Usage
const result = validateCardForm('8600069195406311', '0399');
if (!result.valid) {
  console.error('Validation errors:', result.errors);
}

Validate with Custom Messages

typescript
import { Validator, ValidationError } from '@joyida/payme';

function validateAmount(amount: number, fieldName: string = 'Amount') {
  try {
    Validator.validateAmount(amount);
  } catch (error) {
    if (error instanceof ValidationError) {
      throw new Error(`${fieldName}: ${error.message}`);
    }
  }
}

// Usage
try {
  validateAmount(-100, 'Payment amount');
} catch (error) {
  console.error(error.message); // "Payment amount: Amount must be a positive integer"
}

Batch Validation

typescript
import { Validator, ValidationError } from '@joyida/payme';

function validatePaymentData(data: {
  amount: number;
  cardNumber: string;
  cardExpiry: string;
  phone: string;
}) {
  const errors: Record<string, string> = {};
  
  // Validate amount
  try {
    Validator.validateAmount(data.amount);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.amount = error.message;
    }
  }
  
  // Validate card number
  try {
    Validator.validateCardNumber(data.cardNumber);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.cardNumber = error.message;
    }
  }
  
  // Validate card expiry
  try {
    Validator.validateCardExpiry(data.cardExpiry);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.cardExpiry = error.message;
    }
  }
  
  // Validate phone
  try {
    Validator.validatePhone(data.phone);
  } catch (error) {
    if (error instanceof ValidationError) {
      errors.phone = error.message;
    }
  }
  
  return {
    valid: Object.keys(errors).length === 0,
    errors
  };
}

// Usage
const result = validatePaymentData({
  amount: 500000,
  cardNumber: '8600069195406311',
  cardExpiry: '0399',
  phone: '998901234567'
});

if (!result.valid) {
  console.error('Validation errors:', result.errors);
}

Automatic Validation

The library automatically validates inputs before API calls:

typescript
// This will automatically validate amount and account
await payme.checkPerformTransaction({
  amount: 500000,
  account: { order_id: 'ORD-123' }
});

// This will automatically validate card number and expiry
await subscribe.cardsCreate({
  card: {
    number: '8600069195406311',
    expire: '0399'
  },
  save: true
});

Best Practices

✅ Do's

  1. Validate early

    typescript
    // Validate user input before processing
    Validator.validateAmount(userInput.amount);
  2. Provide user-friendly messages

    typescript
    try {
      Validator.validateCardNumber(cardNumber);
    } catch (error) {
      if (error instanceof ValidationError) {
        showError('Please enter a valid card number');
      }
    }
  3. Validate all inputs

    typescript
    // Validate all fields before API call
    Validator.validateAmount(amount);
    Validator.validateAccount(account);
    Validator.validatePaymeId(id);

❌ Don'ts

  1. Don't skip validation

    typescript
    // ❌ BAD - No validation
    await payme.createTransaction(params);
    
    // ✅ GOOD - Validate first
    Validator.validateAmount(params.amount);
    await payme.createTransaction(params);
  2. Don't ignore validation errors

    typescript
    // ❌ BAD - Ignore errors
    try {
      Validator.validateAmount(amount);
    } catch (error) {
      // Ignore
    }
    
    // ✅ GOOD - Handle errors
    try {
      Validator.validateAmount(amount);
    } catch (error) {
      if (error instanceof ValidationError) {
        console.error(error.message);
        throw error;
      }
    }

Next Steps

Released under MIT License.