Skip to content

Migration Guide


v2.1.x to v2.2.0

Bump the constraint to ^2.2.0 and rebuild. No code changes are required. The one item below applies only if your app or your network restricts outbound hosts.

1. Do you restrict outbound hosts?

The SDK's diagnostics now go to api.mixpanel.com. Allow that host.

If it stays blocked, nothing visible breaks: checkout and payments are unaffected, and there is no error or callback. The SDK retries a failed diagnostic event once and then drops it, so the only symptom is that your integration becomes harder for us to support when you report a problem.

api.segment.io is no longer contacted and can be removed from your allowlist. The segment_analytics dependency is gone from the SDK along with it - see Dependency Notes.

Additions that need no migration

  • appColorScheme is optional and defaulted to auto, so an integration that sets nothing compiles and behaves as it did, except that the checkout now follows your app's theme instead of always being light. If that is not what you want, pass light explicitly. See Dark mode.

Behaviour changes that need no code

  • On Android, keep uiMode in your activity's android:configChanges. Flutter's MainActivity template already has it, so this is only a problem if your app removed it. Without it, an OS dark-mode toggle destroys and recreates your activity mid-checkout and loses the payment in flight. Pre-existing behaviour, but users now have a reason to toggle mid-payment.
  • If you are coming from v2.1.2 or earlier you also pick up v2.1.3, where the bank page closes itself on a confirmed payment failure instead of staying on top of the checkout's error screen. Nothing to change unless your integration deliberately relied on the old two-press exit. See the Changelog.

v2.1.x to v2.1.2

Bump the constraint to ^2.1.2 and rebuild.

Two behavioural changes, neither of which needs a change

  • The checkout WebView stays on Glomo's own pages. A top-level navigation anywhere other than https on glomopay.com or glomo.one - is stopped and reported to onSdkError with SdkErrorType.unknown and field: 'navigation'. The checkout keeps running. Bank pages, 3DS challenges and card frames are unaffected, so card payments and bank redirects behave as they did on v2.1.1.
  • Payment results are accepted only from Glomo's checkout page. A result-shaped message from a bank page, a 3DS page or a third-party frame inside the checkout no longer reaches onPaymentSuccess, onPaymentFailure, onUserJourneyCompleted or onEvent. A message from a frame inside the checkout page is dropped silently; one from a bank or 3DS page is also reported to onSdkError with field: 'flow', and a download refused the same way reports field: 'file.save'. Neither ends the checkout.

If your onSdkError closes the checkout or shows a blocking screen for every error it receives, these two join file.save as errors the session survives. See Origin Policy.

Nothing about signature verification changes. Confirm every payment on your server as before - the origin check narrows what can reach your callbacks, it does not replace verification.


v2.0.0 to v2.1.0

Bump the constraint to ^2.1.0 and rebuild. No API changed, nothing is deprecated, and no code has to move.

Two things to be aware of, neither of which needs a change:

  • onSdkError can now receive a non-terminal error. A failed document download arrives as SdkErrorType.validationError with field set to 'file.save', and the checkout keeps running. If your onSdkError closes the checkout or shows a blocking screen for every error it receives, skip the ones with field == 'file.save' - the SDK has already told the user, and the payment session is still alive.
  • A throw from onEvent no longer surfaces. It used to propagate into the bridge's catch and reach onSdkError; it is now caught and logged. onEvent is deprecated and this only affects code that was throwing from it.

Downloads themselves need no integration - no callback, no configuration, no permission and no new dependency.


v1.11.x to v2.0.0

v2.0.0 renames nothing. It is a behavioural release: the same callbacks you already supply now fire at different times, and each failure reports its actual semantic instead of being funnelled into onPaymentFailure.

Two changes break compilation, and the compiler will point at both:

  1. The new required onUserJourneyCompleted callback (step 1)
  2. The removal of devMode from GlomoPayConfig (step 2)

The remaining steps apply only if they describe your code. The SDK now closes itself on every path that ends a checkout, so nothing here can leave a user stranded while you migrate.

For the complete v2 API reference, see the Flutter SDK v2 documentation. For the full list of changes, see the Changelog.

Update the dependency first:

dependencies:
  glomopay_sdk: ^2.0.0

1. Supply the new onUserJourneyCompleted callback

Required for every integration. Your build will not compile until you do, which is deliberate.

onUserJourneyCompleted: (GlomoPayUserJourneyPayload journey) {
  // The user submitted their bank transfer details. A settlement may not have happened and
  // there is no paymentId or signature, so reconcile journey.orderId on your
  // backend rather than treating this as paid.
},

Before v2.0.0, a submitted bank transfer was delivered to onPaymentSuccess with paymentId and signature both null - a payment reported as received that your backend had nothing to verify. It now reports here instead, and no longer reaches onPaymentSuccess.

If onPaymentSuccess currently special-cases a null paymentId, move that branch into this callback. It will no longer be reached where it is.

If you do not take bank transfers, an empty body for onUserJourneyCompleted is a complete migration - the callback simply never fires. It was made required rather than optional to make the behavioural breaking change loud: orderType and merchant configuration decide, on the server, whether an order can accept bank transfers. An optional callback would have let an integration upgrade, keep compiling, and silently stop hearing about a journey it used to be told about.

2. Remove devMode from GlomoPayConfig

If your GlomoPayConfig sets devMode, remove the argument. It is no longer part of GlomoPayConfig, so the compiler will reject it:

No named parameter with the name 'devMode'

There is no replacement to pass; deleting the line is the whole migration. Behaviour is unchanged for any integration that was not setting it, which is the default.

Before

config: const GlomoPayConfig(
  publicKey: 'live_pk_abc123',
  orderId: 'order_xyz789',
  devMode: true,
),

After

config: const GlomoPayConfig(
  publicKey: 'live_pk_abc123',
  orderId: 'order_xyz789',
),

3. Do you close the checkout or run cleanup inside onPaymentFailure?

onPaymentFailure is now reserved for a payment the backend confirms failed. This is the correct behaviour across all Glomo mobile SDKs, and Flutter now reflects it too. It no longer fires when the checkout could not load, or when the user exits one of the SDK's default error screens - no payment is attempted in either case, so it never belonged there.

Those paths now report:

What happenedCallback
The SDK or the order could not proceedonSdkError
Connectivity failed, or the page did not load in timeonConnectionError
The user then exited the error screenonPaymentTerminate(TerminationSource.userDismiss)

Before

onPaymentFailure: (payload) {
  logFailure(payload);
  Navigator.pop(context);
},

After

void _endCheckout() {
  Navigator.pop(context);
}

onPaymentFailure: (payload) {
  logFailure(payload);       // a real, backend-confirmed payment failure
  _endCheckout();
},
onPaymentTerminate: (source) {
  _endCheckout();            // user left, including from an SDK error screen
},

Supplying onPaymentTerminate is safe to do incrementally: the SDK closes the checkout whether or not you supply it, and if you close from the callback as well the SDK will not close a second time.

Note: confirmed payment failures were previously being checked against the rule written for a payment success, which requires a signature that a failure payload has never carried. Every confirmed decline was discarded before reaching your app, in every release build. If you have been treating onPaymentFailure as unreliable, it is now the callback for exactly this.

4. Do you use onEvent?

onEvent is deprecated and will be removed in a future major version. It carries information for internal debugging that is subject to change, and was never part of the SDK's API contract.

If you rely on an event with no callback equivalent, contact the Glomo mobile team so it can be covered before removal.

5. Do you supply your own GlomoPayController and call addEventListener?

The same deprecation applies, and glomo_flutter_sdk.checkout.terminal_error now fires when the error is raised rather than after its dialog is dismissed. Contact the Glomo mobile team for the full event mapping.

6. Did your app inherit the SDK's error handlers?

v2.0.0 no longer installs FlutterError.onError, PlatformDispatcher.instance.onError, or the native crash handlers inside your application. If your app was relying on SDK-installed handlers, it loses them at this upgrade - install your own.

In exchange, the SDK no longer constrains versions for any error-tracking package, so you are free to use your own.

Behaviour changes that need no code

These change what your users see, not what you write.

  • The user can always exit. The back button works while a payment is in progress; the SDK's error screens can no longer be rendered invisible by your app's theme; and closing an error screen closes the checkout rather than returning to a loading screen. Depending on the flow, leaving from inside a bank page may still take two presses, so an accidental press cannot end a payment.
  • One failure, one callback. A single main-frame load failure delivers onConnectionError alone - it used to deliver onSdkError as well.
  • One ending per checkout. A backend-confirmed payment result is the ending; a user closing what remains afterwards no longer also reports onPaymentTerminate.
  • A load timeout is advisory. If the page renders after the timeout expires, the SDK withdraws its own error and the checkout continues. Prefer not to tear the checkout down on ConnectionErrorType.timeout.
  • The SDK no longer draws an error over the checkout page's own. When the checkout webpage reports a failure it handles itself, the SDK stays out of the way.
  • Error callbacks no longer wait on a dialog. They fire as soon as the condition is detected, so your app is informed even if the default dialog is never dismissed.
  • The checkout page's own close control works in every state. It stopped working once the page had reported a payment as pending, which every bank hand-off does.
  • A slow checkout that recovers still reports success. A payment completed after a load-timeout error had been reported is no longer overridden by it.
  • File uploads are no longer filtered by type. Whatever the bank's page asks for can be selected, including formats the picker previously greyed out. The bank's page is the authority on what it accepts.

Additions that need no migration

  • CheckoutStatus gained bankTransferSubmitted and error. Both are appended, so existing members keep the indices they shipped with - anything persisting a raw status.index keeps reading what it wrote. Only an exhaustive switch over CheckoutStatus needs new arms.
  • path_provider is now a direct dependency (^2.0.0). It was already resolved transitively, so no new package enters your dependency graph, but the constraint is now the SDK's own and may affect resolution in a pinned host app.
  • Diagnostics survive process death. SDK diagnostics are spooled to the application support directory and flushed on the next initialisation. Only SDK diagnostics are written there, and no payment data.

Before / After

v1.11.x:

GlomoPayCheckout(
  config: const GlomoPayConfig(
    publicKey: 'live_pk_abc123',
    orderId: 'order_xyz789',
    devMode: true,
  ),
  onPaymentSuccess: (payload) {
    if (payload.paymentId == null) {
      // Bank transfer submitted - nothing to verify
      markAwaitingFunds(payload.orderId);
    } else {
      verifyOnBackend(payload.paymentId!, payload.signature!);
    }
  },
  onPaymentFailure: (payload) {
    logFailure(payload);
    Navigator.pop(context);
  },
  onSdkError: (errors) => showError(errors.first.message),
  onConnectionError: (error) => showError(error.message),
)

v2.0.0:

GlomoPayCheckout(
  config: const GlomoPayConfig(
    publicKey: 'live_pk_abc123',
    orderId: 'order_xyz789',
  ),
  onPaymentSuccess: (payload) {
    // paymentId and signature are now always present here
    verifyOnBackend(payload.paymentId!, payload.signature!);
  },
  onUserJourneyCompleted: (journey) {
    // The null-paymentId branch moved here
    markAwaitingFunds(journey.orderId);
  },
  onPaymentFailure: (payload) {
    logFailure(payload);   // backend-confirmed declines only
    _endCheckout();
  },
  onPaymentTerminate: (source) {
    _endCheckout();        // user left, including from an SDK error screen
  },
  onSdkError: (errors) => showDismissibleError(errors.first.message),
  onConnectionError: (error) {
    if (error.type == ConnectionErrorType.timeout) {
      logTimeout(error);   // advisory - the page may still render
      return;
    }
    showDismissibleError(error.message);
  },
)

v0.0.x to v1

The v0.0.x releases predate the current callback surface and are past end of life. Versions 1.0.3 and below are deprecated.

If you are still on a v0.0.x release, upgrade straight to the latest v2 rather than stepping through v1, and treat the v2 documentation as the integration reference. The deprecated pages below are kept for historical context only: