This shows you how to accept QR Code payments via API
QR code payments allow you accept payments using a QR code image, the steps to execute the payment are listed below.
How QR Payments work
-
You display a QR
base64
image to the customer. See a guide for displaying base64 URIs here. -
The customer would open up their mobile banking app, Barter app or any financial app that has a QR payment functionality, to scan the QR code for payment. Currently, the banks who support QR payments are Diamond Bank, Ecobank, Skye Bank, Zenith Bank, Access Bank, First Bank and the GetBarter app.
-
The customer scans the QR code and completes payments.
-
We notify you via Webhooks to get the status of the completed payment.
Pre-requisites for accepting QR payments on rave.
-
Sign-up for an account here .
-
You can use Webhooks to get notified of transactions.
-
QR payments is an asynchronous payment method, it is implemented in 2 steps,
initiate payment
,verify payment
after a webhook is sent to you.
Available in Nigeria only
QR code payment on rave is for Nigeria only. Please ensure you only pass NGN as currency.
Also, QR payments can only be tested with live credentials, and you would need an app that can process QR payments to complete an end to end test. You can make use of the GetBarter app to easily test your QR payment flow download it on Android & IOS
Step 1: Collect customer details
You can initiate a QR payment by sending the following details to the charge endpoint.
{
"PBFPubKey":"FLWPUBK_TEST-589490616a6297324231c5e89b58f3f6-X",
"currency":"NGN",
"country":"NG",
"amount":100,
"email":"[email protected]",
"phonenumber":"",
"firstname":"ayomide",
"payment_type":"nibss-qr",
"is_nqr":1,
"lastname":"jimi",
"redirect_url":"https://google.com",
"txRef":"1627916295672"
}
{
"PBFPubKey": "FLWPUBK-981ae1ed1ef801254329cb7b318a0ea5-X",
"amount": 40,
"txRef": "m3s4m0c1526722407366",
"is_qr": "qr",
"payment_type": "pwc_qr",
"ip": "::1",
"device_fingerprint": "ada1d43c29279d9f743956edfb98d801",
"meta": [
{
"metaname": "flightid",
"metavalue": "93849-MK5000"
}
],
"email": "[email protected]"
}
Parameter Description
Parameter | Required | Description |
---|---|---|
PBFPubKey | true | This is a unique key generated for each button created on Rave’s dashboard. It starts with a prefix FLWPUBK and ends with suffix X . |
amount | true | This is the amount to be charged, it is passed as - (“amount”:10). Pass 0 as amount if you would like the customer to enter an amount for payment in their respective mobile banking or QR app. |
currency | falsedefaults to NGN | This is the specified currency to charge the customer's payment source in. QR payments can only be done in NGN . |
country | falsedefaults to NG | This is the pair country for the transaction with respect to the currency. See a list of Multicurrency support here Multicurrency Payments ] |
txRef | true | This is the unique reference, unique to the particular transaction being carried out. It is generated by the merchant for every transaction |
is_qr | trueexpected value: qr | This is a flag identifying that it's a QR payment being initiated. |
is_nqr | trueexpected value: 1 | This is a flag identifying that it's a NQR payment being initiated. |
payment_type | true expected values: pwc_qr or nibss-qr | This recognises the payment type as QR or NQR payment |
IP | false | IP - Internet Protocol. This represents the current IP address of the customer carrying out the transaction. |
device_fingerprint | false | This is the fingerpringt for the device being used. It can be generated using a library on whatever platform is being used. |
meta | false | Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. |
email | true | This is the email address of the customer. |
phonenumber | false | This is the phone number of the customer. |
firstname | false | This is the first name of the card holder or the customer. |
lastname | false | This is the last name of the card holder or the customer. |
submerchant_business_name | false | This allows you pass a dynamic merchant name that would be displayed on the QR app. |
Step 2: Encrypt QR payment details
To see how to encrypt using any of our encryption function copy the sample request below and visit the Rave Encryption section.
Step 3: Initiate payment
After encryption, the next step is to initiate your payment using the encrypted string by sending a request to the /charge
endpoint. See how to do that below.
https://api.ravepay.co/flwv3-pug/getpaidx/api/charge
Sample Request:
Copy the curl request and make a request in your terminal to see how it works!
curl --location --request POST 'https://api.ravepay.co/flwv3-pug/getpaidx/api/charge' \
--header 'Content-Type: application/json' \
--data-raw '{
"PBFPubKey":"FLWPUBK_TEST-589490616a6297324231c5e89b58f3f6-X", "client":"ndL3/LmzJnJjG3CICLi43IvDutVPHCfIX8XiDz8hx3Eo9cRgXoiXLzFVrhaFmHDQJNJQekY+a5W7ruf+w46nf1kl9AySq9m57sn5CO5IqUvX0tNHnS33MEZq6O7OsrgAQKArfedeHymihVnOClkCfpVAu+JmyxWAEWCCCM5tWnFPSJuaagiLNVMD+GKz1PnpFyYedYFDmERJV93chgTtloeGonevmAVduu8meU/xHnE7esXUZiLyBpoGKS2QjBDzfVhD0pWPEDB3N8GIkW84AsNxr1IMX2a45t8VoJ0Rsbr22j4/AOqtLMCrPI3KEPcnv03qQQztjsALRLqGb1cPvPAqffLlQ04ZuQOjwJcmosrAYm2vizjEuROyjc+CxtGMppERs2qIZDg=",
"alg":"3DES-24"
}'
{
"PBFPubKey":"FLWPUBK_TEST-589490616a6297324231c5e89b58f3f6-X", "client":"ndL3/LmzJnJjG3CICLi43IvDutVPHCfIX8XiDz8hx3Eo9cRgXoiXLzFVrhaFmHDQJNJQekY+a5W7ruf+w46nf1kl9AySq9m57sn5CO5IqUvX0tNHnS33MEZq6O7OsrgAQKArfedeHymihVnOClkCfpVAu+JmyxWAEWCCCM5tWnFPSJuaagiLNVMD+GKz1PnpFyYedYFDmERJV93chgTtloeGonevmAVduu8meU/xHnE7esXUZiLyBpoGKS2QjBDzfVhD0pWPEDB3N8GIkW84AsNxr1IMX2a45t8VoJ0Rsbr22j4/AOqtLMCrPI3KEPcnv03qQQztjsALRLqGb1cPvPAqffLlQ04ZuQOjwJcmosrAYm2vizjEuROyjc+CxtGMppERs2qIZDg=",
"alg":"3DES-24"
}
curl --request POST \
--url https://ravesandboxapi.flutterwave.com/flwv3-pug/getpaidx/api/charge \
--header 'content-type: application/json' \
--data '{"PBFPubKey":"FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X","client":"VodhvFFsni0CBeieHPq9HTuG5lbNPgmD5rbEw6Uxb0TD9eD9B3VM5uZ1B5lC3thQMbPypNBCAYwvbi+o9E4lKa4gZF+XaDB+zzsNMC/jhHXTQKZt727+8tLzsHDr3IU5O8Uj0/XKWgf525xIjV8yG9zhE0Y+RPeTHWWgnGJsoBuhc1D8/tNo/en31kO3CfZgU9Ku9ltuQBgJd5mqxHVpFeuwXhsohZ0BGMQfcEpKaW0qZysVB7lnLoB6pJeiGiOiNUiiD41IeBj5t2ILIFKCj7mbD9FShJfLpsTK2rLj+k8cj5F1J9K0Dcve4nRizNKUJKdVCbpTjwzmuHzYQzLsvhl2c0KaSXlq1eRgCbFm/oICbLRRwqH5/ZktfJOfVqTAngEtbZ/eIGYcbdDSe2RmXPQTTsKNzIiSrMby3awYap5XeiylHdnHLamAZZ+ZPcRe8yhnWJUgJG0ppk4gdafQa6mAZZ+ZPcRembqjp8mZVAl4e7uBVLTksQ==","alg":"3DES-24"}'
{
"PBFPubKey":"FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X", "client":"VodhvFFsni0CBeieHPq9HTuG5lbNPgmD5rbEw6Uxb0TD9eD9B3VM5uZ1B5lC3thQMbPypNBCAYwvbi+o9E4lKa4gZF+XaDB+zzsNMC/jhHXTQKZt727+8tLzsHDr3IU5O8Uj0/XKWgf525xIjV8yG9zhE0Y+RPeTHWWgnGJsoBuhc1D8/tNo/en31kO3CfZgU9Ku9ltuQBgJd5mqxHVpFeuwXhsohZ0BGMQfcEpKaW0qZysVB7lnLoB6pJeiGiOiNUiiD41IeBj5t2ILIFKCj7mbD9FShJfLpsTK2rLj+k8cj5F1J9K0Dcve4nRizNKUJKdVCbpTjwzmuHzYQzLsvhl2c0KaSXlq1eRgCbFm/oICbLRRwqH5/ZktfJOfVqTAngEtbZ/eIGYcbdDSe2RmXPQTTsKNzIiSrMby3awYap5XeiylHdnHLamAZZ+ZPcRe8yhnWJUgJG0ppk4gdafQa6mAZZ+ZPcRembqjp8mZVAl4e7uBVLTksQ==",
"alg":"3DES-24"
}
-
client
: This is the encrypted request parameters. -
PBFPubKey
: This is your merchant public key. -
alg
: must always be passed as3DES-24
Some of the important responses you need to check are broken down below:
-
data.chargeResponseCode
: This is the response code of the transaction, it typically tells you when a transaction is successful with a response code00
or when the transaction requires validation02
. -
data.chargeResponseMessage
: This is the response message and it can be shown to the customer to show what needs to be done next. -
data.qr_image
: This returns thebase64
encoded URI to load to the customer i.e. the QR code. See a guide on loadingbase64
URIs here
Sample response after Initiate payment call.
{
"status": "success",
"message": "V-COMP",
"data": {
"id": 2383027,
"txRef": "1627916196486",
"orderRef": "RV-QR07B4DB71438A42",
"flwRef": "MKPT737921627916211717",
"redirectUrl": "http://127.0.0",
"device_fingerprint": "N/A",
"settlement_token": null,
"cycle": "one-time",
"amount": 100,
"charged_amount": 100,
"appfee": 0.5,
"merchantfee": 0,
"merchantbearsfee": 1,
"chargeResponseCode": "02",
"raveRef": null,
"chargeResponseMessage": "QR GENERATED. PENDING VALIDATION",
"authModelUsed": "NIBSS-QR",
"currency": "NGN",
"IP": "::ffff:127.0.0.1",
"narration": "FLW-ECO",
"status": "success-pending-validation",
"modalauditid": "67667120bef94a702de525cee38556ae",
"vbvrespmessage": "N/A",
"authurl": "NO-URL",
"vbvrespcode": "N/A",
"acctvalrespmsg": null,
"acctvalrespcode": null,
"paymentType": "nibss-qr",
"paymentPlan": null,
"paymentPage": null,
"paymentId": "N/A",
"fraud_status": "ok",
"charge_type": "normal",
"is_live": 0,
"retry_attempt": null,
"getpaidBatchId": null,
"createdAt": "2021-08-02T14:56:50.000Z",
"updatedAt": "2021-08-02T14:57:03.000Z",
"deletedAt": null,
"customerId": 1355661,
"AccountId": 65896,
"customer": {
"id": 1355661,
"phone": null,
"fullName": "ayomide jimi",
"customertoken": null,
"email": "[email protected]",
"createdAt": "2021-08-02T14:56:50.000Z",
"updatedAt": "2021-08-02T14:56:50.000Z",
"deletedAt": null,
"AccountId": 65896
},
"validateInstructions": "Transaction in progress",
"qr_image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AQAAAACgl2eQAAACpElEQVR42u2ZQXLsIAxE0UXQ/W+Ro6CLiK9uMRV7Fn/nzsZTqYkNb6GAuiXI2P///IwXeIEXeAhYYxi+p2MoYnns6EEZEBgFWMSynF6zFhzXAcsije85p2dFl4ZBMbCwVBVgTRYc6X8A1PDwmq8tqtn0rQawWTW2Ca5aqcFlUwLIz/j+fGf1w8BmpiC2UszyUtCc9q3uh4GSSeWKIdiKLC3BFeRCoBbFa2BMTHXG4kcKLDs+lg4JOR3M8zdpBQDCwWsajQybltgyEwJBuSBTDAqu7apna3NVAW2fcI3NbKkHmNjvZgmA6EKGXN1cJaSu81UHIGmdPlZWWmtUs7aGFKh37BH8m1aK7fsUWxWAhiIhXlSUecR7+g0VwP1aLOqorWgwbOGXEMCyoKwja+u58qUVvIUAbItxQryTXho38QqAbBOlZhFzwtXXHK4ErMsaahkXqV7WuArneQCbhaLmbDsD6YoaIwVgHqeW2en8J7seIZDWB47pFNCCZGJfzFwAsM1p71inqGL7dggBrghXJw/0qXFCACJhYJzhCWggjZUA+zp84wQCZzfo91LcnwfY6iFpj4knH69uLwA2ihgSBc12rRqgqQUS1jEg3tNlODoOCyXACwHGNpEy9JBK2mvz/zgAH2V4nCFifVWiA5ikffCqZIWCPG7iVQCbVs7cTZZTyPkiXgHQXQWCbPFWpOi7Lm4vALqtgnLZ652yYqEEahaBosKj/T4xX/+KxwE0dlgWbBGNlA+MUQbQS+3cjfBwivPxrbg/DtDLkSpouSKPeON+YfUwwK4bXQ0vy1he0exNUwK4GqFaP81FsO8LNdC+Faf579RVA7MvL1lbI8fn5k4GdE2ZvKtBtlBFtxuMx4HVN8jd2XB8eWtaB7z/S3qBF5AD/wAE11+pyqXbSQAAAABJRU5ErkJggg=="
}
}
{
"status": "success",
"message": "V-COMP",
"data": {
"id": 150744,
"txRef": "m3s5660c1526780007366",
"orderRef": "RV16D4AA38C8A7E0",
"flwRef": "FLW5169a66def65454e955",
"redirectUrl": "http://127.0.0",
"device_fingerprint": "ada1d43c29279d9f743956edfb98d801",
"settlement_token": null,
"cycle": "one-time",
"amount": 40,
"charged_amount": 40,
"appfee": 0,
"merchantfee": 0,
"merchantbearsfee": 1,
"chargeResponseCode": "02",
"raveRef": null,
"chargeResponseMessage": "QR GENERATED. PENDING VALIDATION",
"authModelUsed": "MVISA-QR",
"currency": "NGN",
"IP": "::ffff:10.142.195.245",
"narration": "Synergy Group",
"status": "success-pending-validation",
"modalauditid": "N/A",
"vbvrespmessage": "N/A",
"authurl": "NO-URL",
"vbvrespcode": "N/A",
"acctvalrespmsg": null,
"acctvalrespcode": null,
"paymentType": "mvisa-qr",
"paymentPlan": null,
"paymentPage": null,
"paymentId": "118",
"fraud_status": "ok",
"charge_type": "normal",
"is_live": 0,
"createdAt": "2018-05-19T11:53:23.000Z",
"updatedAt": "2018-05-19T11:53:26.000Z",
"deletedAt": null,
"customerId": 28276,
"AccountId": 134,
"customer": {
"id": 28276,
"phone": null,
"fullName": "Dele Moruf Quadri",
"customertoken": null,
"email": "[email protected]",
"createdAt": "2018-05-19T11:53:22.000Z",
"updatedAt": "2018-05-19T11:53:22.000Z",
"deletedAt": null,
"AccountId": 134
},
"validateInstructions": "No Message",
"qr_image": "data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAABWQAAAVkCAYAAABTjRaxAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAP+lSURBVHhe7NhBii1btizZ1/9OZxaCiJI4mCPKcf1z6QAp62TZ9svl/N//NzMzMzMzMzMzMzP/xP5BdmZmZmZmZmZmZuYf2T/IzszMzMzMzMzMzPwj+wfZmZmZmZmZmZmZmX9k................base64uri.............."
}
}
Step 3: Receive webhook response
Rave allows you to configure Webhooks so you can get notified when actions like a successful payment are taken place, it is a seamless way to handle offline transactions. Webhooks are returned in application/x-www-form-urlencoded
, but you can configure to receive your responses in JSON
.
Visit the Webhooks section to see more details on implementing and receiving webhooks.
{
"id": 130438,
"txRef": "m3s5660c1526780007366",
"flwRef": "FLW5169a66def65454e955",
"orderRef": "1998935614_1884_1523809926391",
"paymentPlan": null,
"createdAt": "2018-04-15T16:32:06.000Z",
"amount": 2000,
"charged_amount": 2028,
"status": "successful",
"IP": "41.86.149.34",
"currency": "NGN",
"customer": {
"id": 23858,
"phone": "254791498442",
"fullName": "Dele Moruf Quadri",
"customertoken": null,
"email": "[email protected]",
"createdAt": "2018-04-15T16:32:05.000Z",
"updatedAt": "2018-04-15T16:32:05.000Z",
"deletedAt": null,
"AccountId": 1884
},
"entity": {
"id": "NO-ENTITY"
}
}
Step 4: Verify the payment
After charging a customer via QR successfully, you need to verify that the payment was successful with Rave before giving value to your customer.
Below are the important things to check for when validating the payment:
Verify the transaction reference.
Verify the data.status
of the transaction to be successful
.
Verify the currency to be the expected currency
Most importantly validate the amount paid to be equal to or at least greater than the amount of the value to be given.
Below is sample code of how to implement server-side validation in different programming languages
curl --request POST \
--url https://api.ravepay.co/flwv3-pug/getpaidx/api/v2/verify \
--header 'content-type: application/json' \
--data '{"txref":"<Your live reference>","SECKEY":"<Your live secret key>"}'
When you successfully verify a completed payment see sample response below.
{
"status": "success",
"message": "Tx Fetched",
"data": {
"txid": 873293,
"txref": "m3s5660c1526780007366",
"flwref": "FLW5169a66def65454e955",
"devicefingerprint": "69e6b7f0b72037aa8428b70fbe03986c",
"cycle": "one-time",
"amount": 10,
"currency": "NGN",
"chargedamount": 10.13,
"appfee": 0.125,
"merchantfee": 0,
"merchantbearsfee": 0,
"chargecode": "00",
"chargemessage": "Approved",
"authmodel": "MVISA-QR",
"ip": "::ffff:10.101.207.111",
"narration": "Raver",
"status": "successful",
"vbvcode": "N/A",
"vbvmessage": "N/A",
"authurl": "NO-URL",
"acctcode": null,
"acctmessage": null,
"paymenttype": "mvisa-qr",
"paymentid": "9584",
"fraudstatus": "ok",
"chargetype": "normal",
"createdday": 1,
"createddayname": "MONDAY",
"createdweek": 14,
"createdmonth": 3,
"createdmonthname": "APRIL",
"createdquarter": 2,
"createdyear": 2018,
"createdyearisleap": false,
"createddayispublicholiday": 0,
"createdhour": 11,
"createdminute": 38,
"createdpmam": "am",
"created": "2018-04-02T11:38:31.000Z",
"customerid": 557049,
"custphone": "08166009393",
"custnetworkprovider": "MTN",
"custname": "Dele Moruf Quadri",
"custemail": "[email protected]",
"custemailprovider": "COMPANY EMAIL",
"custcreated": "2018-04-02T10:45:31.000Z",
"accountid": 48,
"acctbusinessname": "Raver",
"acctcontactperson": "Desola Adesina",
"acctcountry": "NG",
"acctbearsfeeattransactiontime": 0,
"acctparent": 1,
"acctvpcmerchant": "N/A",
"acctalias": "raver",
"acctisliveapproved": 0,
"orderref": "RVDAED218620CE66",
"paymentplan": null,
"paymentpage": null,
"raveref": null,
"amountsettledforthistransaction": 10.005
}
}