While this is a more streamlined approach for merchants to collect card payments, there are other ways to charge customers. Some use cases for pre-auth transactions include:
- Hospitality (hotels, lounges, restaurants and bars): Use pre-auth to confirm funds on customers’ cards to cover any additional charges.
- Transportation and Logistics (airlines, delivery services): Hold ticket purchase and cancellation fees on each booking.
- Rentals and Leasing: Lien rental fees and other costs can be released on the successful return of the car/leased item.
Pre-authorization vs Escrow Payments
It’s important to note that while pre-auth is similar to escrowed payments, it should not replace escrow payments. Escrow payments refer to any form of payment (Card, Bank Transfer, Mobile Money etc.) collected from customers, and held by a third party rather than being directly collected by the merchant. These funds remain in escrow until a specific condition is met, such as the provision of a service or product or the occurrence of an unforeseen circumstance necessitating a refund. Once the condition is met, the funds held in escrow can be transferred to your wallet. Additionally, in cases where the service is not provided or the product is not offered, partial or full refunds can be initiated. It is also possible to split the payments held in escrow among multiple sellers (sub-accounts) on your platform.
Prerequisites for Preauthorization Transactions
Now that we have covered the basics of this feature, the following requirements are essential to successfully implement pre-auth charges in your app:
- A live Flutterwave for Business account. Ensure you have completed your KYC and that your Flutterwave for business account is approved.
- Basic understanding of how to collect card payments using our Card Charge API. We cover this in great detail here.
- Pre-auth Enablement: This feature is not available by default to all our customers, request this feature on your account via an email to hi@flutterwavego.com.
- Basic Understanding of APIs – requests and responses.
Making Pre-Auth Payments
We’re gradually getting to the fun part of this article. Before we dive deep into this, we’ll discuss the basic flow of charging the customer using pre-auth. To make a successful charge:
- Collect the customer’s information and card details. Add the pre-auth flag to your request.
- Encrypt your payment request.
- Redirect the user to their bank’s page to authorize the payment.
- Verify the status of the payment.
- Capture the payment (or void the payment depending on your use case).
- Verify the status of the payment.
Forming Your Payment Requests
Collect your customers’ information such as email, name, phone number and card details. Pass this information into your payment request and include the preauthorize and usesecureauth flags to ensure the transaction is processed as a pre-auth charge.
Our API reference has more information on how you can send the correct payment request for your pre-auth charge. Here is a sample request to guide you:
{
"card_number": "5377283645077450",
"cvv": "789",
"expiry_month": "09",
“expiry_year”: ”31 ”,
"preauthorize": true,
"usesecureauth": true,
...
}
Encrypt Your Payment Requests
Your payment request contains sensitive customer information like card details and private data. To keep this information safe when communicating with our systems, it is important to encrypt your request before sending it to us.
Encrypting your request is quite easy, here’s what you need to do:
- Get your encryption key from the API keys settings in your dashboard.
- Apply the 3DES (triple data encryption standard) algorithm.
Example of an encryption function:
function encrypt(encryptionKey, paymentRequest) {
const text = JSON.stringify(paymentRequest);
const forge = require("node-forge");
const cipher = forge.cipher.createCipher(
"3DES-ECB",
forge.util.createBuffer(encryptionKey)
);
cipher.start({
iv: ""
});
cipher.update(forge.util.createBuffer(text, "utf-8"));
cipher.finish();
const encrypted = cipher.output;
return forge.util.encode64(encrypted.getBytes());
}
After encrypting your request, send it to the card charge endpoint for processing.
Authorizing The Payments
If your encryption is done correctly, you will get a successful (200) response.
From your response, confirm that data.charge_type is preauth and meta.authorization.redirect is a valid URL. After concluding this check, redirect your customer to the redirect URL specified in meta.authorization.redirect.
{
"status": "success",
"message": "Charge initiated",
"data": {
“id”:4994738
"flw_ref":"FLW-MOCK-PREAUTH-77cb605d59aaddcf34279e9c6f95070d",
"status": "pending",
"charge_type": "preauth",
...
},
"meta": {
"authorization": {
"mode": "redirect",
"redirect": "https://ravesandboxapi.flutterwave.com/mockvbvpage?ref=FLW-MOCK-PREAUTH-d8444c6f5ec17b25f744a414a03e75ac&code=00&message=Approved.%20Successful&receiptno=RN1710253606134"
}
}
}
On redirection, the customer is presented with their bank’s page where they complete a challenge to authorize the payment.
Verifying Your Pre-authorization Charge
It is essential to verify your customer’s pre-authorization charge before deciding whether to capture the charge or not. While we append the transaction status to your redirect_url after payment is completed, you should not rely solely on this means of verification as transaction details on the front-end can be susceptible to tampering or manipulation.
Another means of verification is making a GET request to either of our verification endpoints. One requires your unique transaction reference (tx_ref) passed in your payment request while the other requires you to pass in the data.id returned in your charge response. The status is returned as pending.
Sample request using the data.id:
GET “https://api.flutterwave.com/v3/transactions/data.id/verify”
-header 'Content-Type: application/json' \
-header 'Authorization: Bearer YOUR_SECRET_KEY-X'
Sample Response:
{
"status": "success",
"message": "Transaction fetched successfully",
"data": {
"id": 5227562,
.........
"status": "pending",
......
}
}
Make sure to take note of the id and flw_ref fields. The flw_ref is what you’ll need for capturing and voiding transactions, while the id is used for initiating refunds.
To capture or not to capture?
At this stage of the transaction, a hold is placed on the customer’s account. The next step would be to capture or void the charge.
You should capture the charge if:
- The transaction is complete i.e. you have provided the product/service to the customer.
- All internal processes and checks relating to the payment are concluded.
To capture funds for a transaction, pass the flutterwave reference for the transaction in your request and send it to the capture charge endpoint. Once captured successfully, the transaction status updates to ‘successful’ and the response message is “Charge captured”.
{
"status": "success"
"message": "Charge captured",
"data": {
...
"status": "successful",
...
}
}
Note: We also send webhooks after the funds have been successfully captured. If you are interested in this service, email hi@flutterwavego.com with your account information (Merchant ID and Business Name) to have it enabled.
Webhook example:
{
"event": "charge.completed",
"data": {
"id": 5413328,
"tx_ref": "samnplffdolheckS-ref",
"flw_ref": "FLW-MOCK-PREAUTH-c555e679c55da53474345a3bc6dbfef3",
"device_fingerprint": "N/A",
. . .
}
"event.type": "CARD_TRANSACTION"
}
If you encounter an error during capturing, review the transaction id to make sure that the correct transaction is being captured. Here are some reasons for the capture error:
- Incorrect transaction id.
- The transaction is already captured or voided.
- The transaction has been refunded.
{
"status": "error",
"message": "This transaction has been voided or refunded",
"data": null
}
If there is a dispute on the service/product from the customer, you should consider voiding the transaction (provided that the dispute is legitimate). To release the hold on the transaction amount, send the transaction’s flutterwave reference to the void endpoint.
A successful call should return the message as ‘Charge voided’ and status as ‘voided’.
{
"status": "success",
"message": "Charge voided",
"data": {
....
"status": "voided",
.......
}
}
Refunding Transactions
In the event of a dispute after capturing the funds, you can initiate a full or partial refund. Refunds are easy to initiate, send the refund amount as your request body to our refund endpoint. Where the transaction amount is more than the refund amount, a partial refund is initiated.
{
“amount”:100
}
A successful refund should have a successful status in the response returned
{
"status": "success",
"message": "Charge refunded",
"data": {
.......
"narration": "FLW-PBF CARD Transaction ",
"status": "successful",
......
}
}
What’s Next?
Now that you have completed the basics, head to our documentation to get more information on customizations you can make to your pre-authorization card charge.
For additional integration support, we have implemented a chatbot on the Flutterwave dashboard to assist with any questions you may have on pre-authorization. It is conveniently positioned at the lower right corner of your dashboard and is readily available whenever you require support, not limited to integration-related queries.
Join our developer community to learn more about our payment features and get firsthand access to valuable developer content; click here to join us.