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

verifyet-sdk

v1.2.2

Published

Verify Et JavaScript SDK for payment verification

Readme

Verify Et SDK

JavaScript SDK for integrating Verify Et payment verification into your website.

NPM: verifyet-sdk
CDN: https://unpkg.com/verifyet-sdk/dist/verifyet.min.js
API Docs: https://api.verifyet.com/docs
API Base URL: https://api.verifyet.com/api/v1

Installation

NPM

npm install verifyet-sdk

CDN

<script src="https://unpkg.com/verifyet-sdk/dist/verifyet.min.js"></script>

Quick Start

Checkout Flow (Recommended)

The checkout flow shows users your payment details, waits for them to pay, then verifies:

import { VerifyEt } from 'verifyet-sdk';

const verifyEt = new VerifyEt({
  apiKey: 'pk_live_your_key_here'
});

// Create checkout and redirect user
document.getElementById('pay-button').addEventListener('click', async () => {
  await verifyEt.checkout({
    amount: 1500,                    // Amount in ETB
    service: 'cbe',                  // 'cbe' or 'telebirr' (optional)
    returnUrl: 'https://yoursite.com/success',
    cancelUrl: 'https://yoursite.com/cancel'
  });
});

Verification Flow (For Already-Paid Transactions)

If the user already made a payment and you just need to verify:

import { VerifyEt } from 'verifyet-sdk';

const verifyEt = new VerifyEt({
  apiKey: 'pk_live_your_key_here'
});

// Open verification modal
document.getElementById('verify-button').addEventListener('click', async () => {
  try {
    const result = await verifyEt.verify({
      mode: 'modal',
      amount: 1500,  // Optional: verify specific amount
      onSuccess: async (result) => {
        // Send token to your server for confirmation
        const response = await fetch('/api/confirm-payment', {
          method: 'POST',
          body: JSON.stringify({ token: result.token })
        });
        
        if (response.ok) {
          window.location.href = '/thank-you';
        }
      },
      onError: (error) => {
        console.error('Verification failed:', error.message);
      }
    });
  } catch (error) {
    console.error('Verification cancelled or failed');
  }
});

Flows Explained

1. Checkout Flow (Pay-Then-Verify)

Best for: E-commerce, subscriptions, services

┌─────────────────────────────────────────────────────────────┐
│  1. User clicks "Pay Now"                                   │
│  2. SDK creates checkout session                            │
│  3. User redirected to verifyet.com/checkout                │
│     - Sees your account number & name                       │
│     - Sees amount to pay                                    │
│     - Countdown timer                                       │
│  4. User makes payment via their bank app                   │
│  5. User scans receipt on checkout page                     │
│  6. We verify payment went to YOUR account                  │
│  7. User redirected to your returnUrl with token            │
│  8. Your server confirms token                              │
└─────────────────────────────────────────────────────────────┘

2. Verification Flow (Already-Paid)

Best for: Invoice payments, manual transfers, remittances

┌─────────────────────────────────────────────────────────────┐
│  1. User already made a payment                             │
│  2. User clicks "Verify Payment"                            │
│  3. Modal opens with QR scanner / manual entry              │
│  4. User scans their receipt                                │
│  5. We verify transaction exists                            │
│  6. Your onSuccess callback receives token                  │
│  7. Your server confirms token                              │
└─────────────────────────────────────────────────────────────┘

Configuration

Initialize Options

import { VerifyEt } from 'verifyet-sdk';

const verifyEt = new VerifyEt({
  // Required
  apiKey: 'pk_live_...',
  
  // Optional
  baseUrl: 'https://api.verifyet.com/api/v1',  // Override API URL
  locale: 'en',       // 'en' | 'am' (Amharic)
  theme: 'dark',      // 'dark' | 'light'
  debug: false,       // Enable console logging
});

Checkout Options

await verifyEt.checkout({
  // Required
  amount: 1500,              // Amount in ETB
  
  // Optional
  service: 'cbe',            // 'cbe' | 'telebirr' | undefined (user choice)
  orderReference: 'ORD-123', // Your order ID
  description: 'Product X',  // What they're paying for
  expiresInMinutes: 15,      // Session timeout (default: 15)
  returnUrl: 'https://...',  // Success redirect
  cancelUrl: 'https://...',  // Cancel redirect
  metadata: { orderId: 123 }, // Custom data (returned in webhook)
  mode: 'redirect',          // 'redirect' | 'popup' | 'modal'
  
  // Modal mode callbacks (only used when mode: 'modal')
  onSuccess: (result) => {}, // { checkoutId, token, status }
  onCancel: () => {},        // User closed modal
  onError: (err) => {},      // { code, message }
});

Checkout Display Modes

| Mode | Description | Use Case | |------|-------------|----------| | redirect | Full page redirect to checkout (default) | Standard web checkout | | popup | Opens in new browser window | Desktop apps | | modal | Iframe overlay on your page | SPA apps, better UX |

Important: Modal mode requires allowed_origins to be configured during client registration. Only domains listed in allowed_origins can embed checkout in an iframe. This is a security feature to prevent unauthorized embedding.

Modal Mode Example:

await verifyEt.checkout({
  amount: 1500,
  mode: 'modal',
  onSuccess: (result) => {
    console.log('Payment verified!', result.token);
    // Send token to your server to confirm
  },
  onCancel: () => {
    console.log('User cancelled checkout');
  },
  onError: (error) => {
    console.error('Checkout error:', error.message);
  }
});

Verify Options

await verifyEt.verify({
  // Optional
  mode: 'modal',            // 'modal' | 'redirect' | 'inline'
  service: 'cbe',           // Pre-select service
  amount: 1500,             // Expected amount
  theme: 'dark',            // Override global theme
  locale: 'en',             // Override global locale
  returnUrl: 'https://...', // For redirect mode
  cancelUrl: 'https://...', // For redirect mode
  metadata: { ... },        // Custom data
  
  // Override global callbacks
  onSuccess: (result) => {},
  onCancel: () => {},
  onError: (error) => {},
});

Handling Results

Success Redirect (Checkout Flow)

After successful checkout, user is redirected to your returnUrl:

https://yoursite.com/success?checkout_id=chk_abc123&token=eyJ...&status=verified

Parse Redirect Parameters

// On your success page
const params = new URLSearchParams(window.location.search);
const checkoutId = params.get('checkout_id');
const token = params.get('token');
const status = params.get('status');

if (status === 'verified' && token) {
  // Confirm on your server
  confirmPayment(token);
}

Server-Side Confirmation (Required!)

Always confirm tokens on your server before fulfilling orders!

Node.js Example

const fetch = require('node-fetch');

async function confirmPayment(token) {
  const response = await fetch('https://api.verifyet.com/api/v1/verifications/confirm', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.VERIFYET_SECRET_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ token }),
  });
  
  const data = await response.json();
  
  if (data.success) {
    console.log('Payment verified!');
    console.log('Amount:', data.verification.amount);
    console.log('Payer:', data.verification.payer_name);
    console.log('Transaction ID:', data.verification.transaction_id);
    return data.verification;
  } else {
    throw new Error(data.error);
  }
}

Python Example

import requests
import os

def confirm_payment(token):
    response = requests.post(
        'https://api.verifyet.com/api/v1/verifications/confirm',
        headers={
            'Authorization': f'Bearer {os.environ["VERIFYET_SECRET_KEY"]}',
            'Content-Type': 'application/json'
        },
        json={'token': token}
    )
    
    data = response.json()
    
    if data.get('success'):
        print(f"Payment verified! Amount: {data['verification']['amount']}")
        return data['verification']
    else:
        raise Exception(data.get('error', 'Confirmation failed'))

PHP Example

<?php
function confirmPayment($token) {
    $ch = curl_init('https://api.verifyet.com/api/v1/verifications/confirm');
    
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . getenv('VERIFYET_SECRET_KEY'),
            'Content-Type: application/json'
        ],
        CURLOPT_POSTFIELDS => json_encode(['token' => $token])
    ]);
    
    $response = curl_exec($ch);
    curl_close($ch);
    
    $data = json_decode($response, true);
    
    if ($data['success']) {
        return $data['verification'];
    }
    
    throw new Exception($data['error'] ?? 'Confirmation failed');
}

Webhooks

Receive real-time notifications when payments are verified.

Webhook Payload

{
  "event": "verification.completed",
  "data": {
    "verification_id": "chk_abc123",
    "status": "verified",
    "transaction_id": "FT26028ABCDEF",
    "amount": 1500,
    "payer_name": "CUSTOMER NAME",
    "receiver_name": "YOUR BUSINESS",
    "service": "cbe",
    "metadata": { "orderId": "123" },
    "verified_at": 1706813800
  },
  "timestamp": 1706813801
}

Verify Webhook Signature

const crypto = require('crypto');

function verifyWebhook(payload, signature, webhookSecret) {
  const expected = crypto
    .createHmac('sha256', webhookSecret)
    .update(JSON.stringify(payload))
    .digest('hex');
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express middleware
app.post('/webhook', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  
  if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  
  const { event, data } = req.body;
  
  if (event === 'verification.completed') {
    // Process payment
    processOrder(data.metadata.orderId, data);
  }
  
  res.status(200).send('OK');
});

TypeScript Support

Full TypeScript support with exported types:

import { 
  VerifyEt, 
  VerifyEtConfig, 
  VerificationResult,
  TransactionInfo,
  VerifyEtError 
} from 'verifyet-sdk';

const config: VerifyEtConfig = {
  apiKey: 'pk_live_...',
  debug: true,
  locale: 'en',
  theme: 'dark'
};

const verifyEt = new VerifyEt(config);

// With type-safe callbacks
verifyEt.verify({
  mode: 'modal',
  onSuccess: (result: VerificationResult) => {
    console.log(result.token, result.amount);
  },
  onError: (error: VerifyEtError) => {
    console.error(error.code, error.message);
  }
});

Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 11+
  • Edge 79+

Security Best Practices

  1. Never expose your secret key in client-side code
  2. Always confirm tokens on your server before fulfilling orders
  3. Verify webhook signatures before processing
  4. Use HTTPS everywhere
  5. Implement idempotency to prevent double-processing

Troubleshooting

"Invalid API key" Error

  • Check that you're using a publishable key (pk_live_...)
  • Verify the key is correct and active
  • Secret keys (sk_live_...) should only be used server-side

Checkout Session Expired

  • Default expiry is 15 minutes
  • Increase expiresInMinutes if needed
  • User must complete payment before timer runs out

CORS Errors

  • SDK automatically handles CORS
  • If self-hosting, ensure your API allows your domain

Local Development (localhost)

When developing locally, the SDK uses /api/v1 as the base URL (expecting a proxy). You need to configure your dev server to proxy API requests to https://api.verifyet.com.

Vite (vite.config.js):

export default {
  server: {
    proxy: {
      '/api/v1': {
        target: 'https://api.verifyet.com',
        changeOrigin: true,
      }
    }
  }
}

Next.js (next.config.js):

module.exports = {
  async rewrites() {
    return [
      {
        source: '/api/v1/:path*',
        destination: 'https://api.verifyet.com/api/v1/:path*',
      },
    ];
  },
};

Alternative: Pass baseUrl explicitly to bypass auto-detection:

const verifyEt = new VerifyEt({
  apiKey: 'pk_live_...',
  baseUrl: 'https://api.verifyet.com/api/v1'
});

Popup Blocked

  • checkout({ mode: 'popup' }) may be blocked by browsers
  • SDK automatically falls back to redirect
  • Recommended: Use mode: 'modal' instead for a better UX that won't be blocked

Support

  • Documentation: https://docs.verifyet.com
  • Email: [email protected]
  • GitHub: https://github.com/verifyet/sdk