- Overview
- Installation
- Quick Start
- Core Methods
- API Reference
- Digital Services (Missions)
- Bank Integration (CIB)
- Real-time Transaction Streaming
- Response Format
- Security Best Practices
- Use Cases
- Support
The SofizPay JS SDK is a full-featured library for integrating DZT digital payments into any JavaScript environment β Node.js, React, Vue, or plain Browser. It provides a clean async API for on-chain Stellar payments, exhaustive transaction history, CIB bank deposits, and digital service recharges (Missions).
Key Benefits:
- β‘
async/awaitAPI β no callback hell - π Works in Node.js, React, Vue, and browsers (CDN)
- π Exhaustive 24-transaction history (Path Payments, Trustlines, Account Creation)
- π΄ Real-time transaction streaming with configurable intervals
- π¦ CIB/Dahabia bank deposit links
- π± Phone, Internet & Game recharges (Mission APIs)
npm install sofizpay-sdk-js
# or
yarn add sofizpay-sdk-jsLoad the following scripts in order before the SDK:
<script src="https://unpkg.com/[email protected]/dist/stellar-sdk.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>
<script src="https://unpkg.com/sofizpay-sdk-js@latest/dist/sofizpay-sdk.umd.js"></script>import SofizPaySDK from 'sofizpay-sdk-js';
const sdk = new SofizPaySDK();
// 1. Check DZT balance
const balance = await sdk.getBalance('YOUR_PUBLIC_KEY');
if (balance.success) {
console.log(`π° Balance: ${balance.balance} DZT`);
}
// 2. Send a DZT payment
const result = await sdk.submit({
secretkey: 'YOUR_SECRET_KEY',
destinationPublicKey: 'RECIPIENT_PUBLIC_KEY',
amount: 100,
memo: 'Invoice #1234'
});
if (result.success) {
console.log(`β
Payment sent! TX: ${result.transactionId}`);
} else {
console.error(`β Failed: ${result.error}`);
}Returns the current DZT balance for a given Stellar account.
const result = await sdk.getBalance('GCAZI...YOUR_PUBLIC_KEY');
// Response
{
success: true,
balance: '1500.0000000',
publicKey: 'GCAZI...',
asset_code: 'DZT',
asset_issuer: 'GCAZI7YBLIDJWIVEL7ETNAZGPP3LC24NO6KAOBWZHUERXQ7M5BC52DLV',
timestamp: '2025-07-28T10:30:00.000Z'
}Submits a DZT payment to the Stellar network.
const result = await sdk.submit({
secretkey: 'SXXX...YOUR_SECRET', // 56-char Stellar seed starting with 'S'
destinationPublicKey: 'GXXX...RECIPIENT', // Recipient's public key
amount: 250.50, // Amount in DZT
memo: 'Order #5567' // Optional memo (max 28 chars)
});
// Success Response
{
success: true,
transactionId: 'abc123...hash',
transactionHash: 'abc123...hash',
amount: '250.50',
memo: 'Order #5567',
destinationPublicKey: 'GXXX...',
timestamp: '2025-07-28T10:30:00.000Z'
}
β οΈ Memo Truncation: Memos longer than 28 characters are automatically truncated.
Fetches exhaustive transaction history via the Stellar /operations?join=transactions endpoint. This ensures that all four operation types are captured.
const history = await sdk.getTransactions('YOUR_PUBLIC_KEY', 100);
if (history.success) {
history.transactions.forEach(tx => {
console.log(`[${tx.timestamp}] ${tx.type.toUpperCase()} β ${tx.amount} ${tx.asset_code || 'DZT'}`);
});
}
// Each transaction object:
{
id: 'transaction_hash',
hash: 'transaction_hash',
type: 'sent' | 'received' | 'trustline' | 'account_created',
amount: '100.0000000',
from: 'GXXX...sender',
to: 'GXXX...recipient',
asset_code: 'DZT',
memo: 'Payment memo',
timestamp: '2025-07-28T10:30:00.000Z',
successful: true
}Captured transaction types:
| Type | Description |
|---|---|
sent |
DZT payment sent from this account |
received |
DZT payment received by this account |
trustline |
DZT trustline created (account activation) |
account_created |
Account creation / initial funding |
Derives the Stellar public key from a secret key without making any network calls.
const result = await sdk.getPublicKey('SXXX...YOUR_SECRET_KEY');
if (result.success) {
console.log('Public key:', result.publicKey);
}Performs a case-insensitive substring search over a user's recent transactions.
const results = await sdk.searchTransactionsByMemo('YOUR_PUBLIC_KEY', 'Order #12345', 10);
if (results.success) {
console.log(`Found ${results.transactions.length} matching transactions`);
}Fetches a single transaction object by its hash.
const tx = await sdk.getTransactionByHash('abc123...hash');
if (tx.success && tx.found) {
console.log('Amount:', tx.transaction.amount);
} else {
console.log('Transaction not found');
}| Method | Parameters | Returns | Description |
|---|---|---|---|
submit(data) |
{secretkey, destinationPublicKey, amount, memo?} |
PaymentResult |
Submit DZT payment |
getBalance(publicKey) |
string |
BalanceResult |
Get DZT balance |
getPublicKey(secretKey) |
string |
PublicKeyResult |
Derive public key from secret |
getTransactions(publicKey, limit?) |
string, number |
TransactionsResult |
Full transaction history |
getTransactionByHash(hash) |
string |
TransactionResult |
Find specific transaction |
searchTransactionsByMemo(publicKey, memo, limit?) |
string, string, number |
TransactionsResult |
Search by memo |
startTransactionStream(publicKey, callback, fromNow?, interval?) |
See streaming section | StreamResult |
Start real-time monitoring |
stopTransactionStream(publicKey) |
string |
StreamResult |
Stop monitoring |
getStreamStatus(publicKey) |
string |
StreamStatusResult |
Check stream status |
makeCIBTransaction(data) |
See CIB section | CIBResult |
Create bank payment link |
checkCIBStatus(orderNumber) |
string |
ServiceResult |
Check CIB order status |
rechargePhone(data) |
{encrypted_sk, phone, operator, amount, offer} |
ServiceResult |
Phone recharge |
rechargeInternet(data) |
{encrypted_sk, phone, amount, offer} |
ServiceResult |
Internet recharge |
rechargeGame(data) |
{encrypted_sk, operator, playerId, amount, offer} |
ServiceResult |
Game top-up |
payBill(data) |
{encrypted_sk, operator, bill_id, amount} |
ServiceResult |
Bill payment |
getProducts(encSk?) |
string? |
ServiceResult |
List available products |
getOperationHistory(encSk, limit, offset) |
string, number, number |
ServiceResult |
Mission history |
getOperationDetails(id, encSk) |
string, string |
ServiceResult |
Single operation details |
Mission APIs let your users spend DZT on real-world digital services. All Mission calls require the user's encrypted_sk (not the raw secret key).
const result = await sdk.rechargePhone({
encrypted_sk: 'USER_ENCRYPTED_SECRET_KEY',
phone: '0661000000',
operator: 'Mobilis', // 'Mobilis' | 'Djezzy' | 'Ooredoo'
amount: '100',
offer: 'Top' // e.g., 'Top', 'Pix', etc.
});
if (result.success) {
console.log('β
Phone recharged!', result.data);
} else {
console.error('β Recharge failed:', result.error);
}const result = await sdk.rechargeInternet({
encrypted_sk: 'USER_ENCRYPTED_SECRET_KEY',
phone: '0661000000',
operator: 'idoom', // e.g., 'idoom'
amount: '2000',
offer: 'adsl' // e.g., 'adsl', '4g', etc.
});const result = await sdk.rechargeGame({
encrypted_sk: 'USER_ENCRYPTED_SECRET_KEY',
operator: 'freefire', // e.g., 'freefire', 'pubg'
playerId: '123456789',
amount: '500', // 'amount' from getProducts()
offer: 'diamonds' // 'name' from getProducts()
});const result = await sdk.payBill({
encrypted_sk: 'USER_ENCRYPTED_SECRET_KEY',
operator: 'sonelgaz', // e.g., 'sonelgaz', 'ade'
bill_id: 'BILL_999',
amount: '1500'
});Fetches the list of available services, operators, and their associated offers (products).
const products = await sdk.getProducts();
if (products.success) {
// Use products.data to populate Missions 'offer' and 'amount'
console.log('Available services:', products.data);
}Tip
Each product in the data array usually contains name and amount. When calling recharge methods, use the product's name for the offer field and the product's amount for the amount field.
// Recent operations (paginated)
const history = await sdk.getOperationHistory('USER_ENCRYPTED_SK', 10, 0);
if (history.success) {
console.log('Last 10 operations:', history.data);
}
// Details of a specific operation
const details = await sdk.getOperationDetails('OPERATION_ID', 'USER_ENCRYPTED_SK');Generate a secure Dahabia/CIB bank payment link. The user is redirected to a hosted payment page.
const result = await sdk.makeCIBTransaction({
account: 'YOUR_STELLAR_PUBLIC_KEY', // Your SofizPay account
amount: 2500, // Amount in DZT
full_name: 'Ahmed Benali',
phone: '0661234567',
email: '[email protected]',
memo: 'Order #789', // Optional
return_url: 'https://yoursite.com/callback', // Optional redirect
redirect: 'no' // 'yes' for auto-redirect
});
if (result.success) {
// Redirect user to payment page
window.location.href = result.url;
}To monitor the progress of a CIB/Dahabia payment, use the cib_transaction_id returned in the data of the makeCIBTransaction response.
// result is the object from makeCIBTransaction()
const cibId = result.data.cib_transaction_id;
const status = await sdk.checkCIBStatus(cibId);
if (status.success) {
console.log('Payment status:', status.data.status);
}For maximum security, never expose the cib_transaction_id (order_number) to the client-side. Always store it in your database and verify the status server-side.
// 1. Merchant backend starts transaction
const result = await sdk.makeCIBTransaction({
account: 'YOUR_PUBLIC_KEY',
amount: 5000,
memo: 'Order #9921'
});
if (result.success) {
const cibId = result.data.cib_transaction_id;
// β
SAVE to database linked to Order #9921
await db.orders.update({ id: 9921 }, { cib_transaction_id: cibId });
// Send user to payment URL
const url = result.data.payment_url;
}
// 2. Later, when checking status, fetch from database
const order = await db.orders.findOne({ id: 9921 });
const status = await sdk.checkCIBStatus(order.cib_transaction_id);
if (status.success && status.data.status === 'success') {
// β
Mark order as PAID in your database
}Monitor an account for new incoming/outgoing transactions in real-time using polling.
| Parameter | Type | Default | Description |
|---|---|---|---|
publicKey |
string |
required | Stellar account to monitor |
callback |
function |
required | Called on each new transaction |
fromNow |
boolean |
true |
true: only future txs; false: load history first, then monitor |
checkInterval |
number |
30 |
Polling interval in seconds (5β300) |
// Monitor only new transactions (live feed)
await sdk.startTransactionStream(
'YOUR_PUBLIC_KEY',
(tx) => {
console.log(`New ${tx.type}: ${tx.amount} DZT β memo: ${tx.memo}`);
},
true, // fromNow
15 // check every 15 seconds
);
// Load full history first, then monitor new transactions
await sdk.startTransactionStream(
'YOUR_PUBLIC_KEY',
(tx) => {
if (tx.isHistorical) {
console.log('Historical:', tx);
} else {
console.log('Live:', tx);
}
},
false, // fromNow = false β load history first
30
);
// Check stream is active
const status = await sdk.getStreamStatus('YOUR_PUBLIC_KEY');
console.log('Active:', status.isActive);
// Stop monitoring
await sdk.stopTransactionStream('YOUR_PUBLIC_KEY');All methods return a uniform object with a success flag:
// β
Success
{
success: true,
// ... method-specific fields
timestamp: '2025-07-28T10:30:00.000Z'
}
// β Failure
{
success: false,
error: 'Human-readable error description',
timestamp: '2025-07-28T10:30:00.000Z'
}Always guard with if (result.success) before accessing data fields.
| Rule | Why |
|---|---|
| β Never expose secret keys client-side | Frontend code is visible to all users |
| β Use environment variables | process.env.SECRET_KEY β never hardcode |
β
Keep encrypted_sk server-side |
Protects Mission API access |
| β Use HTTPS only | Ensure all network calls are encrypted |
// β
Correct β environment variable
const result = await sdk.submit({
secretkey: process.env.SOFIZPAY_SECRET_KEY,
...
});
// β Never do this
const result = await sdk.submit({
secretkey: 'SXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
...
});// Process a customer's order payment
async function chargeOrder(orderId, customerKey, amount) {
const result = await sdk.submit({
secretkey: process.env.STORE_SECRET_KEY,
destinationPublicKey: customerKey,
amount: amount,
memo: `Order #${orderId}`
});
if (result.success) {
await db.updateOrderStatus(orderId, 'paid', result.transactionHash);
}
return result;
}import { useState, useEffect } from 'react';
import SofizPaySDK from 'sofizpay-sdk-js';
const sdk = new SofizPaySDK();
export function Wallet({ publicKey }) {
const [balance, setBalance] = useState('--');
useEffect(() => {
sdk.getBalance(publicKey).then(r => {
if (r.success) setBalance(r.balance);
});
}, [publicKey]);
return (
<div className="wallet-card">
<h3>π° {balance} DZT</h3>
</div>
);
}// Alert users when they receive a payment
await sdk.startTransactionStream(userPublicKey, (tx) => {
if (tx.type === 'received') {
sendPushNotification(userId, `You received ${tx.amount} DZT!`);
}
}, true, 10);- π Website: SofizPay.com
- π Full Docs: GitHub Repository
- π Bug Reports: Open an Issue
- π¬ Discussions: Community Forum
MIT Β© SofizPay Team
Built with β€οΈ for JavaScript developers | Version 1.1.11
