# GoTrust Mobile SDK for Flutter

The GoTrust Flutter SDK (`go_trust_mobile_sdk`) enables cross-platform mobile applications to present consent-collection forms and preference centers natively within Flutter UI trees for compliant privacy and consent management.

---

## Requirements

- **Flutter SDK:** `>= 3.19.0`
- **Dart SDK:** `>= 3.3.0`
- **Android:** `minSdkVersion 24`
- **iOS:** `iOS 14.0` or higher
- **Package:** [pub.dev/packages/go_trust_mobile_sdk](https://pub.dev/packages/go_trust_mobile_sdk)

---

## Getting Started

### Step 1: Add SDK Dependency

Add the latest version of `go_trust_mobile_sdk` to your `pubspec.yaml`:

```yaml
dependencies:
  flutter:
    sdk: flutter
  go_trust_mobile_sdk: ^latest_version

Fetch the package:

flutter pub get


Step 2: Configure Environment Parameters

Store tenant credentials securely using environment variables or remote configuration rather than hardcoding them inside UI widgets.

abstract class GoTrustConfig {
  static const String baseUrl = "[https://your-environment.gotrust.tech](https://your-environment.gotrust.tech)";
  static const String sourceId = "YOUR_SOURCE_ID";
  static const String preferenceFormId = "YOUR_PREFERENCE_FORM_ID";
  static const String customerId = "YOUR_CUSTOMER_ID";
  static const String pfToken = "YOUR_PREFERENCE_CENTER_TOKEN";
  static const String consentUserToken = "YOUR_CONSENT_USER_TOKEN"; // minor/token-flow, consent form
  static const String pfUserToken = "YOUR_PREFERENCE_USER_TOKEN";   // minor/token-flow, preference center
}


Step 3: Define Subject Identity & Parameters

Declare the target subject's identity as key-value pairs matching your GoTrust dashboard field configuration (e.g., "107" for phone, "10085" for email).

// Required: Subject identity key-value map
static const Map<String, dynamic> subjectIdentityValues = {
  "107": "9891737651",
  "10085": "user@example.com",
};

// Optional: Supplementary prefill data (not used for identity lookup)
static const Map<String, dynamic> additionalParams = <String, dynamic>{
  "2": "Jane Doe",
  "6": "1994-07-21",
};


Implementation & Flow Control

Important: Always execute the consent check before presenting the UI to avoid unnecessary dialogs when a valid consent record already exists.

Use GoTrustSdkHelper.showConsentForm to verify if the form needs to be displayed. Pass sourceId + subjectIdentityValues for the standard flow, or userSpecificToken for the token flow (never both).

final bool shouldShowConsent = await GoTrustSdkHelper.showConsentForm(
  baseUrl: GoTrustConfig.baseUrl,
  sourceId: GoTrustConfig.sourceId,
  subjectIdentityValues: subjectIdentityValues,
);

  • true — No valid record found; present ConsentFormPage.
  • false — Valid consent already on record; skip display.

A. Standard Flow

if (shouldShowConsent == true && context.mounted) {
  await Navigator.of(context).push(
    MaterialPageRoute(
      builder: (_) => ConsentFormPage(
        baseUrl: GoTrustConfig.baseUrl,
        sourceId: GoTrustConfig.sourceId,
        initialSubjectValues: subjectIdentityValues,
        additionalParams: additionalParams,
        enableCaptcha: false,
        callbacks: ConsentCallbacks(
          onSuccess: (int? statusCode, String? message, List<Map<String, dynamic>>? data) {
            debugPrint('Consent Submitted! Status: $statusCode');
            if (data != null) debugPrint('Received data: $data');
          },
          onError: (int? statusCode, String? message) {
            debugPrint('Consent Failed! Status: $statusCode, Message: $message');
          },
          onClose: (String? message) {
            debugPrint('Consent Form Closed by User: $message');
          },
          onNothingTapped: (String? message) {
            debugPrint('Nothing button tap by User: $message');
          },
        ),
      ),
    ),
  );
}

B. Fallback Flow (Handling Server Outages)

Define a FallbackConfig and pass it to both showConsentForm and ConsentFormPage:

final fallbackConfig = FallbackConfig(
  displayUrl: '[https://your-api.example.com/v1/display](https://your-api.example.com/v1/display)',
  submitUrl: '[https://your-api.example.com/v2/submit](https://your-api.example.com/v2/submit)',
  headers: {
    'X-Client-Api-Key': 'your-api-key',
    'X-Client-Id': 'your-client-id',
    'X-CSRF-Token': 'initial-csrf-token',
    'Cookie': '_bb_mid=xyz; CSRF-TOKEN=initial-csrf-token;',
  },
  csrfHeaderName: 'X-CSRF-Token',
  csrfCookieName: 'CSRF-TOKEN',
  refreshCsrfToken: () async {
    final response = await yourApiService.refreshCsrf();
    return response.headers['x-csrf-token'];
  },
);

// Verify with fallback
final bool shouldShow = await GoTrustSdkHelper.showConsentForm(
  baseUrl: GoTrustConfig.baseUrl,
  sourceId: GoTrustConfig.sourceId,
  subjectIdentityValues: subjectIdentityValues,
  fallback: fallbackConfig,
);

// Display with fallback
if (shouldShow == true && context.mounted) {
  await Navigator.of(context).push(
    MaterialPageRoute(
      builder: (_) => ConsentFormPage(
        baseUrl: GoTrustConfig.baseUrl,
        sourceId: GoTrustConfig.sourceId,
        initialSubjectValues: subjectIdentityValues,
        additionalParams: additionalParams,
        fallback: fallbackConfig,
        enableCaptcha: false,
        callbacks: ConsentCallbacks(
          onSuccess: (statusCode, message, data) { /* ... */ },
          onError: (statusCode, message) { /* ... */ },
          onClose: (message) { /* ... */ },
          onNothingTapped: (message) { /* ... */ },
        ),
      ),
    ),
  );
}

Pass only the pre-generated token. The SDK resolves IDs and PII server-side. Do not supply sourceId, initialSubjectValues, or additionalParams.

final bool shouldShow = await GoTrustSdkHelper.showConsentForm(
  baseUrl: GoTrustConfig.baseUrl,
  userSpecificToken: GoTrustConfig.consentUserToken,
);

if (shouldShow == true && context.mounted) {
  await Navigator.of(context).push(
    MaterialPageRoute(
      builder: (_) => ConsentFormPage(
        baseUrl: GoTrustConfig.baseUrl,
        token: GoTrustConfig.consentUserToken,
        enableCaptcha: false,
        callbacks: ConsentCallbacks(
          onSuccess: (statusCode, message, data) { /* ... */ },
          onError: (statusCode, message) { /* ... */ },
          onClose: (message) { /* ... */ },
          onNothingTapped: (message) { /* ... */ },
        ),
      ),
    ),
  );
}

Use GoTrustSdkHelper.closeConsentForm() to close the consent form when you want to close it explicitly.

GoTrustSdkHelper.closeConsentForm();


3. Render Preference Center

Presenting LoginPage is all the host app needs to do. Verification (OTP) and preference dashboards are handled internally by the SDK.

Option A: Known customerId and preferenceFormId

void openPreferenceCenter(BuildContext context) {
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (_) => LoginPage(
        baseUrl: GoTrustConfig.baseUrl,
        customerId: GoTrustConfig.customerId,
        preferenceFormId: GoTrustConfig.preferenceFormId,
        initialSubjectValues: subjectIdentityValues,
        additionalParams: additionalParams,
        enableCaptcha: true,
        onSuccess: (String? message, List<Map<String, dynamic>>? data) {
          // Preferences successfully updated
        },
        onError: (String? message) {
          // Preference update failed
        },
        onClose: (String? message) {
          // Preference center closed without saving
        },
      ),
    ),
  );
}

Option B: Using pfToken

void openPreferenceCenter(BuildContext context) {
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (_) => LoginPage(
        baseUrl: GoTrustConfig.baseUrl,
        pfToken: GoTrustConfig.pfToken,
        initialSubjectValues: subjectIdentityValues,
        additionalParams: additionalParams,
        enableCaptcha: true,
        onSuccess: (message, data) {},
        onError: (message) {},
        onClose: (message) {},
      ),
    ),
  );
}

Option C: Using User-Specific Token

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (_) => LoginPage(
      baseUrl: GoTrustConfig.baseUrl,
      token: GoTrustConfig.pfUserToken,
      enableCaptcha: true,
      onSuccess: (message, data) {},
      onError: (message) {},
      onClose: (message) {},
    ),
  ),
);


Parameter Reference

Parameter Type Required Description
baseUrl String Yes Target GoTrust API environment domain URL.
sourceId String Conditional Unique consent form identifier. Required unless token is used.
token String Conditional Pre-issued token from GoTrust API. Overrides sourceId/pfToken.
initialSubjectValues Map<String, dynamic> Conditional Dashboard field IDs mapping user identity. Omit when using token.
callbacks ConsentCallbacks Yes ConsentFormPage only: Callbacks for onSuccess, onError, and onClose.
fallback FallbackConfig Optional Outage fallback URLs/headers for ConsentFormPage only.
additionalParams Map<String, dynamic> Optional Form field prefill data. Omit when using token.
showCrossButton bool Optional Toggles dismiss button visibility (default: true).
enableCaptcha bool Optional Toggles CAPTCHA verification on submit/save.
pfToken String Optional Preference center access token. Superseded by token.
customerId String Conditional Customer ID for Preference Center. Omit when using token.
preferenceFormId String Conditional Preference Form ID. Omit when using token.

Troubleshooting & Best Practices

  • Prevent Duplicate Modals: Maintain a local boolean flag (e.g., bool _isFormActive = false) to guard navigation calls against rapid user taps.
  • Platform Versions: Check that android/app/build.gradle defines minSdkVersion 24 and ios/Podfile specifies platform :ios, '14.0'.
  • Identity Key Mapping: Field IDs in initialSubjectValues must match the string IDs configured in the GoTrust Admin Console.
  • Token Freshness: Generate a fresh single-use token per session. Expired tokens will fail server-side decryption and block rendering.
  • Unified Callbacks: On LoginPage, provide onSuccess, onError, and onClose directly; child views (OTP/dashboard) automatically inherit them.

Appendix: Release Workflow & Lifecycle SLA

Classification Trigger Criteria Action Required Targeted SLA
Compliance-Critical Legal mandates, security updates, presentation flow changes Out-of-band fast-track release < 5 Business Days
Routine Bug fixes, performance tuning, non-breaking changes Standard sprint backlog ingestion Next app release cycle

Integration Verification Workflow

[GoTrust Package Update Published]
                 │
                 ▼
      [Assess Classification]
       /                   \
(Compliance-Critical)    (Routine)
       │                     │
       ▼                     ▼
[Fast-Track: Out-of-Band] [Standard Sprint]
       │                     │
       └──────────┬──────────┘
                  │
                  ▼
[Step 1: Bump version in pubspec.yaml & run flutter pub get]
                  │
                  ▼
[Step 2: Review pub.dev changelog & parameter updates]
                  │
                  ▼
[Step 3: Perform Dual-Platform QA in Sandbox]
    ├── Android Build Verification (minSdkVersion 24+)
    ├── iOS Build Verification (iOS 14.0+)
    ├── Verify Async Check (GoTrustSdkHelper.showConsentForm)
    ├── Verify ConsentFormPage Navigation & Callbacks
    └── Verify Preference Center Flow
                  │
                  ▼
        [Validation Successful?]
         /                    \
       (Yes)                  (No) ──► [Escalate to GoTrust Support]
         │
         ▼
[Step 4: Build Release Binaries (AAB / IPA) & Deploy]

Libraries

core/native/native_sdk_bridge
core/utils/api_logo_widget
core/utils/app_constants
core/utils/appbar_helper
core/utils/colors
core/utils/dialogmixin
core/utils/server_constants
core/utils/string_utils
core/utils/styles
core/utils/text_widget_helper
core/utils/tv_appbar_helper
core/utils/utils
features/consent_form/model/call_back_response
features/consent_form/model/digilocker_response_model
features/consent_form/model/frequency_list_response_model
features/consent_form/model/get_source_id_response_model
features/consent_form/model/language_response
features/consent_form/model/logo_download_api_response
features/consent_form/model/privacy_notice_response_model
features/consent_form/privacy_notice_screen
features/consent_form/services/api_service
features/consent_form/services/go_trust_sdk_helper
features/consent_form/services/recaptcha_service
features/consent_form/tv/tv_privacy_notice_screen
features/consent_form/tv/tv_web_view_screen
features/consent_form/widgets/digilocker_web_view_screen
features/consent_form/widgets/language_selector_widget
features/consent_form/widgets/tv_digilocker_web_view_screen
features/consent_form/widgets/tv_language_selector_widget
features/consent_preferences/model/audit_log_model
features/consent_preferences/model/dashboard_model
features/consent_preferences/model/login_model
features/consent_preferences/model/send_otp_model
features/consent_preferences/model/verify_otp_model
features/consent_preferences/services/api_services
features/consent_preferences/tv/tv_login_page
features/consent_preferences/tv/tv_otp_page
features/consent_preferences/tv/tv_preference_dashboard_page
features/consent_preferences/widgets/login_page
features/consent_preferences/widgets/otp_page
features/cookie_consent/services/api_services
features/cookie_consent/widgets/category_widget
features/cookie_consent/widgets/service_widget
features/dsr/dsr_form_page
features/dsr/model/country_model
features/dsr/model/custom_select_option_model
features/dsr/model/dsr_form_response
features/dsr/model/dsr_language_model
features/dsr/model/dsr_submit_model
features/dsr/model/ip_info_model
features/dsr/services/dsr_api_service
features/dsr/widgets/dsr_otp_verification_page
features/dsr/widgets/dsr_text_styles
features/dsr/widgets/dynamic_form_fields
features/dsr/widgets/language_selector_widget
features/dsr/widgets/searchable_bottom_sheet
features/util/dialog_helper
features/util/fallback_screen
features/util/progress_helper
features/util/styles
features/util/tv_remote_input_dialog
features/util/utils
main