Advanced Configuration
This guide covers advanced configuration options for the GOFA WebView SDK.
Highlights
- Flexible callback configuration for WebView events
- Environment-based configuration using helper classes and environment variables
- Secure authentication with client credentials and Firebase custom tokens
- Customizable navigation URLs for different GOFA services
- Support for custom headers
- Build-time and runtime configuration via Dart defines
- Configuration validation with clear error handling
- Troubleshooting tips and configuration best practices
Callback Configuration
When embedding the GOFA web app in your Flutter app using the WebView SDK, the web app communicates important events back to Flutter via the updateCallback function you provide to WebViewSdkManager.
The web app posts messages using the postMessage API. The Flutter SDK receives these messages and invokes your updateCallback with the event name and event data.
Basic Event Handler Setup
final webViewSdkManager = WebViewSdkManager(
environment: Environment.DEV,
updateCallback: (String eventName, dynamic eventData) {
// Handle different event types
switch (eventName) {
case 'START_ASSESSMENT':
// Handle assessment initiation
_handleAssessmentStart(eventData);
break;
case 'FINISH_ASSESSMENT':
// Handle assessment completion
_handleAssessmentFinish(eventData);
break;
case 'GENERATED_REPORT':
// Handle report generation
_handleReportGenerated(eventData);
break;
case 'EARLY_QUIT':
// Handle early exit scenarios
_handleEarlyQuit(eventData);
break;
default:
print('Unknown event: $eventName');
}
},
);
Tip: The
updateCallbackreceives the event name and a data map. You can use this to trigger navigation, analytics, or other business logic in your Flutter app.
For specific event types and data structures for different GOFA modules (such as MSK assessments), refer to the respective integration guides:
- MSK Integration Guide - Complete MSK event handling
Event Data Structure
Most events follow a consistent data structure pattern:
// Common event data fields
{
'eventId': 'unique-event-identifier',
'timestamp': 'iso-date-string',
'userId': 'user-identifier',
'moduleType': 'msk|wellness|other',
// Additional event-specific data
}
Environment Helper Class
Create a helper class for environment-specific configuration:
class EnvironmentConfig {
static const String _envString = String.fromEnvironment('GOFA_ENVIRONMENT', defaultValue: 'DEV');
static const String clientId = String.fromEnvironment('GOFA_CLIENT_ID');
static const String clientSecret = String.fromEnvironment('GOFA_CLIENT_SECRET');
static const String clientUserId = String.fromEnvironment('GOFA_CLIENT_USER_ID');
/// Converts the GOFA_ENVIRONMENT string to the SDK enum.
static Environment get environment {
switch (_envString.toUpperCase()) {
case 'PRD': return Environment.PRD;
case 'UAT': return Environment.UAT;
default: return Environment.DEV;
}
}
static bool get isProduction => environment == Environment.PRD;
static String get baseUrl {
switch (environment) {
case Environment.PRD: return 'https://client.gofa.app';
case Environment.UAT: return 'https://client.uat.gofa.app';
default: return 'https://client.dev.gofa.app';
}
}
}
URL Examples
If you navigate with Navigator.pushNamed(..., GofaWebView.routeName, ...), ensure GofaWebView.routeName is registered in your app's MaterialApp.routes first.
Navigator.pushNamed(
context,
GofaWebView.routeName,
arguments: {
// Example: MSK (Musculoskeletal) services
'url': 'https://your-client.gofa.app/msk/home',
'clientId': clientId,
'locale': const Locale.fromSubtags(
languageCode: 'zh',
scriptCode: 'Hant',
),
},
);
Authentication Configuration
Client Credentials
Configure your application's authentication credentials:
const clientId = String.fromEnvironment('GOFA_CLIENT_ID', defaultValue: 'your-client-id');
const clientSecret = String.fromEnvironment('GOFA_CLIENT_SECRET', defaultValue: 'your-client-secret');
const clientUserId = String.fromEnvironment('GOFA_CLIENT_USER_ID', defaultValue: 'unique-user-id');
Basic Authentication (Deprecated)
HTTP Basic Auth for MSK routes has been replaced by Firebase custom token authentication. The basicAuthUser and basicAuthPass parameters are deprecated and will be removed in a future version. You can safely omit them. See MSK Authentication for the current auth flow.
Custom Headers
You can configure custom headers for WebView requests:
// The SDK automatically handles authentication headers
// Custom headers can be added through the initialization process
await webViewSdkManager.init(
clientId: clientId,
clientSecret: clientSecret,
clientUserId: clientUserId,
environment: EnvironmentConfig.environment,
);
Runtime Configuration
Environment Variables
Set up environment variables for different build configurations:
# Development build
flutter build apk --dart-define=GOFA_ENVIRONMENT=DEV \
--dart-define=GOFA_CLIENT_ID=dev-client-id \
--dart-define=GOFA_CLIENT_SECRET=dev-secret
# UAT build
flutter build apk --dart-define=GOFA_ENVIRONMENT=UAT \
--dart-define=GOFA_CLIENT_ID=uat-client-id \
--dart-define=GOFA_CLIENT_SECRET=uat-secret
# Production build
flutter build apk --dart-define=GOFA_ENVIRONMENT=PRD \
--dart-define=GOFA_CLIENT_ID=prod-client-id \
--dart-define=GOFA_CLIENT_SECRET=prod-secret
Configuration Validation
Validation Function
Create a validation function to ensure proper configuration:
class ConfigValidator {
static Future<bool> validateConfiguration() async {
// Check environment
if (![Environment.DEV, Environment.UAT, Environment.PRD].contains(EnvironmentConfig.environment)) {
print('❌ Invalid environment: ${EnvironmentConfig.environment}');
return false;
}
// Check required credentials
if (EnvironmentConfig.clientId.isEmpty) {
print('❌ CLIENT_ID is required');
return false;
}
if (EnvironmentConfig.clientSecret.isEmpty) {
print('❌ CLIENT_SECRET is required');
return false;
}
if (EnvironmentConfig.clientUserId.isEmpty) {
print('❌ CLIENT_USER_ID is required');
return false;
}
// Validate production settings
if (EnvironmentConfig.isProduction) {
if (EnvironmentConfig.clientId == 'abc' ||
EnvironmentConfig.clientSecret == 'abcSecret') {
print('❌ Cannot use default credentials in production');
return false;
}
}
print('✅ Configuration validation passed');
return true;
}
}
// Use in your app initialization
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (await ConfigValidator.validateConfiguration()) {
runApp(const MyApp());
} else {
runApp(const ConfigErrorApp());
}
}
Troubleshooting & Best Practices
- Use environment variables for all sensitive configuration
- Validate configuration before app initialization
- Use different credentials for each environment
- Never hardcode production credentials in source code
- Test configuration changes in development first
- If you encounter authentication or network issues, double-check your environment and credentials
- Ensure all required parameters are provided during SDK initialization
Next Steps
- SDK Reference: Complete API documentation
Change History
| Date | Change |
|---|---|
| 2026-02-24 | Added route-registration prerequisite note for Navigator.pushNamed WebView navigation example. |
| 2026-02-13 | Updated EnvironmentConfig helper to use Environment enum. Fixed init() call to use await. |
| 2026-02-11 | Replaced Bupa-specific URL example with generic your-client.gofa.app placeholder. |
| 2026-02-11 | Deprecated Basic Authentication section. Removed basicAuthUser/basicAuthPass from code examples. MSK routes now use Firebase custom tokens. |