NaabigaPay · .NET
QuickstartsDocs

DocsQuickstarts › .NET

Backend

Inté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.

Program.cs · minimal API
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.

Program.cs (suite) · webhook
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éthodeEndpointRôle
POST/v1/payment-linksCré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.