Exploring Web and PhonePe Switch with Flutter

Exploring Web and PhonePe Switch with Flutter

Shipsy’s Mobile Engineering Team solves complex technical challenges by leveraging innovative and rapidly evolving mobile technologies.

By Kushal Jain and Daksh Pokar

Mobile technology evolved by leaps and bounds in the last decade, and along with it came skyrocketing demand for building apps for archaic company websites. Soon businesses realized the true potential of cloud-based apps with regards to scalability and supporting growing traffic volumes of their online business. Result? Millions of apps on the Play Store, App Store, and more.

However, apps have one major disadvantage in contrast to traditional websites. It is the ease of access. Any web browser can easily access a website by accessing its URL. But when it comes to using an app, one needs to have access to an Application Store. Along with that emerges the need to have an account. In other words, in App Store, one needs an Apple ID and a Google Account for Play Store.

So, is it a good idea then to have a website on a mobile device? It’s also not an ideal approach. A mobile website tends to be slow and it’s not adaptive to ever-evolving mobile screens. According to KissMetrics, Out of 100 people visiting a website, 40 abandon it just because it takes too much time to load. Just imagine the revenue that is lost because of website downtime. Research highlights that just 15 minutes worth of website downtime can cost businesses $12,495 in lost profits. No wonder the man below is so angry!

Gif description

These usual problems with traditional websites and accessibility constraints of apps were enough to fuel the next major evolution in the app industry. As a result, the world was introduced to PWAs (Progressive Web Apps).

What are PWAs?

PWAs are simple web apps built using common web technologies like HTML, CSS, and JavaScript. The idea of PWA is not new, and it was first introduced by Steve Jobs. For the first time, he presented the concept in front of the world during the iPhone introduction in 2007. However, the term “PWA” is recent and was coined by Google Chrome developer Alex Russel and designer Frances Berriman in an article in 2015.

PWAs are faster, light-weight, easily extensible, and even work offline. The big advantage of PWAs is that they can be easily found on the web and can work on any mobile device that supports a web browser.

Also Read: A Progressive Web App Might Be Right for Your Brand

In India, where mobile data speeds are still limited, it made sense for companies to adopt PWAs and PhonePe. Considering the potential opportunity in delivering the PWAs, it launched its microapps platform called PhonePe Switch.

What is PhonePe Switch?

PhonePe Switch is a platform that hosts a vast collection of microapps with over 300 million active users. It reduces customer acquisition costs for any company by providing a user with one-click access to hundreds of apps and seamless integration with its secure payments channel. Existing mobile sites or even a PWA can easily be hosted on the platform by easy-to-follow guidelines provided in this documentation.

Looking at this opportunity we decided to host our Flutter App on the platform, considering that Flutter now supports building PWAs with the introduction of Flutter Web.

We ran our flutter app on chrome and we came across the following challenges:

  1. Routes are hashed by default. For ex: localhost54724. These routes create problems in reading the query parameters and we were planning to use them
  2. Some packages like geocoder and place picker didn’t support web platform
  3. Image uploading and some other I/O operations have different implementations in web and mobile For different implementations, we had to separate the code for image upload for web and mobile platforms

Solution:

The above challenges can be solved if we make a web-specific service and encapsulate all the web-specific implementations there (same for mobile):

Define an interface for IOService containing all the methods to be implemented

abstract class IOService {}

Implement IOServiceMobile and IOServiceWeb from the interface and define platform-specific code

class IOServiceMobile implements IOService {}
class IOServiceWeb implements IOService {}

Conditionally import the service

import 'web_service_mobile.dart' if (dart.library.js) 'web_service_web.dart';

In the web service constructor, we can change the path URL strategy to solve our challenge for hashed routes (challenge no 1). For different implementations in web and mobile for the same logic (challenge no 2 and 3), we can implement package-specific methods and separate implementations for mobile and web, so the conditional import will execute the specific method from the platform-specific service.

Now our PWA is running, so we deployed it on our AWS ec2 instance. The next step is to make it work inside the PhonePe switch

According to PhonePe switch docs, we have the following requirements:

  1. Deployed PWA
  2. Pre Prod APK for PhonePe
  3. Unique ID from PhonePe

Also if you want your app to work on a switch platform, you need:

1. SSO login feature

image3.png

On the login screen, you should get a prompt for logging in via PhonePe SSO. If the user skips the login, then normal login can be done.

2. Payment using PhonePe

image2.png

When a user makes a payment, the PhonePe payment screen has to be shown directly.

To implement the PhonePe switch, we implemented a PhonePeService for both mobile and web. Just like IOService and implemented the PhonePe JS SDK using our dart code. This also took some time to do but was achievable. We managed to load the SDK using JS wrappers in dart, Futures, and Completers.

  Future<void> loadSdk() {
   final Completer _completer = new Completer();
   if (isPhonePeSwitchPlatform()) {
     var head = document.getElementsByTagName('head')[0];
     var jsScript = document.createElement("script");

     jsScript.attributes.addAll({
       'type': 'text/javascript',
       'src': 'scripts/phonepe-sdk.js',
     });

     jsScript.addEventListener('load', (event) {
       window.console.log('[PHONEPE] Script Loaded');
       _initializeSdk();
       _completer.complete();
     });

     head.append(jsScript);
   }
   return _completer.future;
 }

 Future<void> _initializeSdk() async {
   var phonePeParent = jsUtil.getProperty(window, 'PhonePe');
   var phonePe = jsUtil.getProperty(phonePeParent, 'PhonePe');
   var constants = jsUtil.getProperty(phonePeParent, 'Constants');
   var species = jsUtil.getProperty(constants, 'Species');
   jsUtil.setProperty(phonePe, 'loggingEnabled', true);
   window.console.log('[PHONEPE] LOGGING ENABLED');
   _sdk = await jsUtil.promiseToFuture(jsUtil
       .callMethod(phonePe, 'build', [jsUtil.getProperty(species, 'web')]));
   window.console.log('[PHONEPE] SDK INIT DONE');
 }

Window and document are imported from dart:html and jsUtil is imported from dart:js_util package as:

import 'dart:js_util' as jsUtil;

Similarly, we managed to achieve the SDK methods implementation by wrapping them up like this.

The web application can be done using flutter and is not that tedious. Try it out yourself. If you love to solve complex engineering problems like this one, we would love to know you better. Check out the open job positions here , we would like to start engaging.