Part 4: Install the integration
This tutorial is part of a series that builds a Zendesk integration for Slack:
- Part 1: Build a Zendesk app with OAuth
- Part 2: Connect to Slack
- Part 3: Add a configuration UI
- Part 4: Install the integration — YOU ARE HERE
The integration listens forTicket Createdevents in Zendesk. When it detects an event with a specific ticket priority, the integration posts a related message to a provided Slack channel.
If you followed along in the series, you should now have a working Zendesk app. The app serves as a user interface (UI) for your integration. In this tutorial, you'll install the integration and finish building the app.
Create a bundle
运行,your integration requires a Zendesk Integration Services (ZIS) bundle. A bundle contains JSON objects that define the logic and resources for an integration.
The bundle for this integration should include JSON objects for:
- A custom action that gets ticket data
- A custom action that posts a message to a Slack channel
- A ZIS flow that defines the integration's logic as states
- A job spec that runs the above flow when ZIS detects a Ticket Created event
Create a bundle skeleton
To start, create a skeleton file for your bundle.
Create a file namedzendesk-to-slack-bundle.json.
Add the following JSON to the file:
{
"name":"Post Slack message on ticket creation",
"description":"Posts ticket data to Slack channel on ticket creation",
"zis_template_version":"2019-10-14",
"resources":{
"get_zendesk_ticket_http_action":{
"_placeholder_":"Action properties here"
},
"post_message_to_slack_http_action":{
"_placeholder_":"Action properties here"
},
“post_ticket_update_flow”:{
"_placeholder_":"Flow properties here"
},
"post_message_to_slack_on_ticket_created_job_spec":{
"_placeholder_":"Job spec properties here"
}
}
}
The JSON contains placeholders for the bundle's action, flow, and job spec objects.
Define the custom actions
Next, define the bundle's custom actions.
Inzendesk-to-slack-bundle.json, replace the
get_zendesk_ticket_http_action
placeholder with the following:"get_zendesk_ticket_http_action":{
"type":"ZIS::Action::Http",
"properties":{
"name":"get_zendesk_ticket_http_action",
"definition":{
"method":"GET",
"path":"/api/v2/tickets/{{$.ticketId}}.json",
"connectionName":"zendesk"
}
}
},
When run, the action calls the ZendeskShow Ticketendpoint to get ticket data. To make the call, the action requires the "zendesk" OAuth connection and the
{{$.ticketId}}
输入变量。你本身t the{{$.ticketId}}
variable when you define the bundle's flow.Replace the
post_message_to_slack_http_action
placeholder with the following:"post_message_to_slack_http_action":{
"type":"ZIS::Action::Http",
"properties":{
"name":"post_message_to_slack_http_action",
"definition":{
"method":"POST",
"url":"https://slack.com/api/chat.postMessage",
"connectionName":"slack",
"requestBody":{
"channel":"{{$.channelId}}",
"blocks":[
{
"type":"section",
"text":{
"type":"mrkdwn",
"text":"{{$.title}}"
},
"fields":[
{
"type":"mrkdwn",
"text":"*Subject*"
},
{
"type":"mrkdwn",
"text":"*Description*"
},
{
"type":"plain_text",
"text":"{{$.ticketSubject}}"
},
{
"type":"plain_text",
"text":"{{$.ticketDescription}}"
}
]
},
{
"type":"section",
"text":{
"type":"mrkdwn",
"text":"{{$.link}}"
}
}
]
}
}
}
},
When run, the action calls the Slack API'schat.postMessagemethod to post a message to a Slack channel. To post the message, the action requires the "slack" OAuth connection and the following input variables:
{{$.channelId}}
{{$.title}}
{{$.ticketSubject}}
{{$.ticketDescription}}
{{$.link}}
你本身t the input variables when you define the bundle's flow.
Define the flow
Next, define a ZIS flow for the bundle.
Inzendesk-to-slack-bundle.json, replace thepost_ticket_update_flow
placeholder with the following JSON. In the JSON, replace "SUBDOMAIN" with your Zendesk subdomain.
“post_ticket_update_flow”:{
"type":"ZIS::Flow",
"properties":{
"name":“post_ticket_update_flow”,
"definition":{
"StartAt":"LoadSettings",
"States":{
"LoadSettings":{
"Type":"Action",
"ActionName":"zis:common:action:LoadConfig",
"Parameters":{
"scope":"slackNotification"
},
"ResultPath":"$.settings",
"Next":"IsTicketPriorityMatch"
},
"IsTicketPriorityMatch":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.input.ticket_event.ticket.priority",
"StringEqualsPath":"$.settings.priority",
"Next":"GetZendeskTicket"
}
],
"Default":"Done"
},
"GetZendeskTicket":{
"Type":"Action",
"ActionName":"zis:SUBDOMAIN_zendesk_to_slack:action:get_zendesk_ticket_http_action",
"Parameters":{
"ticketId.$":"$.input.ticket_event.ticket.id"
},
"ResultPath":“.retrievedTicket美元”,
"Next":"PostMessageToSlack"
},
"PostMessageToSlack":{
"Type":"Action",
"ActionName":"zis:SUBDOMAIN_zendesk_to_slack:action:post_message_to_slack_http_action",
"Parameters":{
"channelId.$":"$.settings.channel",
"ticketSubject.$":"$.retrievedTicket.ticket.subject",
"ticketDescription.$":"$.retrievedTicket.ticket.description",
"title.$":"*_New {{$.input.ticket_event.ticket.priority}} ticket #{{$.input.ticket_event.ticket.id}}_*",
"link.$":"<{{$.retrievedTicket.ticket.url}}|View in Zendesk>"
},
"ResultPath":"$.postMessageResponse",
"Next":"Done"
},
"Done":{
"Type":"Succeed"
}
}
}
}
},
The flow object contains five states:
LoadSettings
保存使用Zendesk加载配置亚博pp'sconfig UI. The state makes the config's data available to other states as the "$.settings" object.IsTicketPriorityMatch
is a choice state. The state compares two properties:- The ticket priority from a Ticket Created event
- The ticket priority from the config settings
If the priorities are the same, the flow moves to the
GetZendeskTicket
state. Otherwise, the flow moves to theDone
state.GetZendeskTicket
uses the customget_zendesk_ticket_http_action
action. The state gets ticket data for the Ticket Created event. The state makes this ticket data available to following states as the "$.retrievedTicket" object.PostMessageToSlack
uses the custompost_message_to_slack_http_action
action. The state posts a message to the Slack channel provided in the config settings. The message contains ticket data from the Ticket Created event and the "$.retrievedTicket" object.The
Done
state ends the flow in a successful state.
Define the job spec
Next, define a job spec for the bundle. The job spec runs the bundle's ZIS flow when it detects a Ticket Created event.
Inzendesk-to-slack-bundle.json, replace the placeholder line in thepost_message_to_slack_on_ticket_created_job_spec
with the following JSON. In the JSON, replace "SUBDOMAIN" with your Zendesk subdomain.
"post_message_to_slack_on_ticket_creation_job_spec":{
"type":"ZIS::JobSpec",
"properties":{
"name":"post_message_to_slack_on_ticket_creation_job_spec",
“event_source”:"support",
"event_type":"ticket.TicketCreated",
"flow_name":"zis:SUBDOMAIN_zendesk_to_slack:flow:post_ticket_update_flow"
}
}
Code complete
Your actions, flow, and job spec now make up a complete ZIS bundle. Yourzendesk-to-slack-bundle.jsonfile should look as follows:
{
"name":"Post Slack message on ticket creation",
"description":"Posts ticket data to Slack channel on ticket creation",
"zis_template_version":"2019-10-14",
"resources":{
"get_zendesk_ticket_http_action":{
"type":"ZIS::Action::Http",
"properties":{
"name":"get_zendesk_ticket_http_action",
"definition":{
"method":"GET",
"path":"/api/v2/tickets/{{$.ticketId}}.json",
"connectionName":"zendesk"
}
}
},
"post_message_to_slack_http_action":{
"type":"ZIS::Action::Http",
"properties":{
"name":"post_message_to_slack_http_action",
"definition":{
"method":"POST",
"url":"https://slack.com/api/chat.postMessage",
"connectionName":"slack",
"requestBody":{
"channel":"{{$.channelId}}",
"blocks":[
{
"type":"section",
"text":{
"type":"mrkdwn",
"text":"{{$.title}}"
},
"fields":[
{
"type":"mrkdwn",
"text":"*Subject*"
},
{
"type":"mrkdwn",
"text":"*Description*"
},
{
"type":"plain_text",
"text":"{{$.ticketSubject}}"
},
{
"type":"plain_text",
"text":"{{$.ticketDescription}}"
}
]
},
{
"type":"section",
"text":{
"type":"mrkdwn",
"text":"{{$.link}}"
}
}
]
}
}
}
},
“post_ticket_update_flow”:{
"type":"ZIS::Flow",
"properties":{
"name":“post_ticket_update_flow”,
"definition":{
"StartAt":"LoadSettings",
"States":{
"LoadSettings":{
"Type":"Action",
"ActionName":"zis:common:action:LoadConfig",
"Parameters":{
"scope":"slackNotification"
},
"ResultPath":"$.settings",
"Next":"IsTicketPriorityMatch"
},
"IsTicketPriorityMatch":{
"Type":"Choice",
"Choices":[
{
"Variable":"$.input.ticket_event.ticket.priority",
"StringEqualsPath":"$.settings.priority",
"Next":"GetZendeskTicket"
}
],
"Default":"Done"
},
"GetZendeskTicket":{
"Type":"Action",
"ActionName":"zis:SUBDOMAIN_zendesk_to_slack:action:get_zendesk_ticket_http_action",
"Parameters":{
"ticketId.$":"$.input.ticket_event.ticket.id"
},
"ResultPath":“.retrievedTicket美元”,
"Next":"PostMessageToSlack"
},
"PostMessageToSlack":{
"Type":"Action",
"ActionName":"zis:SUBDOMAIN_zendesk_to_slack:action:post_message_to_slack_http_action",
"Parameters":{
"channelId.$":"$.settings.channel",
"ticketSubject.$":"$.retrievedTicket.ticket.subject",
"ticketDescription.$":"$.retrievedTicket.ticket.description",
"title.$":"*_New {{$.input.ticket_event.ticket.priority}} ticket #{{$.input.ticket_event.ticket.id}}_*",
"link.$":"<{{$.retrievedTicket.ticket.url}}|View in Zendesk>"
},
"ResultPath":"$.postMessageResponse",
"Next":"Done"
},
"Done":{
"Type":"Succeed"
}
}
}
}
},
"post_message_to_slack_on_ticket_creation_job_spec":{
"type":"ZIS::JobSpec",
"properties":{
"name":"post_message_to_slack_on_ticket_creation_job_spec",
“event_source”:"support",
"event_type":"ticket.TicketCreated",
"flow_name":"zis:SUBDOMAIN_zendesk_to_slack:flow:post_ticket_update_flow"
}
}
}
}
Upload the bundle
After creating your bundle file, you can deploy your integration. First, upload the bundle using theCreate or Update Bundleendpoint.
In your command-line interface, navigate to the folder that contains yourzendesk-to-slack-bundle.jsonfile.
Run:
curl-XPOSThttps://{subdomain}.亚博.com/api/services/zis/registry/{subdomain}_zendesk_to_slack/bundles \
-u{email}:{password}\
-H"Content-Type: application/json"\
-i-d @zendesk-to-slack-bundle.json
If successful, the request returns an empty 200 response.
Add an "Enable integration" button
Next, you'll add anEnable integrationbutton to your Zendesk app. When an admin clicks the button, the app installs the job spec specified in your bundle. ZIS gets the job spec from the bundle you uploaded.
In your Zendesk app'sassetsfolder, openiframe.html. Add the following HTML directly after the
tag containing theConnect to Slackbutton....
Connect to Slack
button>
div>
<divclass="c-txt u-mb">
<buttonid="btnEnableIntegration"class="c-btn c-btn--primary">
Enable integration
button>
div>
...
Inbootstrap.js, add the following:
...
fetchConfig(integrationName);
// Bind button to install the job spec
document
.getElementById("btnEnableIntegration")
.addEventListener("click",function(){
enableIntegration(integrationName);
});
...
The code binds theEnable integrationbutton to the
enableIntegration
function.In theassetsfolder, create aregistry.jsfile. Paste the following into the file:
// Install the job spec.
functionenableIntegration(integrationName){
constjobSpec=
"zis:"+
integrationName+
":job_spec:post_message_to_slack_on_ticket_creation_job_spec";
letrequest={
type:"POST",
url:
"/api/services/zis/integrations/"+
integrationName+
"/job_specs/installation",
contentType:"application/json",
data:JSON.stringify([{name:jobSpec}]),
};
returnclient.request(request).then(
function(){
console.log("Integration enabled");
client.invoke("notify","Integration enabled");
},
function(error){
console.log("Failed to enable flow: ",response);
}
);
}
The code defines the
enableIntegration
function. When called,enableIntegration
uses theInstall Job Specendpoint to install the job spec defined in your bundle.Iniframe.html, add the following:
...
<scripttype="text/javascript"src="config.js">script>
<scripttype="text/javascript"src="registry.js">script>
...
保存iframe.html,bootstrap.js, andregistry.js. Then refresh the app.
Your app now displays anEnable integrationbutton.
Install the job spec
Next, use theEnable Integrationbutton to install the job spec.
In your app, clickEnable integration. A success notification is displayed.
Test the integration
To test the integration, create a ticket with the "urgent" priority in Zendesk. To create the ticket, use the Zendesk Agent Workspace or run:
curl-XPOSThttps://{subdomain}.亚博.com/api/v2/tickets.json \
-u{email_address}:{password}\
-H"Content-Type: application/json"\
-d '
{
"ticket":{
"subject":"My printer is on fire!",
"priority":"urgent",
"status":"open",
"comment":{"body":"The smoke is very colorful."}
}
}'
The integration posts a message in the configured Slack channel.
Congratulations! You've completed this tutorial series. You now have a working integration and Zendesk app.
As a next step, you can install your Zendesk app as a private app if wanted. Refer toUploading and installing a private app.