NetPayBD Flutter Integration Guide

Easily integrate our payment gateway into your Flutter app using WebView.

The WebView Approach

Instead of a native SDK, our gateway is integrated into Flutter applications using the official webview_flutter package. This method is simple, secure, and allows you to use our web-based payment pages directly inside your app, ensuring a consistent user experience without requiring any changes to our backend.

Step 1: Add Dependency

First, add the webview_flutter package to your project's pubspec.yaml file. Always check pub.dev for the latest version.

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.7.0

Then, run flutter pub get in your terminal to install the package.

Step 2: Construct the Payment URL

In your Dart code, build the payment URL with your credentials and transaction details. This URL will be loaded into the WebView.

final String username = 'YOUR_USERNAME';
final String apiKey = 'YOUR_API_KEY';
final double amount = 50.00;

// Use a unique success URL to detect when the payment is complete.
final String successUrl = 'https://yourdomain.com/flutter/payment-success';
final String callbackUrl = 'https://yourbackend.com/payment_callback.php';

final Uri paymentUri = Uri.parse('https://pay.netpaybd.com/').replace(
  queryParameters: {
    'username': username,
    'api': apiKey,
    'amount': amount.toString(),
    'success_url': successUrl,
    'callback_url': callbackUrl,
  },
);

Step 3: Implement the WebView Screen

Create a new Flutter screen (e.g., payment_webview_screen.dart) to display the payment page. This screen will contain the WebView and the logic to detect a successful payment.

The key part is the NavigationDelegate, which listens for URL changes. When the URL matches your successUrl, it means the payment was successful, and you can close the WebView.

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class PaymentWebViewScreen extends StatefulWidget {
  final Uri paymentUrl;
  final String successUrl;

  const PaymentWebViewScreen({
    super.key,
    required this.paymentUrl,
    required this.successUrl,
  });

  @override
  State createState() => _PaymentWebViewScreenState();
}

class _PaymentWebViewScreenState extends State {
  late final WebViewController _controller;
  var _loadingPercentage = 0;

  @override
  void initState() {
    super.initState();

    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageStarted: (url) {
            setState(() { _loadingPercentage = 0; });
          },
          onProgress: (progress) {
            setState(() { _loadingPercentage = progress; });
          },
          onPageFinished: (url) {
            setState(() { _loadingPercentage = 100; });
          },
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.startsWith(widget.successUrl)) {
              Navigator.pop(context, 'success');
              return NavigationDecision.prevent;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(widget.paymentUrl);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Complete Your Payment')),
      body: Stack(
        children: [
          WebViewWidget(controller: _controller),
          if (_loadingPercentage < 100)
            LinearProgressIndicator(
              value: _loadingPercentage / 100.0,
              color: const Color(0xFF00BCD4),
            ),
        ],
      ),
    );
  }
}

Step 4: Launch the WebView and Get the Result

From your checkout page, launch the PaymentWebViewScreen and wait for it to return a result. You can use await Navigator.push(...) to handle this.


ElevatedButton(
  onPressed: () async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => PaymentWebViewScreen(
          paymentUrl: paymentUri, // The URL you built in Step 2
          successUrl: successUrl,  // The same successUrl
        ),
      ),
    );

    if (result == 'success') {
      // Payment was successful!
      // Show a success message to the user.
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Payment Successful!')),
      );
    } else {
      // Payment failed or was cancelled.
      // Show an error or cancellation message.
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Payment Failed or Cancelled.')),
      );
    }
  },
  child: const Text('Pay Now'),
)

Important: While the app handles the user interface flow, your server should always rely on the Server-to-Server Callback (IPN) sent to your callback_url to securely verify the payment and update your database.