2

I am trying to implement Instamojo Payment in my Flutter App using this article:

I am using Flutter Webview plugin for it. Now the problem is during the payment process, Instamojo opens another tab for OTP Verification. But this new tab is not displayed inside the app.

How to handle these multiple tabs in flutter? I can't find any WebView Plugin which supports multiple browser tabs.

This is the code:

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:http/http.dart' as http;

class Insta extends StatefulWidget {
  @override
  _InstaState createState() => _InstaState();
}

class _InstaState extends State<Insta> {
  FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin();

  @override
  void initState() {
    super.initState();
    createRequest(); //creating the HTTP request
// Add a listener on url changed
    flutterWebviewPlugin.onUrlChanged.listen((String url) {
      if (mounted) {
        if (url.contains('http://www.example.com/redirect')) {
          Uri uri = Uri.parse(url);
//Take the payment_id parameter of the url.
          String paymentRequestId = uri.queryParameters['payment_id'];
//calling this method to check payment status
          _checkPaymentStatus(paymentRequestId);
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Text('data'),
    );
  }

  _checkPaymentStatus(String id) async {
    var response = await http.get(
        Uri.encodeFull("https://t7+st.instamojo.com/api/1.1/payments/$id/"),
        headers: {
          "Accept": "application/json",
          "Content-Type": "application/x-www-form-urlencoded",
          "X-Api-Key": "**Hidden for security reasons**",
          "X-Auth-Token": "**Hidden for security reasons**"
        });
    var realResponse = json.decode(response.body);
    print(realResponse);
    if (realResponse['success'] == true) {
      if (realResponse["payment"]['status'] == 'Credit') {
        print('sucesssssssssssful');
//payment is successful.
      } else {
        print('failed');
//payment failed or pending.
      }
    } else {
      print("PAYMENT STATUS FAILED");
    }
  }

  static const kAndroidUserAgent =
      "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Mobile Safari/537.36";
  Future createRequest() async {
    Map<String, String> body = {
      "amount": "9", //amount to be paid
      "purpose": "Advertising",
      "buyer_name": '',
      "email": '',
      "phone": '',
      "allow_repeated_payments": "true",
      "send_email": "false",
      "send_sms": "false",
      "redirect_url": "http://www.example.com/redirect/",
      //Where to redirect after a successful payment.
      "webhook": "http://www.example.com/webhook/",
    };
//First we have to create a Payment_Request.
//then we'll take the response of our request.
    var resp = await http.post(
        Uri.encodeFull("https://www.instamojo.com/api/1.1/payment-requests/"),
        headers: {
          "Accept": "application/json",
          "Content-Type": "application/x-www-form-urlencoded",
          "X-Api-Key": "**Hidden for security reasons**",
          "X-Auth-Token": "**Hidden for security reasons**"
        },
        body: body);
    if (json.decode(resp.body)['success'] == true) {
//If request is successful take the longurl.
      String selectedUrl =
          json.decode(resp.body)["payment_request"]['longurl'].toString() +
              "?embed=form";
      flutterWebviewPlugin.close();
//Let's open the url in webview.
      flutterWebviewPlugin.launch(selectedUrl,
          rect: new Rect.fromLTRB(
              5.0,
              MediaQuery.of(context).size.height / 7,
              MediaQuery.of(context).size.width - 5.0,
              7 * MediaQuery.of(context).size.height / 7),
          userAgent: kAndroidUserAgent);
    } else {
      print(json.decode(resp.body)['message'].toString());
//If something is wrong with the data we provided to
//create the Payment_Request. For Example, the email is in incorrect format, the payment_Request creation will fail.
    }
  }
}
Raj Dhakad
  • 852
  • 2
  • 17
  • 39

1 Answers1

0

What you can do here as a workaround is to let the external browser to handle the link that's being opened. To do this, you can set navigationDelegate on the WebView to handle specific URLs. I suggest on using Flutter's official WebView plugin.

WebView(
  ...
  navigationDelegate: (NavigationRequest request) {
    // open URL on external browser if matches root URL for OTP
    if (request.url.startsWith("OTP root URL goes here")) {
      _launchURL(request.url);
      return NavigationDecision.prevent;
    } else {
      return NavigationDecision.navigate;
    }
  },
),

You can use url_launcher plugin to handle the opening of URLs externally.

_launchURL(String url) async {
  if (await canLaunch(url)) {
    await launch(url);
  } else {
    debugPrint('Could not launch $url');
  }
}
Omatt
  • 8,564
  • 2
  • 42
  • 144