Flutter NearPay Odoo Integration
Developer Guide for Seamless Payment Processing
Table of Contents
Overview
The NearPay-Odoo integration enables seamless payment processing through a Flutter mobile application communicating with Odoo's POS and Accounting modules.
Key Features
- POS Payments: Process payments via NearPay terminal with customer display and automatic receipt printing
- Invoice Payments: Pay invoices from Accounting module with transaction metadata storage
- Bidirectional Communication: Odoo communicates with Flutter via InAppWebView bridge
- Real-time Logging: Complete transaction logging and reconciliation
Key Concepts
- WebView Bridge: Odoo runs in a Flutter InAppWebView and communicates via JavaScript handlers
- Single Payment Channel: Both POS and Invoice payments use the same
payment_requesthandler - Callback Pattern: Flutter returns results via
window.paymentComplete() - Base64 PDF Printing: Receipts are sent as Base64-encoded PDFs to Flutter for printing
Architecture
Communication Architecture
Communication Channels
| Direction | From | To | Method | Status |
|---|---|---|---|---|
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("payment_request", payload) |
Active |
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("print_request", data) |
Active |
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("customer_display", url) |
Active |
| Flutter → Odoo | Flutter | WebView JavaScript | window.paymentComplete(result) |
Active |
Setup & Dependencies
Flutter Dependencies
Add to pubspec.yaml:
dependencies:
flutter_inappwebview: ^6.0.0
nearpay_flutter_sdk: ^1.0.0
json_annotation: ^4.8.0
dev_dependencies:
json_serializable: ^6.7.0
Android Configuration
Update android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
}
}
iOS Configuration
Update ios/Podfile:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_NEARPAY=1',
]
end
end
end
Implementation Guide
1. Basic WebView Setup
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:nearpay_flutter_sdk/nearpay_flutter_sdk.dart';
class OdooNearPayBridge extends StatefulWidget {
final String odooUrl;
final String sessionToken;
const OdooNearPayBridge({
Key? key,
required this.odooUrl,
required this.sessionToken,
}) : super(key: key);
@override
State createState() => _OdooNearPayBridgeState();
}
class _OdooNearPayBridgeState extends State {
InAppWebViewController? _webViewController;
NearPay? _nearPay;
@override
void initState() {
super.initState();
_initializeNearPay();
}
Future _initializeNearPay() async {
_nearPay = await NearPay.instance;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Odoo POS + Invoicing')),
body: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse(widget.odooUrl),
headers: {'Authorization': 'Bearer ${widget.sessionToken}'},
),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
),
onWebViewCreated: _onWebViewCreated,
),
);
}
void _onWebViewCreated(InAppWebViewController controller) {
_webViewController = controller;
_registerPaymentHandlers(controller);
}
}
2. Register Payment Handlers
void _registerPaymentHandlers(InAppWebViewController controller) {
// Payment processor (POS + Invoices)
controller.addJavaScriptHandler(
handlerName: 'payment_request',
callback: (args) => _handlePaymentRequest(args, controller),
);
// Receipt printing
controller.addJavaScriptHandler(
handlerName: 'print_request',
callback: (args) => _handlePrintRequest(args),
);
// Customer display
controller.addJavaScriptHandler(
handlerName: 'customer_display',
callback: (args) => _handleCustomerDisplay(args),
);
}
3. Payment Request Handler
Future
4. Print Handler
Future
5. Customer Display Handler
Future
Handler Reference
payment_request
Called By: Odoo POS (payment screen) and Accounting (invoice payment wizard)
Example Payload
Expected Response (Success)
print_request
Called By: Odoo POS (receipt screen)
customer_display
Called By: Odoo POS (payment and receipt screens)
/ics_pos/customer_display/welcome/ics_pos/customer_display/payment?amount=190.50/ics_pos/customer_display/order?order_id=POS001/ics_pos/customer_display/thanks?order_id=POS001
Payment Flows
POS Payment Flow
1. Order Creation
Customer adds products → Click "Payment"
2. Payment Request
Odoo POS calls payment_request handler
3. NearPay Processing
Flutter processes payment via NearPay
4. Response Handling
Flutter calls window.paymentComplete(result)
5. Validation
Odoo validates and creates pos.payment record
6. Completion
Receipt printed, customer display updated
Invoice Payment Flow
1. Invoice Open
User opens invoice → Click "Register Payment"
2. Method Selection
Select NearPay payment method
3. Payment Request
Odoo calls payment_request handler
4. NearPay Processing
Flutter processes payment via NearPay
5. Reconciliation
Odoo reconciles invoice with payment
6. Redirect
Odoo redirects to invoice list
Error Handling
Network Errors
Future _handleNetworkError(String error) async {
int retries = 0;
const maxRetries = 3;
const delayMs = 2000;
while (retries < maxRetries) {
try {
await Future.delayed(Duration(milliseconds: delayMs));
// Retry payment
break;
} catch (e) {
retries++;
if (retries >= maxRetries) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Payment failed after $maxRetries attempts')
),
);
}
}
}
}
}
NearPay SDK Errors
Future _handleNearPayError(dynamic error) async {
String errorMessage = 'Unknown error';
if (error is PlatformException) {
errorMessage = error.message ?? 'Platform error';
} else if (error is FormatException) {
errorMessage = 'Invalid response format';
} else {
errorMessage = error.toString();
}
await _webViewController?.evaluateJavascript(
source: '''
window.paymentComplete({
"error": "$errorMessage",
"is_approved": false
});
''',
);
}
Common Error Scenarios
Implement a 120-second timeout for all payment operations. If NearPay doesn't respond, notify the user and allow retry.
Always validate that amount is positive and greater than zero before processing payment.
Check if InAppWebViewController is available before calling handlers. This prevents crashes if WebView is closed unexpectedly.
Testing
Console Testing in Odoo
Without a physical NearPay terminal, test using Odoo's built-in helpers:
In Odoo POS Console
// Simulate approved payment
window.testInvoicePayment(true);
// Simulate declined payment
window.testInvoicePayment(false);
Flutter Unit Tests
import 'package:flutter_test/flutter_test.dart';
void main() {
group('OdooNearPayBridge', () {
test('Payment request handler processes valid payload', () async {
final payload = {
'amount': 190.50,
'currency': 'SAR',
};
final response = {
'receipts': [
{
'transaction_uuid': 'test-tx-123',
'is_approved': true,
'amount_authorized': {'value': '190.50'},
}
]
};
expect(response['receipts'][0]['is_approved'], true);
});
test('Payment handler rejects invalid amount', () async {
final payload = {'amount': -10, 'currency': 'SAR'};
expect(payload['amount'], lessThan(0));
});
test('Parses Base64 receipt correctly', () {
final base64String = 'SGVsbG8gV29ybGQ=';
final decoded = utf8.decode(base64Decode(base64String));
expect(decoded, equals('Hello World'));
});
});
}
Integration Testing
void main() {
testWidgets('Full payment flow', (WidgetTester tester) async {
await tester.pumpWidget(
OdooNearPayBridge(
odooUrl: 'http://localhost:8069',
sessionToken: 'test-token',
),
);
// Verify WebView is created
expect(find.byType(InAppWebView), findsOneWidget);
// Simulate payment
await tester.pumpAndSettle();
});
}
Troubleshooting
JavaScript Handler Not Called
Solutions:
- Verify JavaScript is enabled in InAppWebViewSettings
- Check that handlers are registered in onWebViewCreated
- Ensure Odoo WebView code is calling window.flutter_inappwebview.callHandler()
- Check browser console for errors in Odoo
Debug Code
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
),
onConsoleMessage: (ctrl, msg) {
print('Console: ${msg.message}');
}
paymentComplete Not Executing in Odoo
Solutions:
- Verify evaluateJavascript syntax is correct
- Check that result JSON is valid
- Ensure WebView context has window.paymentComplete defined
- Check for JavaScript errors in Odoo console
Debug Code
await _webViewController?.evaluateJavascript(
source: '''
console.log('About to call paymentComplete');
console.log(typeof window.paymentComplete);
if (window.paymentComplete) {
window.paymentComplete(${jsonEncode(result)});
} else {
console.error('paymentComplete not found');
}
''',
);
NearPay SDK Initialization Fails
Solutions:
- Check that NearPay plugin is properly installed
- Verify platform-specific permissions are granted
- Ensure Android minimum SDK ≥ 21
- Check NearPay API credentials
- Review NearPay documentation at https://docs.nearpay.io
Receipt Printing Doesn't Work
Solutions:
- Implement actual printer integration (Bluetooth, cloud print, etc.)
- Test Base64 decoding:
base64Decode(base64String) - Verify printer is connected and available
- Log decoded bytes size for debugging
Debug Code
try {
final bytes = base64Decode(base64File);
print('Decoded ${bytes.length} bytes');
// Attempt to print
} catch (e) {
print('Error: $e');
}
Odoo WebView Not Loading
Solutions:
- Verify Odoo URL is correct and accessible
- Check network connectivity
- Verify authentication token is valid
- Check Odoo server logs for errors
Debug Code
onLoadStop: (controller, uri) {
print('Page loaded: $uri');
},
onLoadError: (controller, url, code, message) {
print('Load error: $code - $message');
}
Best Practices
Code Quality
- Input Validation: Always validate amount and payload before processing
- Error Handling: Use try-catch for all async operations
- Logging: Log extensively for debugging and auditing
- Timeouts: Implement 120-second maximum timeout for payments
- State Management: Track payment processing state to prevent duplicates
Security
- HTTPS Only: Always use HTTPS for Odoo connections
- Token Management: Securely store and manage session tokens
- Input Sanitization: Sanitize all JSON strings before passing to evaluateJavascript
- Error Messages: Don't expose sensitive information in error messages
User Experience
- Loading Indicators: Show loading state during payment processing
- Clear Feedback: Provide clear success/failure messages
- Retry Mechanism: Allow users to retry failed payments
- Transaction Details: Display transaction ID and receipt information
Offline Support
- Queue Payments: Store failed payments locally for retry
- Sync Later: Implement background sync when connection is restored
- Offline Indicator: Show user when offline mode is active
Resources & Documentation
Official Documentation
- NearPay Flutter SDK: https://github.com/nearpayio/nearpay-flutter-sdk
- NearPay Official Docs: https://docs.nearpay.io
- Flutter InAppWebView: https://pub.dev/packages/flutter_inappwebview
- Odoo Developer Guide: https://www.odoo.com/documentation/18.0/
Odoo Module Source Code
- POS Module: Check
ics_pos_nearpay_integration/static/src/js/ - Invoice Module: Check
ics_account_nearpay_payment/static/src/js/
Additional Resources
- Dart/Flutter Documentation: https://dart.dev/guides
- JSON Serialization in Dart: https://dart.dev/guides/json
- HTTP Client in Dart: https://pub.dev/packages/http
Support & Contact
iCloud Solutions Team
- Email: contact@icloud-solutions.net
- WhatsApp: +216 50 271 737
- Website: https://icloud-solutions.net
Getting Help
- Check the troubleshooting section first
- Review error logs and console messages
- Test with a simple payload first
- Consult the official NearPay documentation
- Contact support with detailed error information
Flutter NearPay Odoo Integration
Developer Guide for Seamless Payment Processing
Table of Contents
Overview
The NearPay-Odoo integration enables seamless payment processing through a Flutter mobile application communicating with Odoo's POS and Accounting modules.
Key Features
- POS Payments: Process payments via NearPay terminal with customer display and automatic receipt printing
- Invoice Payments: Pay invoices from Accounting module with transaction metadata storage
- Bidirectional Communication: Odoo communicates with Flutter via InAppWebView bridge
- Real-time Logging: Complete transaction logging and reconciliation
Key Concepts
- WebView Bridge: Odoo runs in a Flutter InAppWebView and communicates via JavaScript handlers
- Single Payment Channel: Both POS and Invoice payments use the same
payment_requesthandler - Callback Pattern: Flutter returns results via
window.paymentComplete() - Base64 PDF Printing: Receipts are sent as Base64-encoded PDFs to Flutter for printing
Architecture
Communication Architecture
Communication Channels
| Direction | From | To | Method | Status |
|---|---|---|---|---|
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("payment_request", payload) |
Active |
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("print_request", data) |
Active |
| Odoo → Flutter | Odoo WebView | Flutter InAppWebView | callHandler("customer_display", url) |
Active |
| Flutter → Odoo | Flutter | WebView JavaScript | window.paymentComplete(result) |
Active |
Setup & Dependencies
Flutter Dependencies
Add to pubspec.yaml:
dependencies:
flutter_inappwebview: ^6.0.0
nearpay_flutter_sdk: ^1.0.0
json_annotation: ^4.8.0
dev_dependencies:
json_serializable: ^6.7.0
Android Configuration
Update android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
}
}
iOS Configuration
Update ios/Podfile:
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_NEARPAY=1',
]
end
end
end
Implementation Guide
1. Basic WebView Setup
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:nearpay_flutter_sdk/nearpay_flutter_sdk.dart';
class OdooNearPayBridge extends StatefulWidget {
final String odooUrl;
final String sessionToken;
const OdooNearPayBridge({
Key? key,
required this.odooUrl,
required this.sessionToken,
}) : super(key: key);
@override
State<OdooNearPayBridge> createState() => _OdooNearPayBridgeState();
}
class _OdooNearPayBridgeState extends State<OdooNearPayBridge> {
InAppWebViewController? _webViewController;
NearPay? _nearPay;
@override
void initState() {
super.initState();
_initializeNearPay();
}
Future<void> _initializeNearPay() async {
_nearPay = await NearPay.instance;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Odoo POS + Invoicing')),
body: InAppWebView(
initialUrlRequest: URLRequest(
url: Uri.parse(widget.odooUrl),
headers: {'Authorization': 'Bearer ${widget.sessionToken}'},
),
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
),
onWebViewCreated: _onWebViewCreated,
),
);
}
void _onWebViewCreated(InAppWebViewController controller) {
_webViewController = controller;
_registerPaymentHandlers(controller);
}
}
2. Register Payment Handlers
void _registerPaymentHandlers(InAppWebViewController controller) {
// Payment processor (POS + Invoices)
controller.addJavaScriptHandler(
handlerName: 'payment_request',
callback: (args) => _handlePaymentRequest(args, controller),
);
// Receipt printing
controller.addJavaScriptHandler(
handlerName: 'print_request',
callback: (args) => _handlePrintRequest(args),
);
// Customer display
controller.addJavaScriptHandler(
handlerName: 'customer_display',
callback: (args) => _handleCustomerDisplay(args),
);
}
3. Payment Request Handler
Future<Map<String, dynamic>> _handlePaymentRequest(
List<dynamic> args,
InAppWebViewController controller,
) async {
if (args.isEmpty) {
return {'success': false, 'error': 'Invalid payload'};
}
try {
final payload = args[0] as Map<String, dynamic>;
final amount = payload['amount'] as num?;
final currency = payload['currency'] as String? ?? 'SAR';
if (amount == null || amount <= 0) {
throw Exception('Invalid amount: $amount');
}
// Call NearPay SDK
final result = await _nearPay?.pay(
amount: amount.toDouble(),
currency: currency,
);
if (result == null) {
throw Exception('No result from NearPay');
}
// Send result back to Odoo
await controller.evaluateJavascript(
source: 'window.paymentComplete(${jsonEncode(result)});',
);
return {'success': true};
} catch (e) {
await controller.evaluateJavascript(
source: '''
window.paymentComplete({
"error": "${e.toString().replaceAll('"', '\\"')}",
"is_approved": false
});
''',
);
return {'success': false, 'error': e.toString()};
}
}
4. Print Handler
Future<Map<String, dynamic>> _handlePrintRequest(List<dynamic> args) async {
try {
final payload = args[0] as Map<String, dynamic>;
final base64File = payload['file'] as String?;
if (base64File == null || base64File.isEmpty) {
return {'success': false, 'error': 'No file provided'};
}
final bytes = base64Decode(base64File);
// TODO: Implement your printing logic here
// Options:
// - Bluetooth printer package
// - Android Print framework
// - Cloud print service
return {'success': true, 'message': 'Receipt sent to printer'};
} catch (e) {
return {'success': false, 'error': e.toString()};
}
}
5. Customer Display Handler
Future<Map<String, dynamic>> _handleCustomerDisplay(
List<dynamic> args,
) async {
try {
final displayPath = args[0] as String?;
if (displayPath == null) {
return {'success': false, 'error': 'No display path'};
}
if (displayPath.contains('payment')) {
_showPaymentDisplay();
} else if (displayPath.contains('thanks')) {
_showThanksDisplay();
} else if (displayPath.contains('welcome')) {
_showWelcomeDisplay();
}
return {'success': true};
} catch (e) {
return {'success': false, 'error': e.toString()};
}
}
void _showPaymentDisplay() {
// Implement customer-facing payment screen
}
void _showThanksDisplay() {
// Show thank you and transaction details
}
void _showWelcomeDisplay() {
// Show welcome/standby screen
}
Handler Reference
payment_request
Called By: Odoo POS (payment screen) and Accounting (invoice payment wizard)
Example Payload
Expected Response (Success)
print_request
Called By: Odoo POS (receipt screen)
customer_display
Called By: Odoo POS (payment and receipt screens)
/ics_pos/customer_display/welcome/ics_pos/customer_display/payment?amount=190.50/ics_pos/customer_display/order?order_id=POS001/ics_pos/customer_display/thanks?order_id=POS001
Payment Flows
POS Payment Flow
1. Order Creation
Customer adds products → Click "Payment"
2. Payment Request
Odoo POS calls payment_request handler
3. NearPay Processing
Flutter processes payment via NearPay
4. Response Handling
Flutter calls window.paymentComplete(result)
5. Validation
Odoo validates and creates pos.payment record
6. Completion
Receipt printed, customer display updated
Invoice Payment Flow
1. Invoice Open
User opens invoice → Click "Register Payment"
2. Method Selection
Select NearPay payment method
3. Payment Request
Odoo calls payment_request handler
4. NearPay Processing
Flutter processes payment via NearPay
5. Reconciliation
Odoo reconciles invoice with payment
6. Redirect
Odoo redirects to invoice list
Error Handling
Network Errors
Future<void> _handleNetworkError(String error) async {
int retries = 0;
const maxRetries = 3;
const delayMs = 2000;
while (retries < maxRetries) {
try {
await Future.delayed(Duration(milliseconds: delayMs));
// Retry payment
break;
} catch (e) {
retries++;
if (retries >= maxRetries) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Payment failed after $maxRetries attempts')
),
);
}
}
}
}
}
NearPay SDK Errors
Future<void> _handleNearPayError(dynamic error) async {
String errorMessage = 'Unknown error';
if (error is PlatformException) {
errorMessage = error.message ?? 'Platform error';
} else if (error is FormatException) {
errorMessage = 'Invalid response format';
} else {
errorMessage = error.toString();
}
await _webViewController?.evaluateJavascript(
source: '''
window.paymentComplete({
"error": "$errorMessage",
"is_approved": false
});
''',
);
}
Common Error Scenarios
Implement a 120-second timeout for all payment operations. If NearPay doesn't respond, notify the user and allow retry.
Always validate that amount is positive and greater than zero before processing payment.
Check if InAppWebViewController is available before calling handlers. This prevents crashes if WebView is closed unexpectedly.
Testing
Console Testing in Odoo
Without a physical NearPay terminal, test using Odoo's built-in helpers:
In Odoo POS Console
// Simulate approved payment
window.testInvoicePayment(true);
// Simulate declined payment
window.testInvoicePayment(false);
Flutter Unit Tests
import 'package:flutter_test/flutter_test.dart';
void main() {
group('OdooNearPayBridge', () {
test('Payment request handler processes valid payload', () async {
final payload = {
'amount': 190.50,
'currency': 'SAR',
};
final response = {
'receipts': [
{
'transaction_uuid': 'test-tx-123',
'is_approved': true,
'amount_authorized': {'value': '190.50'},
}
]
};
expect(response['receipts'][0]['is_approved'], true);
});
test('Payment handler rejects invalid amount', () async {
final payload = {'amount': -10, 'currency': 'SAR'};
expect(payload['amount'], lessThan(0));
});
test('Parses Base64 receipt correctly', () {
final base64String = 'SGVsbG8gV29ybGQ=';
final decoded = utf8.decode(base64Decode(base64String));
expect(decoded, equals('Hello World'));
});
});
}
Integration Testing
void main() {
testWidgets('Full payment flow', (WidgetTester tester) async {
await tester.pumpWidget(
OdooNearPayBridge(
odooUrl: 'http://localhost:8069',
sessionToken: 'test-token',
),
);
// Verify WebView is created
expect(find.byType(InAppWebView), findsOneWidget);
// Simulate payment
await tester.pumpAndSettle();
});
}
Troubleshooting
JavaScript Handler Not Called
Solutions:
- Verify JavaScript is enabled in InAppWebViewSettings
- Check that handlers are registered in onWebViewCreated
- Ensure Odoo WebView code is calling window.flutter_inappwebview.callHandler()
- Check browser console for errors in Odoo
Debug Code
initialSettings: InAppWebViewSettings(
javaScriptEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
),
onConsoleMessage: (ctrl, msg) {
print('Console: ${msg.message}');
}
paymentComplete Not Executing in Odoo
Solutions:
- Verify evaluateJavascript syntax is correct
- Check that result JSON is valid
- Ensure WebView context has window.paymentComplete defined
- Check for JavaScript errors in Odoo console
Debug Code
await _webViewController?.evaluateJavascript(
source: '''
console.log('About to call paymentComplete');
console.log(typeof window.paymentComplete);
if (window.paymentComplete) {
window.paymentComplete(${jsonEncode(result)});
} else {
console.error('paymentComplete not found');
}
''',
);
NearPay SDK Initialization Fails
Solutions:
- Check that NearPay plugin is properly installed
- Verify platform-specific permissions are granted
- Ensure Android minimum SDK ≥ 21
- Check NearPay API credentials
- Review NearPay documentation at https://docs.nearpay.io
Receipt Printing Doesn't Work
Solutions:
- Implement actual printer integration (Bluetooth, cloud print, etc.)
- Test Base64 decoding:
base64Decode(base64String) - Verify printer is connected and available
- Log decoded bytes size for debugging
Debug Code
try {
final bytes = base64Decode(base64File);
print('Decoded ${bytes.length} bytes');
// Attempt to print
} catch (e) {
print('Error: $e');
}
Odoo WebView Not Loading
Solutions:
- Verify Odoo URL is correct and accessible
- Check network connectivity
- Verify authentication token is valid
- Check Odoo server logs for errors
Debug Code
onLoadStop: (controller, uri) {
print('Page loaded: $uri');
},
onLoadError: (controller, url, code, message) {
print('Load error: $code - $message');
}
Best Practices
Code Quality
- Input Validation: Always validate amount and payload before processing
- Error Handling: Use try-catch for all async operations
- Logging: Log extensively for debugging and auditing
- Timeouts: Implement 120-second maximum timeout for payments
- State Management: Track payment processing state to prevent duplicates
Security
- HTTPS Only: Always use HTTPS for Odoo connections
- Token Management: Securely store and manage session tokens
- Input Sanitization: Sanitize all JSON strings before passing to evaluateJavascript
- Error Messages: Don't expose sensitive information in error messages
User Experience
- Loading Indicators: Show loading state during payment processing
- Clear Feedback: Provide clear success/failure messages
- Retry Mechanism: Allow users to retry failed payments
- Transaction Details: Display transaction ID and receipt information
Offline Support
- Queue Payments: Store failed payments locally for retry
- Sync Later: Implement background sync when connection is restored
- Offline Indicator: Show user when offline mode is active
Resources & Documentation
Official Documentation
- NearPay Flutter SDK: https://github.com/nearpayio/nearpay-flutter-sdk
- NearPay Official Docs: https://docs.nearpay.io
- Flutter InAppWebView: https://pub.dev/packages/flutter_inappwebview
- Odoo Developer Guide: https://www.odoo.com/documentation/18.0/
Odoo Module Source Code
- POS Module: Check
ics_pos_nearpay_integration/static/src/js/ - Invoice Module: Check
ics_account_nearpay_payment/static/src/js/
Additional Resources
- Dart/Flutter Documentation: https://dart.dev/guides
- JSON Serialization in Dart: https://dart.dev/guides/json
- HTTP Client in Dart: https://pub.dev/packages/http
Support & Contact
iCloud Solutions Team
- Email: contact@icloud-solutions.net
- WhatsApp: +216 50 271 737
- Website: https://icloud-solutions.net
Getting Help
- Check the troubleshooting section first
- Review error logs and console messages
- Test with a simple payload first
- Consult the official NearPay documentation
- Contact support with detailed error information