Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.tybritelabs.com/llms.txt

Use this file to discover all available pages before exploring further.

The PaymentsService class (accessed via client.payments) handles the core initialization and status verification for diverse payment providers including Stripe, Paystack, M-Pesa, and Airtel Money.

πŸ” Security & Signing (HMAC & Idempotency)

To prevent unauthorized payment initiation and duplicate charges, initializePayment requires both an HMAC-SHA256 signature and a mandatory Idempotency Key.

Signing & Idempotency Process

  1. Generate ID: Create a unique key for the transaction (e.g., payment-{order_id}-{timestamp}).
  2. Generate Timestamp: Get the current Unix timestamp in seconds.
  3. Prepare Payload: Concatenate timestamp and JSON body: timestamp + "." + JSON_body.
  4. Generate Signature: Compute HMAC-SHA256 signature using your HMAC Secret.
  5. Base64 Encode: The signature must be Base64 encoded.

Code Implementation (TypeScript)

import crypto from 'crypto';

// 1. Define Signing Helper
function generateHmacSignature(payload: string, secret: string): string {
  return crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('base64');
}

// 2. Prepare Data & Sign
const idempotencyKey = `payment-${orderId}-${Date.now()}`;
const timestamp = Math.floor(Date.now() / 1000);
const body = JSON.stringify(paymentData);
const payload = `${timestamp}.${body}`;
const signature = generateHmacSignature(payload, hmacSecret);

// 3. Initialize Payment
const response = await client.payments.initializePayment({
  idempotencyKey: idempotencyKey,
  xTimestamp: timestamp,
  xSignature: signature,
  requestBody: paymentData
});

// If response.idempotent is true, this was a duplicate request
Financial Integrity: Payment initialization triggers money movement. The Idempotency-Key prevents duplicate sessions and charges. Requests missing this header will return 400 missing_idempotency_key.

Methods

getPaymentMethods

Retrieve all active payment methods configured in your Tybrite Admin Panel. This endpoint accepts both publishable (pk_*) and secret (sk_*) API keys β€” storefronts can safely call it client-side to discover available providers before checkout.
const { methods } = await client.payments.getPaymentMethods({
  fields: 'provider,display_name,supported_currencies'
});

initializePayment

Create a payment session with your chosen provider. Requires a Secret Key, a valid HMAC signature, and a mandatory Idempotency-Key. On the first successful call this returns 201 Created; subsequent calls with the same idempotency key and identical payload return 200 OK with idempotent: true and the original session.
Secret Key required. initializePayment will reject publishable keys with 403. Never call this from untrusted client environments β€” keep your sk_* key and HMAC secret server-side.
const paymentData = {
  provider: 'stripe',
  amount: 5000,
  currency: 'USD',
  email: 'customer@email.com',
  success_url: 'https://store.com/thanks',
  cancel_url: 'https://store.com/checkout'
};

const timestamp = Math.floor(Date.now() / 1000);
const idempotencyKey = `pay-stripe-${Date.now()}`;
const signature = generateHmacSignature(`${timestamp}.${JSON.stringify(paymentData)}`, hmacSecret);

// HTTP 201 Created on first call; HTTP 200 OK with idempotent:true on replay
const response = await client.payments.initializePayment({
  idempotencyKey: idempotencyKey,
  xTimestamp: timestamp,
  xSignature: signature,
  requestBody: paymentData
});

// Example 201 response body
// {
//   "provider": "stripe",
//   "reference": "pi_3Q...",
//   "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_...",
//   "status": "pending",
//   "idempotent": false
// }

// Redirect to Stripe Checkout
window.location.href = (response as any).checkout_url;

verifyPayment

Retrieve the absolute source of truth for a transaction. This is a read operation and does not require HMAC signing.
Secret Key required. verifyPayment will reject publishable keys with 403. Verification responses include charge details (amounts, customer email, payment intents) and must not be exposed to untrusted clients.
const result = await client.payments.verifyPayment({
  requestBody: {
    provider: 'mpesa',
    reference: 'PAYMENT_REFERENCE_UUID'
  }
});

Response shape (per-provider oneOf)

The response shape depends on the provider field β€” the worker returns one of four variants:
{
  "provider": "stripe",
  "reference": "cs_test_a1b2c3...",
  "status": "success",
  "amount": 5000,
  "currency": "USD",
  "customer_email": "customer@email.com",
  "payment_intent": "pi_3Q...",
  "metadata": {
    "order_id": "ord_01HX..."
  }
}
Status semantics by provider:
  • Stripe β€” success when the session/intent is paid, otherwise the raw Stripe payment_status (unpaid, no_payment_required, etc.).
  • Paystack β€” Mirrors Paystack’s status field (success, failed, abandoned).
  • M-Pesa β€” Enum: pending | success | cancelled | failed. Result code 1032 (user cancelled on phone) maps to cancelled.
  • Airtel β€” Sourced from the payment_transaction_logs table. If no log row exists for the reference, the response is { "status": "not_found", "message": "..." } instead of the shape above.

Provider Support Matrix

ProviderBest ForRequirementVerification Method
StripeInternational CardsEmailSession Query
PaystackAfrican CardsEmailRef Verification
M-PesaKenyan Mobile MoneyPhone (254)STK Query
AirtelRegional Mobile MoneyPhone + CountryCollection Query

Formatting Tip: For African mobile money (M-Pesa/Airtel), always provide the phone number in international format without the + prefix (e.g., 2547...).

Response Codes

initializePayment

CodeMeaning
201Payment session created (new on first call with idempotency key).
200Idempotent replay β€” same key and identical payload, original initialization returned.
400Invalid request (missing provider/amount, invalid phone format for mpesa/airtel).
401Invalid API key, or invalid/expired HMAC signature (5-minute replay window).
403Publishable key supplied β€” initialize requires a secret key.
404order_id provided but no matching order exists.
429Rate limit exceeded (100 / hour per API key on initialize).
500Upstream provider error or worker configuration error.

verifyPayment

CodeMeaning
200Verification result returned. status field varies per provider β€” see shapes above.
400Invalid request, or provider returned a validation error.
401Invalid API key.
403Publishable key supplied β€” verify requires a secret key.
429Rate limit exceeded.
500Server error.

getPaymentMethods

CodeMeaning
200List of configured payment methods.
400Invalid fields parameter.
401Invalid API key.
429Rate limit exceeded.
500Server error.