JavaScript EventSource прослушивает Webhook, отправленный в PHP скрипт - PullRequest
1 голос
/ 22 марта 2020

Я искал и экспериментировал и просто не могу понять это. Я был бы признателен за любое понимание. Спасибо!

Итак, у меня есть магазин Shopify, и у меня есть Webhook, который срабатывает, когда я совершаю продажу, то есть он отправляет JSON данные этой продажи в скрипт PHP на моем сервере. Сейчас у меня есть сценарий PHP, который вставляет соответствующие данные в базу данных и помечает эту продажу как «непрочитанную». Затем у меня будет отдельная страница HTML / JavaScript, которую я буду запускать отдельно, опрашивая сервер на предмет непрочитанных продаж каждые 10 секунд или около того. Есть еще кое-что, но это общая идея. Это неуклюже, и я хотел бы модернизировать это.

Вот то, что я пытался и не могу заставить работать.

  1. Настройте страницу EventSource, которая слушает отдельный PHP скрипт.
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Sales Notification!</title>

</head>
<body>
    <div id="widget">
        <div id="notification_box"></div>
    </div>
    <script type="text/javascript">
        if (!!window.EventSource) {
            var source = new EventSource('alert_listener.php');
        } else {
                console.log("Window.EventSource fail!");
        }

        source.addEventListener('message', function(e) {
            console.log(e.data);
        }, false);

        source.addEventListener('open', function(e) {
            // Connection was opened.
        }, false);

        source.addEventListener('error', function(e) {
            if (e.readyState == EventSource.CLOSED) {
                // Connection was closed.
            }
        }, false);
    </script>   
</body>
</html>

Это действительно хорошо работает, когда я делаю что-то простое, например в этом примере . В любом случае, вот мой PHP код для прослушивания JSON, отправленный из Websocket (часть этого кода предоставляется Shopify):

<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");

error_reporting(0);
define('SHOPIFY_APP_SECRET', 'NOT_PUBLIC_HAR_HAR');

function verify_webhook($data, $hmac_header) {
  $calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPIFY_APP_SECRET, true));
  return ($hmac_header == $calculated_hmac);
}

function sendMsg($id, $msg) {
  echo "id: $id" . PHP_EOL;
  echo "data: $msg" . PHP_EOL;
  echo PHP_EOL;
  ob_flush();
  flush();
}
$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
while (1) {
    if ($data !== "") {
        sendMsg("test id", "Data: " . $data);
    }
    sleep(1);
}
?>

Когда я sh передаю данные из Shopify в эту * Сценарий 1038 *, первый пример JavaScript должен прослушивать эти данные, но ничего не происходит. Ничего. Понятия не имею почему. Я не знаю, как заставить сценарий PHP сказать: «Эй! Пришел приказ! Йо JavaScript, сделай что-нибудь!» а затем JavaScript go, «Новый заказ получен! Давайте сделаем что-нибудь!»

TLDR:

  1. Shopify толкает JSON к PHP сценарию ( через webhook)
  2. Отдельный JavaScript файл слушает этот PHP скрипт через объект EventSource и реагирует соответственно
  3. Я не могу заставить это работать. Пожалуйста, помогите.

Вот и все. Спасибо.

1 Ответ

0 голосов
/ 27 марта 2020

Я видел это в Твиттере - и нет, на это можно ответить.

Прежде всего я должен признать, что я не слишком хорошо знаком с EventSource - но из того, что я вижу, вы используете именно один сценарий, чтобы сделать две вещи одновременно; получить данные Shopify и немедленно экспортировать их в JS. Однако каждый запускаемый скрипт PHP имеет ровно один контекст запроса и ответа - и в этом случае вы возвращали свои данные обратно в Shopify.

Вам понадобятся две конечные точки:

  1. Первая конечная точка действует как получатель веб-хитов Shopify (shopify_webhook.php). Каждый раз, когда он получает данные, вы можете хранить их в базе данных для таких действий, как Redis, где вы устанавливаете, возможно, низкий TTL. Насколько я знаю, в Redis также есть очереди - так что это, вероятно, будет лучшим подходом.
  2. Второй конечной точкой является ваш источник событий, который продолжает потоковую передачу входящих записей очереди на ваш запрос JavaScript (то есть shopify_eventsource.php ).

Redis здесь является лишь предложением - но так или иначе, вам придется использовать промежуточное хранилище, чтобы иметь возможность перемещать входящие данные в другой выходной канал. Вы можете записать все это в один файл PHP, в котором вы проверяете входящий запрос, чтобы увидеть, является ли он запросом Shopify (и потоком) или это ваш код JavaScript, запрашивающий вывод. Но использование двух конечных точек и, следовательно, разделение кода может сделать его более читабельным и настраиваемым, если Shopify API изменения или ваш собственный JavaScript получатель.

TL; DR:

  1. Shopify -> Your endpoint -> intermediate storage.
  2. Intermediate storage -> your endpoint -(stream)> your javascript.
...