Skip to content

[In-App-Purchase] [iOS] When the app opens, it doesn't give old incomplete purchases to consume/process. #45425

@DeanPack

Description

@DeanPack

According to the documentation, you want to initialize the stream listener first thing in your app because when it starts you get a list of purchase details sent to the purchase listener that need to be processed and marked as consumed. Because this happens, it makes it so users can't purchase more of that consumable. The apple store simply returns that the consumable has already been purchased and will be refunded for free.

To follow the documentation, I put my subscription listener at the very top of the main function. I have to do some weird things to make sure the transactions are run properly, because I need the users Id to validate the receipts on our firebase server, and the user isn't signed in yet at the top of main.

While debugging in Xcode, I see firebase analytics capturing the old purchase events and not sending them because they recognize them as duplicates. but the purchaseUpdates listener doesn't capture any of these. Here is the output in Xcode
Screen Shot 2019-11-22 at 2 41 06 PM

The code I use for initializing the transaction listener is here.

void main() {
  WidgetsFlutterBinding.ensureInitialized();
    List<dynamic> purchaseDetails = List<dynamic>();
    Stream _purchaseUpdates = InAppPurchaseConnection.instance.purchaseUpdatedStream;
    _purchasesSubscription = _purchaseUpdates.listen((purchases) {
      for(int i = 0; i < purchases.length; i++) {
        print(purchases.status);
        print(purchases.purchaseID);
      }
      purchaseDetails.addAll(purchases);
    });
    try{
    StreamingSharedPreferences.instance.then((value){
    });
    // set up Sentry to catch Flutter errors
    FlutterError.onError = (FlutterErrorDetails details) {
      if (SentryHelper.isInDebugMode()) {
        FlutterError.dumpErrorToConsole(details);
      } else {
        Zone.current.handleUncaughtError(details.exception, details.stack);
      }
    };
    } catch(e) {
      var state = AppState.getDefault()
        .rebuild((b) => b..message = "in catch " + e.toString());
      runHallo(state, '/login');
    }
    FirebaseAuth auth = FirebaseAuth.instance;
    Future.wait([auth.currentUser(), loadState()])
        .timeout(Duration(seconds: 5)).then((futures) {
        try{ 
          FirebaseUser user = futures[0];
          AppState appState = futures[1];
          var isLoggedIn = user != null;
          var isAppStateLoggedIn = appState.isAuthenticated();
          var message =
              (isLoggedIn ? "user is logged in," : "user is not logged in,") +
                  (isAppStateLoggedIn
                      ? "appState.isAuthenticated()=true"
                      : "appState.isAuthenticated()=false");
          var state = appState.rebuild((b) => b..message = message);
          if (isLoggedIn) {
            message += [
              (appState.auth.userId == user.uid).toString(),
              appState.getAuthUser()?.needsSetup()?.toString() ?? "false"
            ].join(', ');
          }
          if (user != null &&
              appState.auth.userId == user.uid &&
              !appState.getAuthUser().needsSetup()) {
                _setupIAP(purchaseDetails);
                _purchasesSubscription.cancel();
                _purchasesSubscription = _purchaseUpdates.listen((purchases) {
                  _setupIAP(purchases);
                });
            runHallo(state, '/home');
          } else {
            var state = appState.rebuild((b) => b..message = message);
            runHallo(state, '/login');
          }
        } catch (e) {
          var state = AppState.getDefault()
              .rebuild((b) => b..message = "in catch " + e.toString());
          runHallo(state, '/login');
        }
    });
}

I don't get any print statements from within the flutter app.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work listcustomer: crowdAffects or could affect many people, though not necessarily a specific customer.p: in_app_purchasePlugin for in-app purchasepackageflutter/packages repository. See also p: labels.platform-iosiOS applications specifically

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions