Entegrasyon Kurulum Rehberi
Bu entegrasyon, SDP On-Premise üzerindeki ticketların Jira Cloud'da otomatik olarak issue oluşturmasını sağlar. Teknisyen, SDP ticket detay sayfasındaki butona bastığında süreç başlar ve Jira'da yeni bir issue oluşturulur.
Teknisyen SDP ticket sayfasındaki "Create JIRA Ticket" butonuna basar.
SDP Page Script, URL'den ticket ID'sini alır ve Callback Function'ı POST isteği ile çağırır.
Deluge script, SDP API'den ticket detaylarını çeker (subject, description, item, tarih vb.).
Callback function, toplanan verilerle Jira REST API'ye POST isteği gönderir.
Jira'da issue oluşturulur. Teknisyene başarı/hata mesajı gösterilir.
| Bilgi | Açıklama | Örnek |
|---|---|---|
| SDP Sunucu URL (lokal) | SDP'nin iç ağ adresi | https://itsm.firma.local |
| SDP Teknisyen URL | Teknisyenlerin giriş yaptığı URL | https://itsm.firma.com.tr |
| SDP Auth Token | SDP API için kimlik doğrulama | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX |
| Jira Domain | Atlassian instance adresi | firma.atlassian.net |
| Jira Servis Hesabı Email | API işlemleri için kullanılacak hesap | sdp-service@firma.com |
| Jira API Token | Atlassian API erişim anahtarı | ATATT3xFfGF0... |
| Jira Proje Key | Hedef Jira projesi kodu | PROJE_KEY |
| Jira Issue Type ID | Oluşturulacak issue tipi | 10XXX |
SDP sunucusundan Jira Cloud'a erişim için firewall kuralı gereklidir. Bu adım atlanırsa Deluge script'ten Jira'ya bağlantı kurulamaz.
| Kaynak | Hedef | Port | Protokol | Yön |
|---|---|---|---|---|
| SDP Sunucusu | *.atlassian.net | 443 | HTTPS/TCP | Outbound |
| SDP Sunucusu | JIRA_DOMAIN.atlassian.net | 443 | HTTPS/TCP | Outbound |
curl -v https://JIRA_DOMAIN.atlassian.net| Sonuç | Anlam | Yapılacak İş |
|---|---|---|
| ✅ HTML/JSON yanıtı | Bağlantı başarılı | Devam edin |
| ❌ ConnectTimeoutException | Firewall engelliyor | IT'ye firewall kuralı açtırın |
| ⚠️ SSL hatası | Sertifika sorunu | SSL ayarlarını kontrol edin |
SDP Admin > Automation > Custom Functions altında aşağıdaki test scriptini çalıştırın:
testUrl = "https://JIRA_DOMAIN.atlassian.net";
response = invokeurl
[
url: testUrl
type: GET
];
info response.toString();
return response.toString();
https://id.atlassian.com/manage-profile/security/api-tokens adresine gidin.
"Create API Token" butonuna tıklayın. Token'a anlamlı bir isim verin (örn: SDP Integration).
Oluşturulan token'ı kopyalayın. Bu token bir daha gösterilmez!
Jira REST API, Basic Auth için email ve API token'ın birleşik Base64 kodunu kullanır.
echo -n "email@firma.com:API_TOKEN" | base64
https://www.base64encode.org adresine gidin. email@firma.com:API_TOKEN formatında girin ve "Encode" butonuna basın.
Basic öneki ile eklenir:headers.put("Authorization", "Basic BASE64_STRING");curl --request GET \
--url "https://JIRA_DOMAIN.atlassian.net/rest/api/3/project/search" \
--user "email@firma.com:API_TOKEN" \
--header "Accept: application/json"
curl --request GET \
--url "https://JIRA_DOMAIN.atlassian.net/rest/api/3/issuetype/project?projectId=PROJE_ID" \
--user "email@firma.com:API_TOKEN" \
--header "Accept: application/json"
curl --request GET \
--url "https://JIRA_DOMAIN.atlassian.net/rest/api/3/field" \
--user "email@firma.com:API_TOKEN" \
--header "Accept: application/json"
Response'da alan adlarını arayarak ilgili "id" değerlerini bulunuz. Örnek:
| Alan Adı | Field ID Formatı | Tip |
|---|---|---|
| Ticket No Alanı | customfield_XXXXX | Number |
| İşlem Kodu / Fiori / Rapor | customfield_XXXXX | Text |
| Talep Kanalı | customfield_XXXXX | Dropdown |
| Sorumlu Modüller | customfield_XXXXX | Multiselect |
| İş Birimi | customfield_XXXXX | Group picker |
| Hata Tespit Tarihi | customfield_XXXXX | Date (yyyy-MM-dd) |
Method: POST | URL: https://JIRA_DOMAIN.atlassian.net/rest/api/3/issue
Authorization: Basic Auth | Username: email | Password: api_token
{
"fields": {
"project": { "key": "PROJE_KEY" },
"issuetype": { "id": "ISSUE_TYPE_ID" },
"summary": "Test Ticket",
"description": {
"type": "doc", "version": 1,
"content": [{
"type": "paragraph",
"content": [{ "type": "text", "text": "Test açıklama" }]
}]
},
"customfield_XXXXX": "deger"
}
}{"id":"XXXXX","key":"PROJE-XXX","self":"..."} response'u.Callback Function, Jira API'ye POST isteğini gönderecek Deluge scriptini barındıran yapıdır. Page Script bu fonksiyonu URL üzerinden çağırarak tetikler.
Admin > General Settings > Automation > Callback Functions > New
| Alan | Girilecek Değer | Açıklama |
|---|---|---|
| Function Name | Create Jira Issue | Fonksiyona verilecek isim |
| Return Type | Map | Dropdown'dan Map seçin |
| API Name | create_jira_issue | Yalnızca harf, rakam ve alt çizgi |
| Publish | ✅ İşaretli | Checkbox işaretlenmeli! |
| Parameters - Name | request_id | Parametre adı |
| Parameters - Type | string | Parametre tipi |
// ============================================
// SDP -> Jira Cloud Entegrasyonu
// Callback Custom Function
// ============================================
// 1. SDP API'den ticket bilgilerini çek
sdpUrl = "https://SDP_LOKAL_URL/api/v3/requests/" + request_id;
sdpHeaders = {
"authtoken": "SDP_AUTH_TOKEN",
"PORTALID": "1"
};
sdpResponse = invokeurl
[
url: sdpUrl
type: GET
headers: sdpHeaders
];
requestObj = sdpResponse.get("request");
// 2. Item - Modül Mapping
// Müşteri ortamına göre güncelleyiniz
modulMap = Map();
modulMap.put("SDP_ITEM_ADI_1", "JIRA_MODUL_DEGERI_1");
modulMap.put("SDP_ITEM_ADI_2", "JIRA_MODUL_DEGERI_2");
// Diğer item'ları buraya ekleyiniz...
sdpItem = requestObj.get("item").get("name");
sdpModul = modulMap.get(sdpItem);
if(sdpModul == null || sdpModul == "")
{
sdpModul = "VARSAYILAN_MODUL";
}
// 3. SDP alanlarını al
sdpSubject = requestObj.get("subject");
// Description HTML'den temizle
sdpDescriptionRaw = requestObj.get("description");
sdpDescription = sdpDescriptionRaw
.replaceAll("<[^>]*>", "")
.replaceAll(" ", " ")
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
sdpTicketID = requestObj.get("id");
// Tarihi Jira formatına (yyyy-MM-dd) dönüştür
sdpDetectDateRaw = requestObj.get("created_time").get("display_value");
sdpDetectDate = sdpDetectDateRaw
.toDate("MMM dd, yyyy hh:mm a")
.toString("yyyy-MM-dd");
// 4. Jira API'ye POST gönder
jiraUrl = "https://JIRA_DOMAIN.atlassian.net/rest/api/3/issue";
headers = Map();
headers.put("Authorization", "Basic BASE64_STRING");
headers.put("Content-Type", "application/json");
body = "{\"fields\":{" +
"\"project\":{\"key\":\"PROJE_KEY\"}," +
"\"issuetype\":{\"id\":\"ISSUE_TYPE_ID\"}," +
"\"summary\":\"" + sdpSubject + "\"," +
"\"description\":{\"type\":\"doc\",\"version\":1," +
"\"content\":[{\"type\":\"paragraph\"," +
"\"content\":[{\"type\":\"text\"," +
"\"text\":\"" + sdpDescription + "\"}]}]}," +
"\"customfield_TICKET_NO_ID\":" + sdpTicketID + "," +
"\"customfield_ISLEM_KODU_ID\":\"-\"," +
"\"customfield_MODUL_ID\":[{\"value\":\"" + sdpModul + "\"}]," +
"\"customfield_IS_BIRIMI_ID\":[{\"name\":\"IS_BIRIMI_DEGERI\"}]," +
"\"customfield_TARIH_ID\":\"" + sdpDetectDate + "\"" +
"}}";
response = invokeurl
[
url: jiraUrl
type: POST
parameters: body
headers: headers
content-type: "application/json"
];
// 5. Sonucu döndür
returnObj = Collection();
if(response.get("key") != null)
{
returnObj.insert("result":"success");
returnObj.insert("message":"Jira issue olusturuldu: " + response.get("key"));
}
else
{
returnObj.insert("result":"failure");
returnObj.insert("message":"Hata: " + response.toString());
}
return returnObj;
| Değişken | Açıklama | Nasıl Bulunur |
|---|---|---|
SDP_LOKAL_URL | SDP'nin iç ağ adresi | SDP sunucu yapılandırması |
SDP_AUTH_TOKEN | SDP API kimlik doğrulama tokeni | SDP Admin > API Token |
JIRA_DOMAIN | Jira subdomain'i | Jira URL'sinden |
BASE64_STRING | email:token base64 karşılığı | Bölüm 3.2 |
PROJE_KEY | Jira proje kodu | Jira proje ayarları |
ISSUE_TYPE_ID | Issue tipi sayısal ID'si | Jira API /issuetype endpoint |
customfield_TICKET_NO_ID | Ticket no alanının ID'si | Jira API /field endpoint |
customfield_MODUL_ID | Sorumlu modül alanının ID'si | Jira API /field endpoint |
customfield_IS_BIRIMI_ID | İş birimi alanının ID'si | Jira API /field endpoint |
customfield_TARIH_ID | Tarih alanının ID'si | Jira API /field endpoint |
IS_BIRIMI_DEGERI | Jira'daki grup adı | Jira grup ayarları |
VARSAYILAN_MODUL | Mapping eşleşemezse kullanılacak | Müşteriye göre belirlenir |
Page Script, SDP ticket detay sayfasına "Create JIRA Ticket" butonu ekler. Teknisyen butona bastığında Callback Function tetiklenir.
Admin > General Settings > Page Scripts > New
| Alan | Değer |
|---|---|
| Rule Name | Create Jira Button |
| Apply for | Technicians |
| Page | Request Details Page |
| Condition | Gerek yoksa boş bırakılabilir |
// ============================================
// SDP -> Jira Cloud | Page Script
// Request Details Page - Create Jira Button
// ============================================
$CS.addButton("edit", "Create JIRA Ticket", function(){
// Ticket ID'yi URL'den al
var woID = window.location.href.match(/woID=(\d+)/);
var requestId = woID ? woID[1] : null;
if(!requestId){
alert("Request ID alinamadi!");
return;
}
// Callback Function URL
// NOT: Teknisyenlerin erişim URL'si ile aynı domain olmalıdır (CORS)
var callbackUrl = "https://SDP_TEKNISYEN_URL/AppIntegrations" +
"?serviceName=callbackFunctions" +
"&api_name=create_jira_issue" +
"&auth_token=CALLBACK_AUTH_TOKEN" +
"&PORTALID=1";
// Arguments encode et ve POST ile gönder
var bodyData = "arguments=" +
encodeURIComponent('{"request_id":"' + requestId + '"}');
var promise = fetch(callbackUrl, {
method: "POST",
headers: {"Content-Type": "application/x-www-form-urlencoded"},
body: bodyData
});
promise.then(function(response){
return response.text();
}).then(function(text){
try {
var result = JSON.parse(text);
var output = result.output;
if(output && output.result === "success"){
alert("Jira ticket basariyla olusturuldu!\n" + output.message);
} else {
alert("Jira ticket olusturulamadi!\n" +
(output ? output.message : text));
}
} catch(e){
alert("Sunucu yaniti: " + text);
}
}).catch(function(err){
alert("Baglanti hatasi: " + err);
});
}, {
"class": "btn btn-default btn-xs ml10",
"style": "background-color: #e57373; color: white; border-color: #e57373;"
});
Admin > General Settings > Automation > Callback Functions gidin.
"create_jira_issue" fonksiyonunu açın.
"URL to execute this Custom Function" alanındaki URL'yi kopyalayın.
URL'deki auth_token=... parametresini kopyalayın ve Page Script'e yapıştırın.
https://itsm.firma.com.tr üzerinden giriyorsa, callbackUrl'de de aynı domain kullanılmalıdır.| Hata Mesajı | Neden | Çözüm |
|---|---|---|
ConnectTimeoutException | Firewall engelliyor | Bölüm 2'deki firewall kuralını uygulayın |
401 Unauthorized | API token hatalı | Token'ı yenileyin, Base64'ü yeniden oluşturun |
400 Bad Request | JSON parse hatası / özel karakter | replaceAll satırlarını kontrol edin |
404 Not Found | Callback publish edilmemiş | Publish checkbox'ını işaretleyin |
Failed to fetch | CORS hatası - farklı domain | Page Script URL'sini teknisyen URL'si ile aynı yapın |
415 Unsupported Media Type | Content-Type yanlış | content-type: "application/json" ekleyin |
undefined mesaj | response.output path hatası | result.output.message kullanın |
| Modül boş geliyor | Item mapping eksik | modulMap'e yeni item-modül çifti ekleyin |
| Tarih format hatası | Tarih parse edilemiyor | toDate format string'ini SDP'den gelen formata göre güncelleyin |
testUrl = "https://JIRA_DOMAIN.atlassian.net/rest/api/3/myself";
headers = Map();
headers.put("Authorization", "Basic BASE64_STRING");
response = invokeurl
[
url: testUrl
type: GET
headers: headers
];
info response.toString();
return response.toString();
accountId ve emailAddress içeren JSON yanıtı.Her yeni müşteri kurulumunda aşağıdaki adımları sırayla tamamlayın.