Authentication Guide
Understanding authentication in Payme API.
Overview
Payme uses two different authentication methods:
- Merchant API: Basic Authentication with Base64 encoding
- Subscribe API: X-Auth header with merchant ID and password
Merchant API Authentication
How It Works
The Merchant API uses HTTP Basic Authentication:
Authorization: Basic base64(Paycom:SECRET_KEY)Manual Implementation
const merchantId = 'your_merchant_id';
const secretKey = 'your_secret_key';
// Create auth string
const authString = `Paycom:${secretKey}`;
// Encode to Base64
const authHeader = `Basic ${Buffer.from(authString).toString('base64')}`;
// Use in request
const response = await fetch('https://checkout.paycom.uz/api', {
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'CheckPerformTransaction',
params: {
amount: 500000,
account: { order_id: 'ORD-123' }
}
})
});Using PaymeMerchant
The library handles authentication automatically:
import { PaymeMerchant } from '@joyida/payme';
const payme = new PaymeMerchant({
merchantId: 'your_merchant_id',
secretKey: 'your_secret_key'
});
// Authentication is handled automatically
await payme.checkPerformTransaction({
amount: 500000,
account: { order_id: 'ORD-123' }
});Subscribe API Authentication
How It Works
The Subscribe API uses X-Auth header with different formats for client and server modes:
Client Mode (card tokenization):
X-Auth: MERCHANT_IDServer Mode (card management and receipts):
X-Auth: MERCHANT_ID:PASSWORDManual Implementation
const merchantId = 'your_merchant_id';
const password = 'your_password';
// Client mode (card tokenization)
const clientAuthHeader = merchantId;
// Server mode (card management and receipts)
const serverAuthHeader = `${merchantId}:${password}`;
// Use in request
const response = await fetch('https://checkout.paycom.uz/api', {
method: 'POST',
headers: {
'X-Auth': serverAuthHeader,
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'cards.check',
params: {
token: 'card_token_here'
}
})
});Using PaymeSubscribe
The library handles authentication automatically:
import { PaymeSubscribe } from '@joyida/payme';
// Client mode (only merchant ID needed)
const subscribeClient = new PaymeSubscribe({
merchantId: 'your_merchant_id'
}, 'client');
// Server mode (merchant ID and password needed)
const subscribeServer = new PaymeSubscribe({
merchantId: 'your_merchant_id',
password: 'your_password'
}, 'server');
// Authentication is handled automatically
await subscribeClient.cardsCreate({
card: { number: '8600069195406311', expire: '0399' },
save: true
});
await subscribeServer.cardsCheck({
token: 'card_token_here'
});Auth Helper Functions
The library provides standalone auth functions for advanced use cases:
createBasicAuth
Creates Basic auth header for Merchant API:
import { createBasicAuth } from '@joyida/payme';
const header = createBasicAuth('my_secret_key');
// Returns: "Basic UGF5Y29tOm15U2VjcmV0S2V5"createXAuth
Creates X-Auth header for Subscribe API:
import { createXAuth } from '@joyida/payme';
// Client mode
const clientHeader = createXAuth('merchant_id', undefined, 'client');
// Returns: "merchant_id"
// Server mode
const serverHeader = createXAuth('merchant_id', 'password', 'server');
// Returns: "merchant_id:password"Deprecated: AuthManager Class
Deprecation Notice
The AuthManager class is deprecated and will be removed in version 0.5.0. Please use the named auth functions instead.
Migration:
// ❌ Old (deprecated)
import { AuthManager } from '@joyida/payme';
AuthManager.createBasicAuth('secret');
// ✅ New (recommended)
import { createBasicAuth } from '@joyida/payme';
createBasicAuth('secret');Getting Credentials
Merchant ID and Secret Key
- Log in to Payme Business
- Go to Settings → API
- Find your Merchant ID
- Generate or view your Secret Key
Subscribe API Password
- Log in to Payme Business
- Go to Settings → Subscribe API
- Generate or view your Password
Security Best Practices
✅ Do's
Store credentials securely
typescript// Use environment variables const payme = new PaymeMerchant({ merchantId: process.env.PAYME_MERCHANT_ID!, secretKey: process.env.PAYME_SECRET_KEY! });Use different credentials for test and production
typescriptconst isDevelopment = process.env.NODE_ENV === 'development'; const payme = new PaymeMerchant({ merchantId: isDevelopment ? process.env.PAYME_MERCHANT_ID_TEST! : process.env.PAYME_MERCHANT_ID!, secretKey: isDevelopment ? process.env.PAYME_SECRET_KEY_TEST! : process.env.PAYME_SECRET_KEY! });Rotate credentials regularly
- Change secret keys every 3-6 months
- Update immediately if compromised
Use HTTPS only
typescriptconst payme = new PaymeMerchant({ merchantId: 'your_merchant_id', secretKey: 'your_secret_key', baseURL: 'https://checkout.paycom.uz/api' // ✅ HTTPS });Restrict access to credentials
- Use environment variables
- Don't commit to version control
- Use secret management services
❌ Don'ts
Never hardcode credentials
typescript// ❌ BAD const payme = new PaymeMerchant({ merchantId: '5e730e8e0b852a417aa49ceb', secretKey: 'my_secret_key_123' }); // ✅ GOOD const payme = new PaymeMerchant({ merchantId: process.env.PAYME_MERCHANT_ID!, secretKey: process.env.PAYME_SECRET_KEY! });Never commit credentials to Git
bash# .gitignore .env .env.local .env.productionNever expose credentials in client-side code
typescript// ❌ BAD - Never use Merchant API in browser const payme = new PaymeMerchant({ merchantId: 'your_merchant_id', secretKey: 'your_secret_key' // ❌ Exposed to users! }); // ✅ GOOD - Use Subscribe API client mode in browser const subscribe = new PaymeSubscribe({ merchantId: 'your_merchant_id' // ✅ Safe to expose }, 'client');Never log credentials
typescript// ❌ BAD console.log('Secret key:', process.env.PAYME_SECRET_KEY); // ✅ GOOD console.log('Payme client initialized');Never share credentials
- Don't send via email or chat
- Don't share between environments
- Don't reuse across projects
Environment Variables
.env File
# Development
PAYME_MERCHANT_ID_TEST=test_merchant_id
PAYME_SECRET_KEY_TEST=test_secret_key
PAYME_PASSWORD_TEST=test_password
# Production
PAYME_MERCHANT_ID=prod_merchant_id
PAYME_SECRET_KEY=prod_secret_key
PAYME_PASSWORD=prod_password
# Environment
NODE_ENV=developmentLoading Environment Variables
// Bun loads .env when you run with: bun --env-file=.env run src/index.ts
const payme = new PaymeMerchant({
secretKey: process.env.PAYME_SECRET_KEY!
});Authentication Errors
Invalid Credentials
import { PaymeError } from '@joyida/payme';
try {
await payme.checkPerformTransaction(params);
} catch (error) {
if (error instanceof PaymeError && error.code === -32504) {
console.error('Invalid credentials');
// Check merchantId and secretKey
}
}Missing Password (Subscribe API)
import { ValidationError } from '@joyida/payme';
try {
// ❌ Missing password for server mode
const subscribe = new PaymeSubscribe({
merchantId: 'your_merchant_id'
}, 'server');
} catch (error) {
if (error instanceof ValidationError) {
console.error('Password required for server mode');
}
}Testing Authentication
Test Credentials
async function testAuthentication() {
try {
const payme = new PaymeMerchant({
merchantId: process.env.PAYME_MERCHANT_ID!,
secretKey: process.env.PAYME_SECRET_KEY!
});
// Try a simple request
await payme.checkPerformTransaction({
amount: 100,
account: { test: 'test' }
});
console.log('✅ Authentication successful');
} catch (error) {
if (error instanceof PaymeError && error.code === -32504) {
console.error('❌ Authentication failed: Invalid credentials');
} else {
console.error('❌ Authentication test failed:', error.message);
}
}
}
testAuthentication();Next Steps
- Learn about Configuration
- Understand the Payment Flow
- Explore Card Tokenization
- Check Error Handling