Code samples
Copy-paste starting points for common integration tasks. Replace placeholders with your credentials and business references.
Build the Authorization header
const crypto = require('crypto');
function lipachapAuthHeader(apiKey, apiSecret, requestPath, rawBody = '') {
const digest = crypto
.createHash('sha256')
.update(apiSecret + requestPath + rawBody)
.digest('hex');
const token = Buffer.from(`${apiKey}:${digest}`).toString('base64');
return `GATEWAY ${token}`;
}
// Example
const path = '/v1/walletcashin/process';
const body = JSON.stringify({
transid: 'TXN-001',
amount: 5000,
msisdn: '255712345678',
utilityref: 'ORDER-123',
utilitycode: 'VMCASHIN',
vendor: 'YOUR_VENDOR',
pin: '0000',
});
const authorization = lipachapAuthHeader(process.env.LIPACHAP_API_KEY, process.env.LIPACHAP_API_SECRET, path, body);import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import org.apache.commons.codec.digest.DigestUtils;
public final class LipachapAuth {
public static String authorizationHeader(String apiKey, String apiSecret, String path, String rawBody) {
String signed = apiSecret + path + (rawBody == null ? "" : rawBody);
String digest = DigestUtils.sha256Hex(signed);
String credentials = apiKey + ":" + digest;
return "GATEWAY " + Base64.getEncoder().encodeToString(credentials.getBytes(StandardCharsets.UTF_8));
}
}
// Usage
String path = "/v1/walletcashin/process";
String body = "{\"transid\":\"TXN-001\",\"amount\":5000,\"msisdn\":\"255712345678\"}";
String auth = LipachapAuth.authorizationHeader(apiKey, apiSecret, path, body);<?php
function lipachap_auth_header(string $apiKey, string $apiSecret, string $path, string $rawBody = ''): string {
$digest = hash('sha256', $apiSecret . $path . $rawBody);
$token = base64_encode($apiKey . ':' . $digest);
return 'GATEWAY ' . $token;
}
$path = '/v1/walletcashin/process';
$body = json_encode([
'transid' => 'TXN-001',
'amount' => 5000,
'msisdn' => '255712345678',
'utilityref' => 'ORDER-123',
], JSON_UNESCAPED_SLASHES);
$authorization = lipachap_auth_header(getenv('LIPACHAP_API_KEY'), getenv('LIPACHAP_API_SECRET'), $path, $body);import base64
import hashlib
import json
import os
def lipachap_auth_header(api_key: str, api_secret: str, path: str, raw_body: str = "") -> str:
digest = hashlib.sha256((api_secret + path + raw_body).encode("utf-8")).hexdigest()
token = base64.b64encode(f"{api_key}:{digest}".encode("utf-8")).decode("ascii")
return f"GATEWAY {token}"
path = "/v1/walletcashin/process"
body = json.dumps({
"transid": "TXN-001",
"amount": 5000,
"msisdn": "255712345678",
"utilityref": "ORDER-123",
"utilitycode": "VMCASHIN",
"vendor": "YOUR_VENDOR",
"pin": "0000",
}, separators=(",", ":"))
authorization = lipachap_auth_header(
os.environ["LIPACHAP_API_KEY"],
os.environ["LIPACHAP_API_SECRET"],
path,
body,
)package lipachap
import (
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"fmt"
)
func AuthHeader(apiKey, apiSecret, path, rawBody string) string {
sum := sha256.Sum256([]byte(apiSecret + path + rawBody))
digest := hex.EncodeToString(sum[:])
token := base64.StdEncoding.EncodeToString([]byte(apiKey + ":" + digest))
return "GATEWAY " + token
}
// Usage in a handler:
// path := "/v1/walletcashin/process"
// body := `{"transid":"TXN-001","amount":5000,"msisdn":"255712345678"}`
// req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))Collection (CASHIN)
const baseUrl = process.env.LIPACHAP_BASE_URL; // sandbox or live
const path = '/v1/walletcashin/process';
const body = JSON.stringify({
transid: 'TXN-' + Date.now(),
utilitycode: 'VMCASHIN',
utilityref: 'ORDER-123',
amount: 5000,
msisdn: '255712345678',
vendor: 'YOUR_VENDOR',
pin: '0000',
});
const res = await fetch(baseUrl + path, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
'X-Request-Id': crypto.randomUUID(),
},
body,
});
const data = await res.json();
// { resultcode: '000', result: 'SUCCESS', reference, transid, status, ... }String path = "/v1/walletcashin/process";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "TXN-" + System.currentTimeMillis());
payload.addProperty("utilitycode", "VMCASHIN");
payload.addProperty("utilityref", "ORDER-123");
payload.addProperty("amount", 5000);
payload.addProperty("msisdn", "255712345678");
payload.addProperty("vendor", "YOUR_VENDOR");
payload.addProperty("pin", "0000");
String body = payload.toString();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", LipachapAuth.authorizationHeader(apiKey, apiSecret, path, body));
ResponseEntity<String> response = restTemplate.exchange(
baseUrl + path, HttpMethod.POST, new HttpEntity<>(body, headers), String.class);$path = '/v1/walletcashin/process';
$payload = [
'transid' => 'TXN-' . time(),
'utilitycode' => 'VMCASHIN',
'utilityref' => 'ORDER-123',
'amount' => 5000,
'msisdn' => '255712345678',
'vendor' => 'YOUR_VENDOR',
'pin' => '0000',
];
$body = json_encode($payload, JSON_UNESCAPED_SLASHES);
$ch = curl_init(getenv('LIPACHAP_BASE_URL') . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: ' . lipachap_auth_header(getenv('LIPACHAP_API_KEY'), getenv('LIPACHAP_API_SECRET'), $path, $body),
],
]);
$response = curl_exec($ch);import requests
path = "/v1/walletcashin/process"
payload = {
"transid": f"TXN-{int(time.time())}",
"utilitycode": "VMCASHIN",
"utilityref": "ORDER-123",
"amount": 5000,
"msisdn": "255712345678",
"vendor": "YOUR_VENDOR",
"pin": "0000",
}
body = json.dumps(payload, separators=(",", ":"))
response = requests.post(
os.environ["LIPACHAP_BASE_URL"] + path,
data=body,
headers={
"Content-Type": "application/json",
"Authorization": lipachap_auth_header(api_key, api_secret, path, body),
},
timeout=30,
)
data = response.json()path := "/v1/walletcashin/process"
body := `{"transid":"TXN-001","utilitycode":"VMCASHIN","utilityref":"ORDER-123","amount":5000,"msisdn":"255712345678","vendor":"YOUR_VENDOR","pin":"0000"}`
req, _ := http.NewRequest(http.MethodPost, baseURL+path, strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()Disbursement (CASHOUT)
const path = '/v1/gateway/cashin';
const body = JSON.stringify({
transid: 'PAYOUT-' + Date.now(),
utilityref: 'DISB-456',
amount: 10000,
msisdn: '255712345678',
vendor: 'YOUR_VENDOR',
pin: '0000',
providerFee: 0,
platformFee: 150,
totalFee: 150,
totalCharged: 10150,
});
const res = await fetch(baseUrl + path, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
},
body,
});String path = "/v1/gateway/cashin";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "PAYOUT-" + System.currentTimeMillis());
payload.addProperty("utilityref", "DISB-456");
payload.addProperty("amount", 10000);
payload.addProperty("msisdn", "255712345678");
payload.addProperty("vendor", "YOUR_VENDOR");
payload.addProperty("pin", "0000");
payload.addProperty("providerFee", 0);
payload.addProperty("platformFee", 150);
payload.addProperty("totalFee", 150);
payload.addProperty("totalCharged", 10150);
String body = payload.toString();
// POST with Authorization header (same as cash-in)$path = '/v1/gateway/cashin';
$body = json_encode([
'transid' => 'PAYOUT-' . time(),
'utilityref' => 'DISB-456',
'amount' => 10000,
'msisdn' => '255712345678',
'vendor' => 'YOUR_VENDOR',
'pin' => '0000',
'providerFee' => 0,
'platformFee' => 150,
'totalFee' => 150,
'totalCharged' => 10150,
], JSON_UNESCAPED_SLASHES);path = "/v1/gateway/cashin"
body = json.dumps({
"transid": f"PAYOUT-{int(time.time())}",
"utilityref": "DISB-456",
"amount": 10000,
"msisdn": "255712345678",
"vendor": "YOUR_VENDOR",
"pin": "0000",
"providerFee": 0,
"platformFee": 150,
"totalFee": 150,
"totalCharged": 10150,
}, separators=(",", ":"))path := "/v1/gateway/cashin"
body := `{"transid":"PAYOUT-001","utilityref":"DISB-456","amount":10000,"msisdn":"255712345678","vendor":"YOUR_VENDOR","pin":"0000","totalCharged":10150}`
req.Header.Set("Authorization", AuthHeader(apiKey, apiSecret, path, body))Transaction status
const path = '/v1/checkout/status';
const body = JSON.stringify({ transid: 'TXN-001' });
const res = await fetch(baseUrl + path, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: lipachapAuthHeader(apiKey, apiSecret, path, body),
},
body,
});
const txn = await res.json();
// status: PENDING | SUCCESS | FAILEDString path = "/v1/checkout/status";
JsonObject payload = new JsonObject();
payload.addProperty("transid", "TXN-001");
String body = payload.toString();
// POST with signed Authorization header$path = '/v1/checkout/status';
$body = json_encode(['transid' => 'TXN-001'], JSON_UNESCAPED_SLASHES);path = "/v1/checkout/status"
body = json.dumps({"transid": "TXN-001"}, separators=(",", ":"))path := "/v1/checkout/status"
body := `{"transid":"TXN-001"}`Verify webhooks
const crypto = require('crypto');
function verifyWebhook(rawBody, timestamp, signature, secret, maxSkewSec = 300) {
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - Number(timestamp)) > maxSkewSec) return false;
const expected = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const received = signature.replace(/^sha256=/, '');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
}
// Express example
app.post('/webhooks/lipachap', express.raw({ type: 'application/json' }), (req, res) => {
const rawBody = req.body.toString('utf8');
const ok = verifyWebhook(
rawBody,
req.get('X-Gateway-Timestamp'),
req.get('X-Gateway-Signature'),
process.env.LIPACHAP_WEBHOOK_SECRET,
);
if (!ok) return res.sendStatus(401);
const event = JSON.parse(rawBody);
// event.transid, event.status, event.amount, ...
res.sendStatus(200);
});import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
public boolean verifyWebhook(String rawBody, String timestamp, String signature, String secret) {
String payload = timestamp + "." + rawBody;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
String expected = HexFormat.of().formatHex(mac.doFinal(payload.getBytes(StandardCharsets.UTF_8)));
String received = signature.replace("sha256=", "");
return MessageDigest.isEqual(expected.getBytes(), received.getBytes());
}function verify_lipachap_webhook(string $rawBody, string $timestamp, string $signature, string $secret): bool {
$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
$received = preg_replace('/^sha256=/', '', $signature);
return hash_equals($expected, $received);
}
$rawBody = file_get_contents('php://input');
$ok = verify_lipachap_webhook(
$rawBody,
$_SERVER['HTTP_X_GATEWAY_TIMESTAMP'] ?? '',
$_SERVER['HTTP_X_GATEWAY_SIGNATURE'] ?? '',
getenv('LIPACHAP_WEBHOOK_SECRET'),
);import hmac
import hashlib
import time
def verify_webhook(raw_body: bytes, timestamp: str, signature: str, secret: str, max_skew: int = 300) -> bool:
if abs(int(time.time()) - int(timestamp)) > max_skew:
return False
expected = hmac.new(secret.encode(), f"{timestamp}.{raw_body.decode()}".encode(), hashlib.sha256).hexdigest()
received = signature.removeprefix("sha256=")
return hmac.compare_digest(expected, received)func VerifyWebhook(rawBody []byte, timestamp, signature, secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(timestamp + "." + string(rawBody)))
expected := hex.EncodeToString(mac.Sum(nil))
received := strings.TrimPrefix(signature, "sha256=")
return hmac.Equal([]byte(expected), []byte(received))
}