Merchant API Reference

InnovaPay África Merchant API

Accept wallet, gateway, and hosted checkout payments with environment-aware credentials, merchant-level currency control, and dashboard-managed payment gateway rules.

Pronto para produção
POST /api/v1/initiate-payment
GET /api/v1/verify-payment/{trxId}
Sandbox Multi-currency Signed API Gateway lock
Latest Merchant Flow Gateways are now configured after API generation from the merchant API Config page. Checkout only shows gateways that match the merchant currency and the active receiver wallet.

Fast Hosted Checkout

Create a payment session, redirect the customer, then verify or receive IPN updates when the transaction completes.

Wallet-aware Currency

The requested currency must be enabled for the merchant and backed by an active merchant wallet.

Configurable Gateways

Merchants can choose eligible payment gateways from API Config without regenerating API credentials.

Authentication

InnovaPay África API uses API keys to authenticate requests. You can obtain your credentials from your merchant dashboard.

Environment-Aware API Integration

InnovaPay África API supports both sandbox (testing) and production environments. Always test in sandbox first before going live.

Configuração do ambiente
Sandbox Mode

Use for: Development, testing, integration

X-Environment: sandbox

Credentials: Use test_* prefixed API keys

Production Mode

Use for: Live payments, real money

X-Environment: production

Credentials: Use production API keys (no prefix)

Gateway Configuration Payment gateway selection is dashboard-managed. After generating API credentials, open Merchant -> Config -> Payment Gateway Controls to choose eligible gateways without changing your integration keys.
Signed requests Every API call must include X-Timestamp and X-Signature unless merchant API signatures are disabled by admin configuration.
Replay protection The timestamp must be fresh. Default tolerance is 300 seconds, configurable by admin.
Rate limit Merchant API calls are rate limited per merchant and IP. Default limit is 120 requests per minute.

Required Credentials

Credential Cabeçalho Descrição Localização
ID do comerciante X-Merchant-Key Your unique merchant identifier Painel de controlo → Comerciante → Configuração
Chave de API X-API-Key API authentication key Painel de controlo → Comerciante → Configuração
Request Timestamp X-Timestamp Unix timestamp in seconds used for replay protection Generated by your server for each API request
API Signature X-Signature HMAC-SHA256 signature for the request Generated using your Client Secret
Client Secret - Used for API request signing and webhook signature verification Painel de controlo → Comerciante → CONFIG
Production API Key X-API-Key Production API key (no prefix) Painel do comerciante > Configuração da API > Production Mode
Production Merchant Key X-Merchant-Key Production merchant identifier (no prefix) Painel do comerciante > Configuração da API > Production Mode
Security Notice Never expose your Client Secret in client-side code. Store all credentials securely on your server.
Signature Payload

When API signatures are required, sign this exact payload with your Client Secret:

timestamp.HTTP_METHOD.path_with_query.raw_body

Quick Start

Use this flow for a production-safe integration. Credentials identify the merchant, while currency and gateway availability are controlled from the merchant dashboard.

01

Generate API Keys

Open Dashboard -> Merchant -> Config and copy the Merchant Key, API Key, and Client Secret for sandbox or production.

02

Confirm Currencies

Make sure the merchant supports the checkout currency and the merchant owner has an active wallet for that currency.

03

Select Gateways

From API Config, enable the payment gateways that should appear on hosted checkout for each eligible currency.

04

Sign & Create Payment

POST to /api/v1/initiate-payment with X-Timestamp and X-Signature, redirect the customer to payment_url, then verify or listen for IPN.

Configuração da API Currency + Wallet Gateway Filter Hosted Checkout
Open Testing Console

Use sandbox credentials first, then switch to production when your checkout and IPN are verified.

Última atualização do comerciante A Configuração da API controla a finalização após a geração das chaves

Configuração do comerciante e da API

A API do comerciante já não é um fluxo de moeda única e gateway fixo. Um comerciante pode agora suportar múltiplos canais de moeda, manter credenciais sandbox e de produção separadas e escolher gateways elegíveis na página de Configuração da API sem regenerar chaves de API.

Painel do comerciante

Uma integração, finalização controlada pelo painel

O seu código envia montante, moeda, redirecionamentos, URL de IPN e palavras-chave opcionais de gateway. O painel decide quais canais de moeda, carteiras e gateways de pagamento estão realmente disponíveis para esse comerciante.

Chaves sandbox Chaves de produção Canais de carteira Controlos do gateway
Modo predefinido Sandbox
Acesso ao vivo Requer aprovação
Fonte do gateway Configuração da API

Estado de revisão do comerciante

Os comerciantes pendentes podem testar em sandbox. O acesso à API de produção e a finalização ao vivo estão disponíveis apenas após aprovação do administrador.

Canais de moeda

Cada currency_code do pedido deve existir na lista de moedas suportadas pelo comerciante. Moedas não suportadas são rejeitadas antes da finalização abrir.

Correspondência da carteira do recetor

O proprietário do comerciante deve ter uma carteira ativa para a moeda solicitada, caso contrário a API devolve um erro de disponibilidade de carteira.

Controlos do gateway de pagamento

Apenas gateways automáticos ativos que correspondem à moeda solicitada e à seleção do comerciante podem aparecer na finalização alojada.

Ordem de decisão em tempo de execução

  1. 01
    Autenticar o ambiente

    X-Environment decide qual chave de comerciante, chave de API e segredo de API são usados.

  2. 02
    Verificar disponibilidade do comerciante

    Comerciantes rejeitados ou desativados são bloqueados. A produção também exige estado de comerciante aprovado.

  3. 03
    Validar moeda solicitada

    currency_code deve corresponder a um canal suportado pelo comerciante, como USD, EUR ou BDT.

  4. 04
    Confirmar carteira do recetor

    O proprietário do comerciante precisa de uma carteira ativa para essa mesma moeda.

  5. 05
    Resolver gateways configurados

    As seleções na Configuração da API do Comerciante restringem a finalização aos gateways elegíveis escolhidos. Se nenhum for selecionado, o fallback seguro é todos os gateways automáticos ativos para essa moeda.

  6. 06
    Aplicar filtro opcional da API

    allow_payment_methods pode restringir a lista de gateways disponíveis, mas não pode expor um gateway não configurado ou com moeda errada.

Casos reais e resultados

Caso Resultado da API Correção
O comerciante suporta USD e EUR, mas só existe carteira USD. 422 Receiver wallet for this currency is not available. Crie/ative a carteira de comerciante EUR antes de aceitar finalização em EUR.
O Stripe USD está selecionado, mas o pedido envia currency_code EUR. O Stripe USD não aparecerá na finalização. Selecione um gateway EUR ativo ou envie USD.
O comerciante ainda não selecionou nenhum gateway. A finalização recorre a todos os gateways automáticos ativos que correspondem à moeda solicitada. Use a Configuração da API para bloquear a finalização a gateways preferidos.
allow_payment_methods=["paypal"] mas o PayPal não está configurado para o comerciante. O PayPal permanece oculto. Ative o PayPal nos Controlos do Gateway de Pagamento se a sua moeda corresponder.
O comerciante pendente chama a API de produção. 403 Merchant Pending Approval Use sandbox até a aprovação do administrador estar concluída.
Sem gateways de moeda cruzada

Um gateway configurado para USD não pode processar finalização em EUR a menos que exista um gateway EUR separado.

Os segredos permanecem no lado do servidor

O Segredo da API é usado apenas para assinar pedidos de API servidor-a-servidor e verificar assinaturas IPN.

O URL de finalização assinado expira

O payment_url devolvido tem tempo limitado. Crie uma nova sessão de pagamento para ligações de finalização expiradas.

A verificação tem âmbito de comerciante

Um comerciante só pode verificar a sua própria transação e apenas no ambiente sandbox ou de produção correspondente.

Regras de moeda e gateway

A finalização da API do comerciante é controlada por três camadas: moeda suportada pelo comerciante, carteira de recetor ativa e gateways de pagamento configurados. Isto mantém as opções de finalização precisas após a geração das credenciais da API.

Matriz de correspondência de gateways

Um gateway aparece na finalização alojada apenas quando todas as regras abaixo são verdadeiras. Se o comerciante selecionou gateways, esses gateways selecionados tornam-se o conjunto permitido para finalização.

Fonte do painel Comerciante -> Configuração -> Controlos do gateway de pagamento
Moeda ativada para o comerciante O currency_code do pedido deve existir na lista de moedas suportadas pelo comerciante.
Existe carteira de comerciante ativa O proprietário do comerciante deve ter uma carteira ativa para a moeda solicitada.
A moeda do gateway corresponde Apenas métodos de depósito automáticos ativos para essa moeda exata são elegíveis.
A seleção de gateway do comerciante passa Quando os gateways são selecionados na Configuração da API, a finalização é restrita a esses métodos selecionados.

Como funciona agora allow_payment_methods

Camada Quem o controla Efeito
currency_code Pedido de API Deve corresponder a uma moeda suportada pelo comerciante com uma carteira de recetor ativa.
Controlos do gateway de pagamento Painel do comerciante Define o conjunto de gateways disponível para a finalização alojada para cada moeda elegível.
allow_payment_methods Pedido de API Filtro opcional de palavra-chave de nome/código aplicado após as regras de gateway do comerciante. Não pode expor um gateway que o comerciante não configurou.
Predefinição segura Se um comerciante não selecionou nenhum gateway, a finalização recorre a todos os gateways automáticos ativos que correspondem à moeda solicitada. Assim que o comerciante seleciona gateways, a finalização usa apenas essa lista configurada.
POST

Iniciar pagamento

Crie uma sessão de finalização alojada para uma moeda suportada pelo comerciante. O payment_url devolvido deve ser aberto pelo cliente.

https://innovapayafrica.com/api/v1/initiate-payment
Chave de API necessária Assinatura HMAC necessária Sandbox + produção Carteira de moeda verificada
Seleção de gateway A finalização alojada aplica primeiro as regras de moeda e carteira do comerciante, depois os gateways selecionados na Configuração da API do Comerciante. allow_payment_methods é apenas um filtro extra opcional.

Cabeçalhos do pedido

Cabeçalho Valor Obrigatório Descrição
Content-Type application/json Sim Tipo de conteúdo do pedido
Accept application/json Sim Tipo de resposta esperado
X-Environment sandbox | production Sim Use sandbox para testes e produção para pagamentos ao vivo
X-Merchant-Key {merchant_key} Sim Identificador do comerciante da página de Configuração da API
X-API-Key {api_key} Sim Chave de API para o ambiente selecionado
X-Timestamp {unix_timestamp} Sim Timestamp Unix atual em segundos. Pedidos fora da tolerância permitida são rejeitados.
X-Signature sha256={hmac} Sim HMAC-SHA256 de timestamp.METHOD.path_with_query.raw_body usando o Segredo da API para o ambiente selecionado.

Parâmetros do pedido

Parâmetro Tipo Obrigatório Descrição
payment_amount number Sim Montante do pagamento. O valor mínimo é 1.00.
currency_code string Sim Código de moeda de 3 letras. Deve estar ativado para o comerciante e suportado por uma carteira de comerciante ativa.
ref_trx string Sim A sua referência única de encomenda ou transação. Máx 60 caracteres.
success_redirect url Sim O cliente é redirecionado para aqui após uma finalização alojada bem-sucedida.
cancel_redirect url Sim O cliente é redirecionado para aqui quando a finalização é cancelada ou não pode continuar.
ipn_url url Sim URL de webhook servidor-a-servidor para atualizações de estado de pagamento.
description string Não Descrição do pagamento visível no contexto de transação do comerciante.
customer_name string Não Nome do cliente. Máx 100 caracteres.
customer_email email Não Endereço de email do cliente. Máx 100 caracteres.
customer_phone string Não Customer phone number, preferably with the country code (e.g. +256770123456). A mobile money gateway (MTN MoMo, Airtel Money) requests the payment from this number. If you leave it out, the checkout page asks the customer for it.
allow_payment_methods string | array Não Optional keyword filter applied after merchant gateway rules. Example: "stripe,paypal" or ["stripe","paypal"].

Campos de resposta de disponibilidade do gateway

Campo Tipo Significado
info.merchant_payment_methods_restricted boolean true quando o comerciante selecionou gateways específicos na Configuração da API.
info.merchant_payment_method_ids array IDs de métodos de depósito elegíveis para a moeda solicitada.
info.merchant_payment_method_codes array Códigos de métodos elegíveis que podem aparecer na finalização alojada.

Exemplos de código

curl -X POST "https://innovapayafrica.com/api/v1/initiate-payment" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature" \
  -d '{
    "payment_amount": 250.00,
    "currency_code": "USD",
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "success_redirect": "https://merchant.example/payments/success",
    "cancel_redirect": "https://merchant.example/payments/cancel",
    "ipn_url": "https://merchant.example/webhooks/innovapay África",
    "customer_name": "John Doe",
    "customer_email": "john@example.com",
    "customer_phone": "+256770123456",
    "allow_payment_methods": ["stripe", "paypal"]
  }'
<?php

use Illuminate\Support\Facades\Http;

$payload = [
    'payment_amount' => 250.00,
    'currency_code' => 'USD',
    'ref_trx' => 'ORDER_12345',
    'description' => 'Premium Subscription',
    'success_redirect' => route('payments.success'),
    'cancel_redirect' => route('payments.cancel'),
    'ipn_url' => route('webhooks.innovapay África'),
    'customer_name' => 'John Doe',
    'customer_email' => 'john@example.com',
    'customer_phone' => '+256770123456',
    'allow_payment_methods' => ['stripe', 'paypal'],
];

$body = json_encode($payload, JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$path = '/api/v1/initiate-payment';
$signature = hash_hmac(
    'sha256',
    $timestamp.'.POST.'.$path.'.'.$body,
    config('services.innovapay África.api_secret')
);

$response = Http::withHeaders([
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'X-Environment' => 'sandbox',
    'X-Merchant-Key' => config('services.innovapay África.merchant_key'),
    'X-API-Key' => config('services.innovapay África.api_key'),
    'X-Timestamp' => $timestamp,
    'X-Signature' => 'sha256='.$signature,
])->withBody($body, 'application/json')
    ->post('https://innovapayafrica.com/api/v1/initiate-payment')
    ->throw()
    ->json();

return redirect()->away($response['payment_url']);
const crypto = require('crypto');

const payload = {
  payment_amount: 250.00,
  currency_code: 'USD',
  ref_trx: 'ORDER_12345',
  description: 'Premium Subscription',
  success_redirect: 'https://merchant.example/payments/success',
  cancel_redirect: 'https://merchant.example/payments/cancel',
  ipn_url: 'https://merchant.example/webhooks/innovapay África',
  customer_name: 'John Doe',
  customer_email: 'john@example.com',
  customer_phone: '+256770123456',
  allow_payment_methods: ['stripe', 'paypal']
};

const body = JSON.stringify(payload);
const timestamp = Math.floor(Date.now() / 1000).toString();
const path = '/api/v1/initiate-payment';
const signature = crypto
  .createHmac('sha256', process.env.DIGIKASH_API_SECRET)
  .update(`${timestamp}.POST.${path}.${body}`)
  .digest('hex');

const response = await fetch('https://innovapayafrica.com/api/v1/initiate-payment', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Environment': 'sandbox',
    'X-Merchant-Key': process.env.DIGIKASH_MERCHANT_KEY,
    'X-API-Key': process.env.DIGIKASH_API_KEY,
    'X-Timestamp': timestamp,
    'X-Signature': `sha256=${signature}`
  },
  body
});

const data = await response.json();

if (!response.ok) {
  throw new Error(data.error || 'Payment initiation failed');
}

window.location.href = data.payment_url;

Resposta de sucesso

200 OK Sessão de pagamento criada
{
  "payment_url": "https://innovapayafrica.com/payment/checkout?token=encrypted&signature=signed",
  "info": {
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "ipn_url": "https://merchant.example/webhooks/innovapay África",
    "cancel_redirect": "https://merchant.example/payments/cancel",
    "success_redirect": "https://merchant.example/payments/success",
    "customer_name": "John Doe",
    "customer_email": "john@example.com",
    "customer_phone": "+256770123456",
    "merchant_id": 1,
    "merchant_name": "Demo Store",
    "amount": 250,
    "currency_code": "USD",
    "environment": "sandbox",
    "is_sandbox": true,
    "allow_payment_methods": ["stripe", "paypal"],
    "merchant_payment_methods_restricted": true,
    "merchant_payment_method_ids": [7],
    "merchant_payment_method_codes": ["stripe-usd"]
  }
}

Respostas de erro comuns

422 A moeda não está ativada para este comerciante.

O currency_code solicitado não está na lista de moedas suportadas pelo comerciante.

422 A carteira do recetor para esta moeda não está disponível.

O proprietário do comerciante não tem uma carteira ativa para a moeda solicitada.

401 Credenciais de API inválidas.

Verifique X-Environment, X-Merchant-Key e X-API-Key para o mesmo ambiente.

GET

Verificar pagamento

Obtenha o estado mais recente para uma transação de finalização alojada. Verifique sempre no lado do servidor antes de cumprir uma encomenda.

https://innovapayafrica.com/api/v1/verify-payment/{trxId}
Use após redirecionamento ou IPN Com âmbito de comerciante

Cabeçalhos do pedido

Cabeçalho Valor Obrigatório Descrição
Accept application/json Sim Tipo de resposta esperado
X-Environment sandbox | production Sim Deve corresponder ao ambiente usado para iniciar o pagamento
X-Merchant-Key {merchant_key} Sim Identificador do comerciante da Configuração da API
X-API-Key {api_key} Sim Chave de API para o ambiente selecionado
X-Timestamp {unix_timestamp} Sim Use o mesmo formato de timestamp que na iniciação do pagamento.
X-Signature sha256={hmac} Sim Assine timestamp.GET./api/v1/verify-payment/{trxId}. usando o Segredo da API correspondente. O corpo bruto está vazio para pedidos GET.

Parâmetro de caminho

Parâmetro Tipo Obrigatório Descrição
trxId string Sim InnovaPay África transaction ID returned by hosted checkout or IPN.

Exemplo cURL

curl -X GET "https://innovapayafrica.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature"

Resposta de sucesso

200 OK Pagamento concluído
{
  "status": "success",
  "trx_id": "TXNQ5V8K2L9N3XM1",
  "amount": 237.5,
  "fee": 12.5,
  "currency": "USD",
  "net_amount": 237.5,
  "customer": {
    "name": "John Doe",
    "email": "john@example.com"
  },
  "description": "Premium Subscription",
  "created_at": "2026-05-13T10:30:00.000000Z",
  "updated_at": "2026-05-13T10:35:45.000000Z"
}

Valores do estado do pagamento

Estado Descrição Ação recomendada
pending O pagamento ainda está a ser processado. Aguarde o IPN ou verifique novamente mais tarde.
success Pagamento concluído com sucesso. Cumpra a encomenda após verificações de idempotência.
failed O pagamento falhou ou foi cancelado. Não cumpra; mostre o estado de repetição ou cancelamento.

Exemplos de código

curl -X GET "https://innovapayafrica.com/api/v1/verify-payment/TRXAB12CD34EF" \
  -H "Accept: application/json" \
  -H "X-Environment: production" \
  -H "X-Merchant-Key: live_merchant_key" \
  -H "X-API-Key: live_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature"
<?php

use Illuminate\Support\Facades\Http;

$trxId = 'TRXAB12CD34EF';
$timestamp = (string) time();
$path = '/api/v1/verify-payment/'.$trxId;
$signature = hash_hmac(
    'sha256',
    $timestamp.'.GET.'.$path.'.', // GET has an empty body
    config('services.innovapay África.api_secret')
);

$response = Http::withHeaders([
    'Accept' => 'application/json',
    'X-Environment' => 'production',
    'X-Merchant-Key' => config('services.innovapay África.merchant_key'),
    'X-API-Key' => config('services.innovapay África.api_key'),
    'X-Timestamp' => $timestamp,
    'X-Signature' => 'sha256='.$signature,
])->get('https://innovapayafrica.com/api/v1/verify-payment/'.$trxId)
    ->throw()
    ->json();

// $response['status'], $response['refunded_amount'], $response['fully_refunded']
const crypto = require('crypto');

const trxId = 'TRXAB12CD34EF';
const timestamp = Math.floor(Date.now() / 1000).toString();
const path = `/api/v1/verify-payment/${trxId}`;
const signature = crypto
  .createHmac('sha256', process.env.DIGIKASH_API_SECRET)
  .update(`${timestamp}.GET.${path}.`) // GET has an empty body
  .digest('hex');

const response = await fetch(`https://innovapayafrica.com/api/v1/verify-payment/${trxId}`, {
  method: 'GET',
  headers: {
    'Accept': 'application/json',
    'X-Environment': 'production',
    'X-Merchant-Key': process.env.DIGIKASH_MERCHANT_KEY,
    'X-API-Key': process.env.DIGIKASH_API_KEY,
    'X-Timestamp': timestamp,
    'X-Signature': `sha256=${signature}`
  }
});

const data = await response.json();
Idempotência Use o seu ref_trx e o trx_id devolvido para tornar o cumprimento idempotente. Um webhook e um pedido de verificação podem chegar próximos um do outro.
POST

Refund Payment

Refund all or part of a completed payment. The merchant wallet is debited, a refund transaction is recorded, and your IPN endpoint is notified.

https://innovapayafrica.com/api/v1/refund-payment
Chave de API necessária Assinatura HMAC necessária Full or partial Com âmbito de comerciante
What this does This reverses the platform-side ledger — it debits the amount back out of the merchant wallet and records a refund. Returning the money to the buyer's card is completed by the platform through the original payment gateway, since the card is never held by this system.

Cabeçalhos do pedido

Cabeçalho Valor Obrigatório Descrição
Accept application/json Sim Tipo de resposta esperado
X-Environment sandbox | production Sim Deve corresponder ao ambiente usado para iniciar o pagamento
X-Merchant-Key {merchant_key} Sim Identificador do comerciante da Configuração da API
X-API-Key {api_key} Sim Chave de API para o ambiente selecionado
X-Timestamp {unix_timestamp} Sim Unix seconds, used for the HMAC signature
X-Signature {hmac_sha256} Sim HMAC-SHA256 of the request, signed with your API secret

Parâmetros do pedido

Parâmetro Tipo Obrigatório Descrição
trx_id string Sim The trx_id of the completed payment to refund
amount number Não Amount to refund. Omit for a full refund; pass a smaller value for a partial refund. Partial refunds accumulate and cannot exceed the original amount.
reason string Não Optional human-readable reason stored with the refund
ref_refund string Não Your own refund reference. When supplied, the same reference never refunds twice (idempotent).

Exemplos de código

curl -X POST "https://innovapayafrica.com/api/v1/refund-payment" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "X-Environment: production" \
  -H "X-Merchant-Key: live_merchant_key" \
  -H "X-API-Key: live_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature" \
  -d '{
    "trx_id": "TRXAB12CD34EF",
    "amount": 10.00,
    "reason": "Customer returned item",
    "ref_refund": "RFD-10231"
  }'
<?php

use Illuminate\Support\Facades\Http;

// Omit "amount" for a full refund. Pass a unique "ref_refund" so a retry
// never refunds twice.
$payload = [
    'trx_id' => 'TRXAB12CD34EF',
    'amount' => 10.00,
    'reason' => 'Customer returned item',
    'ref_refund' => 'RFD-10231',
];

$body = json_encode($payload, JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$path = '/api/v1/refund-payment';
$signature = hash_hmac(
    'sha256',
    $timestamp.'.POST.'.$path.'.'.$body,
    config('services.innovapay África.api_secret')
);

$response = Http::withHeaders([
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'X-Environment' => 'production',
    'X-Merchant-Key' => config('services.innovapay África.merchant_key'),
    'X-API-Key' => config('services.innovapay África.api_key'),
    'X-Timestamp' => $timestamp,
    'X-Signature' => 'sha256='.$signature,
])->withBody($body, 'application/json')
    ->post('https://innovapayafrica.com/api/v1/refund-payment')
    ->throw()
    ->json();

// $response['refund_trx_id'], $response['remaining_refund'], $response['fully_refunded']
const crypto = require('crypto');

// Omit `amount` for a full refund. A unique `ref_refund` makes the call
// idempotent — the same reference never refunds twice.
const payload = {
  trx_id: 'TRXAB12CD34EF',
  amount: 10.00,
  reason: 'Customer returned item',
  ref_refund: 'RFD-10231'
};

const body = JSON.stringify(payload);
const timestamp = Math.floor(Date.now() / 1000).toString();
const path = '/api/v1/refund-payment';
const signature = crypto
  .createHmac('sha256', process.env.DIGIKASH_API_SECRET)
  .update(`${timestamp}.POST.${path}.${body}`)
  .digest('hex');

const response = await fetch('https://innovapayafrica.com/api/v1/refund-payment', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'X-Environment': 'production',
    'X-Merchant-Key': process.env.DIGIKASH_MERCHANT_KEY,
    'X-API-Key': process.env.DIGIKASH_API_KEY,
    'X-Timestamp': timestamp,
    'X-Signature': `sha256=${signature}`
  },
  body
});

const data = await response.json();

Resposta de sucesso

{
    "status": "success",
    "message": "Refund processed successfully.",
    "refund_trx_id": "TRXZ9YX87WV65",
    "original_trx_id": "TRXAB12CD34EF",
    "refunded_amount": 10.00,
    "total_refunded": 10.00,
    "remaining_refund": 39.99,
    "fully_refunded": false,
    "currency": "USD"
}

Refund Webhook (IPN)

After a successful refund, your ipn_url receives a signed POST. Verify the X-Signature header (HMAC-SHA256 of the raw body, using your API secret) before trusting it.

{
    "event": "payment.refunded",
    "status": "refunded",
    "data": {
        "original_trx_id": "TRXAB12CD34EF",
        "refund_trx_id": "TRXZ9YX87WV65",
        "ref_trx": "ORDER-10231",
        "ref_refund": "RFD-10231",
        "refunded_amount": 10.00,
        "total_refunded": 10.00,
        "remaining_refund": 39.99,
        "fully_refunded": false,
        "currency": "USD"
    },
    "message": "Payment refunded.",
    "timestamp": 1719750000
}
Common errors 422 — "Only completed payments can be refunded", "Refund amount exceeds the refundable balance", "This payment has already been fully refunded", or "Merchant wallet balance is insufficient to process this refund". The processing fee charged on the original payment is not returned.
GET

Informação do site

Obtenha a marca do gateway, etiquetas de ambiente e metadados de finalização voltados para o cliente para uma integração autenticada de comerciante.

https://innovapayafrica.com/api/v1/site-info
Autenticação de comerciante necessária Marca da finalização Etiquetas de ambiente

Exemplo cURL

curl -X GET "https://innovapayafrica.com/api/v1/site-info" \
  -H "Accept: application/json" \
  -H "X-Environment: sandbox" \
  -H "X-Merchant-Key: test_merchant_key" \
  -H "X-API-Key: test_api_key" \
  -H "X-Timestamp: 1778650000" \
  -H "X-Signature: sha256=generated_hmac_signature"

Resposta de sucesso

200 OK Metadados do gateway
{
  "site_name": "InnovaPay África",
  "site_logo": "https://innovapayafrica.com/storage/images/2026/10/07/20261007_085648_default_QlJ6.png",
  "site_url": "https://innovapayafrica.com",
  "gateway_name": "InnovaPay África Payment Gateway",
  "gateway_description": "Secure payment powered by InnovaPay África",
  "features": {
    "ssl_secured": "SSL Secured",
    "instant_processing": "Instant",
    "global_support": "Global",
    "mobile_ready": "Mobile Ready"
  },
  "environments": {
    "production": "Production Mode - Live payment processing is active",
    "sandbox": "Test Mode - This is a test transaction. No real money will be charged"
  },
  "api_version": "1.0",
  "status": "active"
}

Recurring Payments & Subscriptions

Create, retrieve, cancel, and renew external subscriptions through dedicated Merchant API endpoints. DigiKash persists the schedule, generates hosted invoices, and advances the subscription after verified payment completion.

Customer-authorized recurring billing DigiKash automatically creates each due renewal invoice, but it does not store a buyer card or payment mandate. The customer authorizes every hosted checkout. Unattended card-on-file charging still requires a gateway-specific recurring-billing customization.

Built-in plans

DigiKash platform plans can renew automatically from a user wallet when the server scheduler is running. Trials, grace periods, cancellations, plan changes, transactions, and invoices are handled inside DigiKash.

Dedicated API lifecycle

DigiKash stores the external reference, amount, cycle, next billing date, status, and invoices. Merchant-scoped endpoints expose the current state without leaking another merchant or environment.

Customer authorization

Send or display the invoice payment_url. DigiKash activates or extends the subscription only after payment completion; your application should still verify the signed completed IPN before granting its own access.

Subscription Endpoints

Método Endpoint Finalidade
POST /api/v1/subscriptions Create a subscription and its first invoice, or schedule it for a future start.
GET /api/v1/subscriptions List subscriptions for the authenticated merchant and selected environment.
GET /api/v1/subscriptions/{subscriptionId} Retrieve current status and the latest 20 invoices.
POST /api/v1/subscriptions/{subscriptionId}/cancel Cancel at period end by default, or immediately with at_period_end=false.
POST /api/v1/subscriptions/{subscriptionId}/renew Create or recover a due hosted renewal checkout. Active subscriptions cannot renew early.

Required Headers

Cabeçalho Obrigatório Descrição
X-Merchant-Key / X-API-Key Sim Use the credentials that belong to the selected sandbox or production environment.
X-Environment Recomendado production ou sandbox. Defaults to production.
X-Timestamp / X-Signature Sim HMAC-SHA256 request authentication described in the Authentication section.
Idempotency-Key Strongly recommended A UUID or another unique value, up to 255 characters. Retrying the identical request within 24 hours returns the original response with Idempotent-Replayed: true. Reusing the key with different parameters returns 409.

Create Subscription Fields

Campo Obrigatório Regras
external_referenceSimUnique per merchant and environment; maximum 100 characters.
billing_cycleSimdaily, weekly, monthly, half_yearly, ou yearly.
payment_amountSimNumeric and at least 1 in the selected currency.
currency_codeSimAn enabled currency for this merchant.
customer_emailSimValid email; maximum 150 characters.
success_redirect, cancel_redirect, ipn_urlSimAbsolute URLs with a maximum of 255 characters. ipn_url must use HTTPS and resolve to a public address; redirects and private/internal webhook targets are blocked.
customer_name, descriptionNãoCustomer-facing context for the hosted invoice.
starts_atNãoISO 8601 date-time. Omit for immediate checkout; past start dates are rejected.
allow_payment_methodsNãoA method code, comma-separated codes, or an array of enabled method codes.
metadataNãoJSON object with at most 50 top-level entries. Do not store secrets or card data.

Subscription Status Lifecycle

Estado Significado Merchant action
pendingThe first invoice is unpaid or the future start date has not arrived.Open latest_invoice.payment_url when available.
activeThe current billing period has a verified completed payment.Grant access only through current_period_end.
past_dueThe paid period ended or the due renewal failed and payment is still required.Deliver the pending checkout or call the renew endpoint after failure or expiry.
cancelledNo more invoices will be generated.Create a new subscription to restart billing.

Recommended Renewal Flow

STEP 1

Create subscription

POST the customer, amount, billing cycle, callbacks, and your unique external_reference.

STEP 2

Collect first invoice

Open latest_invoice.payment_url so the customer can authorize the initial hosted checkout.

STEP 3

Confirm payment

Verify the completed IPN. DigiKash marks the invoice paid, activates access, and sets next_billing_at.

STEP 4

Collect renewals

The scheduler creates due invoices. Poll GET subscription, then deliver the new pending invoice payment_url to the customer.

Create subscription Hosted invoice Completed IPN Active period Next due invoice

Complete PHP Example: Monthly Renewal

This server-side example creates a monthly subscription, signs the exact raw JSON body, calls DigiKash, and redirects the customer to the first hosted invoice.

<?php

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;

$path = '/api/v1/subscriptions';
$payload = [
    'external_reference' => 'CUSTOMER-PRO-1042',
    'billing_cycle' => 'monthly',
    'currency_code' => 'USD',
    'payment_amount' => 29.00,
    'description' => 'Pro plan monthly subscription',
    'customer_name' => 'Jane Doe',
    'customer_email' => 'jane@example.com',
    'success_redirect' => 'https://merchant.example/billing/success',
    'cancel_redirect' => 'https://merchant.example/billing/cancel',
    'ipn_url' => 'https://merchant.example/webhooks/innovapay África',
];

$body = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$timestamp = (string) time();
$idempotencyKey = (string) Str::uuid(); // Persist this key until the request succeeds.
$signaturePayload = implode('.', [$timestamp, 'POST', $path, $body]);
$signature = hash_hmac(
    'sha256',
    $signaturePayload,
    config('services.innovapay África.api_secret'),
);

$checkout = Http::withHeaders([
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'X-Environment' => 'production',
    'X-Merchant-Key' => config('services.innovapay África.merchant_key'),
    'X-API-Key' => config('services.innovapay África.api_key'),
    'X-Timestamp' => $timestamp,
    'X-Signature' => 'sha256='.$signature,
    'Idempotency-Key' => $idempotencyKey,
])->withBody($body, 'application/json')
    ->post('https://innovapayafrica.com'.$path)
    ->throw()
    ->json();

// Save the subscription ID and open the first hosted invoice.
$subscription = $checkout['data'];

return redirect()->away($subscription['latest_invoice']['payment_url']);

Expected Checkout Response

201 Created Subscription and first hosted invoice created
{
  "data": {
    "id": "2bbcf684-3156-43ac-a06d-a5c641641eef",
    "external_reference": "CUSTOMER-PRO-1042",
    "environment": "production",
    "status": "pending",
    "billing_cycle": "monthly",
    "amount": "29.00000000",
    "currency_code": "USD",
    "next_billing_at": "2026-08-13T06:00:00+00:00",
    "latest_invoice": {
      "id": "cbf09fac-c188-4219-ac66-e114a7b48dc5",
      "reference": "MSI-2BBCF684315643AC-1",
      "sequence": 1,
      "status": "pending",
      "payment_url": "https://InnovaPay África.example/payment/checkout?token=encrypted&signature=signed",
      "checkout_expires_at": "2026-08-13T21:00:00+00:00"
    }
  }
}

List, Cancel, and Renew Examples

# List, 1-100 records per page. Sign the complete path including the query string.
GET /api/v1/subscriptions?per_page=20&page=1

# Retrieve one subscription and its latest 20 invoices.
GET /api/v1/subscriptions/{subscriptionId}

# Cancel at the end of the paid period (default).
POST /api/v1/subscriptions/{subscriptionId}/cancel
Idempotency-Key: 63632250-3170-421f-8021-9d0a730e90aa
{"at_period_end":true}

# Cancel immediately and invalidate every pending hosted invoice.
POST /api/v1/subscriptions/{subscriptionId}/cancel
Idempotency-Key: a2ce7c46-4bb8-4675-8c45-58f2eed6ff84
{"at_period_end":false}

# Recover a due, failed, or expired renewal checkout.
POST /api/v1/subscriptions/{subscriptionId}/renew
Idempotency-Key: 890508df-f54c-4ec0-a603-e4f5da2a8206
{"force_new":false}
Scheduler requirement Run php artisan schedule:run every minute. DigiKash executes merchant-subscriptions:process --limit=100 without overlapping, creates one due invoice under a database lock, and changes an expired active period to past_due until payment completes.

HTTP Responses and Safe Retries

Estado Significado What to do
200Read, cancellation, or renewal completed.Use the returned resource as the source of truth.
201Subscription created, including a replay of the original create response.Store data.id and the Idempotency-Key.
401 / 403Credentials, signature, environment, or merchant state is invalid.Correct authentication; do not blindly retry.
404The subscription does not exist in this merchant/environment scope.Check the ID and X-Environment.
409Reference conflict, invalid lifecycle transition, reused idempotency key, or an identical request is still running.Read message; honor Retry-After when present.
422Payload or payment configuration validation failed.Correct the fields before retrying.
429Merchant API rate limit exceeded.Wait for Retry-After, then retry with exponential backoff.
503Temporary checkout creation failure.Retry the identical POST with the same Idempotency-Key.

Payment Confirmation Rules

  • Keep your access pending: subscription status=pending and an invoice payment URL do not mean payment has completed.
  • Verify the IPN signature: calculate HMAC-SHA256 over the raw webhook body with the API secret for the webhook environment and compare it with X-Signature.
  • Match your reference: data.ref_trx must match the open renewal invoice and data.environment must match the expected environment.
  • Confirm completed status: only status=completed should activate or extend access. Use data.trx_id with GET /api/v1/verify-payment/{trxId} when an additional server-to-server check is needed.
  • Poll for scheduled invoices: GET the subscription at or after next_billing_at. A new pending latest_invoice contains the customer-authorized renewal checkout URL.
  • Make fulfillment idempotent: store the DigiKash transaction ID and never grant your own service twice if an IPN is retried.
  • Handle failed renewals: status becomes past_due after failure. POST the renew endpoint to create a fresh checkout for the unpaid period.
Practical result The API supports daily, weekly, monthly, half-yearly, and yearly billing cycles with separate sandbox and production records, while preserving hosted-checkout card security.

Webhooks (IPN)

InnovaPay África sends real-time notifications to your specified IPN URL when payment status changes. This ensures you're immediately notified of payment completions, failures, and other status updates. Os webhooks funcionam de forma idêntica nos ambientes sandbox e produção.

Webhooks com reconhecimento de ambiente

Use the same webhook URL for both sandbox and production. InnovaPay África will include environment context in webhook payloads to help you differentiate between test and live transactions.

Entrega fiável InnovaPay África delivers webhooks from a queue and retries any delivery that does not get a 2xx response — up to 6 attempts over roughly 8 hours (after 1 min, 5 min, 30 min, 2 h and 6 h). Every attempt carries the same body, the same signature and the same X-Delivery-Id, so use that id to ignore a repeat. Return a 2xx response as soon as the payload is safely queued or processed.

Cabeçalhos do webhook

Cabeçalho Descrição Exemplo
Content-Type Sempre application/json application/json
X-Signature Assinatura HMAC-SHA256 bruta para verificação a8b9c2d1e5f3...
X-Environment Contexto do ambiente do webhook sandbox | production
X-Event O que aconteceu payment.completed | payment.failed | payment.refunded
X-Delivery-Id Stable id for this webhook; the same on every retry, so you can de-duplicate 4821
X-Attempt Which attempt this is, starting at 1 1

Payload do webhook

Todos os payloads de webhook incluem informação de ambiente para o ajudar a diferenciar entre transações sandbox e de produção:

Contexto do ambiente: environment o campo será sandbox para transações de teste ou production para transações ao vivo. Os IDs de transação são prefixados de acordo (SANDBOX_ ou PRODUCTION_).
{
    "data": {
        "ref_trx": "TXNT4AQFESTAG4F",
        "description": "Order #1234",
        "ipn_url": "https://webhook.site/5711b7d5-917a-4d94-bbb3-c28f4a37bea5",
        "cancel_redirect": "https://merchant.com/cancel",
        "success_redirect": "https://merchant.com/success",
        "customer_name": "John Doe",
        "customer_email": "john@example.com",
        "merchant_name": "Xanthus Wiggins",
        "amount": 200,
        "currency_code": "USD",
        "environment": "production",
        "is_sandbox": false
    },
    "message": "Pagamento concluído",
    "status": "concluído",
    "timestamp": 1705747245
}

Verificação de assinatura

Verifique sempre as assinaturas de webhook para garantir a autenticidade e prevenir pedidos não autorizados. Use o seu segredo de API (específico do ambiente) para verificar assinaturas:

Segredos específicos do ambiente: Use test_webhook_secret para sandbox e webhook_secret para ambientes de produção.
<?php
// Manipulador de webhook Laravel
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use App\Enums\EnvironmentMode;

class InnovaPay ÁfricaWebhookController extends Controller
{
    public function handle(Request $request)
    {
        // Obter cabeçalhos do webhook
        $environment = $request->header('X-Environment', 'production');
        $signature = $request->header('X-Signature');
        
        // Obter o segredo apropriado com base no ambiente
        $secret = $this->getSecretForEnvironment($environment);
        
        // Verificar assinatura
        if (!$this->verifySignature($request->getContent(), $signature, $secret)) {
            Log::warning('InnovaPay África webhook signature verification failed', [
                'environment' => $environment
            ]);
            
            return response()->json(['error' => 'Assinatura inválida'], 401);
        }
        
        $payload = $request->json()->all();
        
        // Lidar com base no ambiente
        if ($environment === EnvironmentMode::SANDBOX->value) {
            return $this->handleSandboxWebhook($payload);
        } else {
            return $this->handleProductionWebhook($payload);
        }
    }
    
    private function getSecretForEnvironment(string $environment): string
    {
        // Devolver segredo de teste para sandbox, segredo ao vivo para produção
        return $environment === 'sandbox' 
            ? config('innovapay África.test_webhook_secret')
            : config('innovapay África.webhook_secret');
    }
    
    private function verifySignature(string $payload, string $signature, string $secret): bool
    {
        $expectedSignature = hash_hmac('sha256', $payload, $secret);
        $providedSignature = str_starts_with($signature, 'sha256=') ? substr($signature, 7) : $signature;

        return hash_equals($expectedSignature, $providedSignature);
    }
    
    private function handleSandboxWebhook(array $payload): JsonResponse
    {
        Log::info('A processar webhook sandbox', $payload);
        
        // A sua lógica específica de sandbox aqui
        // Don't fulfill orders, don't send emails to real customers, etc.
        
        return response()->json(['status' => 'sandbox_processed']);
    }
    
    private function handleProductionWebhook(array $payload): JsonResponse
    {
        Log::info('A processar webhook de produção', $payload);
        
        // A sua lógica de produção aqui
        // Cumpra encomendas, envie emails de confirmação, etc.
        
        return response()->json(['status' => 'processado']);
    }
}
const crypto = require('crypto');
const express = require('express');

const EnvironmentMode = {
    SANDBOX: 'sandbox',
    PRODUCTION: 'production'
};

// Manipulador de webhook
app.post('/api/webhooks/innovapay África', async (req, res) => {
    const environment = req.headers['x-environment'] || 'production';
    const signature = req.headers['x-signature'];
    
    # Obter o segredo apropriado com base no ambiente
    const secret = getSecretForEnvironment(environment);
    
    # Verificar assinatura
    if (!verifySignature(JSON.stringify(req.body), signature, secret)) {
        console.warn('InnovaPay África webhook signature verification failed', {
            environment: environment
        });
        
        return res.status(401).json({ error: 'Assinatura inválida' });
    }
    
    const payload = req.body;
    
    try {
        # Lidar com base no ambiente
        if (environment === EnvironmentMode.SANDBOX) {
            await handleSandboxWebhook(payload);
        } else {
            await handleProductionWebhook(payload);
        }
        
        res.json({ status: 'processado' });
    } catch (error) {
        console.error('Erro de processamento de webhook:', error);
        res.status(500).json({ error: 'Processamento falhou' });
    }
});

function getSecretForEnvironment(environment) {
    # Devolver segredo de teste para sandbox, segredo ao vivo para produção
    return environment === 'sandbox' 
        ? process.env.INNOVAPAY ÁFRICA_TEST_WEBHOOK_SECRET
        : process.env.INNOVAPAY ÁFRICA_WEBHOOK_SECRET;
}

function verifySignature(payload, signature, secret) {
    if (!signature) {
        return false;
    }
    
    const expectedSignature = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
    const providedSignature = signature.startsWith('sha256=') ? signature.slice(7) : signature;
    
    return crypto.timingSafeEqual(
        Buffer.from(expectedSignature),
        Buffer.from(providedSignature)
    );
}

async function handleSandboxWebhook(payload) {
    console.log('A processar webhook sandbox:', payload);
    
    # A sua lógica específica de sandbox aqui
    # Don't fulfill orders, don't send emails to real customers, etc.
}

async function handleProductionWebhook(payload) {
    console.log('A processar webhook de produção:', payload);
    
    # A sua lógica de produção aqui
    # Cumpra encomendas, envie emails de confirmação, etc.
}
import hmac
import hashlib
import json
import logging
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods

logger = logging.getLogger(__name__)

ENVIRONMENT_MODE = {
    'SANDBOX': 'sandbox',
    'PRODUCTION': 'production'
}

@csrf_exempt
@require_http_methods(["POST"])
def innovapay África_webhook(request):
    environment = request.headers.get('X-Environment', 'production')
    signature = request.headers.get('X-Signature', '')
    
    # Obter o segredo apropriado com base no ambiente
    secret = get_secret_for_environment(environment)
    
    # Verificar assinatura
    if not verify_signature(request.body, signature, secret):
        logger.warning('InnovaPay África webhook signature verification failed', extra={
            'environment': environment
        })
        
        return JsonResponse({'error': 'Assinatura inválida'}, status=401)
    
    try:
        payload = json.loads(request.body)
        
        # Lidar com base no ambiente
        if environment == ENVIRONMENT_MODE['SANDBOX']:
            handle_sandbox_webhook(payload)
        else:
            handle_production_webhook(payload)
        
        return JsonResponse({'status': 'processado'})
    
    except Exception as e:
        logger.error(f'Erro de processamento de webhook:{str(e)}')
        return JsonResponse({'error': 'Processamento falhou'}, status=500)

def get_secret_for_environment(environment):
    from django.conf import settings
    
    # Devolver segredo de teste para sandbox, segredo ao vivo para produção
    return (settings.INNOVAPAY ÁFRICA_TEST_WEBHOOK_SECRET 
            if environment == 'sandbox' 
            else settings.INNOVAPAY ÁFRICA_WEBHOOK_SECRET)

def verify_signature(payload, signature, secret):
    if not signature:
        return False
    
    expected_signature = hmac.new(
        secret.encode('utf-8'),
        payload,
        hashlib.sha256
    ).hexdigest()
    provided_signature = signature[7:] if signature.startswith('sha256=') else signature
    
    return hmac.compare_digest(expected_signature, provided_signature)

def handle_sandbox_webhook(payload):
    logger.info('A processar webhook sandbox', extra=payload)
    
    # A sua lógica específica de sandbox aqui
    # Don't fulfill orders, don't send emails to real customers, etc.

def handle_production_webhook(payload):
    logger.info('A processar webhook de produção', extra=payload)
    
    # A sua lógica de produção aqui
    # Cumpra encomendas, envie emails de confirmação, etc.

Boas práticas específicas do ambiente

Webhooks sandbox
  • Use para testar a integração de webhooks
  • Sem transações de dinheiro real
  • Don't fulfill actual orders
  • Don't send emails to real customers
  • Use o segredo de webhook de teste para verificação
Webhooks de produção
  • Processe encomendas reais de clientes
  • Envie emails de confirmação
  • Atualize sistemas de inventário
  • Acione processos de cumprimento
  • Use o segredo de webhook de produção para verificação

Exemplos de integração

Exemplos de integração orientados para produção para plataformas e frameworks populares. Mantenha a seleção de gateway na Configuração da API do Comerciante e depois assine cada pedido de API a partir do seu servidor.

Configuração do ambiente: Substitua {environment} por sandbox ou produção e use as credenciais correspondentes - prefixo test_ para sandbox, sem prefixo para produção nos seus ficheiros de configuração.
Regras de finalização mais recentes A moeda solicitada deve corresponder à configuração do comerciante e à carteira ativa. A visibilidade do gateway é controlada na Configuração da API do Comerciante; allow_payment_methods apenas restringe a lista de gateways já elegíveis.
Assinatura necessária Os exemplos devem incluir X-Timestamp e X-Signature gerados com o Segredo da API para o ambiente sandbox ou de produção selecionado. Consulte Autenticação para o payload exato da assinatura.
<?php
// Laravel Integration Service
namespace App\Services;

use Illuminate\Support\Facades\Http;
use Exception;

class InnovaPay ÁfricaService
{
    private string $baseUrl;
    private string $merchantKey;
    private string $apiKey;
    private string $environment;

    public function __construct()
    {
        $this->baseUrl = config('innovapay África.base_url');
        $this->merchantKey = config('innovapay África.merchant_key');
        $this->apiKey = config('innovapay África.api_key');
        $this->environment = config('innovapay África.environment'); // 'sandbox' or 'production'
    }

    public function initiatePayment(array $paymentData): array
    {
        try {
            $response = Http::withHeaders([
                'Content-Type' => 'application/json',
                'X-Environment' => $this->environment,
                'X-Merchant-Key' => $this->merchantKey,
                'X-API-Key' => $this->apiKey,
            ])->post("{$this->baseUrl}/api/v1/initiate-payment", $paymentData);

            if ($response->successful()) {
                return $response->json();
            }

            throw new Exception('InnovaPay África API Error: Payment initiation failed');
        } catch (Exception $e) {
            throw new Exception('InnovaPay África API Error: ' . $e->getMessage());
        }
    }

    public function verifyPayment(string $transactionId): array
    {
        try {
            $response = Http::withHeaders([
                'Accept' => 'application/json',
                'X-Environment' => $this->environment,
                'X-Merchant-Key' => $this->merchantKey,
                'X-API-Key' => $this->apiKey,
            ])->get("{$this->baseUrl}/api/v1/verify-payment/{$transactionId}");

            if ($response->successful()) {
                return $response->json();
            }

            throw new Exception('InnovaPay África API Error: Payment verification failed');
        } catch (Exception $e) {
            throw new Exception('InnovaPay África API Error: ' . $e->getMessage());
        }
    }
}

// Configuration (config/innovapay África.php)
return [
    'base_url' => env('INNOVAPAY ÁFRICA_BASE_URL', 'https://innovapayafrica.com'),
    'environment' => env('INNOVAPAY ÁFRICA_ENVIRONMENT', 'sandbox'), // sandbox or production
    'merchant_key' => env('INNOVAPAY ÁFRICA_MERCHANT_KEY'), // Use appropriate prefix
    'api_key' => env('INNOVAPAY ÁFRICA_API_KEY'), // Use appropriate prefix
];

// Usage in Controller
class PaymentController extends Controller
{
    public function initiatePayment(Request $request, InnovaPay ÁfricaService $innovapay África)
    {
        $paymentData = [
            'payment_amount' => $request->amount,
            'currency_code' => 'USD',
            'ref_trx' => 'ORDER_' . time(),
            'description' => $request->description,
            'success_redirect' => route('payment.success'),
            'cancel_redirect' => route('payment.cancelled'),
            'ipn_url' => route('webhooks.innovapay África'),
            'allow_payment_methods' => ['stripe', 'paypal'],
        ];

        try {
            $result = $innovapay África->initiatePayment($paymentData);
            return redirect($result['payment_url']);
        } catch (Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }
}
// Node.js Integration Service
const axios = require('axios');

class InnovaPay ÁfricaService {
    constructor() {
        this.baseUrl = process.env.INNOVAPAY ÁFRICA_BASE_URL || 'https://innovapayafrica.com';
        this.environment = process.env.INNOVAPAY ÁFRICA_ENVIRONMENT || 'sandbox'; // sandbox or production
        this.merchantKey = process.env.INNOVAPAY ÁFRICA_MERCHANT_KEY; // Use appropriate prefix
        this.apiKey = process.env.INNOVAPAY ÁFRICA_API_KEY; // Use appropriate prefix
    }

    async initiatePayment(paymentData) {
        try {
            const response = await axios.post(`${this.baseUrl}/api/v1/initiate-payment`, paymentData, {
                headers: {
                    'Content-Type': 'application/json',
                    'X-Environment': this.environment,
                    'X-Merchant-Key': this.merchantKey,
                    'X-API-Key': this.apiKey
                }
            });

            return response.data;
        } catch (error) {
            throw new Error(`InnovaPay África API Error: ${error.message}`);
        }
    }

    async verifyPayment(transactionId) {
        try {
            const response = await axios.get(`${this.baseUrl}/api/v1/verify-payment/${transactionId}`, {
                headers: {
                    'Accept': 'application/json',
                    'X-Environment': this.environment,
                    'X-Merchant-Key': this.merchantKey,
                    'X-API-Key': this.apiKey
                }
            });

            return response.data;
        } catch (error) {
            throw new Error(`InnovaPay África API Error: ${error.message}`);
        }
    }
}

// Express.js Route Example
const express = require('express');
const app = express();
const innovapay África = new InnovaPay ÁfricaService();

app.post('/initiate-payment', async (req, res) => {
    const paymentData = {
        payment_amount: req.body.amount,
        currency_code: 'USD',
        ref_trx: `ORDER_${Date.now()}`,
        description: req.body.description,
        success_redirect: `${req.protocol}://${req.get('host')}/payment/success`,
        cancel_redirect: `${req.protocol}://${req.get('host')}/payment/cancelled`,
        ipn_url: `${req.protocol}://${req.get('host')}/webhooks/innovapay África`,
        allow_payment_methods: ['stripe', 'paypal'],
    };

    try {
        const result = await innovapay África.initiatePayment(paymentData);
        res.redirect(result.payment_url);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

module.exports = InnovaPay ÁfricaService;
# Python/Django Integration Service
import os
import requests
from django.conf import settings

class InnovaPay ÁfricaService:
    def __init__(self):
        self.base_url = getattr(settings, 'INNOVAPAY ÁFRICA_BASE_URL', 'https://innovapayafrica.com')
        self.environment = getattr(settings, 'INNOVAPAY ÁFRICA_ENVIRONMENT', 'sandbox')  # sandbox or production
        self.merchant_key = getattr(settings, 'INNOVAPAY ÁFRICA_MERCHANT_KEY')  # Use appropriate prefix
        self.api_key = getattr(settings, 'INNOVAPAY ÁFRICA_API_KEY')  # Use appropriate prefix

    def initiate_payment(self, payment_data):
        try:
            headers = {
                'Content-Type': 'application/json',
                'X-Environment': self.environment,
                'X-Merchant-Key': self.merchant_key,
                'X-API-Key': self.api_key
            }

            response = requests.post(
                f"{self.base_url}/api/v1/initiate-payment",
                headers=headers,
                json=payment_data,
                timeout=30
            )

            response.raise_for_status()
            return response.json()

        except requests.RequestException as e:
            raise Exception(f'InnovaPay África API Error: {str(e)}')

    def verify_payment(self, transaction_id):
        try:
            headers = {
                'Accept': 'application/json',
                'X-Environment': self.environment,
                'X-Merchant-Key': self.merchant_key,
                'X-API-Key': self.api_key
            }

            response = requests.get(
                f"{self.base_url}/api/v1/verify-payment/{transaction_id}",
                headers=headers,
                timeout=30
            )

            response.raise_for_status()
            return response.json()

        except requests.RequestException as e:
            raise Exception(f'InnovaPay África API Error: {str(e)}')

# Django Settings Configuration
INNOVAPAY ÁFRICA_BASE_URL = 'https://innovapayafrica.com'
INNOVAPAY ÁFRICA_ENVIRONMENT = 'sandbox'  # Change to 'production' for live
INNOVAPAY ÁFRICA_MERCHANT_KEY = os.environ.get('INNOVAPAY ÁFRICA_MERCHANT_KEY')  # Use appropriate prefix
INNOVAPAY ÁFRICA_API_KEY = os.environ.get('INNOVAPAY ÁFRICA_API_KEY')  # Use appropriate prefix

# Django View Example
from django.shortcuts import redirect
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
import json

innovapay África = InnovaPay ÁfricaService()

@csrf_exempt
def initiate_payment(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        
        payment_data = {
            'payment_amount': data['amount'],
            'currency_code': 'USD',
            'ref_trx': f'ORDER_{int(time.time())}',
            'description': data['description'],
            'success_redirect': request.build_absolute_uri('/payment/success/'),
            'cancel_redirect': request.build_absolute_uri('/payment/cancelled/'),
            'ipn_url': request.build_absolute_uri('/webhooks/innovapay África/'),
            'allow_payment_methods': ['stripe', 'paypal'],
        }

        try:
            result = innovapay África.initiate_payment(payment_data)
            return redirect(result['payment_url'])
        except Exception as e:
            return JsonResponse({'error': str(e)}, status=500)
# Environment Variables Setup
export INNOVAPAY ÁFRICA_ENVIRONMENT="sandbox"  # or "production"
export INNOVAPAY ÁFRICA_MERCHANT_KEY="test_merchant_your_key"  # or "merchant_your_key" for production
export INNOVAPAY ÁFRICA_API_KEY="test_your_api_key"  # or "your_api_key" for production

# Initiate Payment
curl -X POST "https://innovapayafrica.com/api/v1/initiate-payment" \
  -H "Content-Type: application/json" \
  -H "X-Environment: $INNOVAPAY ÁFRICA_ENVIRONMENT" \
  -H "X-Merchant-Key: $INNOVAPAY ÁFRICA_MERCHANT_KEY" \
  -H "X-API-Key: $INNOVAPAY ÁFRICA_API_KEY" \
  -d '{
    "payment_amount": 250.00,
    "currency_code": "USD",
    "ref_trx": "ORDER_12345",
    "description": "Premium Subscription",
    "success_redirect": "https://yoursite.com/payment/success",
    "cancel_redirect": "https://yoursite.com/payment/cancelled",
    "ipn_url": "https://yoursite.com/api/webhooks/innovapay África",
    "allow_payment_methods": ["stripe", "paypal"]
  }'

# Verify Payment
curl -X GET "https://innovapayafrica.com/api/v1/verify-payment/TXNQ5V8K2L9N3XM1" \
  -H "Accept: application/json" \
  -H "X-Environment: $INNOVAPAY ÁFRICA_ENVIRONMENT" \
  -H "X-Merchant-Key: $INNOVAPAY ÁFRICA_MERCHANT_KEY" \
  -H "X-API-Key: $INNOVAPAY ÁFRICA_API_KEY"

# Environment-specific credential examples:
# Sandbox: test_merchant_xxxxx, test_api_key_xxxxx
# Production: merchant_xxxxx, api_key_xxxxx

WooCommerce Integration

Advanced InnovaPay África payment gateway with modern WooCommerce Blocks support, dynamic branding, and enterprise-grade security features.

Advanced WooCommerce Integration

Production-ready payment gateway with WooCommerce Blocks (Gutenberg) support, dynamic branding, and secure webhook processing.

3 Minutes Setup
99.9% Uptime
24/7 Webhook Support
Latest Plugin Download

Enterprise-grade WooCommerce payment gateway with modern Blocks support and dynamic branding.

Plugin Size: 45.2 KB
Version: 2.8.0
Last Updated: Oct 27, 2026
System Requirements
  • WordPress 5.8+
  • WooCommerce 6.0+
  • PHP 8.1+ (8.2+ Recommended)
  • SSL Certificate (Required)
  • InnovaPay África Merchant Account
  • WooCommerce Blocks Support
Production Ready

Advanced Features

Enterprise-grade payment processing with modern architecture

WooCommerce Blocks

Full Gutenberg checkout compatibility with React-based UI

Dynamic Branding

Auto-fetch logo, colors, and branding from InnovaPay África API

Secure Webhooks

HMAC-SHA256 signature verification for payment callbacks

Compact Mobile UI

Space-efficient, responsive design for all devices

Advanced Security

Multi-header authentication with environment isolation

Test/Live Mode

Seamless sandbox testing with production deployment

Quick Installation Guide

Get started with InnovaPay África WooCommerce integration in minutes

1
Download Latest Plugin

Download InnovaPay África WooCommerce Gateway v2.8.0 from the download section above. This includes all latest features and security updates.

2
Install via WordPress Admin

Navigate to Plugins → Add New → Upload Plugin and select the downloaded ZIP file. The plugin will auto-extract and install.

3
Activate & Configure

Activate the plugin and go to WooCommerce → Settings → Payments → InnovaPay África. Enter your API credentials and webhook secret.

4
Test Integration

Enable Test Mode, process a sandbox transaction to verify Blocks checkout, webhook delivery, and order completion.

5
Go Live

Disable test mode, ensure production API keys are configured, and start accepting real payments with full webhook processing.

API Configuration

Essential API settings for secure payment processing

API Base URL

https://innovapayafrica.com

Auto-configured
Merchant ID & API Key

Your unique merchant credentials from InnovaPay África dashboard

Required
Webhook Secret

HMAC-SHA256 signature verification for secure callbacks

Recommended
Cabeçalhos de autenticação

Required headers for all InnovaPay África API requests:

X-Environment: sandbox|production
X-Merchant-Key: your_merchant_id
X-API-Key: your_api_key
Content-Type: application/json

Webhook Configuration

Real-time payment status updates and order processing

Endpoint do webhook
https://yoursite.com/wc-api/innovapay África_webhook

Configure this URL in your InnovaPay África merchant dashboard for automatic order updates.

Supported Events
  • Payment Success
  • Payment Failed
  • Payment Cancelled
  • Payment Pending
  • Refund Processed
  • Payment Timeout

WooCommerce Blocks Integration

Modern Gutenberg checkout with React-based payment UI

Responsive Design

Compact, mobile-optimized payment interface that adapts to any screen size.

Dynamic Branding

Automatically fetches and displays your InnovaPay África branding and logos.

Security Indicators

Clear SSL and security badges to build customer trust during checkout.

Test Mode Support

Clear sandbox indicators for testing without affecting live transactions.

Production Deployment Checklist

Ensure everything is configured correctly before going live

Technical Requirements
API Configuration
Final Verification

Troubleshooting

Common issues and solutions for InnovaPay África WooCommerce integration

Payment method not showing in checkout

Solutions:

  • Verify plugin is activated and enabled in WooCommerce → Settings → Payments
  • Clear browser cache and WooCommerce cache
  • Check if API credentials are correctly configured
  • Ensure SSL certificate is properly installed
401 Unauthorized API errors

Solutions:

  • Verify Merchant ID and API Key are correct
  • Ensure environment (sandbox/production) matches your credentials
  • Check that all required headers are being sent
  • Contact InnovaPay África support to verify account status
Orders not updating after payment

Solutions:

  • Verify webhook URL is configured in InnovaPay África dashboard
  • Check webhook secret key matches plugin configuration
  • Review WordPress error logs for webhook processing errors
  • Test webhook delivery using InnovaPay África dashboard tools
Prontidão para lançamento Sandbox primeiro, produção após aprovação

Lista de verificação para sandbox e entrada em produção

Use esta lista de verificação antes de passar de pagamentos de teste para finalização ao vivo. As mesmas rotas de API funcionam em ambos os modos; apenas o cabeçalho de ambiente e o conjunto de credenciais mudam.

Sandbox

Use credenciais de teste e X-Environment: sandbox. As transações são marcadas como sandbox e não representam movimento de dinheiro real.

  • Gere ou copie o ID de Comerciante de teste, a Chave de API e o Segredo da API.
  • Envie pedidos de API assinados com o segredo sandbox.
  • Teste os fluxos de sucesso, cancelamento, pendente, falha, webhook e verificação.

Produção

Use credenciais ao vivo e X-Environment: production apenas após aprovação do administrador, prontidão da carteira e configuração do gateway estarem concluídas.

  • O estado do comerciante deve estar aprovado.
  • Cada moeda ao vivo deve ter uma carteira de comerciante ativa.
  • Os Controlos do Gateway de Pagamento devem conter apenas gateways que deseja que os clientes vejam.
Verificações de lançamento em produção Necessário antes do tráfego ao vivo
Rever configuração
Comerciante aprovado A API de produção devolve 403 até a aprovação do administrador estar concluída.
Assinatura no lado do servidor Cada pedido inclui X-Timestamp e X-Signature gerados com o segredo da API correspondente.
Cobertura de carteira Cada moeda do comerciante tem uma carteira de recetor ativa.
Cobertura de gateway Os gateways selecionados correspondem às moedas que os clientes usarão.
URLs de redirecionamento success_redirect e cancel_redirect são HTTPS e tratam visitas repetidas em segurança.
Verificação de IPN A assinatura do webhook é verificada antes do cumprimento ou atualizações de encomenda no lado da carteira.
Importante Nunca mude apenas o cabeçalho X-Environment. Mude sempre o ID de Comerciante, a Chave de API e o Segredo da API em conjunto para que o ambiente e o conjunto de credenciais correspondam.

Teste interativo da API

Teste InnovaPay África Endpoints da API diretamente a partir desta documentação. Use as credenciais de demonstração abaixo para testes sandbox.

Informação de pagamento de demonstração MODO SANDBOX

Use estas credenciais de demonstração para testar todos os métodos de pagamento no ambiente sandbox:

Carteira de demonstração
ID da carteira: 123456789 PIN da carteira: 123456
Aprovado automaticamente em sandbox
Voucher de demonstração
Código do voucher: TESTVOUCHER
Resgate instantâneo
Pagamento por gateway
Comportamento: Sucesso automático
Sem redirecionamento externo
Diretrizes de teste
  • Cabeçalho de ambiente: Inclua sempre X-ENVIRONMENT: sandbox nos seus pedidos de API
  • Credenciais de demonstração: Use os códigos de carteira/voucher de demonstração fornecidos para testar fluxos de pagamento
  • Comportamento sandbox: Todos os pagamentos são concluídos automaticamente com sucesso sem processamento de dinheiro real
  • Controlos do gateway: A finalização alojada respeita os gateways configurados na Configuração da API do Comerciante para a moeda selecionada.
  • Estado da transação: As transações sandbox são marcadas com "SANDBOX_TRANSACTION" nos comentários
  • Notificações IPN: As notificações webhook funcionam normalmente no modo sandbox
Configuração do ambiente: Use sandbox para testes e production para transações ao vivo. Apenas as credenciais sandbox usam test_ prefixo, as credenciais de produção não têm prefixo.
Consola de teste da API
Cabeçalhos de autenticação
Sandbox: test_*, Produção: sem prefixo
Sandbox: test_*, Produção: sem prefixo
Usado localmente para gerar X-Signature. Prefira segredos sandbox na consola do navegador.
Parâmetros do pedido
O código da moeda deve estar em maiúsculas (ex.: USD, EUR, BDT). Deve usar a moeda que corresponde à configuração da sua loja de comerciante.
Limite os métodos de finalização por nome. Aceita string CSV ou array JSON. Não diferencia maiúsculas de minúsculas.
Ambiente sandbox

URL base: https://innovapayafrica.com

Cabeçalho de ambiente: X-Environment: sandbox

Credenciais: Use test_ chaves com prefixo

Finalidade: Testes seguros sem dinheiro real

Ambiente de produção

URL base: https://innovapayafrica.com

Cabeçalho de ambiente: X-Environment: production

Credenciais: Sem prefixo para chaves de produção

Finalidade: Transações ao vivo com dinheiro real

Error Codes

InnovaPay África API uses conventional HTTP response codes to indicate the success or failure of API requests.

HTTP Status Codes

Código Estado Descrição
200 OK Request succeeded
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API credentials
403 Forbidden Insufficient permissions
404 Not Found Resource not found
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Server error occurred

API Error Codes

Error Code Descrição Solution
INVALID_CREDENTIALS Invalid API credentials provided Check your Merchant ID and API Key
INSUFFICIENT_FUNDS Customer has insufficient funds Customer needs to add funds to their wallet
PAYMENT_DECLINED Payment was declined by payment processor Customer should try a different payment method
INVALID_AMOUNT Payment amount is invalid Check minimum and maximum amount limits
INVALID_CURRENCY Unsupported currency code Use a supported currency code (USD, EUR, etc.)
DUPLICATE_REFERENCE Transaction reference already exists Use a unique transaction reference
EXPIRED_SESSION Payment session has expired Create a new payment request
MERCHANT_SUSPENDED Merchant account is suspended Contacto InnovaPay África support

Formato de resposta de erro

{
  "success": false,
  "message": "Validation failed",
  "error_code": "INVALID_AMOUNT",
  "errors": {
    "payment_amount": [
      "The payment amount must be at least 1.00"
    ]
  },
  "timestamp": "2024-01-20T10:30:00Z"
}
Tratamento de erros Verifique sempre o campo success nas respostas da API e trate os erros adequadamente na sua aplicação.

Suporte

Technical Support

Need assistance with InnovaPay África API integration? Our technical team provides comprehensive support.

Support Hours: 24/7 for critical issues