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

@ariary/pay

v2.0.2

Published

Ariary Payment SDK (ariari.mg) — Accept mobile money payments in Madagascar. Create payment links, manage products, track payment status, handle webhooks. Supports MVola, Orange Money, Airtel Money. Multi-instance, TypeScript-first.

Downloads

1,161

Readme

@ariary/pay

Payment SDK for Madagascar mobile money via the Ariari API.

Server-side only — your secret must never be exposed in client-side code.

Install

yarn add @ariary/pay

Get your credentials

  1. Sign in at ariari.mg
  2. Create a project
  3. You'll receive a projectId and a secret

Setup

import Ariari from '@ariary/pay'

Ariari.config({
  projectId: 'your-project-id',
  secret: 'your-secret',
})

How it works

  1. Your server creates a payment with an amount (in Ariary)
  2. You redirect the end-user to the returned payment.url — a hosted page on ariari.mg
  3. The end-user sends money via mobile money to Ariary numbers and receives ticket codes
  4. The end-user enters their ticket codes on the payment page (or you collect them and call .pay() from your backend)
  5. A payment can be paid in multiple steps — each ticket code applied is a partial payment
  6. Once fully paid, your hooks are called and/or the user is redirected

Create a Payment

Ariari.create() accepts the following fields:

| Field | Type | Required | Description | |---|---|---|---| | amount | number | Yes (without productId) | Payment amount in Ariary | | productId | string | No | Product ID — resolves amount, name, imgUrl automatically | | name | string | No | Payment label shown on the payment page | | imgUrl | string | No | Image URL shown on the payment page | | hooks.redirectSuccess | string | No | URL the user is redirected to on success | | hooks.redirectFailure | string | No | URL the user is redirected to on failure | | hooks.silentSuccess | string | No | Webhook called when payment is fully completed | | hooks.silentProgress | string | No | Webhook called on each partial payment | | hooks.silentFailure | string | No | Webhook called on payment failure |

// with amount only
const payment = await Ariari.create({ amount: 5000 })
console.log(payment.url) // https://pay.ariari.mg/abc123encrypted

// with product (amount, name, imgUrl resolved automatically)
const payment = await Ariari.create({ productId: product.id })

// with product + override amount
const payment = await Ariari.create({ productId: product.id, amount: 3000 })

// with hooks
const payment = await Ariari.create({
  amount: 10000,
  name: 'T-shirt bleu',
  imgUrl: 'https://example.com/img.png',
  hooks: {
    redirectSuccess: 'https://yoursite.com/payment/success',
    redirectFailure: 'https://yoursite.com/payment/failure',
    silentSuccess: 'https://yoursite.com/api/webhook/payment-success',
    silentProgress: 'https://yoursite.com/api/webhook/payment-progress',
    silentFailure: 'https://yoursite.com/api/webhook/payment-failure',
  },
})

Hooks

redirect* hooks are browser-side redirects. After the user completes or fails on the payment page, their browser navigates to the given URL. Best suited when the payment page replaces the current page (same-tab navigation). If you open the payment page in a new tab (target="_blank"), redirect hooks have no effect on the parent page — use silent hooks instead.

silent* hooks are server-to-server webhooks called directly by the Ariari backend. They must be publicly accessible URLs with a valid domain name (e.g. https://yoursite.com/api/webhook). localhost or local IPs will not work — use a tunneling service like ngrok for development.

Both can be used together — e.g. redirect the user and notify your server at the same time.

Track a Payment

Ariari.create() returns a Payment object with two methods:

  • payment.status() — fetches the full payment details from the server (see the response table below)
  • payment.pay(ticketCode) — applies a ticket code from your backend (alternative to the payment page)
const payment = await Ariari.create({ amount: 5000 })

// fetch payment details
const info = await payment.status()
// info.status → the payment's current state (see below)
// info.rest   → remaining amount to pay
// info.parts  → list of partial payments applied so far

// apply a ticket code from your backend
const result = await payment.pay('Y-1234')

The status field

The info.status field (not to be confused with the .status() method) indicates the payment's current state:

| Value | Description | |---|---| | Status.PENDING | Payment created, no ticket code applied yet | | Status.INCOMPLETE | At least one ticket code applied, remaining amount > 0 | | Status.PAID | Fully paid | | Status.FAILED | Server-side error (should not happen under normal conditions) |

import { Status } from '@ariary/pay'

if (info.status === Status.PAID) { ... }

Retrieve an existing Payment

Store payment.id to retrieve it later with .getPayment(). Calling .status() returns the full payment details:

| Field | Type | Description | |---|---|---| | id | string | Payment ID | | amount | number | Total amount in Ariary | | rest | number | Remaining amount to pay | | productId | string? | Linked product ID | | name | string? | Payment label | | imgUrl | string? | Image URL | | status | Status | PENDING | INCOMPLETE | PAID | FAILED | | parts | PaymentPart[] | List of partial payments | | createdAt | string | Creation date | | updatedAt | string | Last update date | | url | string | Payment page URL |

const payment = await Ariari.create({ amount: 5000 })
const paymentId = payment.id // save this

// later
const payment = Ariari.getPayment(paymentId)
const info = await payment.status()

Products

A product is a reusable template so you don't have to send the same name, price, and imgUrl every time you create a payment. When you pass a productId to Ariari.create(), the product's data is automatically applied to the payment.

// create
const product = await Ariari.products.create({ name: 'Forfait Premium', price: 5000, imgUrl: 'https://example.com/img.png' })

// list all
const products = await Ariari.products.list()

// update
const updated = await Ariari.products.update(product.id, { name: 'Forfait Gold', price: 8000 })

// delete
await Ariari.products.delete(product.id)

Multiple instances

Use name to manage separate Ariari instances with different credentials. Ariari.config() returns the instance directly.

const shop = Ariari.config({
  name: 'shop',
  projectId: 'project-a',
  secret: 'secret-a',
})

const billing = Ariari.config({
  name: 'billing',
  projectId: 'project-b',
  secret: 'secret-b',
})

await shop.create({ amount: 5000 })
await billing.create({ productId: 'prod-123' })

You can also retrieve a named instance later with Ariari.get().

const shop = Ariari.get('shop')

Without name, the instance defaults to "main" and is used by static methods (Ariari.create, Ariari.products, Ariari.getPayment).