Flutter PayPal Payment Gateway Integration
At the time of writing, PayPal does not provide an SDK/package for their Paypal payment Integration in Flutter
We will cover how to integrate PayPal into a flutter project using web-view. We must take a few actions to do this.
What is PayPal ?
PayPal is a payment platform featuring a website and a phone app that allows for online money transactions between parties.
PayPal is a highly secure banking service that employs some of the most cutting-edge end-to-end encryption technology available. You should also activate two-factor authentication and erase any inactive bank accounts or email addresses.
Because PayPal is not presently providing an SDK/package for their payment gateway integration in Flutter, I successfully implemented PayPal using WebView. I’ve used several of PayPal’s payment Web services that are available for integration in websites all around the world, so I decided to test it in a flutter to reach my aim.
First, we’ll make a PayPal application.
In this example, PayPal Sandbox is used to test the payment integration.
What is the PayPal sandbox?
The PayPal sandbox is a virtual testing environment that is segregated from the actual PayPal production environment. The PayPal sandbox mimics the functionality accessible on PayPal’s production servers. While several PayPal features, such as account termination, monthly statement creation, preserving shipping preferences, and PayPal Shops support, are not available in the paypal sandbox, it does have the same PayPal API feature set as the live environment. You may test your PayPal procedures in the sandbox. Processes behave precisely as they do on production servers in the sandbox.
PayPal developer dashboard
Now. Go to the PayPal developer account dashboard to start utilizing PayPal with Flutter.
Account for PayPal sandbox testing
You’ll see a sidebar in the SANDBOX option where you may pick the accounts and obtain this screen.
Make a PayPal application.
Select My Apps & Credentials from the left panel as shown in this image, then click the “Build App” button to create an app in PayPal.
Include appName, appType, and sandbox account information.
Include this page in your app’s Name, AppType, and Sandbox Business Accounts, as instructed by PayPal, and then click the “Create App” button to acquire the app credentials.
This screen contains the secret id and client id.
After successfully constructing the application, you must retrieve the secret id and client id by clicking on the application detail.
Implementation of Paypal In Flutter App:
Download/Install dependencies.
Add the required dependencies in pubspec.yaml file as shown below.
http_auth:^any http:^any webview_flutter:^any
Code implement
To begin, we’ll develop a PaypalHomeScreen and populate it with our simple sample UI and Navigation to pay the payment .
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, key: _scaffoldKey, appBar: AppBar( centerTitle: true, backgroundColor: Colors.white, title: const Text( 'Paypal Payment', style: TextStyle( fontSize: 18.0, color: Colors.black, fontWeight: FontWeight.bold, ), ), ), body: SizedBox( width: MediaQuery.of(context).size.width, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Column( children: const [ Text( "Items in your Cart", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ListTile( title: Text( "Product: One plus 10", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), ), subtitle: Text( "Quantity: 1", style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600), ), trailing: Text( "\$100", style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ) ], ), RaisedButton( color: Colors.red, onPressed: () { // make PayPal payment Navigator.of(context).push( MaterialPageRoute( builder: (BuildContext context) => Payment( onFinish: (number) async { // payment done final snackBar = SnackBar( content: const Text("Payment done Successfully"), duration: const Duration(seconds: 5), action: SnackBarAction( label: 'Close', onPressed: () { // Some code to undo the change. }, ), ); _scaffoldKey.currentState!.showSnackBar(snackBar); }, ), ), ); }, child: const Text( 'Pay with Paypal', textAlign: TextAlign.center, style: TextStyle(color: Colors.white), ), ), ], )), ); }
The next step is to establish the PayPalService page, from which we will use the PayPal APIs; for now, because we are testing, we will use the URL https://api.sandbox.paypal.com . If you wish to make an actual transaction, replace that with https://api.paypal.com .
Note : In testing mode, a sandbox account is used, but in live mode, a genuine PayPal account is used.
We will now create a PaypalService.dart screen.
PaypalService.dart
class PaypalServices { String domain = "https://api.sandbox.paypal.com"; /// for testing mode //String domain = "https://api.paypal.com"; /// for production mode /// Change the clientId and secret given by PayPal to your own. String clientId = 'Here add clientId'; String secret = 'Here add secretId'; /// for obtaining the access token from Paypal Future<String?> getAccessToken() async { try { var client = BasicAuthClient(clientId, secret); var response = await client.post( Uri.parse('$domain/v1/oauth2/token?grant_type=client_credentials')); if (response.statusCode == 200) { final body = convert.jsonDecode(response.body); return body["access_token"]; } return null; } catch (e) { rethrow; } } // for generating the PayPal payment request Future<Map<String, String>?> createPaypalPayment( transactions, accessToken) async { try { var response = await http.post(Uri.parse("$domain/v1/payments/payment"), body: convert.jsonEncode(transactions), headers: { "content-type": "application/json", 'Authorization': 'Bearer ' + accessToken }); final body = convert.jsonDecode(response.body); if (response.statusCode == 201) { if (body["links"] != null && body["links"].length > 0) { List links = body["links"]; String executeUrl = ""; String approvalUrl = ""; final item = links.firstWhere((o) => o["rel"] == "approval_url", orElse: () => null); if (item != null) { approvalUrl = item["href"]; } final item1 = links.firstWhere((o) => o["rel"] == "execute", orElse: () => null); if (item1 != null) { executeUrl = item1["href"]; } return {"executeUrl": executeUrl, "approvalUrl": approvalUrl}; } return null; } else { throw Exception(body["message"]); } } catch (e) { rethrow; } } /// for carrying out the payment process Future<String?> executePayment(url, payerId, accessToken) async { try { var response = await http.post(url, body: convert.jsonEncode({"payer_id": payerId}), headers: { "content-type": "application/json", 'Authorization': 'Bearer ' + accessToken }); final body = convert.jsonDecode(response.body); if (response.statusCode == 200) { return body["id"]; } return null; } catch (e) { rethrow; } } }
To submit the order and payment details to PayPal, we will now create a payment screen.
payment screen
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); String? checkoutUrl; String? executeUrl; String? accessToken; PaypalServices services = PaypalServices(); // You may alter the default value to whatever you like. Map<dynamic, dynamic> defaultCurrency = { "symbol": "USD ", "decimalDigits": 2, "symbolBeforeTheNumber": true, "currency": "USD" }; bool isEnableShipping = false; bool isEnableAddress = false; String returnURL = 'return.example.com'; String cancelURL = 'cancel.example.com'; @override void initState() { super.initState(); Future.delayed(Duration.zero, () async { try { accessToken = await services.getAccessToken(); final transactions = getOrderParams(); final res = await services.createPaypalPayment(transactions, accessToken); if (res != null) { setState(() { checkoutUrl = res["approvalUrl"]; executeUrl = res["executeUrl"]; }); } } catch (ex) { final snackBar = SnackBar( content: Text(ex.toString()), duration: const Duration(seconds: 10), action: SnackBarAction( label: 'Close', onPressed: () { // Some code for undoing the alteration. }, ), ); _scaffoldKey.currentState!.showSnackBar(snackBar); } }); } // item name, price and quantity here String itemName = 'One plus 10'; String itemPrice = '100'; int quantity = 1; Map<String, dynamic> getOrderParams() { List items = [ { "name": itemName, "quantity": quantity, "price": itemPrice, "currency": defaultCurrency["currency"] } ]; // Checkout Invoice Specifics String totalAmount = '100'; String subTotalAmount = '100'; String shippingCost = '0'; int shippingDiscountCost = 0; String userFirstName = 'john'; String userLastName = 'smith'; String addressCity = 'USA'; String addressStreet = "i-10"; String addressZipCode = '44000'; String addressCountry = 'Pakistan'; String addressState = 'Islamabad'; String addressPhoneNumber = '+1 223 6161 789'; Map<String, dynamic> temp = { "intent": "sale", "payer": {"payment_method": "paypal"}, "transactions": [ { "amount": { "total": totalAmount, "currency": defaultCurrency["currency"], "details": { "subtotal": subTotalAmount, "shipping": shippingCost, "shipping_discount": ((-1.0) * shippingDiscountCost).toString() } }, "description": "The payment transaction description.", "payment_options": { "allowed_payment_method": "INSTANT_FUNDING_SOURCE" }, "item_list": { "items": items, if (isEnableShipping && isEnableAddress) "shipping_address": { "recipient_name": userFirstName + " " + userLastName, "line1": addressStreet, "line2": "", "city": addressCity, "country_code": addressCountry, "postal_code": addressZipCode, "phone": addressPhoneNumber, "state": addressState }, } } ], "note_to_payer": "Contact us for any questions on your order.", "redirect_urls": {"return_url": returnURL, "cancel_url": cancelURL} }; return temp; } @override Widget build(BuildContext context) { print(checkoutUrl); if (checkoutUrl != null) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).backgroundColor, leading: GestureDetector( child: const Icon(Icons.arrow_back_ios), onTap: () => Navigator.pop(context), ), ), body: WebView( initialUrl: checkoutUrl, javascriptMode: JavascriptMode.unrestricted, navigationDelegate: (NavigationRequest request) { if (request.url.contains(returnURL)) { final uri = Uri.parse(request.url); final payerID = uri.queryParameters['PayerID']; if (payerID != null) { services .executePayment(executeUrl, payerID, accessToken) .then((id) { widget.onFinish!(id); Navigator.of(context).pop(); }); } else { Navigator.of(context).pop(); } Navigator.of(context).pop(); } if (request.url.contains(cancelURL)) { Navigator.of(context).pop(); } return NavigationDecision.navigate; }, ), ); } else { return Scaffold( key: _scaffoldKey, appBar: AppBar( leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { Navigator.of(context).pop(); }), backgroundColor: Colors.black12, elevation: 0.0, ), body: const Center(child: CircularProgressIndicator()), ); } }
Your desired output is 👍
flutter paypal github complete code
https://github.com/kevalv001/paypal_demo.git
Conclusion
This was a brief overview of the PayPal services; I covered the service in the post; you may modify the code to suit your needs. I believe you now have enough information from this blog to experiment with PayPal in your flutter projects.
Thank you very much!!Have a Good day…..