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

@paywallex/node

v1.3.0

Published

SDK serveur officiel de l'API Paywallex /v1 : sessions de paiement Mobile Money, remboursements, litiges, abonnements, webhooks signés.

Readme

@paywallex/node

SDK serveur officiel de l'API Paywallex /v1. Il sert à encaisser par Orange Money, MTN MoMo, Moov Money, Wave ou le solde Paywallex, à rembourser, à suivre les litiges et les abonnements, et à vérifier les webhooks signés.

Node 18 ou plus récent, Bun ou Deno. Aucune dépendance.

Côté serveur uniquement. Ne mettez jamais une clé secrète pwx_sk_… dans un navigateur ou une application mobile.

Installation

Installez le paquet :

npm install @paywallex/node

Créer une session de paiement

Le SDK ne lit pas PAYWALLEX_KEY tout seul. Passez votre clé explicitement à la création du client. Une clé pwx_sk_test_… vise le bac à sable, une clé pwx_sk_live_… vise la production.

Créez une session, puis redirigez le client vers session.url :

import { Paywallex } from "@paywallex/node";

const paywallex = new Paywallex({ apiKey: process.env.PAYWALLEX_KEY! });

const session = await paywallex.checkoutSessions.create({
  currency: "XOF",
  line_items: [
    { name: "Attiéké poisson", unit_amount: 2500, quantity: 2 },
    { name: "Jus de bissap", unit_amount: 500 },
  ],
  success_url: "https://maboutique.ci/merci",
  metadata: { order: "CMD-1042" },
});
// session.amount = 5500, session.url = page de paiement Paywallex

Les montants sont en XOF entiers : 2500 veut dire 2 500 F.

Facturation à l'usage

const plan = await paywallex.plans.create({ name: "Formule SMS", amount: 2000, currency: "XOF", interval: "monthly",
  usage: { mode: "metered", unit: "SMS", unit_amount: 5, cap: 10000 } });
await paywallex.subscriptions.reportUsage(subscriptionId, { quantity: 120 }, { idempotencyKey: "sms-2026-10-25" });
// 402 usage_cap_reached : l'abonné doit relever son plafond dans Paywallex.

Paiements partagés (plateformes)

Indiquez la part de chaque vendeur par son @identifiant : elle part sur son solde dès que l'argent de la vente est disponible chez vous. Vous gardez le reste, frais Paywallex déduits.

const session = await paywallex.checkoutSessions.create({
  currency: "XOF",
  amount: 20000,
  splits: [
    { destination: "@chezpapa", amount: 15000, description: "Commande 1042" },
    { destination: "@livraison-rapide", amount: 2000 },
  ],
});
// session.splits[0].status : "pending", puis "paid" (événement payment_split.paid)

Paywallex Elements (payer sur votre site)

Créez la session sur votre serveur, puis passez seulement client_secret à elements.js dans la page. Le client saisit son @identifiant ou scanne le QR, confirme sur son téléphone avec Face ID, et l'encadré passe à « Payé ». Sans l'app, il paie dans une fenêtre Paywallex.

const session = await paywallex.elementSessions.create({
  mode: "subscription",
  plan: planId,
  allowed_origins: ["https://boutique.ci"],
});
// Envoyez session.client_secret (pwx_es_…) à la page, jamais votre clé pwx_sk_…
<div id="paywallex"></div>
<script src="https://app.paywallex.app/elements.js"></script>
<script>
  Paywallex.elements(clientSecret).on("success", (e) => location.assign("/merci")).mount("#paywallex");
</script>

Confirmez toujours le résultat côté serveur : elementSessions.retrieve(id) (statut succeeded) ou le webhook de la vente (payment.succeeded, subscription.created).

Vérifier un webhook

Vérifiez la signature avant de traiter un événement. Le SDK compare en temps constant et refuse un horodatage de plus de 5 minutes.

Passez-lui le corps brut de la requête, pas un objet déjà lu par votre framework :

import express from "express";
import { Paywallex } from "@paywallex/node";

const app = express();
app.post("/webhooks/paywallex", express.raw({ type: "application/json" }), (req, res) => {
  try {
    const event = Paywallex.constructEvent(req.body, req.get("Paywallex-Signature"), process.env.PAYWALLEX_WEBHOOK_SECRET!);
    if (event.type === "checkout_session.completed") { /* livrer la commande */ }
    res.sendStatus(200);
  } catch {
    res.sendStatus(400);
  }
});

Les webhooks partent des plages 74.220.51.0/24 et 74.220.59.0/24 (liste à jour : GET /api/developer/webhook-ips). Ces plages sont partagées : la signature reste la seule preuve.

Les erreurs

Chaque erreur est une PaywallexError avec un code stable. Testez le code, jamais le message :

import { PaywallexError } from "@paywallex/node";

try {
  await paywallex.refunds.create({ payment: "…", amount: 1000 });
} catch (e) {
  if (e instanceof PaywallexError && e.code === "refund_not_eligible") { /* … */ }
  console.log(e.status, e.code, e.param, e.requestId);
}

Passez language: "en" au client pour recevoir les messages en anglais.

Nouvelles tentatives et idempotence

Le SDK réessaie 2 fois en cas de coupure réseau, de 429 ou d'erreur 5xx, en respectant Retry-After. Chaque POST garde la même clé d'idempotence d'une tentative à l'autre : un paiement ou un remboursement n'est jamais doublé.

Pour rejouer vous-même une requête sans risque, donnez votre propre clé :

await paywallex.refunds.create({ payment: "…" }, { idempotencyKey: `remboursement-${order.id}` });

Ce que couvre le SDK

| Objet | Méthodes | | --- | --- | | checkoutSessions | create, retrieve | | payments | list, retrieve, all (toutes les pages) | | refunds | create, list, retrieve, all | | disputes | list, retrieve, all, addEvidence | | files | upload (justificatifs PDF, PNG, JPEG de 5 Mo au plus) | | payouts, events, statements | list, retrieve (statements.csv) | | customers, paymentLinks, invoices, pots | list, create, retrieve, update, action | | plans, coupons, subscriptions | création, lecture, cancel, pause, resume, changePlan, manageLink, reportUsage, usage | | elementSessions | create, retrieve, cancel (Paywallex Elements) | | webhookEndpoints | list, create, del, rotateSecret | | client | account(), balance(), networkStatus() |

Accepter un litige (rembourser) ou le contester se fait dans le portail Paywallex, jamais par l'API. Un abonnement ou une hausse de prix est toujours accepté par le client dans Paywallex.

Licence

MIT.