Skip to content

Kenandarabeh/sofizpay-sdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

27 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SofizPay Logo

SofizPay JavaScript SDK

The official JavaScript/TypeScript SDK for secure digital payments on the SofizPay platform.

npm version License: MIT Node.js


πŸ“‹ Table of Contents


🌟 Overview

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/await API β€” 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)

πŸ“¦ Installation

npm / yarn

npm install sofizpay-sdk-js
# or
yarn add sofizpay-sdk-js

Browser (CDN)

Load 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>

πŸš€ Quick Start

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}`);
}

πŸ”§ Core Methods

getBalance(publicKey)

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'
}

submit(data)

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.


getTransactions(publicKey, limit)

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

getPublicKey(secretKey)

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);
}

searchTransactionsByMemo(publicKey, memo, limit)

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`);
}

getTransactionByHash(hash)

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');
}

πŸ“š API Reference

Full Method Table

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

πŸ“± Digital Services (Missions)

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).

Phone Recharge

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);
}

Internet Recharge (Idoom 4G)

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.
});

Game Top-up (FreeFire, PUBG)

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()
});

Bill Payment

const result = await sdk.payBill({
  encrypted_sk: 'USER_ENCRYPTED_SECRET_KEY',
  operator:     'sonelgaz', // e.g., 'sonelgaz', 'ade'
  bill_id:      'BILL_999',
  amount:       '1500'
});

Get Available Products

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.

Operation History & Details

// 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');

🏦 Bank Integration (CIB)

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;
}

Check CIB Status

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);
}

πŸ’‘ Best Practice: Secure Order Flow

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
}

πŸ”΄ Real-time Transaction Streaming

Monitor an account for new incoming/outgoing transactions in real-time using polling.

startTransactionStream(publicKey, callback, fromNow?, checkInterval?)

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');

πŸ“€ Response Format

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.


πŸ›‘οΈ Security Best Practices

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',
  ...
});

πŸ’‘ Use Cases

E-commerce / Online Store

// 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;
}

React Wallet Component

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>
  );
}

Real-time Notification System

// 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);

πŸ“ž Support


License

MIT Β© SofizPay Team


Built with ❀️ for JavaScript developers | Version 1.1.11

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors