Skip to content

Commit 6e959ea

Browse files
author
niuweili
committed
Merge branch 'main' of github.com:flashcatcloud/knowledge-base
2 parents a756ad4 + 432d8e3 commit 6e959ea

5 files changed

Lines changed: 579 additions & 9 deletions

File tree

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
---
2+
title: "ServiceNow Sync"
3+
description: "Sync incidents with ServiceNow Incidents through ServiceNow sync webhook."
4+
date: "2025-05-19T10:00:00+08:00"
5+
url: "https://docs.flashcat.cloud/en/flashduty/service-now-sync"
6+
---
7+
8+
Through ServiceNow sync webhook, Flashduty incidents are associated and synchronized with ServiceNow Incidents to achieve integration between Flashduty and ServiceNow.
9+
10+
## In ServiceNow
11+
12+
### Create User
13+
14+
1. Log in to the ServiceNow instance console, select `ALL`, enter `USERS` and select `Organization`-`Users`.
15+
2. Click `New` to create a new user.
16+
3. In the edit page, enter `flashduty` in the `User ID` field.
17+
4. Keep `Password needs reset`, `Web service access only`, and `Internal Integration User` unchecked.
18+
5. Submit and save.
19+
20+
<img alt="drawing" width="600" src="https://download.flashcat.cloud/flashduty/doc/snow/snow-1.png" />
21+
22+
### Configure User
23+
24+
The user used to access ServiceNow needs to have administrator roles.
25+
26+
1. On the user list page, find the newly created `flashduty` user and go to the configuration page.
27+
2. In the edit page, click `Set Password` to set a password.
28+
3. Click `Roles` to add **admin and itil** roles.
29+
4. Click `Update` to update the configuration.
30+
31+
<img alt="drawing" width="600" src="https://download.flashcat.cloud/flashduty/doc/snow/snow-2.png" />
32+
33+
## In Flashduty
34+
35+
### Configure Integration
36+
37+
Enter the username/password and instance name configured above into the integration information on the left and click Next to configure.
38+
39+
- **Integration Name:** Define a name for the current integration.
40+
- **Management Team:** When a management team is selected, only team members and tenant administrators can edit this integration.
41+
- **Channel:** Select the channel where this integration takes effect.
42+
- **Sync Direction:**
43+
- To_ServiceNow: Sync Flashduty incidents to ServiceNow.
44+
- From_ServiceNow: Sync ServiceNow Incidents to Flashduty.
45+
- Two-way: Bidirectional sync between Flashduty and ServiceNow.
46+
- **Trigger Mode**:
47+
- Auto Trigger: Requires configuration of corresponding conditions, Flashduty will automatically sync incidents that meet the conditions to ServiceNow.
48+
- Manual Trigger: Requires manual triggering of ServiceNow sync in the More Actions section of the incident details page (the integration configuration name is the trigger name).
49+
- **Severity Mapping:** ServiceNow's Priority is determined by the combined values of Impact and Urgency, so you can refer to ServiceNow's `Priority Lookup Rules` for configuration. Additionally, note that only when ServiceNow Incident's Urgency changes will it trigger updates to Flashduty incident severity.
50+
- **Custom Field Mapping:** You can choose to sync certain labels or all labels of incidents as well as custom field content to ServiceNow fields (only text-type fields are supported).
51+
52+
## In ServiceNow
53+
54+
When sync direction is set to From_ServiceNow or Two-way, additional configuration is required in ServiceNow to sync ServiceNow Incidents to Flashduty. When syncing to Flashduty, there are two methods available, choose based on your actual needs.
55+
56+
### Manual Sync
57+
58+
This method relies on ServiceNow's UI Action and Script Include configuration. The effect achieved by following the steps below: When creating or updating an Incident, you can see a button to send sync requests in the function area. Triggering this button will sync the current Incident content to Flashduty. Note that if the request fails when triggered, please retry (retry interval should be greater than 10 seconds).
59+
60+
#### Configure UI Action
61+
62+
1. Log in to the ServiceNow instance console, select `ALL`, enter `UI Actions` and select `System Definition`-`UI Actions`.
63+
2. Click `New` to create a new Action.
64+
3. Enter **Send To Flashduty** in `Name`, select **Incident** in `Table`.
65+
4. Keep `Form button`, `Active`, `Show insert`, `Show update`, `Client`, `List v2/3 Compatible` checked.
66+
5. Enter **onClick();** in `Onclick`.
67+
6. Enter the following in `Script`:
68+
69+
```js
70+
function onClick() {
71+
g_form.save();
72+
73+
var ga = new GlideAjax("IncidentWebhookHelperAjax");
74+
ga.addParam("sysparm_name", "sendWebhook");
75+
ga.addParam("sysparm_sys_id", g_form.getUniqueValue());
76+
77+
ga.getXMLAnswer(function (response) {
78+
alert("Webhook Triggered: " + response);
79+
});
80+
}
81+
```
82+
83+
7. Submit and save.
84+
85+
#### Configure Script Include
86+
87+
1. Log in to the ServiceNow instance console, select `ALL`, enter `Script Includes` and select `System Definition`-`Script Includes`.
88+
2. Click `New` to create a new Script Include.
89+
3. Enter **IncidentWebhookHelper** in `Name`, select **All application scopes** in `Accessible from`.
90+
4. Keep `Client callable` and `Active` checked.
91+
5. Enter the following content in `Script`, where you need to add the integration push URL in **request.setEndpoint**:
92+
93+
<div class="hide">
94+
95+
Note: The body configures default receiving fields. If you have custom fields that need to be synced to Flashduty, you need to manually add content to the body. For example, if you want to add a field named: test_001 (this field name can be obtained when adding custom fields in the integration configuration, do not use the field name displayed in the ServiceNow Incident form), then you need to add to the body: test_001: current.getDisplayValue("test_001").
96+
97+
</div>
98+
99+
```js
100+
var IncidentWebhookHelper = Class.create();
101+
IncidentWebhookHelper.prototype = {
102+
initialize: function () {},
103+
104+
sendIncidentWebhook: function (current) {
105+
function getLastComment(sysId) {
106+
var journalGR = new GlideRecord("sys_journal_field");
107+
journalGR.addQuery("element_id", sysId);
108+
journalGR.addQuery("element", "comments");
109+
journalGR.orderByDesc("sys_created_on");
110+
journalGR.setLimit(1);
111+
journalGR.query();
112+
if (journalGR.next()) {
113+
return journalGR.getValue("value");
114+
}
115+
return "";
116+
}
117+
118+
var body = {
119+
action_type: current.isNewRecord() ? "insert" : "update",
120+
number: current.getValue("number"),
121+
sys_id: current.getUniqueValue(),
122+
short_description: current.getValue("short_description"),
123+
description: current.getValue("description"),
124+
state: current.getDisplayValue("state"),
125+
impact: current.getDisplayValue("impact"),
126+
urgency: current.getDisplayValue("urgency"),
127+
comments: getLastComment(current.getUniqueValue()),
128+
<label name='field_mapping' tab='6'>{original.key}: current.getDisplayValue("{original.key}")</label>
129+
};
130+
131+
try {
132+
var request = new sn_ws.RESTMessageV2();
133+
request.setHttpMethod("POST");
134+
request.setEndpoint("PUSH URL");
135+
request.setRequestHeader("Content-Type", "application/json");
136+
request.setRequestBody(JSON.stringify(body));
137+
request.executeAsync();
138+
} catch (ex) {
139+
gs.error("Webhook Call failed: " + ex.message);
140+
}
141+
},
142+
143+
type: "IncidentWebhookHelper",
144+
};
145+
```
146+
147+
6. Submit and save.
148+
7. Return to the Script Includes list and continue creating.
149+
8. Click `New` to create a new Script Include.
150+
9. Enter **IncidentWebhookHelperAjax** in `Name`, select **All application scopes** in `Accessible from`.
151+
10. Keep `Client callable` and `Active` checked.
152+
11. Enter the following content in `Script`:
153+
154+
```js
155+
var IncidentWebhookHelperAjax = Class.create();
156+
IncidentWebhookHelperAjax.prototype = Object.extendsObject(
157+
global.AbstractAjaxProcessor,
158+
{
159+
sendWebhook: function () {
160+
var sysId = this.getParameter("sysparm_sys_id");
161+
var gr = new GlideRecord("incident");
162+
if (gr.get(sysId)) {
163+
var helper = new IncidentWebhookHelper();
164+
helper.sendIncidentWebhook(gr);
165+
return "Success";
166+
}
167+
return "Request failed";
168+
},
169+
}
170+
);
171+
```
172+
173+
12. Submit and save.
174+
175+
### Auto Sync
176+
177+
This method relies on ServiceNow's Business Rules configuration. Using this method, you can automatically sync Incidents to Flashduty when there are new or update events.
178+
179+
#### Configure Business Rules
180+
181+
1. Log in to the ServiceNow instance console, select `ALL`, enter `Business Rules` and select `System Definition`-`Business Rules`.
182+
2. Click `New` to create a new Business Rule.
183+
3. Enter **Send To Flashduty** in `Name`, select **Incident** in `Table`.
184+
4. Keep `Advanced` and `Active` checked.
185+
5. In the `When to run` section, select **async** in `When`, keep `Insert` and `Upsert` checked, configure others as needed.
186+
6. In the `Advanced` section, enter the following content in `Script`, where you need to add the integration push URL in **endpoint**:
187+
188+
<div class="hide">
189+
190+
Note: The body configures default receiving fields. If you have custom fields that need to be synced to Flashduty, you need to manually add content to the body. For example, if you want to add a field named: test_001 (this field name can be obtained when adding custom fields in the integration configuration, do not use the field name displayed in the ServiceNow Incident form), then you need to add to the body: test_001: current.getDisplayValue("test_001").
191+
192+
</div>
193+
194+
```js
195+
(function executeRule(current, previous) {
196+
function getLastComment(recordSysId) {
197+
var journalGR = new GlideRecord("sys_journal_field");
198+
journalGR.addQuery("element_id", recordSysId);
199+
journalGR.addQuery("element", "comments");
200+
journalGR.orderByDesc("sys_created_on");
201+
journalGR.setLimit(1);
202+
journalGR.query();
203+
if (journalGR.next()) {
204+
var comment = journalGR.getValue("value");
205+
return comment;
206+
}
207+
208+
return "";
209+
}
210+
211+
var operation = current.operation() || "unknown";
212+
var isPreviousNull = previous === null;
213+
var createdOn = current.getValue("sys_created_on");
214+
var updatedOn = current.getValue("sys_updated_on");
215+
var isNewRecord = createdOn === updatedOn;
216+
217+
var action = "update";
218+
if (isPreviousNull && isNewRecord) {
219+
action = "insert";
220+
}
221+
222+
var body = {
223+
action_type: action,
224+
number: current.getValue("number"),
225+
sys_id: current.getUniqueValue(),
226+
short_description: current.getValue("short_description"),
227+
description: current.getValue("description"),
228+
state: current.getDisplayValue("state"),
229+
impact: current.getDisplayValue("impact"),
230+
urgency: current.getDisplayValue("urgency"),
231+
comments: getLastComment(current.getUniqueValue()),
232+
<label name='field_mapping' tab='4'>{original.key}: current.getDisplayValue("{original.key}")</label>
233+
234+
};
235+
236+
try {
237+
var endpoint = "";
238+
var request = new sn_ws.RESTMessageV2();
239+
request.setHttpMethod("POST");
240+
request.setEndpoint(endpoint);
241+
request.setRequestHeader("Content-Type", "application/json");
242+
request.setRequestBody(JSON.stringify(body));
243+
request.executeAsync();
244+
} catch (ex) {
245+
gs.error("Error sending webhook: " + ex.message);
246+
}
247+
})(current, previous);
248+
```
249+
250+
7. Submit and save.
251+
252+
## Sync Information
253+
254+
### Form Fields
255+
256+
| ServiceNow | Flashduty | Notes |
257+
| ------------------- | ------------- | ----- |
258+
| Short_description | Title | |
259+
| Description | Description | |
260+
| Additional comments | Comments | |
261+
| State | Progress | |
262+
| Urgency | Severity | |
263+
| Others | Custom Fields | |
264+
265+
### Status Mapping
266+
267+
| ServiceNow | Flashduty | Notes |
268+
| ----------- | ---------- | ---------------------- |
269+
| New | Trigger | |
270+
| In Progress | Processing | |
271+
| On Hold | Snoozed | Default snooze 2 hours |
272+
| Resolved | CLosed | |
273+
| Closed | CLosed | |
274+
| Canceled | CLosed | |
275+
276+
### Priority Mapping
277+
278+
Only when ServiceNow's Urgency value changes will it affect Flashduty's Severity
279+
280+
| ServiceNow | Flashduty | Notes |
281+
| ---------- | --------- | ----- |
282+
| Low | Info | |
283+
| Medium | Warning | |
284+
| High | Critical | |

flashduty/zh/1. On-call/3. 配置管理/4.13 通知机器人.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -208,15 +208,14 @@ FlashDuty 支持多种通知渠道,包括手机短信、邮件、语音通话
208208

209209
**配置步骤:**
210210

211-
1. **创建自定义机器人**
212-
- 进入钉钉群聊
213-
- 打开 `群设置 → 群管理 → 智能群助手`
214-
- 点击"添加机器人" → 选择"自定义"类型
215-
216-
2. **配置安全设置**
217-
- 设置机器人名称
218-
- 添加关键词:`#`
219-
- 同意相关协议
211+
### Zoom
212+
- 打开 Zoom 应用,进入 Add Apps,搜索并添加 Incoming Webhook 应用。
213+
- 返回聊天界面,确认已成功添加“Incoming Webhook”应用。
214+
- 在频道或 Incoming Webhook 应用中输入命令:
215+
/inc connect flashduty 系统会返回应用连接信息。
216+
- 复制返回信息中的 Endpoint 地址(如:https://integrations.zoom.us/chat/webhooks/incomingwebhook/V9S5as-zTXOSUdgMITNEwA),将其填写到通知渠道的 Zoom 机器人 Webhook 地址或 Token 字段中。
217+
- 复制返回信息中的 Verification Token,填写到通知渠道的 Zoom 机器人 Verify Token 字段中。
218+
- 如需使用 @ 功能,需保证 Zoom 和 Flashduty 中的邮箱一致。管理员可在 Zoom 控制后台获取 zoom 的 user_id,并在 Flashduty 的集成中心-映射数据中创建映射表(源标签填写 email,结果标签填写 zoom_jid),最后在协作空间-分派策略中关联对应 Zoom 机器人和 映射表。
220219

221220
3. **完成集成**
222221
- 复制生成的 webhook 地址

0 commit comments

Comments
 (0)