Intégration Web
Copiez-collez des exemples complets pour 7 langages serveur populaires. Chaque exemple inclut la signature, l'initiation d'un paiement et la gestion de la réponse.
PHP
Classe complète prête à l'emploi :
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)
}