В последнее время я имел дело с большим количеством сторонних интеграций, которые требуют, чтобы ServiceNow для обработки веб-хуков, когда происходят определенные события. Итак, сегодня я хочу выделить несколько ключевых моментов о входящих веб-крючках и сравнить методы интеграции-использование Webhooks с подходом на основе опроса.
Представьте себе этот сценарий:
Случай клиента закрыт в ServiceNow. Вскоре после этого клиент получает автоматический телефонный звонок от сторонней системы с просьбой оценить услугу с 1 до 5. Как только они отправит рейтинг, ServiceNow необходимо обновить исходный случай с помощью этой обратной связи. Но вот в чем улов: ServiceNow должен всегда оставаться в курсе статуса опроса.
В этом сценарии я предполагаю, что система, которую мы интегрируем с поддержкой Webhook.
Давайте рассмотрим два решения для этого, но во -первых, нам нужно знать, когда использовать WebHook:
- Сообщения, вызванные конкретными событиями
- Легкая, минимальная информационная полезная нагрузка
- Уведомления на основе толкания для устранения частых опросов
- Требуется только простое подтверждение
Решение 1: подход на основе опроса
1. POST Сообщение REST: ServiceNow сообщает внешней системе, что дело закрыто и просит его запустить опрос.
2. Получите сообщение REST: Периодически проверяет статус и рейтинг из опроса.
3. Запланированная работа или поток: регулярно работает, чтобы проверить, завершил ли клиент опрос и обновляет дело соответственно.
Это решение работает, но оно потребляет ненужные ресурсы из -за непрерывного опроса и немного сложна.
Давайте посмотрим на решение 2
Решение 2: подход на основе веб-хука
1. Разместите сообщение о отдыхе: так же, как и раньше, чтобы внешняя система знала, что корпус закрыт.
2. Scripted REST API: получает уведомления WebHook непосредственно от сторонней системы после завершения опроса или изменения статуса опроса
Это решение выглядит привлекательным, потому что мы получаем обновления в реальном времени, мы уменьшаем использование ресурсов и намного проще и чище.
Пример полезной нагрузки Webhook
Вот что мы получили бы от стороннего веб-крюка:
{
"web_hook_id": "0229302039",
"survey": "complete",
"case_number": "CS0123267",
"customer_rating": 5
}
Вот как создать сценарий REST API для получения WebHook
-
Перейдите к: System Web Services> Scripted REST API.
-
Нажмите «Новое», предоставьте имя и базовый путь API и нажмите «Отправить».
-
Под созданным API REST нажмите «Ресурсы», затем нажмите «Новый».
-
Предоставьте подробности:
Когда дело доходит до аутентификации, в этом примере я генерирую уникальный токен, используя GlideCurerandomutil — GetSecurerAndomString и храня его в качестве свойства зашифрованного системы. Я притворяюсь, что внешняя система передает это как ключ API в заголовке запроса.
Вот как надежно сгенерировать:
var secureRandom = GlideSecureRandomUtil;
sToken = secureRandom.getSecureRandomString(25);
Вот образец сценария для обработки запросов Webshook в сценарии API:
(function process(request, response) {
// Retrieve the request URL to validate incoming request origin
var requestedURI = request.url;
// Fetch the valid API key stored securely in system properties
var validApiKey = gs.getProperty('sn_customerservice.webhook.api.key');
// Get the API key provided in the request header for authentication
var apiKeyFromHeader = request.getHeader('X-API-Key');
// Validate the provided API key and ensure the request URL is from the trusted domain
if (apiKeyFromHeader !== validApiKey || requestedURI.indexOf('trustedDomain') == -1) {
// If validation fails, respond with a 403 Forbidden error
response.setStatus(403);
response.setBody({
"error": "Forbidden",
"message": "Unauthorized: invalid API key or domain"
});
return; // Terminate execution if validation fails
}
// Extract the JSON payload data from the webhook request body
var body = request.body.data;
// Obtain case number and customer rating from the payload
var caseNumber = body.case_number;
var customerRating = body.customer_rating;
// Prepare to update the specific customer service case
var grCS = new GlideRecord('sn_customerservice_case');
grCS.addQuery('number', caseNumber); // Search case by its number
grCS.query();
// If the case record exists, update the customer rating
if (grCS.next()) {
grCS.u_customer_rating = customerRating; // Update rating field
grCS.update(); // Commit changes
// Send a successful response confirming the update
response.setStatus(200);
response.setBody({
"message": "Case updated successfully."
});
} else {
// If case not found, respond with a 404 Not Found error
response.setStatus(404);
response.setBody({
"error": "Case not found."
});
}
})(request, response);