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
- Sign up to be a merchant on Quickteller
- After being setup as a merchant, request for “pay with Quickteller” activation by sending an email to the Quickteller team to activate your website
- You’d receive an email containing all your merchant and security credentials.
- 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:
<!--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:
- Receive these values
- Call a REST service exposed by Quickteller to retrieve other details of the transaction
- As a security check, compare the amount paid with the amount you set above
- 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
- Extract TechQuest.API.dll from the helper libraries
- Add it as a reference to your ASP.Net project
- 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