QR Code Payments

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

  1. You display a QR base64 image to the customer. See a guide for displaying base64 URIs here.

  2. 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.

  3. The customer scans the QR code and completes payments.

  4. We notify you via Webhooks to get the status of the completed payment.

Pre-requisites for accepting QR payments on rave.

  1. Sign-up for an account here .

  2. You can use Webhooks to get notified of transactions.

  3. 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

ParameterRequiredDescription
PBFPubKeytrueThis is a unique key generated for each button created on Rave’s dashboard. It starts with a prefix FLWPUBK and ends with suffix X.
amounttrueThis 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.
currencyfalse
defaults to NGN
This is the specified currency to charge the customer's payment source in.

QR payments can only be done in NGN.
countryfalse
defaults to NG
This is the pair country for the transaction with respect to the currency. See a list of Multicurrency support here Multicurrency Payments ]
txReftrueThis is the unique reference, unique to the particular transaction being carried out. It is generated by the merchant for every transaction
is_qrtrue
expected value: qr
This is a flag identifying that it's a QR payment being initiated.
is_nqrtrue
expected value: 1
This is a flag identifying that it's a NQR payment being initiated.
payment_typetrue
expected values: pwc_qr or nibss-qr
This recognises the payment type as QR or NQR payment
IPfalseIP - Internet Protocol. This represents the current IP address of the customer carrying out the transaction.
device_fingerprintfalseThis is the fingerpringt for the device being used. It can be generated using a library on whatever platform is being used.
metafalseSet 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.
emailtrueThis is the email address of the customer.
phonenumberfalseThis is the phone number of the customer.
firstnamefalseThis is the first name of the card holder or the customer.
lastnamefalseThis is the last name of the card holder or the customer.
submerchant_business_namefalseThis 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 as 3DES-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 code 00 or when the transaction requires validation 02.

  • 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 the base64 encoded URI to load to the customer i.e. the QR code. See a guide on loading base64 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
    }
}