CEX Pay's Payment Widget client library.
Для тестирование библиотеки разработана тест-консоль.
Запуск
./node_modules/.bin/ts-node test.manual/test-console.ts
Choose WidgetServiceClient implementation (1 - WidgetServiceClientMock, 2 - WidgetServiceClientImpl): 2
Creating an instance... done.
The application is ready to use. You will see all events in the console. Also you may raw JSON to call invoke.
....
Для локального тестирования используется mock реализация клиента. Подключение библиотеки выполняется с помощью следующей команды:
yarn add @cexiolabs/cexiopay.gate.widget-client-mock
Использование библиотеки выглядит следующим образом:
JavaScript
const widgetClient = new WidgetServiceClientMock();
widgetClient.onStateChanged = async (state) => {
// do something with new state
};
TypeScript
const widgetClient: WidgetServiceClient = new WidgetServiceClientMock();
widgetClient.onStateChanged = async (state: WidgetServiceClient.State) => {
// do something with new state
};
Конструктор также принимает дополнительный параметр:
const widgetClient = new WidgetServiceClientMock(responseDelayMultiplier: 1);
Это число задаёт значение, на которое будет умножаться задержка всех команд,
которая равна 1 секунде.
Используйте этот параметр, чтобы сделать эмуляцию слабого интернет-соединения,
когда сервер отвечает не моментально, а лишь спустя какое-то время. Этот параметр
повлияет на скорость ответа после вызова widgetClient.invoke(action)
.
Как уже сказано выше, вызов widgetClient.invoke(action)
запускает триггер
события widgetClient.onStateChanged
с задержкой 1 секунду по умолчанию. Флоу
виджета получается следующий:
- Создаём инстанс класса
WidgetServiceClientMock
- Через секунду приходит обновление
widgetClient.onStateChanged
со страницейstate.step === CHOOSE_INPUT_CURRENCY
. Это означает, что рисуем страницу выбора валюты. - Как только валюта выбрана, отправляем её:
const selectedCurrency = "BTC"; // selected value here
await widgetClient.invoke({
step: "SELECT_INPUT_CURRENCY",
callbackMethodName: this.globalStateVariable.callbackMethodName,
fromCurrency: selectedCurrency
});
- Через секунду приходит обновление
widgetClient.onStateChanged
со страницейstate.step === ASK_FOR_EMAIL
. Это означает, что рисуем страницу ввода email. - Как только email введён, отправляем его:
const inputEmail = "email@example.com"; // input value here
await widgetClient.invoke({
step: "SET_EMAIL",
callbackMethodName: this.globalStateVariable.callbackMethodName,
email: inputEmail
});
- Через секунду приходит обновление
widgetClient.onStateChanged
со страницейstate.step === PROCESS_PAYMENT
. Это означает, что рисуем страницу с QR кодом и просьбой оплатить. - Поскольку у mock реализации отсутствует бэкенд, который следит за изменением
состояния оплаты по QR коду, нам необходимо вручную запросить смену страницы в
консоли разработчика в браузере.
Нам нужно найти глобально и вызвать метод
widgetClient.switchState("...")
. Например, для Vue.js SPA это будет выглядеть примерно так: https://stackoverflow.com/a/51848743 Поддерживаемые state значения, которые можно передать в этот метод, следующие:
- CHOOSE_INPUT_CURRENCY - окно выбора валюты
- ASK_FOR_EMAIL - окно ввода эл.почты
- PROCESS_PAYMENT -
- PAYMENT_RECEIVE
- PAYMENT_COMPLETED Также хочу обратить внимание, что PAYMENT_RECEIVE эмулирует вызов сразу двух-трёх событий с задержкой в 10 секунд. Это сделано потому, что между AWAIT_DEPOSIT и COMPLETED есть промежуточные события EXCHANGE/EXCHANGED которые не имеют своей собственной страницы для отображения, поэтому при их возникновении всё ещё будет отображаться страница PAYMENT_RECEIVE, нужно чтобы код был к этому готов.
Для развертывания на сервере используется реализация клиента, которая уже
непосредственно общается через SignalR с бэкендом.
Использование библиотеки выглядит следующим образом:
JavaScript
const options = {
gatewayId: "...",
orderId: "order-123456",
onStateChanged: async (state) => {
// do something with new state
}
};
const widgetClient = new WidgetServiceClientImpl(options);
// Client is listening to callbacks at the moment
// ...
await client.dispose(); // optional call, this method will disconnect from the server
TypeScript
const options: WidgetServiceClient.WidgetServiceClientOptions = {
gatewayId: "...",
orderId: "order-123456",
onStateChanged: async (state: WidgetServiceClient.State) => {
// do something with new state
}
};
const widgetClient: WidgetServiceClient = new WidgetServiceClient.WidgetServiceClientImpl(options);
// Client is listening to callbacks at the moment
// ...
await client.dispose(); // optional call, this method will disconnect from the server