npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dryinov8/zumbopay-ts

v1.0.2

Published

SDK TypeScript/JavaScript oficial e componentes React para o gateway ZumboPay em Moçambique (M-Pesa, e-Mola, mKesh e Cartões)

Downloads

519

Readme

@dryinov8/zumbopay-ts

NPM Version License: MIT TypeScript

SDK oficial em TypeScript / JavaScript e componentes React para integração do gateway de pagamentos ZumboPay em Moçambique.

Compatível com Node.js, Next.js (App Router & Pages), React, Vite, Remix e Express.


🚀 Funcionalidades

  • 🇲🇿 Suporte a Carteiras Móveis Moçambicanas:
    • Vodacom M-Pesa (prefixos 84, 85)
    • Movitel e-Mola (prefixos 86, 87)
    • Tmcel mKesh (prefixos 82, 83)
  • 💳 Cartões Bancários: Checkout hospedado com suporte a cartões Visa e Mastercard (nacionais e internacionais).
  • 🎛️ Interruptor Global / Kill-Switch (enabled: boolean): Ative ou silencie o gateway dinamicamente via código (enabled: false) ou variável de ambiente (ZUMBOPAY_ENABLED=false).
  • ⚛️ Componentes & Hooks React Prontos: Componente <ZumboPayModal /> acessível com abas e deteção visual de operadora, e hook useZumboPay().
  • 🛡️ Segurança & Webhooks: Validação criptográfica de assinaturas HMAC-SHA256 em tempo constante contra timing attacks.
  • 📦 Dual Build: Suporta módulos ESM (import) e CommonJS (require), com tipos TypeScript completos (.d.ts).

📦 Instalação

# npm
npm install @dryinov8/zumbopay-ts

# pnpm
pnpm add @dryinov8/zumbopay-ts

# yarn
yarn add @dryinov8/zumbopay-ts

(Se pretender utilizar os componentes React, certifique-se de que tem react e react-dom instalados no seu projeto).


⚙️ Configuração e Variáveis de Ambiente

Crie ou adicione ao seu ficheiro .env:

# Credenciais Principais
ZUMBOPAY_API_KEY=sua_chave_secreta_aqui
ZUMBOPAY_MERCHANT_ID=seu_merchant_id_aqui
ZUMBOPAY_WEBHOOK_SECRET=seu_webhook_secret_aqui

# Carteiras Pré-configuradas (UUIDs) - Opcional
# (Se deixar vazio, o SDK descobre automaticamente os UUIDs via GET /wallets)
ZUMBOPAY_WALLET_MPESA=uuid-carteira-mpesa
ZUMBOPAY_WALLET_EMOLA=uuid-carteira-emola
ZUMBOPAY_WALLET_MKESH=uuid-carteira-mkesh
ZUMBOPAY_WALLET_CARD=uuid-carteira-cartao

# Gatilho de silenciamento global / Kill-Switch (Opcional - padrão: true)
ZUMBOPAY_ENABLED=true

💼 Como Configurar e Passar as Carteiras (Wallets)

O zumbopay-ts oferece total flexibilidade para passar os UUIDs das suas carteiras do painel ZumboPay:

Forma 1: Automática via .env (Recomendado para Node.js / Next.js)

Basta definir as variáveis no .env como mostrado acima. O cliente lê-as automaticamente:

const zumboPay = new ZumboPayClient({
  apiKey: process.env.ZUMBOPAY_API_KEY!,
  merchantId: process.env.ZUMBOPAY_MERCHANT_ID!,
  // As carteiras MPESA, EMOLA, MKESH e CARD são lidas automaticamente do .env!
});

Forma 2: No Construtor do Cliente

Pode passar o objeto wallets explicitamente no código:

const zumboPay = new ZumboPayClient({
  apiKey: '...',
  merchantId: '...',
  wallets: {
    mpesa: 'd1a2b3c4-....', // UUID carteira Vodacom M-Pesa
    emola: 'e5f6a7b8-....', // UUID carteira Movitel e-Mola
    mkesh: 'c9d0e1f2-....', // UUID carteira Tmcel mKesh
    card:  'a3b4c5d6-....', // UUID carteira Cartão Bancário
  },
});

Forma 3: No Componente React (<ZumboPayModal />)

<ZumboPayModal
  isOpen={isOpen}
  onClose={() => setIsOpen(false)}
  config={{
    apiKey: 'pk_live_...',
    merchantId: 'mer_...',
    wallets: {
      mpesa: 'uuid-mpesa',
      emola: 'uuid-emola',
      mkesh: 'uuid-mkesh',
      card:  'uuid-card',
    },
  }}
  amount={1500}
/>

Forma 4: Por Transação Pontual (Sobrescrita Ad-hoc)

await zumboPay.stkPush({
  amount: 250,
  phone: '841234567',
  walletId: 'uuid-especifico-desta-transacao', // Força este UUID
});

Forma 5: Auto-descoberta Dinâmica

Se não passar nenhum UUID de carteira, o SDK consulta automaticamente a rota GET /wallets da sua conta ZumboPay e mapeia a carteira correta para M-Pesa, e-Mola, mKesh ou Cartão (com cache em memória de 10 minutos).


📖 Guia de Utilização Rápida

1. Iniciar STK Push (M-Pesa, e-Mola ou mKesh) no Backend

import { ZumboPayClient } from '@dryinov8/zumbopay-ts';

const zumboPay = new ZumboPayClient({
  apiKey: process.env.ZUMBOPAY_API_KEY!,
  merchantId: process.env.ZUMBOPAY_MERCHANT_ID!,
  // Ativação / Kill-Switch (lê automaticamente process.env.ZUMBOPAY_ENABLED)
  enabled: process.env.ZUMBOPAY_ENABLED !== 'false',
});

// Envia prompt STK para o telemóvel do cliente
const response = await zumboPay.stkPush({
  amount: 250.00,
  phone: '841234567', // Detecta automaticamente Vodacom M-Pesa
  reference: 'PROP-2026-001',
  customerName: 'Manuel Cossa',
  description: 'Pagamento de Propina Escolar',
});

if (response.success) {
  console.log('Status:', response.status); // 'pending' | 'success'
  console.log('Mensagem:', response.message);
} else {
  console.error('Falha:', response.message);
}

2. Criar Checkout Hospedado (Cartão Visa/Mastercard)

const checkout = await zumboPay.createCheckout({
  amount: 1500.00,
  title: 'Matrícula Anual',
  reference: 'MAT-2026-890',
  returnUrl: 'https://seu-sistema.ac.mz/pagamento/sucesso',
  cancelUrl: 'https://seu-sistema.ac.mz/pagamento/cancelado',
  channels: ['card', 'mpesa', 'emola', 'mkesh'],
});

if (checkout.success && checkout.checkoutUrl) {
  // Redirecionar o cliente para a página de pagamento
  console.log('URL de pagamento:', checkout.checkoutUrl);
}

3. Consultar Estado da Transação

const status = await zumboPay.getStatus('PROP-2026-001');

console.log('Está pago?', status.paid); // true | false
console.log('Estado:', status.status);   // 'success' | 'pending' | 'failed'

🎛️ Gatilho de Silenciamento / Kill-Switch

Pode desativar ou suspender o gateway a qualquer momento sem necessidade de alterar o código dos seus endpoints:

// 1. Via variável de ambiente:
// ZUMBOPAY_ENABLED=false

// 2. Via inicialização:
const client = new ZumboPayClient({
  apiKey: '...',
  merchantId: '...',
  enabled: false, // Silencia STK e checkouts
});

// 3. Via controlo dinâmico em tempo de execução:
client.setEnabled(false);

const res = await client.stkPush({ amount: 100, phone: '841234567' });
// Retorna imediatamente:
// { success: false, status: 'disabled', message: 'O gateway de pagamento ZumboPay está temporariamente desativado.' }
// Nenhuma chamada externa é feita!

⚛️ Utilização com React / Next.js

Importe o componente ou o hook através do submódulo zumbopay-ts/react:

Opção A: Modal Completo (<ZumboPayModal />)

import React, { useState } from 'react';
import { ZumboPayModal } from '@dryinov8/zumbopay-ts/react';

export function CheckoutButton() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button 
        onClick={() => setIsOpen(true)}
        className="px-4 py-2 bg-blue-600 text-white rounded-lg font-bold"
      >
        Pagar com ZumboPay
      </button>

      <ZumboPayModal
        isOpen={isOpen}
        onClose={() => setIsOpen(false)}
        config={{
          apiKey: 'pk_live_...',
          merchantId: 'mer_...',
          enabled: true,
        }}
        amount={1500}
        reference="PEDIDO-994"
        title="Inscrição em Exame"
        onPaymentSuccess={(payment) => {
          alert('Pagamento recebido com sucesso!');
          setIsOpen(false);
        }}
      />
    </>
  );
}

Opção B: Hook Personalizado (useZumboPay)

import { useZumboPay } from '@dryinov8/zumbopay-ts/react';

export function CustomPaymentForm() {
  const {
    phone,
    setPhone,
    operator,
    isLoading,
    status,
    errorMessage,
    initiateStk,
  } = useZumboPay({
    config: {
      apiKey: '...',
      merchantId: '...',
    },
    onSuccess: (res) => console.log('Sucesso!', res),
  });

  return (
    <div>
      <input
        type="tel"
        value={phone}
        onChange={(e) => setPhone(e.target.value)}
        placeholder="84 / 86 / 82..."
      />
      <span>Operadora detectada: {operator}</span>

      <button
        disabled={isLoading}
        onClick={() => initiateStk({ amount: 500 })}
      >
        {isLoading ? 'A processar...' : 'Pagar 500 MZN'}
      </button>

      {errorMessage && <p className="text-red-500">{errorMessage}</p>}
    </div>
  );
}

🔐 Validação de Webhook (Node.js / Express / Next.js)

Para garantir que as notificações de pagamento recebidas no seu servidor provêm legitimamente do ZumboPay:

Exemplo em Next.js (App Router: app/api/webhooks/zumbopay/route.ts)

import { NextRequest, NextResponse } from 'next/server';
import { verifyWebhookSignature } from '@dryinov8/zumbopay-ts';

export async function POST(req: NextRequest) {
  const rawBody = await req.text();
  const signature = req.headers.get('x-signature') || req.headers.get('x-zumbopay-signature') || '';
  const secret = process.env.ZUMBOPAY_WEBHOOK_SECRET!;

  // Validação criptográfica HMAC-SHA256
  const isValid = verifyWebhookSignature(rawBody, signature, secret);

  if (!isValid) {
    return NextResponse.json({ error: 'Assinatura inválida' }, { status: 401 });
  }

  const event = JSON.parse(rawBody);

  if (event.event === 'payment.succeeded') {
    const { reference, amount } = event.data;
    // Liquidar fatura na base de dados
  }

  return NextResponse.json({ received: true });
}

🛠️ Utilitários de Telefonia de Moçambique

import { normalizePhone, detectOperator, isValidMozPhone } from '@dryinov8/zumbopay-ts';

normalizePhone('+258 (84) 123-4567'); // '258841234567'
detectOperator('841234567');           // 'mpesa'
detectOperator('861234567');           // 'emola'
detectOperator('821234567');           // 'mkesh'
isValidMozPhone('841234567');          // true
isValidMozPhone('12345');              // false

🏷️ Versionamento e Política de Releases

Este projeto segue rigorosamente o padrão Semantic Versioning (SemVer):

  • MAJOR (X.0.0): Mudanças incompatíveis na API.
  • MINOR (0.X.0): Adição de novas funcionalidades retrocompatíveis (ex: novos canais ou carteiras).
  • PATCH (0.0.X): Correções de bugs e otimizações retrocompatíveis.

Consulte o histórico de alterações em CHANGELOG.md.


📄 Licença

Distribuído sob a licença MIT. Consulte LICENSE para mais detalhes.

Desenvolvido por Salvado Matavele.