Как проверить, активна ли подписка Google Play на стороне клиента или на стороне сервера

В основном я хочу иметь возможность проверить связанную подписку в учетной записи пользователя (аутентификация firebase с firestore) активна, даже если пользователь вошел в систему с помощью iPhone или веб-приложения, используя API разработчика игр с функциями firebase (на стороне сервера) или код конкретной платформы (на стороне клиента), например android kotlin.

Подробнее

Я использую сохранение пользовательской подписки в firestore в учетной записи пользователя (аутентификация Firebase), используя Pub/Sub, используя облачные функции, и я сохраняю те же данные подписки в локальной БД.

Что я пробовал

Чтобы убедиться, что связанная подписка в учетной записи пользователя активна, я проверяю, что expiryTimeMillis больше текущей даты или автопродление включен:

suspend fun isPremiumActive(userId: String): Boolean {
  val userSubscriptionData = localDB.getUserSubscription(userId)
        if (userSubscriptionData == null)
            return false
        else
            return Date(userSubscriptionData.expiryTimeMillis).after(Date()) ||
                    userSubscriptionData.autoRenewing
    }

но использование java Date имеет много недостатков, поскольку на него влияет дата устройства.

Я думал об использовании метки времени сервера, но это было бы сложно, поскольку подписка пользователя зависит от часового пояса (насколько я знаю).

Итак, есть ли другой способ проверить, активна ли подписка в данный момент? Я что-то упускаю?

Некоторые варианты использования

Пользователь может войти в систему (в приложении с использованием аутентификации Firebase), и эта учетная запись имеет связанную подписку, поэтому я должен предоставлять премиум-функции, если связанная подписка действительна, даже если на устройстве нет той же учетной записи для оплаты подписки или даже пользователь использует iPhone, поэтому я не могу позвонить:

billingClient.queryPurchases()

Обновить

Считается ли этот машинописный код безопасным для проверки активности подписки?

const serverTime = admin.firestore.Timestamp.now().toDate()
const subscriptionTime = new Date(subscripton.exipryTimeInMilis)
if (subscripton.autoRenewing || subscriptionTime > serverTime)
    console.log(`subscription is active`);



Ответы (1)


Вы на правильном пути, но ошибаетесь в одном тонком моменте:

Я думал об использовании метки времени сервера, но это было бы сложно, поскольку подписка пользователя зависит от часового пояса (насколько я знаю).

Это не совсем правильно. expiryTimeMillis определяется в миллисекундах с начала Эпохи (также известной как отметки времени Unix), что составляет < strong>независимо от часовых поясов. Как отмечается в связанной статье, эпоха Unix — это 00:00:00 UTC 1 января 1970 года. Это же время — 16:00:00 31 декабря 1960 года по стандартному тихоокеанскому времени, но оба эти времени в соответствующих часовых поясах иметь одинаковую метку времени: 0.

Таким образом, ваша интуиция верна: Вы должны проверить это на стороне сервера, используя метку времени сервера. Любая попытка проверить устройство будет ненадежной именно по причинам, которые вы описываете: это зависит от времени устройства и любых махинаций, которые пользователь может предпринять со временем своего устройства, будь то путешествие вперед во времени, чтобы получить больше драгоценных камней в своей любимой игре. или путешествие назад, чтобы попытаться продлить подписку с истекшим сроком действия (возможно, вашу!).

Это также решит проблему проверки того, не выполнен ли вход на устройстве в учетную запись Google с подпиской или с использованием iPhone, поскольку вы можете связать учетную запись в своей системе с подпиской в ​​своем бэкэнде.

person Ryan M    schedule 23.06.2020
comment
Именно то, что я хочу, и в моем случае я сравниваю время подписки с отметкой времени сервера, которая в моем случае: /6470661 - person Abed; 24.06.2020
comment
Я обновил вопрос в соответствии с вашим ответом, считаете ли вы, что этот способ проверки подписки безопасен? - person Abed; 24.06.2020
comment
Прочитав документацию по жизненному циклу подписки, можно предположить, что autoRenewing проверка является избыточным, потому что expiryDate в таких случаях должен всегда быть в будущем, но я не думаю, что это вызовет какие-либо проблемы, чтобы проверить это, как вы делаете. В противном случае логика в конце вашего вопроса кажется мне правильной. - person Ryan M; 24.06.2020