# Migration Guide

- [v2.0.0 to v2.1.0](#v200-to-v210) - nothing to do
- [v1.11.x to v2.0.0](#v111x-to-v200) - for merchants currently on v1
- [v0.0.x to v1](#v00x-to-v1) - historical reference


## 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](/platform/sdk/flutter-sdk/v2#document-downloads) 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](#1-supply-the-new-onuserjourneycompleted-callback))
2. The removal of `devMode` from `GlomoPayConfig` ([step 2](#2-remove-devmode-from-glomopayconfig))


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](/platform/sdk/flutter-sdk/v2).
For the full list of changes, see the [Changelog](/platform/sdk/flutter-sdk/changelog).


Update the dependency first:

```yaml
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.

```dart
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**

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

**After**

```dart
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 happened | Callback |
|  --- | --- |
| The SDK or the order could not proceed | `onSdkError` |
| Connectivity failed, or the page did not load in time | `onConnectionError` |
| The user then exited the error screen | `onPaymentTerminate(TerminationSource.userDismiss)` |


**Before**

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

**After**

```dart
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:**

```dart
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:**

```dart
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](/platform/sdk/flutter-sdk/v2) as the integration reference. The deprecated pages below are kept for historical context only:

- [Flutter SDK v0.0.15 (Deprecated)](/platform/sdk/flutter-sdk/v0.0.15)
- [Flutter SDK v0.0.13 (Deprecated)](/platform/sdk/flutter-sdk/v0.0.13)
- [Flutter SDK v0.0.3 (Deprecated)](/platform/sdk/flutter-sdk/v0.0.3)


## Related

- [Flutter SDK v2 documentation](/platform/sdk/flutter-sdk/v2) - complete v2 API reference
- [Flutter SDK v1 documentation (Archived)](/platform/sdk/flutter-sdk/v1) - v1.11.2 API reference
- [Changelog](/platform/sdk/flutter-sdk/changelog) - all release notes
- [React Native SDK Migration Guide](/platform/sdk/react-native-sdk/migration) - the equivalent upgrade path for React Native
- [Checkout overview](/payin/checkout) - server-side checkout integration and signature verification