Skip to main content

Payments

The Payment API for Transfa provides a way to request for payment or check for API statuses. It also allows developers to receive webhook calls and check the availability of the API. On this page, we will discuss the payment life-cycle, quickly expose how to make a successful request using the API-key authentication and the Idempotency feature, and also how to receive webhooks and check their signature.

Here are the actions you can do for the moment:

Authentication

The Transfa API uses API key authentication for most of the endpoints except the API status endpoint. The API Key is passed in the Authorization header with the following format Authorization: Api-Transfa-Key YOUR_API_KEY. Here's an example of a request written in Python. The following request creates a payment of type request-payment.

import requests

url = "https://api.transfapp.com/api/v1/optimus/payment/"

payload = {
"account_alias": "67101010",
"type": "request-payment",
"amount": 1200,
"mode": "mtn-benin",
"webhook_url": "https://ptsv2.com/t/xw7zq-16s57325355/post"
}
headers = {
"Content-Type": "application/json",
"Idempotency-Key": "433753a7ae9d44f4b95903bbe813553a",
"Authorization": "Api-Transfa-Key YOUR_API_KEY"
}

response = requests.request("POST", url, json=payload, headers=headers)

print(response.text)

Types of API Keys

There are two types of API keys: Testing API Keys and Production API Keys.

A Testing API key starts with the prefix ak_test coming with a private key with a prefix ps_test. The private key is used to sign data send/received via the webhooks.

For the production keys, the API key starts with the ak_live prefix and the private key with the ps_live prefix.

tip

The API keys are generated and directly shown to you when you create them. We do not store the keys following our security guidelines. Make sure to keep them safe for usage.

In case of leaking, you can freely revoke the API keys on the dashboard.

Idempotency

Idempotency refers to the property of an operation where applying it multiple times has the same effect as applying it once.

In a system, server timeouts or network issues can cause duplicated requests. To prevent multiple charges to the user, each payment request made to the Payment API requires an idempotency key in the header.

The header name is Idempotency-key, and the value must always be a UUID4 in hexadecimal format. If a payment request with the same idempotency key is detected, the system will ignore the request and return a 429 error, indicating that a resource with this key is already in use.

After handling the payment, whether in a state of success or error, the key will be removed from the database. However, reusing the same key is not recommended.

Webhooks

To retrieve the status of a payment, you can always attempt to poll using the Retrieve a Payment endpoint and check for the status field in the received payload. However, we offer a webhook feature where you can specify a webhook URL webhook_url in the HTTP payload of a payment request.

When a payment is requested, its status changes over time, transitioning from pending to processing, and eventually to either success or failed. Whenever there is an update on the payment status, we will send a request to the provided webhook URL. Here is an example of a payload:

{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"payment": 200,
"event": "payment:processing",
"created": "2024-04-03T20:42:01.182Z",
"updated": "2024-04-03T20:42:01.182Z"
}

The possible events for payments are:

  • payment:processing => Indicates that the payment is processing.
  • payment:success => Indicates that the payment was successful.
  • payment:failed => Indicates that the payment has failed.

However, an important aspect of the webhook feature is the signature.

A webhook request can be intercepted in a Man-In-The-Middle attack, allowing the attacker to modify or tamper with the data in the payload. For instance, imagine receiving confirmation that a payment was successful when, in reality, the payment has failed. This could have detrimental effects on your business.

To address this issue, we include a signature in the request headers. The header name is x-webhook-transfa-signature, and it contains the signature of the payload.

The objective is to utilize the private secret provided on the dashboard when requesting an API key. Upon receiving a request, sign the payload using this secret, and then compare the value you obtain with the x-webhook-transfa-signature header value. If they match, you can trust the request.

The SDKs provide a way to check for the payload authenticity without having to manually write the code logic.

from transfa.webhook import Webhook

...

webhook = Webhook(webhook_token=secret_key, body=body, headers=request.headers)

verified = webhook.verify()

If not, simply ignore it and conduct an investigation into your networks.