@bakissation/fastify-satim
v2.0.0
Published
Fastify plugin for the SATIM (SATIM-IPAY) payment gateway — multi-tenant, built-in routes, schema validation, and typed decorators for CIB & Edahabia payments in Algeria. Works with Fastify v4 and v5.
Maintainers
Readme
@bakissation/fastify-satim
A Fastify plugin for the SATIM (SATIM-IPAY) payment gateway — drop SATIM CIB & Edahabia payments into any Fastify app with a typed fastify.satim decorator, optional built-in routes, schema validation, and multi-tenant support. Works with Fastify v4 and v5.
- 🧩 Typed decorator —
fastify.satimexposes the full SATIM client (register,getOrderStatus,confirm,refund) across all scopes. - 🏢 Multi-tenant — resolve credentials per request via
getClient(request), or stay single-tenant with env vars / a config object / a pre-built client. - 🛣️ Built-in routes (opt-in) —
/register,/status,/confirm,/refundwith JSON-schema validation and per-route hooks — or wire your own. - 🔒 Secure by default — centralized error mapping that never leaks credentials, POST-only by default, no secret logging.
📖 Read the case study → — how this plugin cuts SATIM integration from hundreds of lines of boilerplate per project to a single
register()call.
Install
npm install @bakissation/fastify-satimRequires Node.js ≥ 18 and Fastify v4 or v5. The core SDK @bakissation/satim is included.
Quick start
import Fastify from 'fastify';
import fastifySatim, { interpretOrderStatus } from '@bakissation/fastify-satim';
const fastify = Fastify();
await fastify.register(fastifySatim, { fromEnv: true });
fastify.post('/checkout', async (request, reply) => {
const order = await fastify.satim.register({
orderNumber: 'ORD001',
amount: 5000, // 5000 DZD
returnUrl: 'https://yoursite.com/payment/success',
udf1: 'INV001',
});
if (order.isSuccessful()) return { redirectUrl: order.formUrl };
return reply.status(400).send({ error: 'Failed to create order' });
});
fastify.post('/payment/callback', async (request) => {
const { orderId } = request.body as { orderId: string };
const status = await fastify.satim.getOrderStatus(orderId);
return status.isPaid() ? { status: 'paid' } : { status: interpretOrderStatus(status.orderStatus) };
});
await fastify.listen({ port: 3000 });There are four ways to configure the client (multi-tenant, env, object, pre-built) → docs/configuration.
Documentation
Full docs live in docs/:
| | |
|---|---|
| Overview & concepts | What the plugin is, when to use it vs the raw SDK, design notes |
| Getting started | Install, register, first payment, environments |
| Configuration | The four config modes (multi-tenant, env, object, client) |
| Built-in routes | /register · /status · /confirm · /refund — paths, hooks, bodies |
| Security | Auth, CSRF, error mapping, best practices |
| Architecture | Module map, plugin lifecycle, routes, error handling |
For the SATIM gateway API, environments, and certification, see the core SDK docs.
Contributing
Issues and PRs welcome — read CONTRIBUTING.md and the Code of Conduct. Releases are automated from Conventional Commits via semantic-release; don't bump the version or edit the changelog by hand.
Credits
Built and maintained by Abdelbaki Berkati — berkati.xyz · @bakissation. 📖 Read the case study →
