Create Virtual Accounts on demands, receive funds from customers via Virtual Account Number and get notification on Virtual Accounts usage.
Dedicated Virtual Accounts (DVAs) is a service that lets you create Nigerian virtual accounts for your customers. These accounts allow your customers to receive payment from their customers.
When you create a Dedicated Virtual Account (DVA) for a customer, all bank transfers to that account will automatically be recorded as transactions from that customer.
Coverage
NGN
Integration steps
You can generate a VA and start receiving money in 3 easy steps:
Prepare payload (payload includes: first name, last name, BVN, and email)
Find your keys on the Klasha Dashboard → Settings → Generate API Keys (here)
Klasha Dashboard, Generate API Keys page
Encryption Algorithm
Encrypt the plain request body to get an encrypted request body. We use a Cipher Block Chaining encryption and you will use your entire encryption key size for this encryption mode.
Navigate to Dashboard->Settings->Generate API keys -- Encryption key
Below is a CBC encryption code snippet in Java:
publicstaticStringencryptCBC(String stringToEncrypt,String encryptionkey) {try {SecureRandom sr =newSecureRandom();byte[] salt =newbyte[8];sr.nextBytes(salt);finalbyte[][] keyAndIV =GenerateKeyAndIV(32,16,1, salt,encryptionkey.getBytes(StandardCharsets.UTF_8),MessageDigest.getInstance("MD5"));Cipher cipher =Cipher.getInstance("AES/CBC/PKCS5Padding");cipher.init(Cipher.ENCRYPT_MODE,newSecretKeySpec(keyAndIV[0],"AES"),newIvParameterSpec(keyAndIV[1]));byte[] encryptedData =cipher.doFinal(stringToEncrypt.getBytes(StandardCharsets.UTF_8));byte[] prefixAndSaltAndEncryptedData =newbyte[16+encryptedData.length];// Copy prefix (0-th to 7-th bytes)System.arraycopy("Salted__".getBytes(StandardCharsets.UTF_8),0, prefixAndSaltAndEncryptedData,0,8);// Copy salt (8-th to 15-th bytes)System.arraycopy(salt,0, prefixAndSaltAndEncryptedData,8,8);// Copy encrypted data (16-th byte and onwards)System.arraycopy(encryptedData,0, prefixAndSaltAndEncryptedData,16,encryptedData.length);returnBase64.getEncoder().encodeToString(prefixAndSaltAndEncryptedData); } catch (Exception e) {thrownewRuntimeException(e); }}
public static byte[][] GenerateKeyAndIV(int keyLength, int ivLength, int iterations, byte[] salt, byte[] password, MessageDigest md) {
int digestLength =md.getDigestLength();int requiredLength = (keyLength + ivLength + digestLength -1) / digestLength * digestLength;byte[] generatedData =newbyte[requiredLength];int generatedLength =0;try {md.reset();// Repeat process until sufficient data has been generatedwhile (generatedLength < keyLength + ivLength) {// Digest data (last digest if available, password data, salt if available)if (generatedLength >0)md.update(generatedData, generatedLength - digestLength, digestLength);md.update(password);if (salt !=null)md.update(salt,0,8);md.digest(generatedData, generatedLength, digestLength);// additional roundsfor (int i =1; i < iterations; i++) {md.update(generatedData, generatedLength, digestLength);md.digest(generatedData, generatedLength, digestLength); } generatedLength += digestLength; }// Copy key and IV into separate byte arraysbyte[][] result =newbyte[2][]; result[0] =Arrays.copyOfRange(generatedData,0, keyLength);if (ivLength >0) result[1] =Arrays.copyOfRange(generatedData, keyLength, keyLength + ivLength);return result;} catch (DigestException e) {thrownewRuntimeException(e);} finally {// Clean out temporary dataArrays.fill(generatedData, (byte) 0);}}
Initiate VA creation
create a virtual account
POST {{env_url}}/wallet/virtual/v2/business/create/account
Encrypt the plain request body using the encryption algorithm specified above. Set the encrypted data to the message as shown below. You are required to set the x-auth-token and Authorization in the headers.
Headers
Request Body (encrypted)
{"message":"encrypted-message"}
The result of the encryption of the payload that we specified has to be used with the Create virtual account endpoint as shown below:
When a VA creation is initiated, processing could take a few seconds. These are sample responses you will get below:
{"id":218,"walletId":null,"accountNumber":"8574578073","bankName":"WEMA BANK","orderRef":"fOeatZO40PEJzeiPvq8q","txRef":"klasha-virtual-account-banktransfer-Steph and sons-133","flwRef":"URF_G6Ie8ZP9GZ5hAZk8z6fZ","userId":null,"businessId":133,"bankCode":null,"enabled":true,"accountName":"Stephen Ojerinde","email":"test@steph.com","profileHash":"hwKpOI9+kZR/fFy7hLOpcQ==","createdAt":"2023-07-07 00:42:45","updatedAt":"2023-07-07 00:42:45"}
{"message":"There is no identity available for this bvn.","error":"Operation not allowed"}
{"message":"Bvn name mismatch.","error":"Operation not allowed"}
Requery
GET{{env_url}}/wallet/virtual/v2/account/email
In case of network downtime or failures during VA creation, the virtual account can be re-queried with the user’s email. This can be fetched using the Requery with email API on the Postman collection.
To know the status of a transaction, you can fetch the transaction using the Transaction Status API on the Postman collection. Make use of the session id received from the bank. See an example below: