Docs › Quickstarts › .NET
BackendIntégrer NaabigaPay en .NET
Un endpoint ASP.NET Core crée le lien avec HttpClient, un autre vérifie la signature du webhook avec HMACSHA256, puis marque la commande payée.
Deux endpoints côté serveur : l'un crée un lien de paiement quand un client veut payer, l'autre vérifie la signature du webhook une fois le paiement réussi. La clé secrète (sk_live_…) reste dans votre configuration serveur et n'atteint jamais le navigateur.
1.Créer le lien
Votre front appelle cet endpoint ; il appelle POST/v1/payment-links avec la clé secrète, puis renvoie l'url de paiement.
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
const string NPay = "https://api.pay.naabiga.com/api/v1";
var secret = Environment.GetEnvironmentVariable("NPAY_SECRET"); // sk_live_...
var http = new HttpClient();
// Votre front appelle CET endpoint, jamais NaabigaPay directement.
app.MapPost("/api/pay", async (CommandeDto corps) =>
{
var body = JsonSerializer.Serialize(new
{
amount = corps.Amount, // entier, en FCFA
reference = corps.Commande, // votre numéro de commande
description = $"Commande {corps.Commande}",
return_url = "https://monsite.com/merci",
single_use = true,
});
using var req = new HttpRequestMessage(HttpMethod.Post, $"{NPay}/payment-links");
req.Headers.Add("Authorization", $"Bearer {secret}");
req.Headers.Add("Idempotency-Key", $"cmd-{corps.Commande}"); // évite un double lien
req.Content = new StringContent(body, Encoding.UTF8, "application/json");
var res = await http.SendAsync(req);
using var doc = JsonDocument.Parse(await res.Content.ReadAsStringAsync());
var url = doc.RootElement.GetProperty("url").GetString();
return Results.Ok(new { url }); // le front ouvre cette URL
});
app.Run();
record CommandeDto(string Commande, int Amount);Pour un montant libre, remplacez amount par amount_min, amount_max et une description.
2.Vérifier le webhook
NaabigaPay envoie POST à l'URL enregistrée dans le portail marchand, avec les en-têtes X-NPay-Event et X-NPay-Signature (HMAC-SHA256 du corps brut). Lisez le corps brut avec StreamReader, recalculez le HMAC et comparez en temps constant avec CryptographicOperations.FixedTimeEquals.
var webhookSecret = Encoding.UTF8.GetBytes(
Environment.GetEnvironmentVariable("NPAY_WEBHOOK_SECRET")!);
app.MapPost("/webhook", async (HttpRequest request) =>
{
// Corps BRUT (le texte exact signé), lu avant toute désérialisation.
var raw = await new StreamReader(request.Body).ReadToEndAsync();
var signature = request.Headers["X-NPay-Signature"].ToString();
using var hmac = new HMACSHA256(webhookSecret);
var calcule = Convert.ToHexString(
hmac.ComputeHash(Encoding.UTF8.GetBytes(raw))).ToLowerInvariant();
var egal = CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(calcule),
Encoding.UTF8.GetBytes(signature));
if (!egal) return Results.BadRequest("signature invalide");
if (request.Headers["X-NPay-Event"] == "payment.succeeded")
{
using var doc = JsonDocument.Parse(raw);
// data.merchant_reference = VOTRE numéro de commande (la reference du lien).
var reference = doc.RootElement
.GetProperty("data").GetProperty("merchant_reference").GetString();
MarquerCommandePayee(reference);
}
return Results.Ok();
});Astuce. Lisez le corps une seule fois avec StreamReader et signez sur ce texte brut : si ASP.NET a déjà lié un modèle, le flux est consommé et la signature ne correspond plus.
Référence rapide
| Méthode | Endpoint | Rôle |
|---|---|---|
| POST | /v1/payment-links | Créer un lien de paiement |
| GET | /v1/payments/{reference} | Statut d'un paiement |
Base : https://api.pay.naabiga.com/api/v1 · Auth : Authorization: Bearer sk_…. Voir la documentation complète et le format des webhooks.