Я пытаюсь прослушать изменения подписки (новые и существующие) моего приложения 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), который позволяет мне обновлять данные подписки пользователя, то это также будет приемлемо в качестве ответа.
Во-первых, у меня очень плохой опыт работы с 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
Если бы я был в вашей ситуации, я бы проверил несколько вещей, чтобы отладить проблему:
purchaseToken
на старте, чтобы проверить, что ломает сообщенияДля упрощения отладки:
Для меня проблема не непосредственно в PubSub, а в вашей реализации публикации/получения сообщений.
ОБНОВЛЕНИЕ 21-12-2020:
Поток:
Если вам нужна такая информация, как:
Вы также можете получать сообщения от pubsub с помощью «pull», но я встречал несколько случаев:
Спасибо тебе за это. пожалуйста, смотрите обновление в посте.
Я думаю, что на ваши вопросы ответили мне - я не знаю, что это за экземпляр, поэтому это было просто предположение. Вы должны опубликовать свое сообщение в pubsub, как я уже упоминал в своем ответе, а затем вы должны указать свою подписку, чтобы опубликовать сообщение на своей машине проверки. Там вы можете получить сообщение и можете делать с ним все, что хотите. Для меня лучшей реализацией будет создание сообщения pubsub при создании/обновлении подписки, а затем pubsub для публикации сообщений в программном обеспечении, где вы должны провести свой анализ. Вы также можете использовать учетную запись службы в качестве аутентификации pubsub :)
Есть ли у вас прогресс?