> For the complete documentation index, see [llms.txt](https://docs.expirenza.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.expirenza.com/api/auth.md).

# Авторизація

## Встановлення WebSocket з'єднання

З'єднання від POS-системи до API Expirenza виконується за допомогою WebSocket.

{% hint style="danger" %}
Під час реалізації WebSocket **необхідно** налаштовувати **повторні спроби з'єднання** з сервером Expirenza **не частіше ніж раз на 15 секунд**.
{% endhint %}

<details>

<summary>Як реалізувати з'єднання правильно на боці інтеграції?</summary>

Так виглядає блок схема того, як сервер Expirenza опитує POS-систему для утримання зʼєднання:

![](/files/EoxaniHfuh78mWz4Rcfe)

1. **Expirenza** посилає **ping** у сокет раз в 15 секунд
2. Очікує наявність **pong** у наступні 1.5 хвилини&#x20;
3. Якщо **pong** не було отримано за 1.5 хвилини - Expirenza розриває з'єднання

POS-системи мають перевіряти (не частіше ніж раз у 15 секунд):

1. Якщо з'єднання немає — намагається під'єднатися,
2. Якщо з'єднання є — перевіряє, коли був останній pong від сервера на ping від інтеграції,
3. Якщо пройшло **більше** ніж 1,5 хвилини — значить, щось не так із з'єднанням, **розриває** його(останній коннект) і намагається під'єднатися ще раз,
4. Якщо з'єднання є і останній ping був **менш** **ніж** 1,5 хвилини тому, значить все добре — інтеграція відправляє pong
5. Якщо після перепідключення сервер одразу дисконнектить - то треба розірвати існуюче зʼєднання, і створити нове

</details>

{% hint style="warning" %}
**Headers**.\
Обов'язкова умова передавати наступні хідери, якщо не передати - авторизація не буде працювати.\
\
`cookie: system={{API}};`\
`Де {{API}} - назва вашої POS системи.`&#x20;

`__`\
`user-agent: Apache-HttpClient/5.2.3 (Java/17.0.7) (Приклад)`\
\&#xNAN;*`Значення для заголовку user-agent  - довільне - як правило - це назва технології що використовується для встановлення http зʼєднання`*
{% endhint %}

Запит на встановлення з'єднання відправляється на адресу з використанням Basic Auth.

Адреса запиту:

```http
wss://api.shaketopay.com.ua/restaurantEntryPoint
```

<details>

<summary>Приклад з'єднання  через websocket</summary>

{% code title="Java" overflow="wrap" lineNumbers="true" %}

```java
import javax.websocket.*;
import javax.websocket.ClientEndpointConfig.Builder;
import javax.websocket.ClientEndpointConfig.Configurator;
import javax.xml.bind.DatatypeConverter;

private final WebsocketEndpoint websocketEndpoint;
private final ClientEndpointConfig clientConfig;
private final URI uri;

    Builder configBuilder = Builder.create();
    String authHeaderValue = "Basic " + DatatypeConverter.printBase64Binary((user + ":" + password).getBytes());
    configBuilder.configurator(new Configurator() {
        @Override
        public void beforeRequest(Map<String, List<String>> headers) {
            headers.put("Authorization", Arrays.asList(authHeaderValue));
        }
    });
    clientConfig = configBuilder.build();
    this.uri = new URI(uri);
    this.websocketEndpoint = new WebsocketEndpoint(messageHandler, new        EventListenerI() {
        @Override
        public void notify(Object o) {
            connected = false;
        }
    });
)

void connect() throws IOException {
    WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    container.connectToServer(websocketEndpoint, clientConfig, uri);
}

void sendMessage(String message) throws IOException {
    websocketEndpoint.session.getBasicRemote().sendText(message);
}
...
```

{% endcode %}

</details>

***

## Валідація запиту

На стороні Expirenza буде проведена перевірка справжності запиту після надсилання даних від ресторану.&#x20;

Для проходження перевірки на стороні ПЗ ресторану в заголовках кожного запиту повинні міститися параметри `signature`та `restoId`.

{% tabs %}
{% tab title="signature" %}

1. Тіло запиту необхідно підписати алгоритмом HmacSHA256.
2. Результат роботи алгоритму помістити у значення параметра.
   {% endtab %}

{% tab title="restoId" %}
Передати у параметр RESTO\_ID з файлу налаштувань [properties.txt](/api/integration/prepare.md)
{% endtab %}

{% tab title="header user-agent" %}
`user-agent: Apache-HttpClient/5.2.3 (Java/17.0.7) (Приклад)`\
\&#xNAN;*`Значення для заголовку user-agent  - довільне - як правило - це назва технології що використовується для встановлення http зʼєднання`*
{% endtab %}
{% endtabs %}

<details>

<summary>Приклад генерації підпису та додавання її в заголовок signature</summary>

{% code title="JAVA" %}

```java
String signValue = makeSignature(dataBytes);

ResponseEntity<String> bodyEntity = webClient.post()
.uri(urlPart).body(BodyInserters.fromValue(dataBytes))
.header("signature", signValue).retrieve()
.toEntity(String.class).block();

private String makeSignature(byte[] bytes) throws InvalidKeyException, NoSuchAlgorithmException {
    Mac hasher = Mac.getInstance("HmacSHA256");
    hasher.init(new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"));
    byte[] hash = hasher.doFinal(bytes);
    return DatatypeConverter.printBase64Binary(hash);
}
```

{% endcode %}

Де secretKey - це SECRET\_KEY з файлу properties.txt

</details>

{% hint style="info" %}
Приклад підключення за допомогою [Postman](/api/postman.md).
{% endhint %}

***
