Tingg Class
The main Tingg provider class for processing payments across multiple African countries.
Constructor
new Tingg ( config : TinggConfig )
Parameters
Configuration object for the Tingg provider
TinggConfig Interface
interface TinggConfig {
apiKey : string ;
publicKey : string ;
serviceCode : string ;
paymentOptionCode : string ;
timeout ?: number ;
retries ?: number ;
retryDelay ?: number ;
logger ?: Logger ;
}
Configuration Properties
Your Tingg API key (client secret) for OAuth authentication
Your Tingg public key (client ID) for OAuth authentication
The service code assigned to your merchant account on the Tingg portal
The payer client code for the mobile money operator (e.g., ‘SAFKE’, ‘MTNKE’, ‘AIRKE’)
Request timeout in milliseconds
Number of retry attempts for failed requests
Delay between retry attempts in milliseconds
Custom logger instance for debugging and monitoring
Methods
collection()
Initiates a payment collection request.
async collection (
tx : Transaction ,
environment ?: 'sandbox' | 'production' ,
user ?: string ,
fundkitApiKey ?: string
): Promise < CollectionResult >
Parameters
Transaction details including amount, currency, operator, and account number
environment
'sandbox' | 'production'
default: "production"
Environment mode for the transaction
user
string
default: "anonymous"
User identifier for the transaction
FundKit API key for sandbox routing
Returns
Result object containing transaction details and status
Example
const tingg = new Tingg ({
apiKey: 'your_api_key' ,
publicKey: 'your_public_key' ,
serviceCode: 'YOUR_SERVICE_CODE' ,
paymentOptionCode: 'SAFKE' ,
});
const transaction = {
amount: 10000 ,
currency: 'KES' ,
operator: 'safaricom' ,
accountNumber: '254701234567' ,
externalId: 'order_123' ,
reason: 'Product purchase' ,
};
try {
const result = await tingg . collection ( transaction );
console . log ( 'Payment initiated:' , result . data . transactionId );
} catch ( error ) {
console . error ( 'Payment failed:' , error . message );
}
getTransaction()
Retrieves the status of a transaction.
async getTransaction (
tx : string ,
environment ?: 'sandbox' | 'production' ,
fundkitApiKey ?: string
): Promise < TransactionResult >
Parameters
environment
'sandbox' | 'production'
default: "production"
Environment mode for the query
FundKit API key for sandbox routing
Returns
Transaction details including status, amount, and metadata
Example
try {
const transaction = await tingg . getTransaction ( 'tx_123456789' );
console . log ( 'Transaction status:' , transaction . data . status );
console . log ( 'Amount:' , transaction . data . amount );
} catch ( error ) {
console . error ( 'Failed to get transaction:' , error . message );
}
getCoverage()
Returns the coverage map for supported countries and currencies.
getCoverage (): CoverageMap
Returns
Coverage information including supported countries, currencies, and transaction limits
Example
const coverage = tingg . getCoverage ();
console . log ( 'Supported currencies:' , Object . keys ( coverage ));
console . log ( 'Kenya limits:' , coverage . KES );
Types
TinggCollectionRequest
interface TinggCollectionRequest {
charge_msisdn : string ;
charge_amount : number ;
country_code : string ;
currency_code : string ;
merchant_transaction_id : string ;
service_code : string ;
payment_mode_code : string ;
payment_option_code : string ;
}
TinggCollectionResponse
interface TinggCollectionResponse {
status : {
status_code : number ;
status_description : string ;
};
results : {
checkout_request_id : string ;
merchant_transaction_id : string ;
charge_request_id : number ;
payment_instructions : string ;
language_code : string ;
charge_msisdn : number ;
charge_amount : number ;
charge_request_date : string ;
};
}
TinggTransactionStatus
interface TinggTransactionStatus {
status : {
status_code : string ;
status_description : string ;
};
results : {
checkout_request_id : number ;
merchant_receipt : string ;
payments : Array <{
id : number ;
msisdn : number ;
payment_option_transaction_id : string ;
account_number : string ;
customer_name : string ;
amount_paid : number ;
gateway_transaction_id : string ;
date_payment_received : string ;
gateway_overall_status : number ;
currency_id : string ;
country_id : string ;
service_id : string ;
payer_narration : string ;
checkout_request_id : number ;
merchant_receipt : string ;
receiver_narration : string ;
date_payment_acknowledged : string ;
created_at : string ;
payment_option_id : number ;
}>;
};
}
Status Codes
Transaction Status Codes
Tingg uses specific status codes to indicate transaction states:
130 New Request - Transaction has been created and is waiting for customer action
178 Full Payment - Complete payment received and processed
183 Accepted - Payment received and acknowledged by merchant
188 Received - Payment received, awaiting merchant acknowledgment
99 Failed Payment - Payment failed but request remains open
129 Expired - Request expired with no payment received
179 Expired with Partial - Request expired with partial payments (will be reversed)
180 Rejected - Payment received but rejected by merchant
176 Partial Payment - Partial payment received and marked as closed
184 Refund Initiated - Partial refund initiated
185 Full Refund Initiated - Full refund initiated
186 Partial Refund Complete - Partial refund successfully processed
187 Full Refund Complete - Full refund successfully processed
191 Refund Expired - Refund request has expired
422 Invalid Request - Request contains invalid data
HTTP Status Codes
200 Success - Request processed successfully
400 Bad Request - Invalid request parameters
401 Unauthorized - Invalid or expired authentication
403 Forbidden - Access denied or insufficient permissions
404 Not Found - Resource not found
422 Unprocessable Entity - Request validation failed
500 Internal Server Error - Tingg system error
1001 No Request Found - Transaction ID not found
1007 Missing Country Code - Country code not provided
1013 Not JSON - Request body is not valid JSON
1014 Missing Transaction ID - Merchant transaction ID not provided
1015 Missing Checkout ID - Checkout request ID not provided
1017 Invalid Phone - Phone number format is invalid
1027 Invalid Amount - Amount outside allowed limits
Error Handling
TinggError Class
class TinggError extends Error {
code : string ;
status : number ;
details ?: any ;
provider : string ;
endpoint : string ;
}
Common Error Codes
TINGG_INSUFFICIENT_FUNDS - Customer account has insufficient balance
TINGG_CUSTOMER_CANCELLED - Customer declined the payment TINGG_PAYMENT_TIMEOUT -
Customer didn’t respond in time TINGG_INVALID_PIN - Customer entered incorrect PIN
TINGG_INVALID_PHONE - Phone number format is incorrect TINGG_PHONE_NOT_REGISTERED -
Phone not registered for mobile money TINGG_ACCOUNT_SUSPENDED - Customer account is
suspended TINGG_DAILY_LIMIT_EXCEEDED - Customer exceeded daily limits
TINGG_NETWORK_ERROR - Mobile network unavailable TINGG_SERVICE_UNAVAILABLE - Tingg
service temporarily down TINGG_RATE_LIMITED - Too many requests
TINGG_AUTHENTICATION_FAILED - Invalid API credentials
TINGG_SERVICE_CODE_REQUIRED - Service code not provided TINGG_PAYMENT_OPTION_REQUIRED -
Payment option code not provided TINGG_INVALID_SERVICE_CODE - Service code is invalid
TINGG_INVALID_PAYMENT_OPTION - Payment option code is invalid
Examples
Basic Payment Collection
import { Tingg } from '@fundkit/tingg' ;
const tingg = new Tingg ({
apiKey: process . env . TINGG_API_KEY ! ,
publicKey: process . env . TINGG_PUBLIC_KEY ! ,
serviceCode: process . env . TINGG_SERVICE_CODE ! ,
paymentOptionCode: 'SAFKE' , // Safaricom Kenya
});
const transaction = {
amount: 5000 ,
currency: 'KES' ,
operator: 'safaricom' ,
accountNumber: '254701234567' ,
externalId: 'order_12345' ,
reason: 'Product purchase' ,
};
try {
const result = await tingg . collection ( transaction );
console . log ( 'Payment initiated:' , result . data . transactionId );
} catch ( error ) {
console . error ( 'Payment failed:' , error . message );
}
Multi-Country Payment Processing
const countries = [
{ code: 'KE' , currency: 'KES' , operator: 'safaricom' , paymentOption: 'SAFKE' },
{ code: 'UG' , currency: 'UGX' , operator: 'mtn' , paymentOption: 'MTNUG' },
{ code: 'TZ' , currency: 'TZS' , operator: 'vodacom' , paymentOption: 'SAFTZ' },
];
async function processMultiCountryPayment ( country : any , amount : number , phone : string ) {
const tingg = new Tingg ({
apiKey: process . env . TINGG_API_KEY ! ,
publicKey: process . env . TINGG_PUBLIC_KEY ! ,
serviceCode: process . env . TINGG_SERVICE_CODE ! ,
paymentOptionCode: country . paymentOption ,
});
const transaction = {
amount: amount ,
currency: country . currency ,
operator: country . operator ,
accountNumber: phone ,
externalId: `payment_ ${ country . code } _ ${ Date . now () } ` ,
reason: `Payment for ${ country . code } ` ,
};
return await tingg . collection ( transaction );
}
Transaction Status Monitoring
async function monitorTransaction ( transactionId : string ) {
const tingg = new Tingg ({
apiKey: process . env . TINGG_API_KEY ! ,
publicKey: process . env . TINGG_PUBLIC_KEY ! ,
serviceCode: process . env . TINGG_SERVICE_CODE ! ,
paymentOptionCode: 'SAFKE' ,
});
const maxAttempts = 10 ;
const interval = 5000 ; // 5 seconds
for ( let attempt = 1 ; attempt <= maxAttempts ; attempt ++ ) {
try {
const transaction = await tingg . getTransaction ( transactionId );
const status = transaction . data . status ;
console . log ( `Attempt ${ attempt } : Status = ${ status } ` );
if ( status === 'SUCCESS' || status === 'FAILED' || status === 'EXPIRED' ) {
return transaction ;
}
if ( attempt < maxAttempts ) {
await new Promise ( resolve => setTimeout ( resolve , interval ));
}
} catch ( error ) {
console . error ( `Attempt ${ attempt } failed:` , error . message );
if ( attempt === maxAttempts ) throw error ;
}
}
throw new Error ( 'Transaction monitoring timeout' );
}
Error Handling with Retry Logic
async function collectionWithRetry ( transaction : Transaction , maxRetries : number = 3 ) {
const tingg = new Tingg ({
apiKey: process . env . TINGG_API_KEY ! ,
publicKey: process . env . TINGG_PUBLIC_KEY ! ,
serviceCode: process . env . TINGG_SERVICE_CODE ! ,
paymentOptionCode: 'SAFKE' ,
});
for ( let attempt = 1 ; attempt <= maxRetries ; attempt ++ ) {
try {
return await tingg . collection ( transaction );
} catch ( error ) {
console . error ( `Attempt ${ attempt } failed:` , error . message );
// Don't retry configuration errors
if (
error . code === 'TINGG_SERVICE_CODE_REQUIRED' ||
error . code === 'TINGG_PAYMENT_OPTION_REQUIRED'
) {
throw error ;
}
// Don't retry validation errors
if ( error . code === 'TINGG_INVALID_PHONE' || error . code === 'TINGG_INVALID_AMOUNT' ) {
throw error ;
}
if ( attempt === maxRetries ) {
throw error ;
}
// Wait before retry
await new Promise ( resolve => setTimeout ( resolve , 1000 * attempt ));
}
}
}