@avepay/mcf
v0.1.0
Published
SDK officiel AvePay MCF — certification fiscale (DGI Burkina Faso / SECEF)
Downloads
156
Readme
@avepay/mcf
SDK officiel JavaScript / TypeScript pour l'API AvePay MCF — certification fiscale DGI Burkina Faso / SECEF.
- Client HTTP fin et typé au-dessus de
https://api-mcf-orchestrator.toolsite.io. - Payload friendly (noms lisibles, calculs auto) avec échappatoire brute.
- ESM + CJS, types inclus. Node 18+ (fetch natif).
Installation
npm install @avepay/mcfQuickstart
import { AvePay } from "@avepay/mcf";
const avepay = new AvePay({ apiKey: process.env.AVEPAY_API_KEY!, isf: "1" });
const mcf = avepay.mcf("EL02000015-1");
const receipt = await mcf.certify({
number: "FV-2026-0001",
type: "FV", // FV | FT | EV | ET (défaut FV)
operator: { id: 1, name: "Awa" },
customer: { type: "PP", name: "Client Comptant" },
items: [
{ name: "Riz 25kg", taxGroup: "B", unitPrice: 15000, quantity: 1 },
],
payments: [{ method: "cash", amount: 15000 }],
});
console.log(receipt.sig); // signature SECEF (codeSecef)
console.log(receipt.qr); // contenu QR
console.log(receipt.totalTtc); // 15000
console.log(receipt.counters); // { tc, fvc, frc }Mapping friendly → brut
Le SDK construit le body brut attendu par l'API :
number→invoiceNumber,type→invoiceType,operator:{id,name}→operatorId/operatorName.- items :
amountTtccalculé (unitPrice * quantity),taxRatedéduit dutaxGroup(A = 0 %, B = 18 %). Pour un groupe inconnu (C..N), fournirtaxRateexplicitement. - payments : alias
cash→E,transfer→V,card→C,mobile→M,cheque→B,other→A(les codes bruts sont aussi acceptés). priceModedéfautTTC,isfdéfaut au niveau client.
Tout champ brut fourni (ex. invoiceType, clientType) prime sur l'alias friendly.
Avoir (credit note)
const avoir = await mcf.creditNote({
number: "FA-2026-0001",
from: receipt, // dérive creditNoteRef = `${nim}-${fvc}`
// ou: creditNoteRef: "EL02000015-1-291",
creditNoteNature: "COR", // COR | RAN | RAM | RRR (défaut COR)
operator: { id: 1, name: "Awa" },
customer: { type: "PP" },
items: [{ name: "Riz 25kg", taxGroup: "B", unitPrice: 15000 }],
payments: [{ method: "cash", amount: 15000 }],
});Info / cancel-pending / me
const info = await mcf.info(); // mode, compteurs, marchand
await mcf.cancelPending(); // annule une transaction 38h pendante
const me = await avepay.me(); // org + NIM scopés + état bridgesGestion d'erreurs
import { AvePayError } from "@avepay/mcf";
try {
await mcf.certify(invoice);
} catch (e) {
if (e instanceof AvePayError) {
console.error(e.code, e.httpStatus, e.message, e.requestId);
if (e.isBridgeOffline) {/* MCF hors ligne — réessayer plus tard */}
}
}Codes : INVALID_API_KEY/UNAUTHENTICATED (401), NIM_NOT_IN_SCOPE (403), BRIDGE_OFFLINE (404), BRIDGE_ERROR/INVALID_REQUEST (422), INTERNAL_ERROR (5xx).
Retry réseau/5xx automatique avec backoff + Idempotency-Key réutilisée entre tentatives.
Webhooks
// Express
app.post("/webhook", express.raw({ type: "application/json" }), (req, res) => {
try {
const event = avepay.webhooks.verify(req.body, req.header("X-Avepay-Signature"));
// event.type: "cert.issued" | "mcf.connected" | "mcf.disconnected"
res.sendStatus(200);
} catch {
res.sendStatus(400);
}
});Le secret peut être passé à verify(body, sig, secret) ou au client (new AvePay({ webhookSecret })).
Configuration
new AvePay({
apiKey: "ak_live_…",
isf: "1",
baseUrl: "https://api-mcf-orchestrator.toolsite.io", // défaut
timeoutMs: 30000,
maxRetries: 2,
webhookSecret: "whsec_…",
// fetch: customFetch // runtimes sans fetch global / tests
});URL de l'API
Résolution par ordre de priorité : baseUrl explicite > variable d'env AVEPAY_BASE_URL > défaut https://api-mcf-orchestrator.toolsite.io. Pratique quand le domaine change : définis AVEPAY_BASE_URL côté serveur, sans changer de version.
Développement
npm install
npm test # vitest contre fixtures/ (mock fetch)
npm run build # ESM + CJS + types