Authenticate
Signing a Request
Quickpay Widget API uses merchant API keys and private keys to authenticate all API calls. Depending on your deployment environment, the base API URL will be one of the following:
- Development Environment:
https://sandbox-api.quickpay.best
- Production Environment:
https://api.quickpay.best
Every API request must contain the following headers:
Authorization
- This value should be set toBearer <JWT>
. The access token is a JSON Web Token (JWT) signed with the merchant's private key.
JWT Structure
Authorization: Bearer <JWT>
The JWT payload field should contain the following fields:
uri
- The URI part of the request (e.g., /merchants/profile).nonce
- Unique number or string. Each API request needs to have a different nonce.iat
- The time at which the JWT was issued, in seconds since Epoch.exp
- The expiration time on and after which the JWT must not be accepted for processing, in seconds since Epoch. (Must be less thaniat
+55sec.)sub
- The merchant API Key.bodyHash
- Hex-encoded SHA-256 hash of the raw HTTP request body.
The JWT must be signed with the merchant's private key and the RS256 (RSASSA-PKCS1-v1_5 using SHA-256 hash) algorithm.
Authentication Flow
- Merchant Registration: Merchants register in the system and receive API Key and private key
- Request Signing: Client uses merchant private key to sign the request
- Server Verification: Server verifies the signature using the merchant's public key
- Merchant Identification: Server identifies the merchant through the
merchant_key
field
Security Features
- Replay Attack Prevention: Prevents request replay through
nonce
andbodyHash
- Time Validation: Ensures request timeliness through
iat
andexp
- Request Integrity: Ensures request body integrity through
bodyHash
- Merchant Isolation: Each merchant uses independent key pairs
Code Examples
quickpay-sdk-js
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
const fs = require('fs');
// Merchant configuration
const apiKey = 'ac55d6fe-cc98-436c-a7f9-9c0e5f0873c6';
const privateKey = fs.readFileSync('./merchant_private_key.pem', 'utf8');
function createAuthToken(uri, body = '{}') {
const now = Math.floor(Date.now() / 1000);
const nonce = crypto.randomBytes(16).toString('hex');
const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
const payload = {
uri: uri,
nonce: nonce,
iat: now,
exp: now + 55,
sub: apiKey,
bodyHash: bodyHash
};
return jwt.sign(payload, privateKey, { algorithm: 'RS256' });
}
// Usage example
const token = createAuthToken('/merchants/profile');
console.log(`Authorization: Bearer ${token}`);
quickpay-sdk-python
import jwt
import hashlib
import time
import uuid
from cryptography.hazmat.primitives import serialization
# Merchant configuration
api_key = 'ac55d6fe-cc98-436c-a7f9-9c0e5f0873c6'
with open('./merchant_private_key.pem', 'r') as f:
private_key = f.read()
def create_auth_token(uri, body='{}'):
now = int(time.time())
nonce = str(uuid.uuid4())
body_hash = hashlib.sha256(body.encode()).hexdigest()
payload = {
'uri': uri,
'nonce': nonce,
'iat': now,
'exp': now + 55,
'sub': api_key,
'bodyHash': body_hash
}
return jwt.encode(payload, private_key, algorithm='RS256')
# Usage example
token = create_auth_token('/merchants/profile')
print(f"Authorization: Bearer {token}")
quickpay-sdk-php
<?php
require_once 'vendor/autoload.php';
use Firebase\JWT\JWT;
// Merchant configuration
$apiKey = 'ac55d6fe-cc98-436c-a7f9-9c0e5f0873c6';
$privateKey = file_get_contents('./merchant_private_key.pem');
function createAuthToken($uri, $body = '{}') {
global $apiKey, $privateKey;
$now = time();
$nonce = bin2hex(random_bytes(16));
$bodyHash = hash('sha256', $body);
$payload = [
'uri' => $uri,
'nonce' => $nonce,
'iat' => $now,
'exp' => $now + 55,
'sub' => $apiKey,
'bodyHash' => $bodyHash
];
return JWT::encode($payload, $privateKey, 'RS256');
}
// Usage example
$token = createAuthToken('/merchants/profile');
echo "Authorization: Bearer " . $token;
?>
Error Handling
Common authentication errors include:
401 Unauthorized
- Invalid JWT or signature verification failed401 Token Expired
- JWT has expired401 Invalid Merchant
- Merchant does not exist or is not active401 Body Hash Mismatch
- Request body hash does not match
Best Practices
- Key Security: Safely store merchant private keys, do not hardcode in code
- Time Synchronization: Ensure client time is synchronized with server time
- Nonce Management: Ensure each request uses a unique nonce
- Error Retry: Implement appropriate error retry mechanisms
- Logging: Log authentication failures for debugging
Related Documentation
Updated 24 days ago