Payment Examples
Complete examples for initiating a payment. They use thesignRequest / sign_request / SignRequest helper from the Authentication page, which builds the v1 canonical string and returns the required auth headers.
Initiate Payment
- Node.js
- Python
- Go
const axios = require('axios');
const { signRequest } = require('./gopay-auth'); // see Authentication page
const BASE_URL = 'https://api.gopay.example.com'; // your onboarding base URL
async function initiatePayment() {
const payload = {
merchantId: process.env.GOPAY_MERCHANT_ID,
amount: 100.5,
currency: 'USD',
phoneNumber: '+251912345678',
successUrl: 'https://your-store.com/checkout/success',
failUrl: 'https://your-store.com/checkout/failed',
notifyUrl: 'https://your-store.com/api/gopay-webhook',
};
// Serialize ONCE — the same bytes must be hashed, signed and sent.
const body = Buffer.from(JSON.stringify(payload), 'utf8');
const url = `${BASE_URL}/api/v1/initiate-payment`;
const headers = signRequest('POST', url, body);
headers['Idempotency-Key'] = `order-${Date.now()}`; // safe retries
try {
const res = await axios.post(url, body, { headers });
console.log('Session created:', res.data.sessionId);
return res.data.checkoutUrl; // redirect the customer here
} catch (err) {
const e = err.response?.data?.error;
console.error(`Payment failed [${e?.code}]: ${e?.message} (requestId=${e?.requestId})`);
throw err;
}
}
import json
import requests
from gopay_auth import sign_request # see Authentication page
BASE_URL = "https://api.gopay.example.com" # your onboarding base URL
def initiate_payment(merchant_id: str) -> str:
payload = {
"merchantId": merchant_id,
"amount": 100.5,
"currency": "USD",
"phoneNumber": "+251912345678",
"successUrl": "https://your-store.com/checkout/success",
"failUrl": "https://your-store.com/checkout/failed",
"notifyUrl": "https://your-store.com/api/gopay-webhook",
}
# Serialize ONCE — the same bytes must be hashed, signed and sent.
body = json.dumps(payload).encode("utf-8")
url = f"{BASE_URL}/api/v1/initiate-payment"
headers = sign_request("POST", url, body)
headers["Idempotency-Key"] = f"order-{payload['phoneNumber']}-001"
resp = requests.post(url, data=body, headers=headers, timeout=15)
if resp.status_code != 200:
err = resp.json()["error"]
raise RuntimeError(
f"payment failed [{err['code']}]: {err['message']} "
f"(requestId={err.get('requestId')})"
)
data = resp.json()
print("Session created:", data["sessionId"])
return data["checkoutUrl"] # redirect the customer here
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
const baseURL = "https://api.gopay.example.com" // your onboarding base URL
type initiatePaymentResponse struct {
CheckoutURL string `json:"checkoutUrl"`
SessionID uint32 `json:"sessionId"`
}
type apiError struct {
Error struct {
Code string `json:"code"`
Message string `json:"message"`
RequestID string `json:"requestId"`
} `json:"error"`
}
func initiatePayment(merchantID string) (string, error) {
payload := map[string]any{
"merchantId": merchantID,
"amount": 100.5,
"currency": "USD",
"phoneNumber": "+251912345678",
"successUrl": "https://your-store.com/checkout/success",
"failUrl": "https://your-store.com/checkout/failed",
"notifyUrl": "https://your-store.com/api/gopay-webhook",
}
// Serialize ONCE — the same bytes must be hashed, signed and sent.
body, err := json.Marshal(payload)
if err != nil {
return "", err
}
url := baseURL + "/api/v1/initiate-payment"
// SignRequest is on the Authentication page
headers, err := SignRequest(
os.Getenv("GOPAY_PRIVATE_KEY"),
os.Getenv("GOPAY_PUBLIC_KEY"),
"POST", url, body,
)
if err != nil {
return "", err
}
req, err := http.NewRequest("POST", url, bytes.NewReader(body))
if err != nil {
return "", err
}
for k, v := range headers {
req.Header.Set(k, v)
}
req.Header.Set("Idempotency-Key", "order-0001") // safe retries
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
var apiErr apiError
_ = json.Unmarshal(respBody, &apiErr)
return "", fmt.Errorf("payment failed [%s]: %s (requestId=%s)",
apiErr.Error.Code, apiErr.Error.Message, apiErr.Error.RequestID)
}
var out initiatePaymentResponse
if err := json.Unmarshal(respBody, &out); err != nil {
return "", err
}
fmt.Println("Session created:", out.SessionID)
return out.CheckoutURL, nil // redirect the customer here
}
Getting
INVALID_SIGNATURE? Work through the common mistakes on the Authentication page — the usual culprits are re-serialized bodies, millisecond timestamps, and signing with the wrong host.