NaabigaPay · Ruby on Rails
QuickstartsDocs

DocsQuickstarts › Ruby on Rails

Backend

Intégrer NaabigaPay en Ruby on Rails

Une action de contrôleur crée le lien de paiement avec Net::HTTP, une action webhook vérifie la signature avec OpenSSL::HMAC, puis marque la commande payée.

Deux actions côté serveur : l'une 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 vos variables d'environnement et n'atteint jamais le navigateur.

1.Créer le lien

Votre front appelle cette action ; elle appelle POST/v1/payment-links avec la clé secrète, puis renvoie l'url de paiement. Ici avec Net::HTTP (aucune gem à installer).

app/controllers/paiements_controller.rb
require 'net/http'
require 'json'
require 'uri'

class PaiementsController < ApplicationController
  NPAY = 'https://api.pay.naabiga.com/api/v1'.freeze

  # Votre front appelle CETTE action ; elle seule connaît la clé secrète.
  def creer
    commande = params.fetch(:commande)

    uri = URI("#{NPAY}/payment-links")
    req = Net::HTTP::Post.new(uri)
    req['Authorization']   = "Bearer #{ENV.fetch('NPAY_SECRET')}" # sk_live_... : reste côté serveur
    req['Content-Type']    = 'application/json'
    req['Idempotency-Key'] = "cmd-#{commande}"                    # évite un double lien si retry
    req.body = {
      amount:      params.fetch(:amount).to_i, # entier, en FCFA
      reference:   commande,                   # votre numéro de commande
      description: "Commande #{commande}",
      return_url:  'https://monsite.com/merci',
      cancel_url:  'https://monsite.com/panier',
      single_use:  true
    }.to_json

    res  = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
    lien = JSON.parse(res.body)
    render json: { url: lien['url'] } # le front ouvre cette URL
  end
end

La réponse contient url (ex. https://pay.naabiga.com/link/9f3c…) : la page où le client paie. Pour un montant libre, remplacez amount par amount_min, amount_max et une description. Vous pouvez aussi utiliser la gem faraday à la place de Net::HTTP, le corps et les en-têtes restent identiques.

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 request.raw_post (le corps intact), recalculez le HMAC, comparez avec ActiveSupport::SecurityUtils.secure_compare, et ne créditez qu'ensuite.

app/controllers/webhooks_controller.rb
require 'openssl'
require 'json'

class WebhooksController < ApplicationController
  # Requête serveur à serveur, sans jeton CSRF.
  skip_before_action :verify_authenticity_token

  def naabiga
    corps     = request.raw_post # corps BRUT : la signature porte sur ces octets
    signature = request.headers['X-NPay-Signature'].to_s
    secret    = ENV.fetch('NPAY_WEBHOOK_SECRET')
    attendu   = OpenSSL::HMAC.hexdigest('SHA256', secret, corps)

    # Comparaison à temps constant.
    unless ActiveSupport::SecurityUtils.secure_compare(signature, attendu)
      return head :bad_request
    end

    charge = JSON.parse(corps)
    if request.headers['X-NPay-Event'] == 'payment.succeeded'
      # data.merchant_reference = VOTRE numéro de commande (la reference du lien).
      marquer_commande_payee(charge['data']['merchant_reference'])
    end
    head :ok
  end
end

Astuce. Lisez toujours request.raw_post avant tout parseur : si le corps est déjà transformé, le HMAC ne correspond plus.

Router les deux actions

config/routes.rb
Rails.application.routes.draw do
  post 'api/pay',          to: 'paiements#creer'
  post 'webhooks/naabiga', to: 'webhooks#naabiga'
end

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.