Данные о подписке Google pub/sub не совпадают с данными приложения

Я пытаюсь прослушать изменения подписки (новые и существующие) моего приложения Google Play на сервере. Вот код, который я использую. Здесь используется пакет композитора google/cloud-pubsub:

$projectId = 'app-name';
$keyFile = file_get_contents(storage_path('app/app-name.json'));
$pubsub = new PubSubClient([
    'projectId' => $projectId,
    'keyFile' => json_decode($keyFile, true)
]);

$httpPostRequestBody = file_get_contents('php://input');
$requestData = json_decode($httpPostRequestBody, true);

info(json_encode($requestData));

$message = $pubsub->consume($requestData);
info(json_encode($message));

Приведенный выше код работает, но проблема в том, что данные, которые я получаю, не соответствуют тем, которые я получаю на стороне приложения. Это пример данных:

{
   "message":{
      "data":"eyJ2ZXJ...",
      "messageId":"16797998xxxxxxxxx",
      "message_id":"1679799xxxxxxxxx",
      "publishTime":"2020-12-15T02:09:23.27Z",
      "publish_time":"2020-12-15T02:09:23.27Z"
   },
   "subscription":"projects/app-name/subscriptions/test-subs"
}

Если вы base64_decode() данные, вы получите что-то вроде этого:

{
version: "1.0",
packageName: "com.dev.app",
eventTimeMillis: "1607997631636",
subscriptionNotification: {
    version: "1.0",
    notificationType: 4,
    purchaseToken: "kmloa....",
    subscriptionId: "app_subs1"
  }
}

Здесь я ожидаю, что purchaseToken будет таким же, как тот, который я получаю от клиента.

Вот код на стороне клиента. Я использую покупки в приложении Expo для реализации подписок:

setPurchaseListener(async ({ responseCode, results, errorCode }) => {
if (responseCode === IAPResponseCode.OK) {
    const { orderId, purchaseToken, acknowledged } = results[0];
    if (!acknowledged) {
        await instance.post("/subscribe", {
            order_id: orderId,
            order_token: purchaseToken,
            data: JSON.stringify(results[0]),
        });

        finishTransactionAsync(results[0], true);
        alert(
            "You're now subscribed! You can now use the full functionality of the app."
        );
    }
}
});

Я ожидаю, что purchaseToken, который я извлекаю из results[0], будет таким же, как тот, который возвращает сервер Google, когда он отправляет уведомление в конечную точку. Но это не так.

Обновлять

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

На самом деле это не тот, который публикует сообщение:

await instance.post("/subscribe")

Он просто обновляет базу данных токеном покупки. Я могу просто использовать это, чтобы подписаться на пользователя, но нет никакой гарантии, что запрос является законным. Кто-то может просто создать необходимые учетные данные на основе существующего пользователя и подписаться практически без оплаты. Кроме того, этот метод нельзя использовать для сохранения подписки пользователя. Так что данные действительно должны поступать из Google.

Основываясь на приведенном ниже ответе, я понял, что вы должны инициировать публикацию со своего собственного сервера? а потом вы слушаете для этого? Итак, когда я вызываю это с клиента:

await instance.post("/subscribe", {
  purchaseToken
});

На самом деле мне нужно опубликовать сообщение, содержащее токен покупки, например:

$pubsub = new PubSubClient([
  'projectId' => $projectId,
]);
$topic = $pubsub->topic($topicName);
$message = [
  'purchaseToken' => request('purchaseToken')
];
$topic->publish(['data' => $message]);

Это то, что вы говорите? Но единственная проблема с этим подходом заключается в том, как проверить, является ли токен покупки законным, и как продлить подписку на сервере? У меня есть поле, которое нужно обновлять каждый месяц, чтобы пользователь оставался «подписанным» в глазах сервера.

Возможно, я просто усложняю ситуацию, используя pub/sub. Если на самом деле существует API, из которого я мог бы регулярно извлекать данные (используя cron), который позволяет мне обновлять данные подписки пользователя, то это также будет приемлемо в качестве ответа.

Есть ли у вас прогресс?

GTsvetanov 20.12.2020 20:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
1
787
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, у меня очень плохой опыт работы с php и pubsub из-за php PubSubClient. Если ваш скрипт только ожидает отправки и проверки сообщений, удалите пакет pubsub и обработайте его несколькими строками кода.

Пример:

$message = file_get_contents('php://input');
$message = json_decode($message, true);
if (is_array($message)) {
    $message = (isset($message['message']) && isset($message['message']['data'])) ? base64_decode($message['message']['data']) : false;
    if (is_string($message)) {
        $message = json_decode($message, true);
        if (is_array($message)) {
            $type = (isset($message['type'])) ? $message['type'] : null;
            $data = (isset($message['data'])) ? $message['data'] : [];
        }
    }
}

Я не уверен, как все работает на вашей стороне, но если эта часть публикует сообщение:

await instance.post("/subscribe", {
    order_id: orderId,
    order_token: purchaseToken,
    data: JSON.stringify(results[0]),
});

Похоже, это прокси-метод для публикации ваших сообщений. Потому что полезная нагрузка, отправленная с ним, не похожа на схему, описанную PubSub , и в финальном сообщении она не похожа на IAPQueryResponse

Если бы я был в вашей ситуации, я бы проверил несколько вещей, чтобы отладить проблему:

  • Как я публикую/читаю сообщение в/из PubSub (тема, подписка и полезная нагрузка сообщения)
  • Если все настроено правильно, то я сравню все остальные данные сообщения
  • Если проблема сохранится, то я постараюсь опубликовать в PubSub минимальное количество данных - просто purchaseToken на старте, чтобы проверить, что ломает сообщения

Для упрощения отладки:

  • Создать подписку по запросу
  • Когда вы публикуете сообщение, отметьте сообщения о подписке на подписку с помощью «Просмотр сообщений».

Для меня проблема не непосредственно в PubSub, а в вашей реализации публикации/получения сообщений.

ОБНОВЛЕНИЕ 21-12-2020:

Поток:

Если вам нужна такая информация, как:

  • Количество новых подписчиков
  • Количество обновлений
  • Количество активных подписок Вы можете создать свое собственное приложение для анализа, но если вам нужно что-то более сложное, вам придется выбрать инструмент, отвечающий вашим потребностям.

Вы также можете получать сообщения от pubsub с помощью «pull», но я встречал несколько случаев:

  • В прошлый раз, когда я использовал pull, pubsub возвращает случайное количество сообщений — если мой лимит равен 50 и у меня более 50 сообщений в очереди, я ожидаю получить 50 сообщений, но иногда pubsub дает мне меньше сообщений.
  • PubSub возвращал сообщения в случайном порядке - теперь есть возможность использовать ключ упорядочивания, но это что-то новое.
  • Чтобы реализовать «pull», вам нужно запустить crons или что-то с «push», чтобы вы получили сообщение как можно скорее.
  • При «вытягивании» вы должны зависеть от библиотеки/пакета (или чего-то еще на любом языке, который он называется), но при «выталкивании» вы можете обрабатывать сообщение всего несколькими строками кода, как мой пример php.

Спасибо тебе за это. пожалуйста, смотрите обновление в посте.

Wern Ancheta 21.12.2020 04:26

Я думаю, что на ваши вопросы ответили мне - я не знаю, что это за экземпляр, поэтому это было просто предположение. Вы должны опубликовать свое сообщение в pubsub, как я уже упоминал в своем ответе, а затем вы должны указать свою подписку, чтобы опубликовать сообщение на своей машине проверки. Там вы можете получить сообщение и можете делать с ним все, что хотите. Для меня лучшей реализацией будет создание сообщения pubsub при создании/обновлении подписки, а затем pubsub для публикации сообщений в программном обеспечении, где вы должны провести свой анализ. Вы также можете использовать учетную запись службы в качестве аутентификации pubsub :)

GTsvetanov 21.12.2020 20:49

Другие вопросы по теме