Implementing payments on your website using “Pay with Quickteller”

How it works (general user experience)

At checkout, the user sees a button like this on your website

When he clicks it, a pop up window will appear on your website. (If the user is
on a mobile device, the browser will redirect to a mobile friendly page instead).
On that popup window, the familiar WebPAY card input page will appear for him to
complete his transaction.

By your choice, after payment, the user can be redirected to a page that you specify.
If you specify none, Quickteller will display a default receipt page. In both cases,
both pages will show within the popup. You can programmatically close the popup
if you specified a redirect page.

Test it here.

 

How to get it

This feature is currently available to all merchants listed on Quickteller at no
extra charge

  1. Sign up to be a merchant on Quickteller
  2. After being setup as a merchant, request for “pay with Quickteller” activation by sending an email to the Quickteller team to activate your website
  3. You’d receive an email containing all your merchant and security credentials.
  4. Then come back here to follow these instructions

 

Basic implementation

Once you request to be activated for Pay with Quickteller, you would receive an
activation email that would contain a snippet of Javascript like below. Simply copy
and paste the snippet into the HTML of your website at the very spot where you want
the “pay” button to appear.

Below is a raw version of the snippet that you can copy and paste on your website.
Just change the payment code to yours.

 

     <!--Snippet provided by Interswitch starts here--->
    <em><small><a id="[[paymentcode]]" style="text-align:left;">payment button will appear here shortly...</a></small></em>
    <script type="text/javascript">
        var QTCheckout = QTCheckout || {};
        var testMode = false;
        var baseUrl = "";
        QTCheckout.paymentItems = QTCheckout.paymentItems || [];
        QTCheckout.paymentItems.push({
            paymentCode: [[paymentcode]],
            extraData: {
                amount: 'default',
                buttonSize: 'default',
                customerId: 'default',
                mobileNumber: 'default',
                emailAddress: 'default',
                redirectUrl: 'default'
            }
        });
        if (testMode == true) baseUrl = "https://testwebpay.interswitchng.com/quicktellercheckout/scripts/quickteller-checkout.js?v=";
        else baseUrl = "https://paywith.quickteller.com/scripts/quickteller-checkout-min.js?v=";
        if (!QTCheckout.qtScript) {
            var qtScript = document.createElement('script');
            qtScript.type = 'text/javascript';
            qtScript.async = true;
            qtScript.src = baseUrl + new Date().getDay();
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(qtScript, s);
            QTCheckout.qtScript = qtScript;
        }
        else if (QTCheckout.buildPaymentItemsUI) {
            QTCheckout.buildPaymentItemsUI();
        }

    </script> 
    <!--Snippet provided by Interswitch ends here -->

 

This would generate the Pay with Quickteller button and when clicked, will render
a pop-up like this.

 

Try it now!

Paste the snippet provided above into a test page on your local machine (localhost).
NOTE: It needs to be on localhost because Pay with Quickteller
validates the domain the script is being run from. The test merchant account
has already been enabled for the domain “localhost”. The test merchant (Red Cross) payment code is 218169

 

Advanced implementation

You do not necessarily have to just copy and paste the snippet of Javascript on
your website. You can customize the behavior of the popup to:

  • Land straight on the card input page
  • Redirect to a page on your website after payment
  • Close the pop-up window after the transaction
  • Validate that the amount paid was the exact amount you were expecting (to prevent fraudulent transactions)

In the next few steps I’ll be showing you how to make this happen.

 

NOTE:

You can download the complete ASP.Net MVC project used for this guide 
here
.

 

Step 1: set the ‘ExtraData’ variables programmatically

In the sample ASP.Net MVC project, the controller for my Checkout page looks like
below:

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Checkout(long amount, string email, string phone, string customer_id, string name)
        {
            /**These were passed in from the checkout build up which I have elsewhere**/
            ViewBag.Amount = amount;
            ViewBag.Email = email;
            ViewBag.Phone = phone;
            ViewBag.CustomerId = customer_id + " - " + name;
            bool useCallback = Convert.ToBoolean(ConfigurationManager.AppSettings["pwqusecallback"]);

            /**Set a Page that I want the payment gateway to redirect to after payment**/
            /**NOTE THAT: you can embed an identifier for the transaction (like a unique reference or order number or session Id) in the redirectUrl as a querystring param**/
            if(useCallback)
                ViewBag.RedirectUrl = Utility.GetSiteRoot(true, "siteroot") + "/Advanced/ValidatePaymentWithCallback" + "?unique=" + customer_id;
            else
                ViewBag.RedirectUrl = Utility.GetSiteRoot(true, "siteroot") + "/Advanced/ValidatePaymentWithoutCallback" + "?unique=" + customer_id;
            ViewBag.PaymentCode = ConfigurationManager.AppSettings["pwqpaymentcode"];
            ViewBag.TestMode = ConfigurationManager.AppSettings["pwqtestmode"];

            /**Preserve the amount I expect to be paid in memory. Also Preserve the redirect Url I am setting**/            
            Session["amount"] = amount;
            Session["redirectUrl"] = ViewBag.RedirectUrl;
            Session["customer_id"] = customer_id;
            return View();
        }

On the view for this action, the Pay with Quickteller script has been installed.
But the values of the variables in the script have been changed to values from the
“Checkout” action instead of leaving them as default:

Note all the @ViewBag.VariableName inserts in there.

 

        
         <!--Snippet provided by Interswitch starts here--->
        <em><small><a id="@ViewBag.PaymentCode" style="text-align: left;">
            payment button will appear here shortly...</a></small></em>
        <script type="text/javascript">
          var QTCheckout = QTCheckout || {};
          var testMode = true;
          var baseUrl = "";                      
          QTCheckout.paymentItems = QTCheckout.paymentItems || [];
          QTCheckout.paymentItems.push({
             paymentCode: @ViewBag.PaymentCode,
             extraData: {
                  amount: '@ViewBag.Amount,
                  buttonSize: 'default',
                  customerId: '@ViewBag.CustomerId',
                  mobileNumber: '@ViewBag.Phone',
                  emailAddress: '@ViewBag.Email',
                  redirectUrl: '@ViewBag.RedirectUrl'
              }
           });                        
        if (testMode == true) baseUrl = "https://testwebpay.interswitchng.com/quicktellercheckout/scripts/quickteller-checkout.js?v=";
        else baseUrl = "https://paywith.quickteller.com/scripts/quickteller-checkout-min.js?v=";
        if (!QTCheckout.qtScript) {
            var qtScript = document.createElement('script');
            qtScript.type = 'text/javascript';
            qtScript.async = true;
            qtScript.src = baseUrl + new Date().getDay();
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(qtScript, s); 
            QTCheckout.qtScript = qtScript;
        } 
        else if (QTCheckout.buildPaymentItemsUI) {
            QTCheckout.buildPaymentItemsUI();
        }

        </script> 
    <!--Snippet provided by Interswitch ends here -->

 

An explanation of the fields again:

  • paymentCode: This is the merchant’s payment code on the Quickteller platform
  • amount: this is the value I expect to be paid. In lower denomination. (N10
    = 1000)
  • buttonSize: Pay with Quickteller supports 4 values for this: small, medium,
    large, default.
  • CustomerId: this is a unique reference for this payment or customer. Something
    to ID the payment
  • mobileNumber: a phone number for the paying customer. This number will receive
    an SMS receipt
  • emailAddress: an email address for the paying cutomer. This email address
    will receive an email receipt
  • redirectUrl: This is the page on my web application that I want the payment
    gateway to redirect to after the payment is complete.

The above code guarantees that when a customer clicks the button, they would see
a page that looks like what’s below. Ready for card input.

Step 2: implementing a redirect page with callback

As you can notice above, I have provided a redirectUrl parameter. The payment gateway
will redirect the user to this page on my website after payment. This helps me to
do some house cleaning after the payment. As part of the redirect, the payment gateway
will submit some POST values to the page I have specified. The values I can expect
to receive are below.

  • Resp_code: a value that shows if the transaction was successful or not. ‘00’
    denotes successful. Every other value is a failure.
  • Resp_desc: A textual description of the response code
  • Tx_ref: a unique reference for the transaction. Assigned by the payment gateway
  • Recharge_pin: if the transaction is such that it requires the payer to get
    a voucher (like airtime recharge vouchers or electricity) the voucher number will
    be passed in this value
  • Signature: A unique signature for this trxn using a mix of amount, resp_code, trxn_ref all encrypted using the secret key provided to you by Interswitch

In essence, you have to implement a page that will:

  1. Receive these values
  2. Call a REST service exposed by Quickteller to retrieve other details of the transaction
  3. As a security check, compare the amount paid with the amount you set above
  4. If everything checks out, mark the payment as done and deliver service
NOTE

The security mechanisms required by the callback service is a bit involving, so
Interswitch has developed a few class libraries to abstract that away. The details
of how these libraries work are beyond the scope of this post but the libraries are
available for download here. Currently
available in .Net and PHP. Ruby and Java are work in progress.

 

NOTE

Using the callback mechanism is one way to validate the payment when the payment gateway redirects to your web app.
Another way is not to do a callback at all, but simply re-calculate the signature for your transaction, compare it with the signature POSTed to your web app from the payment gateway. If it matches, then all is well.
The sample application has code samples for both models but this tutorial is focused on the model of using a callback

 

In order to call the REST service, Interswitch has to provide you with some parameters
which you have to pass in the call in order for the service to authenticate your
website as a valid client application. If these values are not correct, the REST
service will decline the request. Refer to the top of this guide for those.

  • ClientId: this is the domain for your website (www.yourwebsite.com). The
    service validates that the request is coming from this domain
  • secretKey: a unique secret key given to you by Interswitch. You would receive
    this as part of the activation email you’d get when you request to be activated
    for Pay with Quickteller
  • base url for the REST service: this, you would also receive as part of the activation
    email

Now let’s go into the details.

 

Implementing the redirect page in ASP.Net MVC
  1. Extract TechQuest.API.dll from the helper libraries
  2. Add it as a reference to your ASP.Net project
  3. Add a ‘using’ directive to the controller where the callback will be implemented
using TechQuest.API.Quickteller;

We would be using two classes in this library.

  • PwQWrapper: this is the main class that wraps around the functionality of the library. It contains a single significant static method “GetTransaction” that will retrieve the required transaction details
  • PwQTrxnResponse: PwQWrapper.GetTransaction() above will return an object of this type.

 

 

  • Prepare the action method for the page that will receive the POST values and do the callback. The implementation for SmartNet (the demo application) is below

 

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ValidatePaymentWithCallback(string resp_code, string resp_desc, string tx_ref, string recharge_pin, string signature)
        {
            /****this should be the amount set on the payment request page that has the PwQ script installed**/
            long amountRequested = Convert.ToInt64(Session["amount"]);

            /***the customer has not paid, till we verify****/
            bool paid = false;

            /****Quick check to avoid any catastophe*****/
            if (string.IsNullOrEmpty(tx_ref))
                throw new Exception("No transaction reference returned from Payment gateway!");

            /***these values would be supplied by Interswitch***/
            var clientId = ConfigurationManager.AppSettings["pwqdomain"];//this will be the domain of your web app
            var secretKey = ConfigurationManager.AppSettings["pwqmackey"];//this is a key Interswitch will provide you
            var baseUrl = ConfigurationManager.AppSettings["pwqcallbackbaseurl"];//the base url of the REST service
            var fullUrl = string.Format("{0}/Transaction.json?transactionRef={1}", baseUrl, tx_ref);
            //var signature = 

            /**variable to hold the response data**/
            PwQTrxnResponse trxnResponse = PwQWrapper.GetTransaction(fullUrl, clientId, secretKey);

            /***test for validity of payment****/
            if (trxnResponse.ResponseCode == "00" && (Convert.ToInt64(trxnResponse.Amount) == amountRequested))
            {
                paid = true;
                //NEXT: deliver the goods!
            }

            /***prepare a response UI****/
            ViewBag.Paid = paid;
            ViewBag.ResponseCode = trxnResponse.ResponseCode;
            ViewBag.ResponseDecription = trxnResponse.ResponseDescription;
            ViewBag.PaymentRef = trxnResponse.PaymentReference;

            /***Serve the UI***/
            return View("AfterPayment");
        }

 

  • Below is what the view for this action looks like. It basically just displays the values received

 

        Response code: @ViewBag.ResponseCode
        Response description: @ViewBag.ResponseDescription
        Payment Ref: @ViewBag.PaymentRef

        <script type="text/javascript">
            window.top.location.href = "../";
        </script>

In PHP, here’s what it would look like…

        <?php
            require dirname(__FILE__) . 'SecurityHelper.php';

            $nonce = SecurityHelper::generateRandomString();
            $client_id = "mywebsite.com";
            $shared_secret_key = "KEY_PROVIDED_BY_ISW";
            $api_base = "https://paywith.quickteller.com/api/v1";
            $endpoint = "/Transaction.json/";
            $url = $api_base . $endpoint;
            $params = array("transactionRef" => $tx_ref);

            $encoded_url = SecurityHelper::url_encode($url, $params);
            $authorization_token = SecurityHelper::get_authorization_token($client_id);

            $timestamp = time();
            $_url = $url . "?" . SecurityHelper::to_query($params);

            $_params = array(
	            'http_verb' => "GET",
	            'url' => $encoded_url,
	            'timestamp' => $timestamp,
	            'nonce' => $nonce,
	            'client_id' => $client_id,
	            'shared_secret_key' => $shared_secret_key
            );

            $signature = SecurityHelper::calculate_signature($_params);

            $opts = array(
              'http'=>array(
                'method'=>"GET",
                'header' => "nonce: $noncern" .
              	            "Authorization: $authorization_tokenrn" .
              	            "signature: $signaturern" .
              	            "timestamp: $timestamprn" .
              )
            );

            $context = stream_context_create($opts);
            $response = file_get_contents($_url, false, $context);
NOTE:

The PHP implementation below actually shows some of what’s going on in the Security libraries provided

That’s it! You are done!!

Getting Help

Our dev Q&A forum is available here

Pay with Quickteller integration options

Pay with Quickteller integration is also available from selected resellers who are approved to provide custom installations and plugin support for the various web shopping carts and various management systems such as Vamcard, Joomla, Magento, Prestashop, OsCommerce, WordPress, WooCommerce and Opencart for Quickteller.

Resellers:
ProjectAngle Ltd: http://quickteller.pluginsprojectangle.com
Contact: John Adebowale john@projectangle.com +447535834681