In an Ionic 4 hybrid app project I had the requirement of opening a third party page (a payment service called Klarna) inside an Ionic 4 app. The payment solution itself uses a payment registration page and sends the user to a confirmation page when the payment is ready. The solutions should work on both iOS and Android. Using Ionic 4 with Cordova, I considered the following options:
- Opening the page in an iFrame
- Using the Ionic Native BrowserTab plugin (Cordova)
- Using the Ionic Native InAppBrowser plugin (Cordova)
The first alternative, the iFrame solution, was skipped because of the risk for getting the app rejected on the iOS App Store when using an iFrame.
In the app, I needed the user to be able to close the third party page with a close button and we needed to listen for the navigation and close events in the app. The BrowserTab plugin does not have a close button (it’s just a Tab!), so we ended up choosing the InAppBrower plugin.
The first step of the solution was to add the Ionic Native Cordova plugin for InAppBrowser to the project:
ionic cordova plugin add cordova-plugin-inappbrowser npm install --save @ionic-native/in-app-browser
There are four available events being emitted from the in-app-browser:
- loadstart: fires when the InAppBrowser starts to load a URL.
- loadstop: fires when the InAppBrowser finishes loading a URL.
- loaderror: fires when the InAppBrowser encounters an error when loading a URL.
- exit: fires when the InAppBrowser window is closed
In my case, I needed to know when the InAppBrowser had loaded the confirmation page of the payment solution (Klarna) in order to get the order id from the url. The source code for the openBrowser function is as follows:
openBrowser(url: string, target: string) { const browser: InAppBrowserObject = this.theInAppBrowser.create(url, target, this.options); const btn: HTMLElement = this.hiddenBtn.nativeElement as HTMLElement; if (browser.on('loadstop')) { browser.on('loadstop').subscribe((ev: InAppBrowserEvent) => { // do whatever is needed here, for example check the url of the browser event if (ev.url) { // do stuff based on url and url parameters // in our solution we got an order id from a confirmation page } // for the event to trigger we added a hidden button to interact with the screen btn.click(); }); } }
When first testing the ‘loadstop’ event I noticed that the event did not trigger before the user touched the screen. Of course, I wanted this event to be triggered without a user interaction so the problem was solved by adding a hidden button to the page that is being “clicked” in code.
<ion-button #hiddenBtn style="display:none">hidden</ion-button>
The hidden button is available in the page component via the Angluar ViewChild directive:
@ViewChild('hiddenBtn') hiddenBtn: ElementRef;
For reference, the options used for the in-app-browser were:
options: InAppBrowserOptions = { location: 'yes', hidden: 'no', clearcache: 'yes', clearsessioncache: 'yes', zoom: 'yes', hardwareback: 'yes', mediaPlaybackRequiresUserAction: 'no', shouldPauseOnSuspend: 'no', closebuttoncaption: 'Close', disallowoverscroll: 'no', toolbar: 'yes', enableViewportScale: 'no', allowInlineMediaPlayback: 'no', presentationstyle: 'pagesheet', fullscreen: 'yes', footer: 'yes' };