@ariary/pay

中文文档
2.2.0发布于 2026/03/25ISCTypeScriptESM + CJS零依赖近 30 天下载 2606

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.

原始使用文档
文档目录11 节
  1. Install
  2. Get your credentials
  3. Setup
  4. How it works
  5. Create a Payment
  6. Hooks
  7. Track a Payment
  8. The status field
  9. Retrieve an existing Payment
  10. Products
  11. Multiple instances

@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 secret

Setup

import Ariari from '@ariary/pay'

Ariari.config({
  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:

FieldTypeRequiredDescription
amountnumberYes (without productId)Payment amount in Ariary
productIdstringNoProduct ID — resolves amount, name, imgUrl automatically
namestringNoPayment label shown on the payment page
imgUrlstringNoImage URL shown on the payment page
hooks.redirectSuccessstringNoURL the user is redirected to on success
hooks.redirectFailurestringNoURL the user is redirected to on failure
hooks.silentSuccessstringNoWebhook called when payment is fully completed
hooks.silentProgressstringNoWebhook called on each partial payment
hooks.silentFailurestringNoWebhook 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:

ValueDescription
Status.PENDINGPayment created, no ticket code applied yet
Status.INCOMPLETEAt least one ticket code applied, remaining amount > 0
Status.PAIDFully paid
Status.FAILEDServer-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:

FieldTypeDescription
idstringPayment ID
amountnumberTotal amount in Ariary
restnumberRemaining amount to pay
productIdstring?Linked product ID
namestring?Payment label
imgUrlstring?Image URL
statusStatusPENDING | INCOMPLETE | PAID | FAILED
partsPaymentPart[]List of partial payments
createdAtstringCreation date
updatedAtstringLast update date
urlstringPayment 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',
  secret: 'secret-a',
})

const billing = Ariari.config({
  name: 'billing',
  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).

版本与发布记录

@ariary/pay 共发布 14 个版本,首次发布于 2026/02/23;过去 12 个月发布了 14 个版本。

版本发布日期距今
2.2.0latest2026/03/257 个月前
2.1.02026/03/247 个月前
2.0.22026/03/058 个月前
2.0.12026/03/058 个月前
2.0.02026/02/288 个月前
1.0.82026/02/278 个月前

关于 @ariary/pay 的常见问题

@ariary/pay 是什么?

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.

如何安装 @ariary/pay?

在项目目录运行 npm install @ariary/pay,或使用 pnpm add / yarn add / bun add。

@ariary/pay 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ariary/pay 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@ariary/pay 可以商用吗?

@ariary/pay 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@ariary/pay 的下载量有多少?

根据 npm 官方下载统计,@ariary/pay 在 2026/10/07 – 2026/11/05 这 30 天内被下载 2,606 次,日均约 87 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ariary/pay 还在维护吗?

最新版本 2.2.0 发布于 2026/03/25(7 个月前);至今共发布 14 个版本,其中过去 12 个月发布了 14 个;首次发布于 2026/02/23。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。