Google Pay Integration (Flutter)
This section explains how to integrate Google Pay using the Novalnet Flutter SDK.
Prerequisites
Before integrating Google Pay, ensure the following:
- Flutter SDK 3.0 or later
- Dart SDK 3.0 or later
- Google Pay & Wallet Console account created
- Merchant profile approved
- Android app registered (Package Name + SHA-256)
- Google Pay API enabled for production
- Supported card added to the device
Step 1: Configure Google Pay on Merchant Side (Google Pay Console)
The merchant must configure the following in their Google Pay Console:
- Merchant ID – Required for production (from Google Pay Console)
- Merchant Name – Displayed in payment sheet
- Package Name – Your Android app ID
- SHA-256 – Your app signing certificate
Step 2: Install Dependency
Add the stable version of PAY plugin under dependencies in pubspec.yaml file.
dependencies: # level 0
pay: ^3.2.0 # +2 spacesRun flutter pub get to fetch and install the dependencies.
Note: Whenever you make changes or updates to the dependencies, run the flutter pub get command to apply and fetch the updated packages
Indentation Notes :
dependencies: must be at the root level (no spaces before it)
pay: must be indented with 2 spaces under dependencies
YAML is space-sensitive, so incorrect indentation will cause errors
Step 3:Import Packages
After adding the dependency, import the Packages in your Google Pay integration file.
import 'package:pay/pay.dart';
import 'package:flutter/material.dart'; //Provides Material Design componentsStep 4: Google Pay Configuration
This configuration defines how Google Pay should process the payment request in your Flutter app. It includes supported payment methods, gateway details, transaction amount, currency, and merchant information shown to the user. The JSON is passed to the pay plugin to initialize and display the Google Pay sheet. Make sure to replace all placeholder values with your actual merchant and transaction details before use.
static String _googlePayConfig() {
return '''
{
"provider": "google_pay",
"data": {
"environment": "ENVIRONMENT",
"apiVersion": 2,
"apiVersionMinor": 0,
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
"allowedCardNetworks": ["VISA", "MASTERCARD"]
},
"tokenizationSpecification": {
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "GATEWAY",
"gatewayMerchantId": " "
}
}
}
],
"transactionInfo": {
"totalPriceStatus": "FINAL",
"totalPrice": "TOTAL AMOUNT",
"currencyCode": "CURRENCY"
},
"merchantInfo": {
"merchantName": "MERCHANT_NAME"
}
}
''';
}
}| Field | Placeholder / Value | Description |
| environment | ENVIRONMENT | Defines the mode (TEST or PRODUCTION) |
| type | CARD (fixed) | Payment method type (predefined, do not change) |
| allowedAuthMethods | ["PAN_ONLY","CRYPTOGRAM_3DS"] (fixed) | Supported authentication methods (predefined) |
| allowedCardNetworks | ["VISA","MASTERCARD"] (configurable) | Supported card networks |
| tokenizationSpecification.type | PAYMENT_GATEWAY (fixed) | Defines how payment data is processed (via gateway) |
| gateway | GATEWAY | Payment gateway provider name |
| gatewayMerchantId | YOUR_GATEWAY_MERCHANT_ID | Merchant ID provided by the gateway |
| totalPriceStatus | FINAL (fixed) | Indicates final transaction amount (do not change) |
| totalPrice | TOTAL_AMOUNT | Payment amount (2 decimals, use dot) |
| currencyCode | CURRENCY | ISO currency code (e.g., EUR, USD, INR) |
| merchantName | MERCHANT_NAME | Name shown in Google Pay payment sheet |
Step 5: Environment Setup
| Environment | Usage |
| Test | No real money, used during development |
| Production | Real payments |
- Use test during development
- Switch to production only after: Merchant Configuration done in Google Pay Console.
Step 6 : Check Google Pay Availability
This step checks whether the device is fully ready to make a Google Pay payment before starting the payment flow. It initializes the payment configuration and uses the userCanPay method to verify support. If canPay returns false, it means Google Pay cannot be used on the device. This typically happens if Google Pay not set up, no supported card is added, or the device/region does not support Google Pay. It can also occur if there is a configuration issue (e.g., incorrect environment or merchant setup).
final config = PaymentConfiguration.fromJsonString(_googlePayConfig());
final payClient = Pay({PayProvider.google_pay: config});
final canPay = await payClient.userCanPay(PayProvider.google_pay);
If canPay returns false, Google Pay is not supported on the device
eg:
if (!canPay) {
return {
"status": "FAILURE",
"message": "Google pay not available",
};
}Step 7: Set payment items, Show Google Pay Button & Get Payment Data
This step defines the payment amount and displays the Google Pay button to the user. When the user completes the payment, the response is returned via onPaymentResult and stored in resultData.
final items = [
PaymentItem(
label: "Total",
amount: AMOUNT, // The amount must be provided as a string in standard decimal format with two digits (e.g., "82.00", not 8200)
status: PaymentItemStatus.final_price,
),
];
Map<String, dynamic>? resultData;
await showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) {
return Padding(
padding: const EdgeInsets.only(bottom: 80),
child: SizedBox(
height: 120,
child: Center(
child: GooglePayButton(
paymentConfiguration: config,
paymentItems: items,
type: GooglePayButtonType.pay,
onPaymentResult: (result) async {
resultData = result;
Navigator.pop(context);
},
onError: (e) {
Navigator.pop(context);
},
loadingIndicator: const CircularProgressIndicator(),
),
),
),
);
},
);Result Data contains the payment response, including the signature, payment token, and encrypted payment data. Once received successfully, this data must be sent to Novalnet for processing and transaction booking.
Step 8: Process Payment with Novalnet SDK
After receiving the payment response from Google Pay, the token must be sent to Novalnet for decryption and transaction processing.
- Import the Novalnet SDK in your file: : import 'package:novalnetsdk/novalnetsdk.dart';
- Call the SDK function with the payment token: :
var result = await NovalnetSDK.openWalletPaymentHandler(
context,
paymentType: "GOOGLEPAY",
token: resultData ?? {},
);The SDK will handle token decryption and complete the transaction processing.
Step 9: Important Notes
- Google Pay production requires proper merchant configuration
- Release build must be used for production testing
- Google Pay is supported only on Android devices
- Ensure correct merchant ID is used
Reference Implementation (Full Payment Flow)
This example provides a complete end-to-end implementation of Google Pay integration using the Flutter pay plugin. It includes configuration setup, availability check, payment UI handling, and capturing the payment response. Developers can use this as a ready-to-use reference to integrate Google Pay quickly. The returned resultData should be sent to Novalnet for final payment processing.
import 'package:flutter/material.dart';
import 'package:pay/pay.dart';
import 'package:novalnetsdk/novalnetsdk.dart';
class GooglePayHandler {
static Future<Map<String, dynamic>?> startPayment(
BuildContext context,
) async {
try {
// Create config
final config = PaymentConfiguration.fromJsonString(_googlePayConfig());
// Create Pay client
final payClient = Pay({PayProvider.google_pay: config});
// Check availability
final canPay = await payClient.userCanPay(PayProvider.google_pay);
if (!canPay) {
return {"status": "FAILURE", "message": "Google pay not available"};
}
// Payment items
final items = [
PaymentItem(
label: "Total",
amount: AMOUNT, //The amount must be provided as a string in standard decimal format with two digits (e.g., "82.00" not 8200)
status: PaymentItemStatus.final_price,
),
];
Map<String, dynamic>? resultData;
// Open UI
await showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (_) {
return Padding(
padding: const EdgeInsets.only(bottom: 80),
child: SizedBox(
height: 120,
child: Center(
child: GooglePayButton(
paymentConfiguration: config,
paymentItems: items,
type: GooglePayButtonType.pay,
onPaymentResult: (result) async {
resultData = result;
Navigator.pop(context);
},
onError: (e) {
Navigator.pop(context);
},
loadingIndicator: const CircularProgressIndicator(),
),
),
),
);
},
);
if (resultData == null || resultData?.isEmpty == true) {
return {
"status": "FAILURE",
"message": "Payment cancelled due to Result data is empty",
};
}
var result = await NovalnetSDK.openWalletPaymentHandler(
context,
paymentType: "GOOGLEPAY",
token: resultData ?? {},
);
return result;
} catch (e) {
return {"status": "FAILURE", "message": "Google Pay failed $e"};
}
}
// CONFIG
static String _googlePayConfig() {
return '''
{
"provider": "google_pay",
"data": {
"environment": "ENVIRONMENT",
"apiVersion": 2,
"apiVersionMinor": 0,
"allowedPaymentMethods": [
{
"type": "CARD",
"parameters": {
"allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
"allowedCardNetworks": ["VISA", "MASTERCARD"]
},
"tokenizationSpecification": {
"type": "PAYMENT_GATEWAY",
"parameters": {
"gateway": "GATEWAY",
"gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
}
}
],
"transactionInfo": {
"totalPriceStatus": "FINAL",
"totalPrice": "TOTAL AMOUNT",
"currencyCode": "CURRENCY"
},
"merchantInfo": {
"merchantName": "MERCHANT_NAME"
}
}
}
''';
}
}The following example demonstrates how to initiate Google Pay when the button is pressed. This is a basic example, and you can handle the response and flow based on your application requirements:
import 'googlepay_handler.dart';
onPressed: () async {
var result = await GooglePayHandler.startPayment(context);
if (result == null) return;
}