Documentation API Intégration Web

Intégration Web

Copy-paste complete integration examples for 7 popular server-side languages. Each example includes signing, initiating a payment and handling the response.

PHP

Complete class ready to use:

GerminoPayClient.php
<?php
class GerminoPayClient
{
    private string $publicKey;
    private string $secretKey;
    private string $baseUrl;

    public function __construct(string $publicKey, string $secretKey, bool $sandbox = false)
    {
        $this->publicKey = $publicKey;
        $this->secretKey = $secretKey;
        $this->baseUrl   = $sandbox
            ? "https://sandbox.germinopay.com/v1"
            : "https://api.germinopay.com/v1";
    }

    private function sign(string $method, string $path, string $body, int $timestamp): string
    {
        $message = $method . $path . $body . $timestamp;
        return hash_hmac("sha256", $message, $this->secretKey);
    }

    private function request(string $method, string $path, array $data = []): array
    {
        $body = $method === "GET" ? "" : json_encode($data);
        $timestamp = time();
        $signature = $this->sign($method, $path, $body, $timestamp);

        $ch = curl_init($this->baseUrl . $path);
        curl_setopt_array($ch, [
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER     => [
                "Content-Type: application/json",
                "X-Public-Key: " . $this->publicKey,
                "X-Timestamp: " . $timestamp,
                "X-Signature: " . $signature,
            ],
            CURLOPT_POSTFIELDS     => $body ?: null,
        ]);

        $response = curl_exec($ch);
        $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $decoded = json_decode($response, true) ?: [];
        if ($code >= 400) {
            throw new RuntimeException($decoded["error"]["message"] ?? "Request failed");
        }
        return $decoded;
    }

    public function initierPaiement(array $params): array
    {
        return $this->request("POST", "/paiement/initier", $params);
    }

    public function getTransaction(string $reference): array
    {
        return $this->request("GET", "/transactions/" . $reference);
    }

    public function getSoldes(): array
    {
        return $this->request("GET", "/soldes");
    }

    public function demanderRetrait(array $params): array
    {
        return $this->request("POST", "/retraits", $params);
    }

    public function rembourser(string $reference, ?float $montant = null, string $raison = ""): array
    {
        $data = array_filter(compact("montant", "raison"));
        return $this->request("POST", "/paiement/" . $reference . "/rembourser", $data);
    }
}

// ---------- Utilisation ----------
$client = new GerminoPayClient(
    publicKey: "pk_live_xxxx",
    secretKey: getenv("GERMINOPAY_SECRET"),
    sandbox: false
);

$result = $client->initierPaiement([
    "montant"      => 5000,
    "devise"       => "XOF",
    "fournisseur"  => "cinetpay",
    "reference"    => "CMD-" . time(),
    "client_email" => "client@example.com",
    "return_url"   => "https://monsite.com/succes",
]);

header("Location: " . $result["data"]["payment_url"]);

Node.js

germinopay.js
const crypto = require('crypto');

class GerminoPay {
  constructor({ publicKey, secretKey, sandbox = false }) {
    this.publicKey = publicKey;
    this.secretKey = secretKey;
    this.baseUrl = sandbox
      ? 'https://sandbox.germinopay.com/v1'
      : 'https://api.germinopay.com/v1';
  }

  sign(method, path, body, timestamp) {
    return crypto
      .createHmac('sha256', this.secretKey)
      .update(`${method}${path}${body}${timestamp}`)
      .digest('hex');
  }

  async request(method, path, data = null) {
    const body = data ? JSON.stringify(data) : '';
    const timestamp = Math.floor(Date.now() / 1000);
    const signature = this.sign(method, path, body, timestamp);

    const res = await fetch(this.baseUrl + path, {
      method,
      headers: {
        'Content-Type': 'application/json',
        'X-Public-Key': this.publicKey,
        'X-Timestamp': timestamp.toString(),
        'X-Signature': signature,
      },
      body: body || undefined,
    });

    const json = await res.json();
    if (!res.ok) throw new Error(json.error?.message || 'Request failed');
    return json;
  }

  initierPaiement(params)       { return this.request('POST', '/paiement/initier', params); }
  getTransaction(reference)     { return this.request('GET', `/transactions/${reference}`); }
  getSoldes()                   { return this.request('GET', '/soldes'); }
  demanderRetrait(params)       { return this.request('POST', '/retraits', params); }
  rembourser(ref, montant, raison) {
    return this.request('POST', `/paiement/${ref}/rembourser`, { montant, raison });
  }
}

// Utilisation (Express)
const express = require('express');
const app = express();
app.use(express.json());

const gp = new GerminoPay({
  publicKey: process.env.GERMINOPAY_PUBLIC,
  secretKey: process.env.GERMINOPAY_SECRET,
});

app.post('/payer', async (req, res) => {
  try {
    const result = await gp.initierPaiement({
      montant: 5000,
      devise: 'XOF',
      fournisseur: 'cinetpay',
      reference: `CMD-${Date.now()}`,
      client_email: req.body.email,
      return_url: 'https://monsite.com/succes',
    });
    res.json({ url: result.data.payment_url });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3000);

Python

germinopay.py
import hashlib
import hmac
import json
import time
import requests


class GerminoPay:
    def __init__(self, public_key, secret_key, sandbox=False):
        self.public_key = public_key
        self.secret_key = secret_key
        self.base_url = (
            "https://sandbox.germinopay.com/v1"
            if sandbox else
            "https://api.germinopay.com/v1"
        )

    def _sign(self, method, path, body, timestamp):
        message = f"{method}{path}{body}{timestamp}"
        return hmac.new(
            self.secret_key.encode(),
            message.encode(),
            hashlib.sha256
        ).hexdigest()

    def _request(self, method, path, data=None):
        body = json.dumps(data, separators=(',', ':')) if data else ""
        timestamp = int(time.time())
        signature = self._sign(method, path, body, timestamp)

        r = requests.request(
            method,
            f"{self.base_url}{path}",
            data=body or None,
            headers={
                "Content-Type": "application/json",
                "X-Public-Key": self.public_key,
                "X-Timestamp": str(timestamp),
                "X-Signature": signature,
            },
        )
        payload = r.json()
        if not r.ok:
            raise Exception(payload.get("error", {}).get("message", "Request failed"))
        return payload

    def initier_paiement(self, params):
        return self._request("POST", "/paiement/initier", params)

    def get_transaction(self, reference):
        return self._request("GET", f"/transactions/{reference}")

    def get_soldes(self):
        return self._request("GET", "/soldes")

    def demander_retrait(self, params):
        return self._request("POST", "/retraits", params)


# Utilisation
if __name__ == "__main__":
    gp = GerminoPay(
        public_key="pk_live_xxxx",
        secret_key="sk_live_xxxx",
    )

    result = gp.initier_paiement({
        "montant": 5000,
        "devise": "XOF",
        "fournisseur": "cinetpay",
        "reference": "CMD-1042",
        "client_email": "client@example.com",
        "return_url": "https://monsite.com/succes",
    })

    print(result["data"]["payment_url"])

Ruby

germinopay.rb
require 'openssl'
require 'json'
require 'net/http'
require 'uri'
require 'time'

class GerminoPay
  def initialize(public_key:, secret_key:, sandbox: false)
    @public_key = public_key
    @secret_key = secret_key
    @base_url = sandbox ?
      'https://sandbox.germinopay.com/v1' :
      'https://api.germinopay.com/v1'
  end

  def initier_paiement(params)
    request('POST', '/paiement/initier', params)
  end

  def get_transaction(reference)
    request('GET', "/transactions/#{reference}")
  end

  def get_soldes
    request('GET', '/soldes')
  end

  private

  def sign(method, path, body, timestamp)
    message = "#{method}#{path}#{body}#{timestamp}"
    OpenSSL::HMAC.hexdigest('SHA256', @secret_key, message)
  end

  def request(method, path, data = nil)
    body = data ? JSON.generate(data) : ''
    timestamp = Time.now.to_i.to_s
    signature = sign(method, path, body, timestamp)

    uri = URI.parse(@base_url + path)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    req = (method == 'GET') ? Net::HTTP::Get.new(uri) :
          Net::HTTP::Post.new(uri)
    req['Content-Type'] = 'application/json'
    req['X-Public-Key'] = @public_key
    req['X-Timestamp']  = timestamp
    req['X-Signature']  = signature
    req.body = body unless body.empty?

    res = http.request(req)
    JSON.parse(res.body)
  end
end

# Utilisation
gp = GerminoPay.new(
  public_key: 'pk_live_xxxx',
  secret_key: ENV['GERMINOPAY_SECRET']
)

result = gp.initier_paiement(
  montant: 5000,
  devise: 'XOF',
  fournisseur: 'cinetpay',
  reference: 'CMD-1042',
  return_url: 'https://monsite.com/succes'
)

puts result['data']['payment_url']

.NET (C#)

GerminoPay.cs
using System;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

public class GerminoPayClient
{
    private readonly string _publicKey;
    private readonly string _secretKey;
    private readonly string _baseUrl;
    private readonly HttpClient _http = new HttpClient();

    public GerminoPayClient(string publicKey, string secretKey, bool sandbox = false)
    {
        _publicKey = publicKey;
        _secretKey = secretKey;
        _baseUrl = sandbox
            ? "https://sandbox.germinopay.com/v1"
            : "https://api.germinopay.com/v1";
    }

    private string Sign(string method, string path, string body, long timestamp)
    {
        var message = $"{method}{path}{body}{timestamp}";
        using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_secretKey));
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }

    public async Task RequestAsync(string method, string path, object data = null)
    {
        var body = data != null ? JsonSerializer.Serialize(data) : "";
        var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var signature = Sign(method, path, body, timestamp);

        var req = new HttpRequestMessage(new HttpMethod(method), _baseUrl + path);
        req.Headers.Add("X-Public-Key", _publicKey);
        req.Headers.Add("X-Timestamp", timestamp.ToString());
        req.Headers.Add("X-Signature", signature);
        if (!string.IsNullOrEmpty(body))
            req.Content = new StringContent(body, Encoding.UTF8, "application/json");

        var res = await _http.SendAsync(req);
        var json = await res.Content.ReadAsStringAsync();
        return JsonDocument.Parse(json);
    }

    public Task InitierPaiementAsync(object p) => RequestAsync("POST", "/paiement/initier", p);
    public Task GetSoldesAsync() => RequestAsync("GET", "/soldes");
}

// Utilisation
var client = new GerminoPayClient("pk_live_xxxx", Environment.GetEnvironmentVariable("GERMINOPAY_SECRET"));
var result = await client.InitierPaiementAsync(new {
    montant = 5000,
    devise = "XOF",
    fournisseur = "cinetpay",
    reference = $"CMD-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
    return_url = "https://monsite.com/succes"
});

Java

GerminoPayClient.java
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.*;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.*;

public class GerminoPayClient {
    private final String publicKey;
    private final String secretKey;
    private final String baseUrl;
    private final HttpClient http = HttpClient.newHttpClient();

    public GerminoPayClient(String publicKey, String secretKey, boolean sandbox) {
        this.publicKey = publicKey;
        this.secretKey = secretKey;
        this.baseUrl = sandbox
            ? "https://sandbox.germinopay.com/v1"
            : "https://api.germinopay.com/v1";
    }

    private String sign(String method, String path, String body, long timestamp) throws Exception {
        String message = method + path + body + timestamp;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        for (byte b : hash) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    public String request(String method, String path, String body) throws Exception {
        if (body == null) body = "";
        long timestamp = Instant.now().getEpochSecond();
        String signature = sign(method, path, body, timestamp);

        HttpRequest.Builder builder = HttpRequest.newBuilder()
            .uri(URI.create(baseUrl + path))
            .header("Content-Type", "application/json")
            .header("X-Public-Key", publicKey)
            .header("X-Timestamp", String.valueOf(timestamp))
            .header("X-Signature", signature);

        if ("GET".equals(method)) {
            builder.GET();
        } else {
            builder.method(method, HttpRequest.BodyPublishers.ofString(body));
        }

        HttpResponse<String> res = http.send(builder.build(), HttpResponse.BodyHandlers.ofString());
        return res.body();
    }

    public String initierPaiement(String json) throws Exception {
        return request("POST", "/paiement/initier", json);
    }

    public String getSoldes() throws Exception {
        return request("GET", "/soldes", null);
    }
}

Go

germinopay.go
package germinopay

import (
    "bytes"
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "time"
)

type Client struct {
    PublicKey string
    SecretKey string
    BaseURL   string
}

func New(publicKey, secretKey string, sandbox bool) *Client {
    url := "https://api.germinopay.com/v1"
    if sandbox {
        url = "https://sandbox.germinopay.com/v1"
    }
    return &Client{publicKey, secretKey, url}
}

func (c *Client) sign(method, path, body string, timestamp int64) string {
    message := fmt.Sprintf("%s%s%s%d", method, path, body, timestamp)
    h := hmac.New(sha256.New, []byte(c.SecretKey))
    h.Write([]byte(message))
    return hex.EncodeToString(h.Sum(nil))
}

func (c *Client) Request(method, path string, data interface{}) (map[string]interface{}, error) {
    var body []byte
    if data != nil {
        body, _ = json.Marshal(data)
    }
    timestamp := time.Now().Unix()
    signature := c.sign(method, path, string(body), timestamp)

    req, _ := http.NewRequest(method, c.BaseURL+path, bytes.NewReader(body))
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("X-Public-Key", c.PublicKey)
    req.Header.Set("X-Timestamp", fmt.Sprintf("%d", timestamp))
    req.Header.Set("X-Signature", signature)

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer res.Body.Close()

    respBody, _ := io.ReadAll(res.Body)
    var result map[string]interface{}
    json.Unmarshal(respBody, &result)
    return result, nil
}

// Utilisation
func main() {
    client := New("pk_live_xxxx", "sk_live_xxxx", false)

    result, _ := client.Request("POST", "/paiement/initier", map[string]interface{}{
        "montant":     5000,
        "devise":      "XOF",
        "fournisseur": "cinetpay",
        "reference":   "CMD-1042",
        "return_url":  "https://monsite.com/succes",
    })

    fmt.Println(result)
}