OneSignal / OneSignal-Flutter-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your flutter app with OneSignal
https://www.onesignal.com
Other
606 stars 204 forks source link

[Bug]: Unable to send notification right after login #816

Open muezz opened 5 months ago

muezz commented 5 months ago

What happened?

Notification is not created if I try right after calling login.

Steps to reproduce?

I am using Supabase auth but this should be reproducible without it. Here is my code:

Future<String> register(OnboardingModel onboarding, String password) async {
    final authResponse = await supabase.auth.signUp(
      email: onboarding.email,
      password: password,
    );
    String t = authResponse.user!.id;
    await OneSignal.login(t);
    await Purchases.logIn(t);
    await _setRole(t);
    await upsertNewUser(onboarding.copyWith(idUser: t));
    await NotificationHelper.scheduleNewUserPush(t);
    FirebaseAnalytics.instance.logSignUp(signUpMethod: 'email');
    return authResponse.user!.id;
  }

Here is the code that schedules a notification as a new user signs up.

static Future<void> scheduleNewUserPush(String userToken) async {
    var res = await http.post(
      Uri.parse(
        'https://onesignal.com/api/v1/notifications',
      ),
      headers: {
        'content-type': 'application/json',
        'accept': 'application/json',
        'Authorization': 'Basic ${dotenv.get('ONESIGNAL_REST_KEY')}',
      },
      body: jsonEncode({
        'app_id': dotenv.get('ONESIGNAL_APP_ID'),
        'target_channel': 'push',
        // 'include_external_user_ids': [userToken],
        "include_aliases": {
          "external_id": [
            userToken,
          ]
        },
        'is_ios': true,
        'name': 'rc_sub_purchase',
        "contents": {
          "en": "Become your best version!",
        },
        "subtitle": {
          "en": "Today you are closer to your goals",
        },
        "data": {
          "action": "show-feedback",
        },
        'send_after': DateTime.now().add(const Duration(minutes: 5)).toUtc().toIso8601String(),
      }),
    );
    log(res.statusCode.toString());
    log(res.body);
  }

What did you expect to happen?

I expected the notification to be scheduled without any issues but that does not happen. Although sometimes it does work.

My suspicion is that I am calling login(external_id) and then trying to set up a notification based on that external_id right away. But maybe that external_id takes a bit longer to be added as an alias? I get the following error: {"id":"","errors":{"invalid_aliases":{"external_id":["04a992ac-91f8-40b6-84f6-43d29a745184"]}}}

Right after this, if I go into the Onesignal dashboard and check my subscriptions, the latest user is there with this particular external ID. So if the user exists, why do I get this error?

OneSignal Flutter SDK version

5.0.4

Which platform(s) are affected?

Relevant log output

No response

Code of Conduct

emawby commented 5 months ago

@muezz I believe you are correct that the external_id has likely not yet been applied to the user in time. We are working on adding callbacks to various methods such as login that will let you know the server response to those calls to ensure they have completed successfully. Those callbacks should help improve scenarios like this one.

muezz commented 5 months ago

@emawby That would be great. But I am confused. Shouldn't awaiting the login mean that by the time this async operation is done, the user is logged in? Why is that not the case?

nan-li commented 5 months ago

Hi @muezz,

I apologize for the confusion with await. The await is actually to send this method call over the native bridge to the corresponding native Android or iOS method that handles login. It is not for the completion of the server call.

We will be adding a User State observer very soon (sooner than login callbacks) that you can use to effectively know when the login call has succeeded on the server.