Checksum

This page describes how to implement checksum for adding quidpay's inline js

How Integrity checksum works

Quidpay helps secure your payments on the client side using an integrity hash, we would explain how integrity hash works:

Using an integrity hash you are meant to sort the payment request parameter's you send in your getpaidSetup function, on your server e.g.

[ 'PBFPubKey',
  'amount',
  'country',
  'currency',
  'custom_description',
  'custom_logo',
  'custom_title',
  'customer_email',
  'customer_firstname',
  'customer_lastname',
  'customer_phone',
  'payment_method',
  'txref' ]

We would pick up the parameters you sent in your getpaidSetup function sort it, compute the hash and compare the it with the value of integrity_hash to make sure they match. This means that values you hash must match the values you passed to us in your getpaidSetup function.

Rule of thumb

  1. Make sure you send your integrity_hash value in lower case, the server computes the hash in lowercase so they need to match.
  1. Make sure your values are sorted and hashed using the same letter cases as what you add in your getpaidSetup function i.e. if you hash customer_firstname: JIDENNA, then you need to pass it to the client as customer_firstname: JIDENNA. and vice-versa.
  1. For amount with decimal places, if decimal places have trailing zero's e.g. 100.000 , remove all trailing zero's.

Hash your pay button values on your server and send the hash to the client page

Quidpay inline secures payment on your site using an Integrity hash. You should always create the values you are passing to your inline js script on your server, after creating the value you hash it using a hashing algorithm called Sha 256 . Once the value is hashed send the value to the client and add it as parameter to your inline script. The steps to hash are listed below:

Step 1: Create payment request parameters and values on your server

integrityValue: (req, res) => {
        const hashedPayload = '';
        const payload = {
            "PBFPubKey": 'FLWPUBK-e634d14d9ded04eaf05d5b63a0a06d2f-X',
            "amount": 20,
            "payment_method": "both",
            "custom_description": "Pay Internet",
            "custom_logo": "http://localhost/payporte-3/skin/frontend/ultimo/shoppy/custom/images/logo.svg",
            "custom_title": "Shoppy Global systems",
            "country": "NG",
            "currency": "NGN",
            "customer_email": '[email protected]',
            "customer_firstname": 'Temi',
            "customer_lastname": "Adelewa",
            "customer_phone": "234099940409",
            "txref": "MG-" + Date.now()
        };
$pb_key = "FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X"; 

$amount_in_naira = 900; 

$customer_email = "[email protected]"; 

$customer_firstname = "user"; 

$customer_lastname = "example"; 

$txref = "MV-1838383-JH"; 

$pmethod = "both"; 

$seckey = "FLWSECK-e6db11d1f8a6208de8cb2f94e293450e-X"; 

$country = "NG"; 

$currency = "NGN"; 

$custom_description = "Hey Quidpay"; 

$custom_logo = "http://logo.com"; 

$custom_title = "Ravepay"; 

$customer_phone = "+2348185615980"; 

$options = array( 
    "PBFPubKey" => $pb_key, 
    "amount" => $amount_in_naira, 
    "customer_email" => $customer_email, 
    "customer_firstname" => $customer_firstname, 
    "txref" => $txref, 
    "payment_method" => $pmethod, 
    "customer_lastname" => $customer_lastname, 
    "country" => $country, 
    "currency" => $currency, 
    "custom_description" => $custom_description, 
    "custom_logo" => $custom_logo, 
    "custom_title" => $custom_title, 
    "customer_phone" => $customer_phone 
);

Step 2: Sort the parameters this way: Ascii (value) Sort keys of data to send

// The keys in step 1 above are sorted by their ASCII value

const keys =  Object.keys(payload).sort();

// The sorted keys would be outputed in this format:

[ 'PBFPubKey',
  'amount',
  'country',
  'currency',
  'custom_description',
  'custom_logo',
  'custom_title',
  'customer_email',
  'customer_firstname',
  'customer_lastname',
  'customer_phone',
  'payment_method',
  'txref' ]
// The keys in step 1 above are sorted by their ASCII value

ksort($options);

var_dump($options); // check the order of the keys in the array.

// The sorted keys would be outputed in this format:

array(13) {
  ["PBFPubKey"]=>
  string(42) "FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X"
  ["amount"]=>
  int(900)
  ["country"]=>
  string(2) "NG"
  ["currency"]=>
  string(3) "NGN"
  ["custom_description"]=>
  string(8) "Hey Quidpay"
  ["custom_logo"]=>
  string(15) "http://logo.com"
  ["custom_title"]=>
  string(7) "Ravepay"
  ["customer_email"]=>
  string(16) "[email protected]"
  ["customer_firstname"]=>
  string(4) "user"
  ["customer_lastname"]=>
  string(7) "example"
  ["customer_phone"]=>
  string(14) "+2348185615980"
  ["payment_method"]=>
  string(4) "both"
  ["txref"]=>
  string(13) "MV-1838383-JH"
}

Step 3: Concatenate the values in the order of your sorted keys e.g.

// The payload is rearranged and the values concatenated in the order of the sorted keys.

        for(var index in keys){
            const key = keys[index];
            hashedPayload += payload[key];
        }

// The above sample would output a string that looks like this:

"FLWPUBK-e634d14d9ded04eaf05d5b63a0a06d2f-X20NGNGNPay Internethttp://localhost/payporte-3/skin/frontend/ultimo/shoppy/custom/images/logo.svgShoppy Global systemsuser@example.comTemiAdelewa234099940409bothMG-1500041286295"
// The payload is rearranged and the values concatenated in the order of the sorted keys.

$hashedPayload = '';

foreach($options as $key => $value){

    $hashedPayload .= $value;
}

// The above sample would output a string that looks like this:

FLWPUBK-7adb6177bd71dd43c2efa3f1229e3b7f-X900NGNGNHey Ravehttp://[email protected]+2348185615980bothMV-1838383-JHFLWSECK-e6db11d1f8a6208de8cb2f94e293450e-X

Step 4: Create a full string to be hashed by concatenating the result from step 3 with your secret key

// This creates a the full string to be hashed:

hashString = hashedPayload + "FLWSECK-bb971402072265fb156e90a3578fe5e6-X";
// This creates a the full string to be hashed:

$completeHash = $hashedPayload.$seckey;

echo "$completeHash\n";

📘

Using Secret key in your application

Always store your secret key in an environment variable, don't expose it in your code, you would most likely commit it, and it would be exposed to the public. You can add it in your code using an environment variable.

Step 5: Generate a Sha256 hash of the hashstring and send to your Client page.

// Generate the sha256 hash of the concatenated strings
const sha256Hash = createHash('sha256').update(hashString, 'utf8').digest('hex');

// Send the hash and any dynamic value to your client.
res.json({hash: sha256Hash, txref: payload.txref});
// Generate the sha256 hash of the concatenated strings

$hash = hash('sha256', $completeHash);

echo "$hash";

Once the user clicks the button for the modal to open up, if they change any value on the browser the modal would not be opened and an error would be returned.

Step 6: Pass the integrity hash to quidpay.

📘

HTML EMBED

When using the html embed pass it in as data-integrity_hash.

<form>
  <button type="button" style="cursor:pointer;" value="Pay Now" id="submit">Pay Now</button>
</form>

<script type="text/javascript" src="https://api.ravepay.co/flwv3-pug/getpaidx/api/quidpay-inline.js"></script>
<script>
	 
  document.addEventListener("DOMContentLoaded", function(event) {
  	
    const paybutton =  document.getElementById("submit");
  
    paybutton.addEventListener("click", function(e) {
    
    const API_publicKey = "FLWPUBK-24b72aebb821aea177483039677df9d3-X";
    
    getpaidSetup({
      PBFPubKey: API_publicKey,
      customer_email: "[email protected]",
      amount: 2000,
      customer_phone: "234099940409",
      currency: "NGN",
      payment_method: "both",
      txref: "quidpay-123456",
      integrity_hash: "<PASS YOUR INTEGRITY HASH HERE>"
      meta: [{metaname:"flightID", metavalue: "AP1234"}],
      onclose: function() {},
      callback: function(response) {
        var flw_ref = response.tx.flwRef; // collect flwRef returned and pass to a 					server page to complete status check.
        console.log("This is the response returned after a charge", response);
        if (
          response.tx.chargeResponseCode == "00" ||
          response.tx.chargeResponseCode == "0"
        ) {
          // redirect to a success page
        } else {
          // redirect to a failure page.
        }
      }
    });
  });
});
</script>

Error returned for a bad integrity hash

832