# Payout

## Summary

Send money locally with Klasha to bank accounts and mobile money wallets in Africa.

### Coverage

* NGN
* [ZAR](https://developers.klasha.com/transfers/payout/zar-payout-new-encryption)
* GHS (beta)
* KES (beta)

You can transfer money in four easy steps:

1. Verify the account number
2. Create transfer recipient
3. Initiate a transfer
4. Listen for status.

***

{% hint style="info" %}

### Before you begin!

* [Link](https://api.postman.com/collections/25963887-8947bcfa-aaf7-471a-9df1-18c54dc736ad?access_key=PMAT-01GWN42BNXSAS7WJ7P46PW6B3R) to the Postman collection
* Find your keys on the Klasha Dashboard → Settings → Generate API Keys ([here](https://dashboard.klasha.com/settings/keys))

<img src="https://257545343-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNw4nU37LIEg41plxXG5u%2Fuploads%2FvBXI8QATrncq17zlRm1P%2Fdashboad-klasha-settings.png?alt=media&#x26;token=1ebaf2b3-7e99-4490-9ede-a660c8d0035c" alt="" data-size="original">

{% endhint %}

<details>

<summary>Generate bearer token</summary>

Using the Token [endpoint](https://developers.klasha.com/~/revisions/UU3P5ANUZVJrY1nR5gP2/overview/token-generation) to generate a bearer token. The token obtained from the api should be passed in the used to authenticate the requests below.

</details>

<details>

<summary>Fetch bank codes</summary>

Use the API below to fetch the available bank codes.

> <mark style="color:blue;">**GET**</mark><mark style="color:blue;">:</mark> {{base\_url}}/wallet/merchant/bank/transfer/request/banks/:currency

```json
{
    "message": "success",
    "error": null,
    "data": [
        {
            "code": "90527",
            "name": " OJOKORO MICROFINANCE BANK"
        },
        ...
        {
            "code": "090384",
            "name": "ZION MFB"
        }
    ]
}
```

</details>

<details>

<summary>Verify account number</summary>

Using the Resolve account number endpoint on the Postman collection [here](https://api.postman.com/collections/8963555-c750eddc-38e9-4866-87ed-c5dc266c25fd?access_key=PMAT-01HZPRY6GFVT9DYGXZYYNM5SS3), verify the account number by making use of the bank codes gotten from here. See an example in the screenshot below

<img src="https://257545343-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNw4nU37LIEg41plxXG5u%2Fuploads%2FTlfTp9nqDurOyu8o21Ki%2Fverify-account-img.png?alt=media&#x26;token=2f5a95e3-a79b-4823-88dc-4b45cdd1ca92" alt="" data-size="original">

</details>

## Generate a transfer reference

It’s a unique reference sent as `requestId` that can be used to uniquely identify a transfer.

#### Initiate a transfer

<details>

<summary>Create payload</summary>

```json
{
	"amount": 1000,
	"country": "NG",
	"currency": "NGN",
	"bankCode": "044",
	"bankName": "Access Bank",
	"accountNumber": "0690000032",
	"accountName": "Pastor Bright",
	"requestId": "kbtr-3857-011-null-166993253334816",
	"description": "certification"
}




Fields specification:

- amount is the amount to payout
- country is the country of the beneficiary
- currency is the currency of payout
- bankcode is the code of the bank which can be gotten by calling the Bank code endpoint
- bankName is the name of the bank
- accountNumber is the beneficiary account number
- accountName is the beneficiary account name
- requestId is the transaction reference
- description is the narration or reason for the payout
```

</details>

* Serialize the payload

#### Encryption Algorithm

You need to encrypt the entire create transfer payload that we specify on the previous point (here). In order to encrypt the body correctly, you’d need the encryptionKey (that you can obtain following this guide here). Find an encryption algorithm code snippet below:

{% tabs %}
{% tab title="Java" %}
{% code overflow="wrap" lineNumbers="true" fullWidth="true" %}

```java
public static String encrypt3DES(String messageToEncrypt, byte[] secret) throws NoSuchPaddingException, NoSuchAlgorithmException,
            InvalidAlgorithmParameterException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
    SecretKeySpec secretKeySpec = new SecretKeySpec(secret, "TripleDES");
    byte[] iv = Arrays.copyOfRange(secret, 0, 8);
    IvParameterSpec ivSpec = new IvParameterSpec(iv);

    Cipher encryptCipher = Cipher.getInstance("TripleDES/CBC/PKCS5Padding");
    encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec);

    byte[] secretMessagesBytes = messageToEncrypt.getBytes(StandardCharsets.UTF_8);
    byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessagesBytes);

    return Base64.getEncoder().encodeToString(encryptedMessageBytes);
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

<details>

<summary>Encrypted Payload</summary>

The result of the encryption of the payload that we specified here have to be used with the Merchant payout endpoint as shown below:

<img src="https://257545343-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNw4nU37LIEg41plxXG5u%2Fuploads%2FdOz6AGCl79uIZljcz28A%2Fencryption-payload-postman.png?alt=media&#x26;token=2dd9f334-11f9-4895-8a48-edd12814b01a" alt="" data-size="original">

</details>

**Merchant Payout request**

## Make a POST call to the Merchant payout request API

> <mark style="color:green;">`POST`</mark> `{{env_url}}/wallet/merchant/{businessId}/bank/transfer/v2/request`

You would need to pass, as a header the <mark style="color:red;">x-auth-token</mark>. This can be obtained from your merchant **dashboard → Settings → Generate API keys → Merchant public key**.

#### Headers

| Key           | Value                    |
| ------------- | ------------------------ |
| Content-Type  | application/json         |
| x-auth-token  | Your merchant public key |
| Authorization | Bearer \<token here>     |

**Request body (encrypted):**

```json
{ 
  "message": "encrypted-request-body"
}
```

## Listen for a status response

When a transfer is initiated, it could take a few seconds or minutes to be processed. This is why we recommend relying on webhooks for verification as opposed to polling.

Once a transfer is processed, we send the final status of the transfer as a POST request to your webhook URL (see [webhook](https://developers.klasha.com/~/revisions/wTs3QfcE0Q2ImN5VimGe/misc/webhook) details here).

### Get wallet balance

To get your wallet balance you would need to make a GET request to the API below:

<mark style="color:green;">`GET`</mark> <mark style="color:red;">{{env\_url}}</mark>/nucleus/business/api/wallets

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `Bearer <token>`   |
| x-auth-token  | `<public key>`     |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "message": "success",
    "error": null,
    "data": [
        {
            "id": 66,
            "currency": "NGN",
            "ledgerBalance": 100.0,
            "availableBalance": 100.0,
            "walletType": "BUSINESS",
            "businessId": 3,
            "createdAt": "2023-12-19 14:54:49",
            "updatedAt": "2023-12-19 14:54:49"
        }
    ]
}
```

{% endtab %}

{% tab title="400" %}

```json
{
    "message": "`error message",
    "error": "error",
    "data": null
}
```

{% endtab %}
{% endtabs %}

The possible statuses are listed and described in the following table:

| Status                                       | Description                                                                   |
| -------------------------------------------- | ----------------------------------------------------------------------------- |
| <mark style="color:green;">successful</mark> | This is sent when the transfer is successful                                  |
| <mark style="color:red;">failed</mark>       | This is sent when the transfer fails                                          |
| <mark style="color:orange;">pending</mark>   | This transfer is still in progress. Please wait for either success or failed. |

#### Polling transfer statuses

* You can fetch the transfer from the `Find by ref` API on the Postman collection to know the status. See example in the below screenshot.

<figure><img src="https://257545343-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FNw4nU37LIEg41plxXG5u%2Fuploads%2FksMLvk8dacZdhRnACT7p%2Fpolling-transfer-status.png?alt=media&#x26;token=90c93adc-6f53-4184-ad06-c6604d0700e0" alt="" width="563"><figcaption></figcaption></figure>

### Source wallet

All transfers would be debited from NGN Wallet balance. Ensure you have sufficient balance before making any transfer request.
