Aller au contenu

SDK 221

Les SDK officiels TypeScript, Python et Dart : installation, premier appel, création d'un paiement et vérification d'un webhook.

Les SDK sont générés depuis l'OpenAPI de l'API. Ils vérifient la signature des webhooks et embarquent un instantané des petits jeux de référence (jours fériés, préfixes d'opérateurs, banques, géographie jusqu'à la commune) pour un usage hors ligne.

Pas encore publiés

Les SDK ne sont pas encore publiés : ils seront disponibles sur npm, PyPI et pub.dev à la publication. Les commandes d'installation ci-dessous fonctionneront à ce moment-là. En attendant, l'API s'appelle directement : voir Premier appel.

PaquetLangageVersion
@221/sdkTypeScript0.2.0
sdk-221 (module sdk221)Python0.2.0
sdk221Dart et Flutter0.2.0

Les exemples lisent API_URL (l'URL de base, https://apps.orvlabs.com), API_KEY (la clé, au format sk_221_pay_test_… ou sk_221_pay_live_…) et WEBHOOK_SECRET dans l'environnement. Les routes de paiement exigent une clé ; les routes de données fonctionnent aussi sans clé, avec un quota bas.

Idempotency-Key est propre à chaque paiement : renvoyer la même valeur ne crée pas de doublon. Un webhook se vérifie sur le corps brut, avant tout décodage JSON, avec les en-têtes X-221-Timestamp et X-221-Signature ; au-delà de 5 minutes, la signature est refusée. Une livraison peut être rejouée : dédupliquer sur l'identifiant de l'événement. Le détail des champs est dans 221 Pay.

TypeScript

Installation
npm install @221/sdk
paiement.ts
import { createApiClient } from '@221/sdk';

const api = createApiClient({ baseUrl: process.env.API_URL, apiKey: process.env.API_KEY });
const { data, error } = await api.POST('/v1/payments', {
  params: { header: { 'Idempotency-Key': 'commande-1042' } },
  body: {
    amount: '5000',
    currency: 'XOF',
    rail: 'sn_wave',
    merchant_reference: 'commande-1042',
    return_url: 'https://boutique.example/paiement/retour',
    customer_phone: '77 123 45 67',
  },
});
if (error) throw new Error(`${error.code}: ${error.message}`);
webhook.ts
import { verifyWebhook } from '@221/sdk/webhook';

// Express : app.post('/webhooks/221', express.raw({ type: 'application/json' }), (req, res) => …)
const ok = verifyWebhook(process.env.WEBHOOK_SECRET!, req.header('X-221-Timestamp') ?? '', req.body, req.header('X-221-Signature') ?? '');
if (!ok) return res.sendStatus(401);

Python

Installation
uv add sdk-221   # ou : pip install sdk-221, dans un environnement virtuel
paiement.py
import os
from sdk221 import client

api = client(os.environ["API_KEY"], os.environ["API_URL"])
response = api.get_httpx_client().post(
    "/v1/payments",
    headers={"Idempotency-Key": "commande-1042"},
    json={
        "amount": "5000",
        "currency": "XOF",
        "rail": "sn_wave",
        "merchant_reference": "commande-1042",
        "return_url": "https://boutique.example/paiement/retour",
        "customer_phone": "77 123 45 67",
    },
)
response.raise_for_status()
payment = response.json()
webhook.py
from sdk221.webhook import verify_webhook

# FastAPI : raw_body = await request.body()
if not verify_webhook(WEBHOOK_SECRET, request.headers.get("X-221-Timestamp", ""), raw_body, request.headers.get("X-221-Signature", "")):
    raise HTTPException(status_code=401)

Dart et Flutter

Installation
dart pub add sdk221   # ou : flutter pub add sdk221
paiement.dart
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' show MultipartFile;
import 'package:sdk221/sdk221.dart';

Future<void> main() async {
  final env = Platform.environment;
  final client = createApiClient(apiKey: env['API_KEY'], baseUrl: env['API_URL'] ?? defaultBaseUrl);
  final payment = await PaymentsApi(client).paymentsCreate(
    MultipartFile.fromString('body', jsonEncode({
      'amount': '5000',
      'currency': 'XOF',
      'rail': 'sn_wave',
      'merchant_reference': 'commande-1042',
      'return_url': 'https://boutique.example/paiement/retour',
      'customer_phone': '77 123 45 67',
    })),
    idempotencyKey: 'commande-1042',
  );
  print(payment);
}
webhook.dart
import 'package:sdk221/sdk221.dart';

final ok = verifyWebhook(webhookSecret, request.headers['x-221-timestamp'] ?? '', rawBody, request.headers['x-221-signature'] ?? '');
if (!ok) return Response(401);

Limite : le client généré importe dart:io. Il fonctionne sur la machine virtuelle Dart, Android, iOS et le bureau, pas sur Flutter web, où la clé ne doit de toute façon pas se trouver.

Hors ligne

Les jours fériés embarqués couvrent les années présentes dans les données au moment de la version. holidays(2099) lève une erreur au lieu de renvoyer une liste vide : pour une autre année, appeler GET /v1/jours-feries?year=.