2
votes

Battement. Comment vérifier que l'abonnement au renouvellement automatique est toujours valide

Mon application dispose d'un abonnement d'un mois au renouvellement automatique. Lorsque l'utilisateur clique sur un bouton «Acheter un abonnement», j'enregistre la date d'achat dans les préférences partagées. Ensuite, après 1 mois, je dois vérifier si cet abonnement est toujours valide. Alors, comment puis-je le mettre en œuvre?


1 commentaires

Veuillez élaborer votre question afin de recevoir une bonne réponse. C'est trop général.


3 Réponses :


3
votes

Il existe plusieurs façons de procéder, mais je ne le ferais pas sur l'appareil mobile.

Sur l'appareil comme vous l'avez demandé

Installez Flutter Cache Manager , au démarrage, définissez une valeur de clé de cache "Subscription" sur true avec maxAgeCacheObject: Durée (jours: 30). À chaque démarrage, vérifiez si cette clé existe toujours dans le cache. Si tel est le cas, il est toujours valide, sinon il a expiré.

Solution suggérée avec FirebaseFunction

Je suggérerais de mettre en place un backend pour gérer tout cela. Ce n'est pas une tâche pour l'appareil mobile. Vous pouvez avoir une Cloud Function de Firebase où vous transmettez un identifiant d'appareil unique et cela retourne si l'abonnement est toujours valide ou non. Une fonction sans serveur devrait fonctionner pour cela. Pseudo étapes:

  1. (Sur l'appareil) Lorsque l'application démarre, générez un GUID et faites une demande de publication http avec votre GUID.
  2. (Serveur) Dans votre fonction sans serveur, enregistrez la date à laquelle la demande est adressée à votre base de données avec l'identifiant unique que vous avez envoyé. Si votre identifiant est déjà dans la base de données, vérifiez s'il a expiré (date ajoutée - date actuelle) <30 jours. Renvoie vrai ou faux à partir de la fonction. Vrai si toujours valide, faux si non valide.
  3. (Sur le périphérique) Lorsque vous recevez true de votre fonction, enregistrez l'identifiant généré localement sur le disque et continuez ce que vous voulez faire. Si c'est faux, verrouillez l'utilisateur ou affichez l'abonnement dont vous souhaitez vous occuper.

5 commentaires

Une solution côté serveur est la bonne façon de mettre en œuvre cela. Sans cela, il existe de nombreuses vulnérabilités telles que 1) un faux reçu 2) obtenir un remboursement après l'achat 3) changer l'heure du système pour continuer l'abonnement. et plus. Ce qui manque ici, c'est de vérifier le reçu plus souvent que 30 jours pour voir s'il a été annulé / remboursé.


@enc_life Je suis d'accord. J'ai mentionné "Quand l'application démarre ..." donc cela se produira à chaque session. Vous ferez la demande à chaque session. Si true est renvoyé, vous continuez, sinon vous bloquez l'utilisateur. Peut-être même faire un verrouillage pour ne pas avoir à refaire la demande jusqu'à ce que vous exécutiez votre logique d'abonnement et la terminiez.


Ouais, vous avez raison de vérifier l'état à chaque démarrage de l'application. Je faisais référence à la revérification périodique du côté serveur de réception pour voir si l'utilisateur a été remboursé avant la date d'expiration prévue et vous devez couper l'accès plus tôt.


@enc_life je vois. J'espère que l'OP lira également ces commentaires et mettra en place un système approprié au lieu de le faire sur l'appareil.


docs.revenuecat.com/discuss/5ea749abbbfeff0018f166f3 Je suis confronté à ce problème. Veuillez aider. Je peux te payer.



6
votes

==== MISE À JOUR du 11.03.2020

Bonjour, je peux voir ce message encore lu par les personnes qui recherchent une méthode pour travailler avec l'abonnement dans Flutter. En 2019, j'ai réalisé deux applications avec des milliers d'installations où les utilisateurs peuvent acheter un abonnement renouvelable sur les 2 plates-formes. Jusqu'en février 2020, j'ai utilisé pour ce package de l'équipe Flutter https://pub.dev/packages/in_app_purchase , MAIS - il n'y a aucun moyen d'obtenir des informations sur l'utilisateur pour se désabonner dans iOS. Ce n'est pas le problème du plugin, mais l'approche iOS pour le processus. Nous devrions implémenter notre propre backend pour des raisons de sécurité (au fait, Google recommande également de faire de même, mais a tout de même laissé le moyen de vérifier l'état directement depuis l'application).

Donc, après quelques recherches, j'ai trouvé les gars qui ont fait du backend et du plugin et c'est gratuit jusqu'à ce que vous ayez moins de 10 000 USD de revenus pour le mois. https://www.revenuecat.com/ https://pub.dev/packages/purchases_flutter

J'ai implémenté ce plugin dans mes applications et cela fonctionne comme un charme. Il existe de bonnes approches qui vous permettent d'obtenir un état d'abonnement à tout moment dans l'application. Je vais faire un exemple et un article, mais je ne suis pas sûr du timing.

====

MISE À JOUR du 15.07.2019. Juste pour gagner du temps. La réponse ci-dessous a été donnée pour un plugin obsolète pour les paiements. Après que l'équipe Flutter a créé un plugin https://pub.dev/packages/in_app_purchase et je recommande de l'utiliser.

=====

La meilleure façon est d'utiliser un serveur backend sécurisé pour recevoir Notifications aux développeurs en temps réel . Mais, il est possible de vérifier l'état directement dans l'application. Ainsi, lorsque l'utilisateur tente d'accéder à certaines fonctionnalités payantes, vous pouvez vérifier si son abonnement est actif ou non. Voici l'exemple:

Créez quelque part le fichier avec la classe

class _SubscriptionState extends State<Subscription> {
  bool userSubscribed;
  _SubscriptionState() {
  SubcsriptionStatus.subscriptionStatus(iapId, const Duration(days: 30), const 
  Duration(days: 0)).then((val) => setState(() {
  userSubscribed = val;
   }));
   }
}

Importez-le là où vous devez vérifier l'état de l'abonnement et l'utiliser dans Constructor. Par exemple:

import 'dart:io' show Platform;
import 'package:flutter/services.dart';
import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';
import 'dart:async';

class SubcsriptionStatus {
static Future<bool> subscriptionStatus(
  String sku,
  [Duration duration = const Duration(days: 30),
  Duration grace = const Duration(days: 0)]) async {
    if (Platform.isIOS) {
      var history = await FlutterInappPurchase.getPurchaseHistory();

      for (var purchase in history) {
        Duration difference =
        DateTime.now().difference(purchase.transactionDate);
        if (difference.inMinutes <= (duration + grace).inMinutes &&
            purchase.productId == sku) return true;
      }
      return false;
    } else if (Platform.isAndroid) {
      var purchases = await FlutterInappPurchase.getAvailablePurchases();

      for (var purchase in purchases) {
        if (purchase.productId == sku) return true;
      }
      return false;
    }
    throw PlatformException(
        code: Platform.operatingSystem, message: "platform not supported");
  }
}

Dans la variable userSubscribed sera l'état - vrai ou faux. (Veuillez noter que vous devez ajouter flutter_inapp_purchase à votre projet).


14 commentaires

Hé là, question rapide, j'ai implémenté votre classe et cela semble fonctionner très bien. Je me demande simplement si les abonnements sont limités à 30 jours ou est-ce une «base mensuelle» parfois 31 jours, parfois 30 et une fois 28? Parce que votre exemple ne fonctionnera que si l'abonnement expire après 30 jours, n'est-ce pas?


Salut! Cool :) Comme vous pouvez le voir à partir du code avec Android, vous n'avez pas vraiment besoin de cette "Durée (jours: 30)" - ils font la facturation et donnent la réponse si l'abonnement est payé ou non. Mais pour IOS, vous devez le gérer de votre côté. Donc, je suppose que vous devriez vérifier le mois en cours et utiliser 28 (29), 30 ou 31 jours. Ajoutez simplement une méthode pour cela. Désolé, en ce moment je suis occupé, je peux le faire la semaine prochaine.


Ah d'accord, je comprends. Je ne sais tout simplement pas comment IOS le gère, si vous l'achetez en février si le produit sera acheté pendant 28/29 jours seulement, par exemple.


Hey awaik, j'ai vérifié maintenant et en effet le système iOS le gère différemment, ce n'est pas 30 jours mais plutôt un mois, comme du 30/04 au 29/05


Ahh, merci pour l'info, je vais implémenter pour iOS d'ici quelques jours dans mon application également.


Hey Frederick, j'ai enfin publié l'application iOS. Il est donc possible de vérifier l'état de l'abonnement sans calcul mois-jour. Quelque chose comme le code ci-dessous gist.github.com/awaik/7806273546b6a901d8691b355a927fac


Donc, c'est possible avec ce nouveau plugin? Ah désolé écrit à bientôt! Merci!


Salut @awaik merci pour cette réponse. Je commence à concevoir une application de flutter. Cette application a un contenu qui ne sera disponible que pour les abonnements payants (abonnements au mois de l'année). Pour cela, ai-je besoin de quelque chose comme revenuecat.com ou puis-je vérifier ce statut dans l'application? Et, comment connecter je authentifié (firebase) à l'abonnement. Si l'utilisateur est connecté (authentification Firebase), comment puis-je maintenant être un client payant?


Salut @ jr00n L'authentification Firebase et la vérification de l'état de l'abonnement ne se connectent pas entre eux. Par exemple, il est possible de créer une application qui n'a pas besoin d'autorisation, mais qui dispose de l'abonnement et des fonctionnalités que l'utilisateur peut obtenir après le paiement. Pour cela, vous avez besoin d'un chèque utilisateur abonné ou non (RevenueCat facilite et accélère la mise en œuvre). Si l'application n'a pas de fonctionnalité gratuite, vous pouvez la rendre payée depuis l'AppStore sans aucun codage. L'utilisateur paiera lors de l'installation de l'application. Dans ce cas, vous n'avez besoin ni de RevenueCat ni d'authentification.


@awaik, merci pour la réponse. Je pense que je comprends. Dans mon cas, j'ai du contenu audio dans Firebase (firestore) que je révélerai aux clients payants (abonnés). Donc, l'utilisateur doit être authentifié auprès de Firebase, afin que le contenu puisse être téléchargé par cet utilisateur dans l'application. Ou est-ce une idée stupide? Il y a donc du contenu gratuit (également dans Firestore) et il y a du contenu pour lequel un client doit avoir un abonnement. Comment exposer ce contenu dans une application Flutter? C'est ma quête en ce moment. Avez-vous des idées? Merci!!


@ jr00n C'est une bonne idée. Vous pouvez donner un accès gratuit sans autorisation et afficher du contenu premium inactif. Lorsque l'utilisateur s'est abonné, demandez-lui de se connecter après l'abonnement, puis de lui donner accès au contenu premium. C'est une logique assez simple et pas si difficile à mettre en œuvre. Bien sûr, si vous êtes nouveau avec Flutter, cela prend plus de temps, mais c'est le temps d'apprentissage, profitez-en :) Peut-être la semaine prochaine ou je me suis préparé à utiliser un exemple d'application, mais pour l'instant, j'ai un projet à terminer.


Merci @awaik, ce serait génial de voir dans une application de démonstration.


docs.revenuecat.com/discuss/5ea749abbbfeff0018f166f3 Je suis confronté à ce problème. Veuillez aider. Je peux te payer.


La raison en est peut-être que "les informations d'identification du Play Store prennent 24 heures pour se propager via Google, donc si vous venez de les configurer, vous devrez malheureusement attendre au moins un jour avant de faire des achats."



0
votes

Oui, en ce qui concerne les vulnérabilités, il existe un moyen de résoudre le problème des utilisateurs qui changent leur heure manuellement juste pour tromper l'application, la solution à laquelle j'ai pensé est de laisser le DateTime provenir du serveur de cette façon, si les utilisateurs modifient le Date et heure ou non, vous vous retrouvez avec la période correcte. J'espère que cela vous aidera.

Pour vérifier si l'abonnement a expiré, suivez simplement l'étape donnée par @awaik et en plus, vous pouvez demander à votre api de stocker la dateHeure à laquelle l'abonnement a été acheté et à quel moment vous prévoyez l'expiration de l'abonnement. Je vous suggère de sauvegarder la date d'achat et la date prévue sur votre serveur plutôt que sur l'appareil de l'utilisateur, car l'effacement du cache ou du répertoire de données de l'application entraînera la perte des données enregistrées. Bonne chance.


0 commentaires