From 3e59693e017742d971f490eb7c58870cb745a98d Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Fri, 18 Jul 2025 03:58:34 +0000 Subject: (김준회) 결재 모듈 개발 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/knox-api/approval/approval-guide.html | 4999 +++++++++++ lib/knox-api/approval/approval.ts | 603 ++ lib/knox-api/employee/employee-guide.html | 2154 +++++ lib/knox-api/employee/employee.ts | 435 + lib/knox-api/index.ts | 6 + lib/knox-api/mail/knox-mail.ts | 312 + lib/knox-api/mail/mail-guide.html | 2114 +++++ lib/knox-api/messenger/messenger-guide.html | 9422 ++++++++++++++++++++ lib/knox-api/messenger/messenger.ts | 925 ++ .../realtime-notification-guide.html | 764 ++ .../realtime-notification/realtime-notification.ts | 333 + 11 files changed, 22067 insertions(+) create mode 100644 lib/knox-api/approval/approval-guide.html create mode 100644 lib/knox-api/approval/approval.ts create mode 100644 lib/knox-api/employee/employee-guide.html create mode 100644 lib/knox-api/employee/employee.ts create mode 100644 lib/knox-api/index.ts create mode 100644 lib/knox-api/mail/knox-mail.ts create mode 100644 lib/knox-api/mail/mail-guide.html create mode 100644 lib/knox-api/messenger/messenger-guide.html create mode 100644 lib/knox-api/messenger/messenger.ts create mode 100644 lib/knox-api/realtime-notification/realtime-notification-guide.html create mode 100644 lib/knox-api/realtime-notification/realtime-notification.ts (limited to 'lib') diff --git a/lib/knox-api/approval/approval-guide.html b/lib/knox-api/approval/approval-guide.html new file mode 100644 index 00000000..b1b085fb --- /dev/null +++ b/lib/knox-api/approval/approval-guide.html @@ -0,0 +1,4999 @@ +
+
+

결재

+
+
+

내부 임직원에 한해 결재 상신이 가능합니다.
결재 상신 뿐만 아니라 결재상황조회 및 상신취소 등이 가능합니다.

+
+
[정책 및 제약사항]
+
+
+
1. 상신인 정보는 녹스포탈 임직원만 지정 가능하며, 상신자의 거점으로 연계 호출해야 + 합니다.
+
2. 본문 사이즈는 최대 1MB 를 넘을 수 없습니다.
+
3. 한번에 10개의 첨부파일을 포함하여 발송할 수 있으며, 전체 첨부 사이즈는 10MB + 를 넘을 수 없습니다.
+
4. 결재경로자 설정은 최대 99명까지 지정이 가능합니다.
+
+
+
[API 목록]    테스트 페이지로 이동(Swagger)*Chrome Browser만 이용 가능합니다.
+
+
+ + + + + + + + + + + + + + + +
APIURIMethodDescription
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
결재상신/approval/api/v2.0/approvals/submit + POST결재를 상신한다 +
보안결재상신/approval/api/v2.0/approvals/secu-submit + POST보안(대외비/극비) 결재를 + 상신한다
결재상세상황조회/approval/api/v2.0/approvals/{apInfId}/detail + GET결재문서의 정보를 상세 + 조회한다
결재본문조회/approval/api/v2.0/approvals/{apInfId}/content + GET결재문서의 본문을 + 조회한다
결재상황조회/approval/api/v2.0/approvals/status + POST결재문서의 진행 상태를 + 조회한다
결재연계ID조회/approval/api/v2.0/approvals/apinfids + GET결재ID로 결재연계ID를 + 조회한다
상신함리스트조회/approval/api/v2.0/approvals/submission + GET요청 연계시스템ID로 연계 + 상신처리된 상신자의 상신함의 정보를 조회한다
연계이력조회/approval/api/v2.0/approvals/apinfidinfos + GET요청 연계시스템ID에서 + 상신된 결재문서의 연계 이력을 조회한다
상신취소/approval/api/v2.0/approvals/{apInfId}/cancel + POST결재문서를 + 상신취소한다
저장된결재경로목록조회/approval/api/v2.0/approvals/ownaplnlist + GET개인별 저장된 결재경로 + 목록을 조회한다
저장된결재경로상세조회 + /approval/api/v2.0/approvals/{pslAplnId}/ownaplndetail + GET개인별 저장된 + 결재경로 ID로 정보를 상세 조회한다
+
+

+
+
결재상신
+
+

/approval/api/v2.0/approvals/submit

+
+
+

삼성 그룹사 임직원 뿐만 아니라 외부수신인을 포함하여 결재 상신이 가능하며, 상신된 결재는 각 + 사용자의 결재함에 저장됩니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2결재본문contentsYBodyStringTEST +
3본문종류contentsType + YBodyStringTEXTTEXT,HTML,MIME
4보안문서타입docSecuType + YBodyStringPERSONALCONFIDENTIAL, + CONFIDENTIAL_STRICT 지정 시 에러
5통보옵션notifyOption + YBodyString0 + 0: 통보자통보 결재경로포함 , 1: 모두통보 결재경로포함
2: 통보자통보 결재경로포함안함 , 3: 모두통보 결재경로포함안함
6긴급여부 + urgYn + YBodyStringN
7상신일시 + sbmDt + YBodyString20190524145033
8타임존timeZoneYBodyStringGMT +
9문서관리저장코드 + docMngSaveCode + YBodyString00 : 문서관리저장안함
1 : + 문서관리저장함
10결재제목subjectYBodyString근태신청 +
11상신언어sbmLangYBodyStringkoko : korean ja : + japanese zh : chinese en : english
12연계IDapInfIdYBodyStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
13중요여부importantYn + NBodyStringY +
14결재경로 + aplns + YBodyJSON String + 상신자, 결재자 1명 이상 필수
※결재자/합의자 없이 + 통보자만 지정된 결재경로 불가
15EPID + epId + YBodyStringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
16사용자IDuserIdYBodyStringqtp03 + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
17사용자이메일emailAddress + YBodyStringqtp03@stage.sasmung.com + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
18결재순번 + seqYBodyString0상신자의 경우 반드시 0, + 병렬결재(합의)자의 경우 seq 일치
19설정구분 + role + YBodyString0기안(0), 결재(1), 합의(2), 후결(3), 병렬합의(4), 병렬결재(7), 통보(9) +
(후결자는 최대 1명, 병렬결재 & 병렬합의자는 최소 2명 + 이상)
20처리구분aplnStatsCode + YBodyString0 + 미결(0), + 결재(1), 반려(2), 전결(3), 자동결재(5)
21전결권한여부arbPmtYnYBodyStringY
22본문수정권한여부 + contentsMdfyPmtYn + YBodyStringY
23경로변경권한여부 + aplnMdfyPmtYn + YBodyStringY + +
24상신의견opinionYBodyString근태결재입니다.
25첨부파일attachments + NBodymultipart/form-data + multipart/form-data로 변환된 + 바이너리 파일 및 파일명
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재연계ID정보dataJSON String + +
결재연계IDapInfIdStringTEST1A000A11ACa02CVQ1A0CA4CA33C1 + 리턴받은 결재 아이디를 + 이용하여, 상황조회 및 상신취소가 가능합니다.
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/approvals/api/v2.0/submit
+Content-Disposition: form-data; name="approval"
+ {
+  "aplns": [
+    {
+      "epId": "M071015062623C988403","seq": "0","role": "0","aplnStatsCode": "0",
+      "arbPmtYn": "Y","contentsMdfyPmtYn": "Y", "aplnMdfyPmtYn": "Y"
+    },
+    {
+      "epId": "M080325053708C989824","seq": "1","role": "1","aplnStatsCode": "0",
+      "arbPmtYn": "Y","contentsMdfyPmtYn": "Y", "aplnMdfyPmtYn": "Y"
+    }
+  ],
+  "contents": "TEST",
+  "contentsType": "TEXT",
+  "docSecuType": "PERSONAL",
+  "notifyOption": "0",
+  "urgYn": "N",
+  "sbmDt": "20190526121212",
+  "subject": "Test application",
+  "sbmLang": "ko",
+  "apInfId": "TEST0000000000002120190514143359",
+  "docMngSaveCode": "0",
+  "timeZone": "GMT+9"
+}
+Content-Disposition: form-data; name="attachments"; filename="attach1.jpg"
+Content-Disposition: form-data; name="attachments"; filename="attach2.txt"
+													
+
+
{
+    "result": "success",
+    "data": {
+        "apInfId": "TEST0000000000002120190514143359"
+    }
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
400APE002입력된 데이터 형식이 + 잘못되었습니다. +
400APE003입력값이 + 잘못되었습니다. +
400APE004본문은 1MB를 초과할 + 수 없습니다. +
400APE006제목에는 엔터값이 + 들어갈 수 없습니다. +
400APE007제목은 300자를 + 초과할 수 없습니다. +
403APE008중복된 데이터가 + 있습니다. +
400APE009후결자는 1명만 지정 + 가능합니다. +
400APE010결재경로는 최소 2명 + 이상입니다. +
400APE011결재경로는 최대 99명 + 이하입니다. +
400APE012상신자를 제외한 + 사용자들은 의견값을 설정할 수 없습니다. +
400APE013미결 상태로 설정된 + 사용자들은 처리일시값을 설정할 수 없습니다. +
400APE014상신의견값의 길이가 + 너무 깁니다. +
400APE016결재자 혹은 합의자가 + 결재경로상에 없습니다. +
400APE017결재경로 내 휴직 또는 + 퇴직자가 포함되어 있습니다. +
400APE018외부 사용자는 + 통보자로만 지정이 가능합니다. +
400APE019결재경로에 포함될 수 + 없는 사용자가 입력되었습니다. +
+
+

+
+
보안결재상신 +
+
+

/approval/api/v2.0/approvals/secu-submit

+
+
+

보안 결재 옵션을 설정하여 대외비, 극비로 보안 결재를 상신할 수 있습니다. +

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2결재본문contentsYBodyStringTEST +
3본문종류contentsType + YBodyStringTEXTTEXT,HTML,MIME
4보안문서타입docSecuType + YBodyStringCONFIDENTIAL + CONFIDENTIAL, + CONFIDENTIAL_STRICT 지정 시 에러
5통보옵션notifyOption + YBodyString0 + 0: 통보자통보 결재경로포함 , 1: 모두통보 결재경로포함
2: 통보자통보 결재경로포함안함 , 3: 모두통보 결재경로포함안함
6긴급여부 + urgYn + YBodyStringN
7상신일시 + sbmDt + YBodyString20190524145033
8타임존timeZoneYBodyStringGMT +
9문서관리저장코드 + docMngSaveCode + YBodyString00 : 문서관리저장안함
1 : + 문서관리저장함
10결재제목subjectYBodyString근태신청 +
11상신언어sbmLangYBodyStringkoko : korean ja : + japanese zh : chinese en : english
12연계IDapInfIdYBodyStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
13중요여부importantYn + NBodyStringY +
14결재경로 + aplns + YBodyJSON String + 상신자, 결재자 1명 이상 필수
※결재자/합의자 없이 + 통보자만 지정된 결재경로 불가
15EPID + epId + YBodyStringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
16사용자IDuserIdYBodyStringqtp03 + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
17사용자이메일emailAddress + YBodyStringqtp03@stage.sasmung.com + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
18결재순번 + seqYBodyString0상신자의 경우 반드시 0, + 병렬결재(합의)자의 경우 seq 일치
19설정구분 + role + YBodyString0기안(0), 결재(1), 합의(2), 후결(3), 병렬합의(4), 병렬결재(7), 통보(9) +
(후결자는 최대 1명, 병렬결재 & 병렬합의자는 최소 2명 + 이상)
20처리구분aplnStatsCode + YBodyString0 + 미결(0), + 결재(1), 반려(2), 전결(3), 자동결재(5)
21전결권한여부arbPmtYnYBodyStringY
22본문수정권한여부 + contentsMdfyPmtYn + YBodyStringY
23경로변경권한여부 + aplnMdfyPmtYn + YBodyStringY + +
24상신의견opinionYBodyString근태결재입니다.
25첨부파일attachments + NBodymultipart/form-data + multipart/form-data로 변환된 + 바이너리 파일 및 파일명
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재연계ID정보dataJSON String + +
결재연계IDapInfIdStringTEST1A000A11ACa02CVQ1A0CA4CA33C1 + 리턴받은 결재 아이디를 + 이용하여, 상황조회 및 상신취소가 가능합니다.
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/v2.0/approvals/secu-submit
+Content-Disposition: form-data; name="approval"
+ {
+  "aplns": [
+    {
+      "epId": "M071015062623C988403","seq": "0","role": "0","aplnStatsCode": "0",
+      "arbPmtYn": "Y","contentsMdfyPmtYn": "Y", "aplnMdfyPmtYn": "Y"
+    },
+    {
+      "epId": "M080325053708C989824","seq": "1","role": "1","aplnStatsCode": "0",
+      "arbPmtYn": "Y","contentsMdfyPmtYn": "Y", "aplnMdfyPmtYn": "Y"
+    }
+  ],
+  "contents": "TEST",
+  "contentsType": "TEXT",
+  "docSecuType": "CONFIDENTIAL",
+  "notifyOption": "0",
+  "urgYn": "N",
+  "sbmDt": "20190526121212",
+  "subject": "Test application",
+  "sbmLang": "ko",
+  "apInfId": "TEST0000000000002120190514143359",
+  "docMngSaveCode": "0",
+  "timeZone": "GMT+9"
+}
+Content-Disposition: form-data; name="attachments"; filename="attach1.jpg"
+Content-Disposition: form-data; name="attachments"; filename="attach2.txt"
+													
+
+
{
+    "result": "success",
+    "data": {
+        "apInfId": "TEST0000000000002120190514143359"
+    }
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
400APE002입력된 데이터 형식이 + 잘못되었습니다. +
400APE003입력값이 + 잘못되었습니다. +
400APE004본문은 1MB를 초과할 + 수 없습니다. +
400APE006제목에는 엔터값이 + 들어갈 수 없습니다. +
400APE007제목은 300자를 + 초과할 수 없습니다. +
403APE008중복된 데이터가 + 있습니다. +
400APE009후결자는 1명만 지정 + 가능합니다. +
400APE010결재경로는 최소 2명 + 이상입니다. +
400APE011결재경로는 최대 99명 + 이하입니다. +
400APE012상신자를 제외한 + 사용자들은 의견값을 설정할 수 없습니다. +
400APE013미결 상태로 설정된 + 사용자들은 처리일시값을 설정할 수 없습니다. +
400APE014상신의견값의 길이가 + 너무 깁니다. +
400APE016결재자 혹은 합의자가 + 결재경로상에 없습니다. +
400APE017결재경로 내 휴직 또는 + 퇴직자가 포함되어 있습니다. +
400APE018외부 사용자는 + 통보자로만 지정이 가능합니다. +
400APE019결재경로에 포함될 수 + 없는 사용자가 입력되었습니다. +
+
+

+
+
결재상세상황조회 +
+
+

/approval/api/v2.0/approvals/{apInfId}/detail

+
+
+

결재 연계 ID를 이용하여 결재문서의 정보(결재현황, 결재문서 상태)를 상세 조회 할 수 + 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
1연계IDapInfIdYPathStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재상세정보dataJSON String + +
본문종류contentsType + StringTEXTTEXT,HTML,MIME
상신일시 + sbmDt + String20190524145033
상신언어sbmLangStringkoko : korean ja : + japanese zh : chinese en : english
연계IDapInfIdStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
연계 시스템 + IDSystem-IDStringCXXREST0001
통보옵션notifyOption + String0 + 0: 통보자통보 결재경로포함 , 1: 모두통보 결재경로포함
2: 통보자통보 결재경로포함안함 , 3: 모두통보 결재경로포함안함
긴급여부 + urgYn + StringN
보안문서타입docSecuType + StringPERSONALCONFIDENTIAL, + CONFIDENTIAL_STRICT 지정 시 에러
결재상태정보statusString1암호화실패(-3),암호화중(-2), + 예약상신(-1),보류(0),진행중(1),완결(2),반려(3),상신취소(4),전결(5),후완결(6)
타임존timeZoneStringGMT +
결재제목subjectString근태신청 +
결재경로 + aplns + JSONList +
처리일시actPrssDt + String20190521015954 + +
개봉일시docOpenDt + String20190521015954 + +
도착일시docArvDt + String20190521015954 + +
상신의견opinionString근태결재입니다.
결재관계자회사코드 + companyCode + StringC98
결재관계자회사명 + companyName + StringSAMSUNG +
결재관계자총괄코드 + subOrgCode + StringC98S01
결재관계자총괄명 + subOrgName + String개발총괄
결재관계자부서코드 + departmentCode + StringC98S0201 +
결재관계자부서명 + departmentName + String개발1팀 +
결재관계자 + epidepIdStringM071015062623C988403 +
결재관계자 + 메일주소emailAddress + Stringqtp03@stage.samsung.com +
결재관계자 + 이름nameStringqtp03
결재관계자 + 직급코드titleCode + StringB3P1 +
결재관계자 직급명 + titleName + StringEngineer +
결재순번 + seqString0상신자의 경우 반드시 0, + 병렬결재(합의)자의 경우 seq 일치
설정구분 + role + String0기안(0), 결재(1), 합의(2), 후결(3), 병렬합의(4), 병렬결재(7), 통보(9) +
(후결자는 최대 1명, 병렬결재 & 병렬합의자는 최소 2명 + 이상)
처리구분aplnStatsCode + String0 + 미결(0), + 결재(1), 반려(2), 전결(3), 자동결재(5)
대리결재자여부 + prxAprYn + StringN
위임결재자EPID + dlgAprEpid + StringM345615062623C988000 +
전결권한여부arbPmtYnStringY
전결수행여부 + arbActYn + String +
경로변경권한여부 + aplnMdfyPmtYn + StringY + +
경로수정수행여부 + aplnMdfyActYn + String
본문수정권한여부 + contentsMdfyPmtYn + StringY
본문수정수행여부 + contentsMdfyActYn + String +
첨부파일정보attachments + JSONList + +
첨부파일명 + attachfileName + JSON String + test.txt + +
첨부파일사이즈 + attachfileSize + String140 + byte단위 +
순번seqString0 +
결재 ID + apId + Stringtest1e1703024e9cbdd0e79569dbb458 +
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
								/approval/api/v2.0/approvals/TEST0000000000002120190514143359/detail
+							
+
+
{
+    "result": "success",
+    "data": {
+        "contentsType": "TEXT",
+        "sbmDt": "20231004061200",
+        "sbmLang": "ko",
+        "apInfId": "TEST0000000000002120190514143359",
+        "systemId": "KCC98REST00008",
+        "notifyOption": "1",
+        "urgYn": "0",
+        "docSecuType": "PERSONAL",
+        "status": "1",
+        "timeZone": "GMT",
+        "subject": "Test application",
+        "aplns": [
+            {
+                "actPrssDt": "20231004061200",
+                "docOpenDt": null,
+                "docArvDt": "20231004061200",
+                "opinion": "",
+                "companyCode": "C98",
+                "companyName": "삼성 Intranet",
+                "departmentCode": "H66329",
+                "departmentName": "autotest",
+                "epId": "M071015062623C988403",
+                "emailAddress": "qtp03@stage.samsung.com",
+                "userId": null,
+                "name": "qtp03",
+                "jobPositionCode": "J2",
+                "jobPosition": "사원",
+                "subOrgCode": "C98S02",
+                "subOrgName": "개발총괄",
+                "seq": "0",
+                "role": "0",
+                "aplnStatsCode": "0",
+                "arbPmtYn": "Y",
+                "arbActYn": "N",
+                "rsrvSbmDt": null,
+                "subSeq": null,
+                "titleCode": "J2",
+                "titleName": "사원",
+                "dlgAprEpid": null,
+                "aplnMdfyPmtYn": "Y",
+                "prxAprYn": "N",
+                "contentsMdfyPmtYn": "Y",
+                "contentsMdfyActYn": "N",
+                "aplnMdfyActYn": "N"
+            },
+            {
+                "actPrssDt": "",
+                "docOpenDt": null,
+                "docArvDt": "20231004061200",
+                "opinion": "",
+                "companyCode": "C60",
+                "companyName": "삼성SDS",
+                "departmentCode": "V8TESTGROUP",
+                "departmentName": "V8 테스트그룹",
+                "epId": "M071015063405C983280",
+                "emailAddress": "qtp06@stage.samsung.com",
+                "userId": null,
+                "name": "qtp06",
+                "jobPositionCode": "G0H0",
+                "jobPosition": "자문역",
+                "subOrgCode": "ASIZE01",
+                "subOrgName": "첨부용량",
+                "seq": "1",
+                "role": "1",
+                "aplnStatsCode": "0",
+                "arbPmtYn": "Y",
+                "arbActYn": "N",
+                "rsrvSbmDt": null,
+                "subSeq": null,
+                "titleCode": "G0H0",
+                "titleName": "자문역",
+                "dlgAprEpid": null,
+                "aplnMdfyPmtYn": "Y",
+                "prxAprYn": "N",
+                "contentsMdfyPmtYn": "Y",
+                "contentsMdfyActYn": "N",
+                "aplnMdfyActYn": "N"
+            }
+        ],
+        "attachments": [
+            {
+                "seq": "0",
+                "attachfileName": "test.txt",
+                "attachfileSize": 23
+            }
+        ]
+    }
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
404APE020해당 연계 ID의 + 결재문서는 존재하지 않습니다. +
+
+

+
+
결재본문조회 +
+
+

/approval/api/v2.0/approvals/{apInfId}/content +

+
+
+

결재 연계 ID를 이용하여 결재문서의 본문을 조회 할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
1연계IDapInfIdYPathStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재본문정보dataJSON String + +
본문종류contentsType + StringTEXTTEXT,HTML,MIME
결재본문contentsStringTEST +
결재연계IDapInfIdStringTEST1A000A11ACa02CVQ1A0CA4CA33C1 +
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/api/v2.0/approvals/TEST0000000000002120190514143359/content
+													
+
+
{
+	"result": "success",
+	"data": {
+		"contents": "test",
+		"contentType": "TEXT",
+		"apInfId": "TEST0000000000002120190521110026"
+	}
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
404APE020해당 연계 ID의 + 결재문서는 존재하지 않습니다. +
+
+

+
+
결재상황조회 +
+
+

/approval/api/v2.0/approvals/status

+
+
+

결재 연계 ID를 이용하여 결재문서의 상황을 조회 할 수 있습니다.(최대 + 1000건)

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2연계 ID + 리스트apinfidsYBodyJSONList최대 1000개 +
3연계 + IDapinfid + YBodyString최대 + 1000개
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재상세정보dataJSONList +
결재연계IDapInfIdStringTEST1A000A11ACa02CVQ1A0CA4CA33C1 + 리턴받은 결재 아이디를 + 이용하여, 상황조회 및 상신취소가 가능합니다.
문서변경횟수docChgNumString0 +
결재상태정보statusString1암호화실패(-3),암호화중(-2), + 예약상신(-1),보류(0),진행중(1),완결(2),반려(3),상신취소(4),전결(5),후완결(6)
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/v2.0/approvals/status
+
+body:
+[
+{"apinfid":"TEST0000000000002120190521155428"},
+{"apinfid":"TEST0000000000002120190521155422"}
+]
+													
+
+
{
+  "result": "success",
+  "data": [
+    {
+      "apInfId": "TEST0000000000002120190521155428",
+      "docChgNum": "0",
+      "status": "1"
+    },
+    {
+      "apInfId": "TEST0000000000002120190521155422",
+      "docChgNum": "1",
+      "status": "2"
+    }
+  ]
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
400APE022최대 1000개의 + 요청만 가능합니다. +
+
+

+
+
결재연계ID조회 +
+
+

/approval/api/v2.0/approvals/apinfids

+
+
+

결재 ID를 이용하여 결재연계 ID를 조회 할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2결재 ID + apId + YQueryStringtest1e1703024e9cbdd0e79569dbb458 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재연계ID정보dataJSON String + +
결재 ID + apId + Stringtest1e1703024e9cbdd0e79569dbb458 +
연계IDapInfIdStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
연계 시스템 + IDsystemIdStringCXXREST0001
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/api/v2.0/approvals/apinfids?apId=testd269bd3743ca8a0b4c0e7d9de5af
+													
+
+
{
+  "result": "success",
+  "data": {
+    "apId": "test1e1703024e9cbdd0e79569dbb458",
+    "apInfId": "TEST0000000000002120190517133353",
+    "systemId": "C60REST0001"
+  }
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
404APE021해당 결재 ID의 + 결재문서는 존재하지 않습니다. +
+
+

+
+
상신함리스트조회
+
+

/approval/api/v2.0/approvals/submission

+
+
+

요청 연계시스템ID로 연계 상신처리된 상신자의 상신함의 정보를 조회 할 수 + 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2EPID + epId + YQueryStringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
3사용자IDuserIdYQueryStringqtp03 + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
4사용자이메일emailAddress + YQueryStringqtp03@stage.sasmung.com + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재연계정보 + dataJSONList +
결재제목subjectString근태신청 +
연계IDapInfIdStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
결재관계자회사코드 + companyCode + StringC98
결재관계자회사명 + companyName + StringSAMSUNG +
결재관계자총괄코드 + subOrgCode + StringC98S01
결재관계자총괄명 + subOrgName + String개발총괄
결재관계자부서코드 + departmentCode + StringC98S0201 +
결재관계자부서명 + departmentName + String개발1팀 +
결재관계자 + 직급코드titleCode + StringB3P1 +
결재관계자 직급명 + titleName + StringEngineer +
EPID + epId + StringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
결재관계자 + 이름nameStringqtp03
상신일시 + sbmDt + String20190524145033
결재상태정보statusString1암호화실패(-3),암호화중(-2), + 예약상신(-1),보류(0),진행중(1),완결(2),반려(3),상신취소(4),전결(5),후완결(6)
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
								/approval/api/v2.0/approvals/submission?epId=M071015062623C988403
+							
+
+
{
+    "result": "success",
+    "data": [
+        {
+            "subject": "Test application",
+            "apInfId": "TEST0000000000002120190514143359",
+            "compCode": "C98",
+            "compName": "삼성 Intranet",
+            "deptCode": "H66329",
+            "deptName": "autotest",
+            "jobPosition": "사원",
+            "jobPositionCode": "J2",
+            "subOrgCode": "C98S02",
+            "subOrgName": "개발총괄",
+            "epId": "M071015062623C988403",
+            "name": "qtp03",
+            "sbmDt": "20231004061200",
+            "status": "1",
+            "companyCode": "C98",
+            "companyName": "삼성 Intranet",
+            "departmentCode": "H66329",
+            "departmentName": "autotest",
+            "titleName": "사원",
+            "titleCode": "J2"
+        },
+        {
+            "subject": "Test application",
+            "apInfId": "TEST0000000000002120190514143359",
+            "compCode": "C98",
+            "compName": "삼성 Intranet",
+            "deptCode": "H66329",
+            "deptName": "autotest",
+            "jobPosition": "사원",
+            "jobPositionCode": "J2",
+            "subOrgCode": "C98S02",
+            "subOrgName": "개발총괄",
+            "epId": "M071015062623C988403",
+            "name": "qtp03",
+            "sbmDt": "20231004061200",
+            "status": "1",
+            "companyCode": "C98",
+            "companyName": "삼성 Intranet",
+            "departmentCode": "H66329",
+            "departmentName": "autotest",
+            "titleName": "사원",
+            "titleCode": "J2"
+        }
+    ]
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
+
+

+
+
연계이력조회
+
+

/approval/api/v2.0/approvals/apinfidinfos +

+
+
+

요청 연계시스템ID에서 상신된 결재문서의 연계 이력을 조회 할 수 있습니다. 조회 + 기준일시 이하 조회 기간(분) 동안 호출 계정의 결재건 정보 리턴 (상신, 결재승인, 경로변경, 본문수정 등 결재건 처리 시)

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2조회기준일시endDateYQueryString201905211500조회의 기준시간 해당 일자 이하로 조회
yyyyMMddHHmm + 형식
3페이지번호 + page + NQueryString1paging 처리 +
4조회기간durationNQueryString1단위 : 분 / 최소 1분 ~ 최대 60분
default : + 1
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
순번 + seq + String1
결재연계정보 + dataJSONList +
순번 + seq + String1
연계IDapInfIdStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
전체 데이터 + 개수totalCountString2 +
전체 페이지 + 개수seqString1 +
페이지번호seqString1 + +
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/v2.0/approvals/apinfidinfos?endDate=201905211500
+													
+
+
{
+	"result": "success",
+	"data": [{
+			"seq": 1,
+			"apInfId": "TEST0000000000002120190521155428",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		},
+		{
+			"seq": 2,
+			"apInfId": "TEST0000000000002220190521155428",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		},
+		{
+			"seq": 3,
+			"apInfId": "TEST0000000000002220190521155428",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		},
+		{
+			"seq": 4,
+			"apInfId": "TEST0000000000002120190521155759",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		},
+		{
+			"seq": 5,
+			"apInfId": "TEST0000000000002220190521155759",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		},
+		{
+			"seq": 6,
+			"apInfId": "TEST0000000000002220190521155759",
+			"totalcount": 6,
+			"totalpage": 1,
+			"currentpage": 1
+		}
+	]
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
400APE002입력된 데이터 형식이 + 잘못되었습니다. +
+
+

+
+
상신취소
+
+

/approval/api/v2.0/approvals/{apInfId}/cancel

+
+
+

연계 ID에 해당하는 결재문서를 상신취소처리 할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계IDapInfIdYPathStringTEST0000000000002120190523185902 + 32자리의 고유 + 결재값
2상신취소의견opinionYQueryString상신취소드립니다 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 + 성공여부resultStringsuccess +
결재연계ID정보dataJSON String + +
결재연계IDapInfIdStringTEST1A000A11ACa02CVQ1A0CA4CA33C1 + 리턴받은 결재 아이디를 + 이용하여, 상황조회 및 상신취소가 가능합니다.
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/api/v2.0/approvals/TEST0000000000002120190521110026/cancel?opinion=reject
+													
+
+
{
+    "result": "success",
+    "data": {
+        "apInfId": "TEST0000000000002120190521110026"
+    }
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
400APE002입력된 데이터 형식이 + 잘못되었습니다. +
404APE020해당 연계 ID의 + 결재문서는 존재하지 않습니다. +
400APE023해당 결재 ID의 + 결재문서는 이미 완결 혹은 상신취소처리 되었습니다. +
+
+

+
+
저장된결재경로목록조회
+
+

/approval/api/v2.0/approvals/ownaplnlist

+
+
+

개인별 저장된 결재경로 목록을 조회 할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2EPID + epId + NQueryStringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
3사용자IDuserIdNQueryStringtest속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
4사용자이메일 + emailAddress + NQueryStringtest@stage.samsung.com + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
저장된 + 결재경로IDpslAplnId + String168cf04db4aa4e64b010f434d9088312 +
저장된 + 결재경로이름pslAplnNm + StringTEST +
등록자EPID + ownEpid + StringM201026053604S204412 +
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/api/v2.0/approvals/ownaplnlist?emailAddress=test@stage.samsung.com
+													
+
+
{
+    "result": "success",
+    "data": [
+        {
+            "pslAplnId": "168cf04db4aa4e64b010f434d9088312",
+            "pslAplnNm": "TEST",
+            "ownEpid": "M201026053604S204412"
+        },
+        {
+            "pslAplnId": "876f1522d1e440288f5ad4fbda42d712",
+            "pslAplnNm": "TEST2",
+            "ownEpid": "M201026053604S204412"
+        }
+    ]
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + +
400APE001데이터가 + 필요합니다. +
404APE030저장된 결재경로가 + 없습니다. +
+
+

+
+
저장된결재경로상세조회
+
+

/approval/api/v2.0/approvals/{pslAplnId}/ownaplndetail +

+
+
+

개인별 저장된 결재경로 목록을 조회 할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + IDSystem-IDYHeaderStringCXXREST0001
2저장된 + 결재경로IDpslAplnIdNPathString168cf04db4aa4e64b010f434d9088312 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
저장된 + 결재경로IDpslAplnId + String168cf04db4aa4e64b010f434d9088312 +
EPID + epId + StringM071015062623C9884속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
순번 + seq + String1
설정구분 + role + String0기안(0), 결재(1), 합의(2), 후결(3), 병렬합의(4), 병렬결재(7), 통보(9) +
(후결자는 최대 1명, 병렬결재 & 병렬합의자는 최소 2명 + 이상)
국문이름fnmStringtest +
영문이름 + enFnm + StringOneTest +
사용자이메일 + emailAddress + Stringtest@stage.samsung.com + 속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
사용자IDuserIdStringtest속성 한가지와 조합하여 사용 우선순위
userId > + epId > emailAddress
+
+
+
Sample
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/approval/api/v2.0/approvals/168cf04db4aa4e64b010f434d9088312/ownaplndetail
+													
+
+
{
+    "result": "success",
+    "data": [
+        {
+                "pslAplnId": "168cf04db4aa4e64b010f434d9088312",
+                "epId": "M201026053604S204412",
+                "seq": "0",
+                "role": "0",
+                "fnm": "test",
+                "enFnm": "OneTest",
+                "emailAddress": "test@stage.samsung.com",
+                "userId": "test"
+        },
+        {
+                "pslAplnId": "168cf04db4aa4e64b010f434d9088312",
+                "epId": "M201026053604S204412",
+                "seq": "1",
+                "role": "1",
+                "fnm": "test2",
+                "enFnm": "TwoTest",
+                "emailAddress": "test2@stage.samsung.com",
+                "userId": "test2"
+        },
+        {
+                "pslAplnId": "168cf04db4aa4e64b010f434d9088312",
+                "epId": "M201026053604S204412",
+                "seq": "2",
+                "role": "1",
+                "fnm": "test3",
+                "enFnm": "ThreeTest",
+                "emailAddress": "test3@stage.samsung.com",
+                "userId": "test3"
+        }
+    ]
+}
+													
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
404APE030저장된 결재경로가 + 없습니다. +
+
+
+
\ No newline at end of file diff --git a/lib/knox-api/approval/approval.ts b/lib/knox-api/approval/approval.ts new file mode 100644 index 00000000..6a21e113 --- /dev/null +++ b/lib/knox-api/approval/approval.ts @@ -0,0 +1,603 @@ +"use server" + +// Knox API Approval 서버 액션들 +// 가이드: lib/knox-api/approval/guide.html + +// ========== 타입 정의 ========== + +// 공통 응답 타입 +export interface BaseResponse { + result: string; +} + +// 결재 경로 타입 +export interface ApprovalLine { + epId?: string; + userId?: string; + emailAddress?: string; + seq: string; + role: string; // 기안(0), 결재(1), 합의(2), 후결(3), 병렬합의(4), 병렬결재(7), 통보(9) + aplnStatsCode: string; // 미결(0), 결재(1), 반려(2), 전결(3), 자동결재(5) + arbPmtYn: string; // 전결권한여부 + contentsMdfyPmtYn: string; // 본문수정권한여부 + aplnMdfyPmtYn: string; // 경로변경권한여부 + opinion?: string; // 상신의견 (상신자만) +} + +// 결재 상신 요청 타입 +export interface SubmitApprovalRequest { + contents: string; // 결재본문 + contentsType: string; // 본문종류 (TEXT, HTML, MIME) + docSecuType: string; // 보안문서타입 (PERSONAL, CONFIDENTIAL, CONFIDENTIAL_STRICT) + notifyOption: string; // 통보옵션 (0-3) + urgYn: string; // 긴급여부 (Y/N) + sbmDt: string; // 상신일시 (YYYYMMDDHHMMSS) + timeZone: string; // 타임존 (GMT, GMT+9 등) + docMngSaveCode: string; // 문서관리저장코드 (0: 안함, 1: 저장) + subject: string; // 결재제목 + sbmLang: string; // 상신언어 (ko, ja, zh, en) + apInfId: string; // 연계ID (32자리 고유값) + importantYn?: string; // 중요여부 (Y/N) + aplns: ApprovalLine[]; // 결재경로 + attachments?: File[]; // 첨부파일 +} + +// 결재 상신 응답 타입 +export interface SubmitApprovalResponse extends BaseResponse { + data: { + apInfId: string; + }; +} + +// 결재 상세 조회 응답 타입 +export interface ApprovalDetailResponse extends BaseResponse { + data: { + contentsType: string; + sbmDt: string; + sbmLang: string; + apInfId: string; + systemId: string; + notifyOption: string; + urgYn: string; + docSecuType: string; + status: string; // 암호화실패(-3), 암호화중(-2), 예약상신(-1), 보류(0), 진행중(1), 완결(2), 반려(3), 상신취소(4), 전결(5), 후완결(6) + timeZone: string; + subject: string; + aplns: any[]; + attachments?: any[]; + }; +} + +// 결재 본문 조회 응답 타입 +export interface ApprovalContentResponse extends BaseResponse { + data: { + contents: string; + contentsType: string; + apInfId: string; + }; +} + +// 결재 상황 조회 요청 타입 +export interface ApprovalStatusRequest { + apinfids: { apinfid: string }[]; +} + +// 결재 상황 조회 응답 타입 +export interface ApprovalStatusResponse extends BaseResponse { + data: { + apInfId: string; + docChgNum: string; + status: string; + }[]; +} + +// 상신 취소 응답 타입 +export interface CancelApprovalResponse extends BaseResponse { + data: { + apInfId: string; + }; +} + +// 개인 결재경로 목록 조회 응답 타입 +export interface OwnApprovalLineListResponse extends BaseResponse { + data: any[]; +} + +// 개인 결재경로 상세 조회 응답 타입 +export interface OwnApprovalLineDetailResponse extends BaseResponse { + data: any; +} + +// 상신함 리스트 조회 응답 타입 +export interface SubmissionListResponse extends BaseResponse { + data: any[]; +} + +// 연계 이력 조회 응답 타입 +export interface ApprovalHistoryResponse extends BaseResponse { + data: any[]; +} + +// 연계 ID 조회 응답 타입 +export interface ApprovalIdsResponse extends BaseResponse { + data: any[]; +} + +// ========== 서버 액션 함수들 ========== + +/** + * 결재 상신 + * POST /approval/api/v2.0/approvals/submit + */ +export async function submitApproval( + request: SubmitApprovalRequest, + systemId: string +): Promise { + try { + const formData = new FormData(); + + // JSON 데이터 생성 + const approvalData = { + contents: request.contents, + contentsType: request.contentsType, + docSecuType: request.docSecuType, + notifyOption: request.notifyOption, + urgYn: request.urgYn, + sbmDt: request.sbmDt, + timeZone: request.timeZone, + docMngSaveCode: request.docMngSaveCode, + subject: request.subject, + sbmLang: request.sbmLang, + apInfId: request.apInfId, + importantYn: request.importantYn, + aplns: request.aplns + }; + + formData.append('approval', JSON.stringify(approvalData)); + + // 첨부파일 처리 + if (request.attachments) { + request.attachments.forEach((file) => { + formData.append('attachments', file); + }); + } + + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/submit`, { + method: 'POST', + headers: { + 'System-ID': systemId, + }, + body: formData, + }); + + if (!response.ok) { + throw new Error(`결재 상신 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('결재 상신 오류:', error); + throw error; + } +} + +/** + * 보안 결재 상신 + * POST /approval/api/v2.0/approvals/secu-submit + */ +export async function submitSecurityApproval( + request: SubmitApprovalRequest, + systemId: string +): Promise { + try { + const formData = new FormData(); + + // JSON 데이터 생성 + const approvalData = { + contents: request.contents, + contentsType: request.contentsType, + docSecuType: request.docSecuType, // CONFIDENTIAL 또는 CONFIDENTIAL_STRICT + notifyOption: request.notifyOption, + urgYn: request.urgYn, + sbmDt: request.sbmDt, + timeZone: request.timeZone, + docMngSaveCode: request.docMngSaveCode, + subject: request.subject, + sbmLang: request.sbmLang, + apInfId: request.apInfId, + importantYn: request.importantYn, + aplns: request.aplns + }; + + formData.append('approval', JSON.stringify(approvalData)); + + // 첨부파일 처리 + if (request.attachments) { + request.attachments.forEach((file) => { + formData.append('attachments', file); + }); + } + + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/secu-submit`, { + method: 'POST', + headers: { + 'System-ID': systemId, + }, + body: formData, + }); + + if (!response.ok) { + throw new Error(`보안 결재 상신 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('보안 결재 상신 오류:', error); + throw error; + } +} + +/** + * 결재 상세 상황 조회 + * GET /approval/api/v2.0/approvals/{apInfId}/detail + */ +export async function getApprovalDetail( + apInfId: string, + systemId: string +): Promise { + try { + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/${apInfId}/detail`, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`결재 상세 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('결재 상세 조회 오류:', error); + throw error; + } +} + +/** + * 결재 본문 조회 + * GET /approval/api/v2.0/approvals/{apInfId}/content + */ +export async function getApprovalContent( + apInfId: string, + systemId: string +): Promise { + try { + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/${apInfId}/content`, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`결재 본문 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('결재 본문 조회 오류:', error); + throw error; + } +} + +/** + * 결재 상황 조회 + * POST /approval/api/v2.0/approvals/status + */ +export async function getApprovalStatus( + request: ApprovalStatusRequest, + systemId: string +): Promise { + try { + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/status`, { + method: 'POST', + headers: { + 'System-ID': systemId, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(request.apinfids), + }); + + if (!response.ok) { + throw new Error(`결재 상황 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('결재 상황 조회 오류:', error); + throw error; + } +} + +/** + * 결재 연계 ID 조회 + * GET /approval/api/v2.0/approvals/apinfids + */ +export async function getApprovalIds( + systemId: string, + apIds?: string[] +): Promise { + try { + let url = `${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/apinfids`; + + if (apIds && apIds.length > 0) { + const params = new URLSearchParams(); + apIds.forEach(id => params.append('apId', id)); + url += `?${params.toString()}`; + } + + const response = await fetch(url, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`결재 연계 ID 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('결재 연계 ID 조회 오류:', error); + throw error; + } +} + +/** + * 상신함 리스트 조회 + * GET /approval/api/v2.0/approvals/submission + */ +export async function getSubmissionList( + systemId: string, + params?: Record +): Promise { + try { + let url = `${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/submission`; + + if (params) { + const searchParams = new URLSearchParams(params); + url += `?${searchParams.toString()}`; + } + + const response = await fetch(url, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`상신함 리스트 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('상신함 리스트 조회 오류:', error); + throw error; + } +} + +/** + * 연계 이력 조회 + * GET /approval/api/v2.0/approvals/apinfidinfos + */ +export async function getApprovalHistory( + systemId: string, + params?: Record +): Promise { + try { + let url = `${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/apinfidinfos`; + + if (params) { + const searchParams = new URLSearchParams(params); + url += `?${searchParams.toString()}`; + } + + const response = await fetch(url, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`연계 이력 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('연계 이력 조회 오류:', error); + throw error; + } +} + +/** + * 상신 취소 + * POST /approval/api/v2.0/approvals/{apInfId}/cancel + */ +export async function cancelApproval( + apInfId: string, + systemId: string +): Promise { + try { + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/${apInfId}/cancel`, { + method: 'POST', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`상신 취소 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('상신 취소 오류:', error); + throw error; + } +} + +/** + * 저장된 결재경로 목록 조회 + * GET /approval/api/v2.0/approvals/ownaplnlist + */ +export async function getOwnApprovalLineList( + systemId: string, + params?: Record +): Promise { + try { + let url = `${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/ownaplnlist`; + + if (params) { + const searchParams = new URLSearchParams(params); + url += `?${searchParams.toString()}`; + } + + const response = await fetch(url, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`저장된 결재경로 목록 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('저장된 결재경로 목록 조회 오류:', error); + throw error; + } +} + +/** + * 저장된 결재경로 상세 조회 + * GET /approval/api/v2.0/approvals/{pslAplnId}/ownaplndetail + */ +export async function getOwnApprovalLineDetail( + pslAplnId: string, + systemId: string +): Promise { + try { + const response = await fetch(`${process.env.KNOX_API_BASE_URL}/approval/api/v2.0/approvals/${pslAplnId}/ownaplndetail`, { + method: 'GET', + headers: { + 'System-ID': systemId, + }, + }); + + if (!response.ok) { + throw new Error(`저장된 결재경로 상세 조회 실패: ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('저장된 결재경로 상세 조회 오류:', error); + throw error; + } +} + +// ========== 유틸리티 함수들 ========== + +/** + * 결재 상신 요청 데이터 생성 도우미 + */ +export async function createSubmitApprovalRequest( + contents: string, + subject: string, + approvalLines: ApprovalLine[], + options: Partial = {} +): Promise { + const now = new Date(); + const sbmDt = now.toISOString().replace(/[-:T]/g, '').slice(0, 14); + const apInfId = `${process.env.KNOX_SYSTEM_ID || 'DEFAULT'}${sbmDt}${Math.random().toString(36).substr(2, 9)}`.padEnd(32, '0'); + + return { + contents, + subject, + aplns: approvalLines, + contentsType: 'TEXT', + docSecuType: 'PERSONAL', + notifyOption: '0', + urgYn: 'N', + sbmDt, + timeZone: 'GMT+9', + docMngSaveCode: '0', + sbmLang: 'ko', + apInfId, + importantYn: 'N', + ...options + }; +} + +/** + * 결재 라인 생성 도우미 + */ +export async function createApprovalLine( + userInfo: { epId?: string; userId?: string; emailAddress?: string }, + role: string, + seq: string, + options: Partial = {} +): Promise { + return { + ...userInfo, + seq, + role, + aplnStatsCode: '0', + arbPmtYn: 'Y', + contentsMdfyPmtYn: 'Y', + aplnMdfyPmtYn: 'Y', + ...options + }; +} + +/** + * 결재 상태 문자열 변환 + */ +export async function getApprovalStatusText(status: string): Promise { + const statusMap: Record = { + '-3': '암호화실패', + '-2': '암호화중', + '-1': '예약상신', + '0': '보류', + '1': '진행중', + '2': '완결', + '3': '반려', + '4': '상신취소', + '5': '전결', + '6': '후완결' + }; + + return statusMap[status] || '알 수 없음'; +} + +/** + * 결재 역할 문자열 변환 + */ +export async function getApprovalRoleText(role: string): Promise { + const roleMap: Record = { + '0': '기안', + '1': '결재', + '2': '합의', + '3': '후결', + '4': '병렬합의', + '7': '병렬결재', + '9': '통보' + }; + + return roleMap[role] || '알 수 없음'; +} diff --git a/lib/knox-api/employee/employee-guide.html b/lib/knox-api/employee/employee-guide.html new file mode 100644 index 00000000..806788fe --- /dev/null +++ b/lib/knox-api/employee/employee-guide.html @@ -0,0 +1,2154 @@ +
+
+

임직원

+
+
+

Knox Suite을 통한 임직원 및 조직 정보 조회 기능을 제공합니다.

+

+
[정책 및 제약사항]
+
+
+
1. 재직, 휴직 상태 임직원만 조회 가능합니다.
+
2. 연계 신청시 요청한 조회대상 회사의 임직원, 조직정보만 조회 가능합니다. +
+
3. 연계 신청 시 파견 포함을 선택한 경우에만 파견된 임직원 정보까지 조회 + 가능합니다.
+
4. 회사코드를 이용한 조회 시, 해당 회사 정보만 조회 가능합니다.
+
5. 조직도 조회의 경우, 조회 대상 회사에 신청 회사 외 타사가 등록되어 있으면 일부 속성만 + 조회 가능합니다.
+
6. 부분이름 검색 시 검색어는 한국어 기준 2자, 영어 기준 4자 이상이어야 + 합니다.
+
7. 부분이름 검색 시 검색 기능 최적화를 위해 1)특정 영문명으로는 조회할 + 수 없습니다.
+
8. 모든 검색어에는 *, % 를 포함할 수 없습니다. 임직원 이름 검색 시 _ 도 포함할 수 + 없습니다.
+
9. 목록으로 검색 시 목록의 값은 중복될 수 없습니다.
+
10. 목록으로 검색 시 목록의 크기는 100을 넘을 수 없으며, 검색어의 길이는 + 100자를 넘을 수 없습니다.
+
11. 임직원 검색 결과는 2,000개, 조직 검색 결과는 5,000개로 제한합니다. +
+
12. 분당 호출 횟수 1,000건 이하로 분산해야 합니다.
+
13. 대량 호출 시 야간(22시 이후) 수행을 권장합니다. (주간 수행 시 Knox + Portal과 협의 필요)
+
 
+
1) kim, lee, park, choi, jung, kang, cho, yoon, + jang, lim, han, shin, oh, seo, kwon, hwang, song, ahn, ryu, hong
   nguy, youn, + young, hyun, sung, sang, jeon, dong, nguye, nguyen, jong, seun, seung, jeong, chan, yong, stre, + stres, stress, nguyễn,
   nguyễn, chang, kyun, kyung, seon, jang, shin, yoon, + yang, song, byun, seong, kwan, hwan, byung, chun, kwang, jaeh, hyung, + hwang,
   wang, sangh, moon, kyou, mari, kuma, kwon, yeon, andr, thi, chen, zhan, + zhang
+
+

+
[API 목록]    테스트 페이지로 이동(Swagger)*Chrome Browser만 이용 가능합니다.
+
+
+ + + + + + + + + + + + + + + +
APIURIMethodDescription
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
임직원 조회/employee/api/v2.0/employeesPOST임직원 정보를 조회한다.
조직도 조회/employee/api/v2.0/organizationsGET부서 정보를 조회한다.
직급정보 조회 + /employee/api/v2.0/titlesGET직급 정보를 조회한다.
+
+



+
+
임직원 조회
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter
Type
Data
Type
Sample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 아이디System-IDYHeaderStringC60REST0001
2회사코드companyCodeNQueryStringC603~10번 속성 + 중 1개의 속성만 사용 가능
3임직원 이름fullNameYQueryString김삼성검색엔진 (검색 + 키워드 완전 일치 검색)
4부서코드departmentCodeQueryStringC60AH959
5사번employeeNumberQueryString123123
6이름nameQueryString삼성검색엔진 (검색 + 키워드 부분일치 검색)
7epIdepIdsQueryStringD100118130308C600299
8IDuserIdsQueryStringknoxportal
9메일주소emailAddressesQueryStringknoxportal@samsung.com
10직급코드titleCodeQueryStringB3KcompCode, page 함께 받아야 + 함
11페이지 번호pageNQueryString1- companyCode&departmentCode /
companyCode&title /
name 인 + 경우에만 paging 적용가능
- page 입력 시 500건씩 + 조회
- page 미입력 시 최대 2000건 조회
12검색결과 타입resultTypeYBodyStringbasic
optional
- basic : 기본 속성 리턴
- optional : + attributes 정의 속성만 리턴
13조회할 임직원 속성attributesNBodyString["emailAddress","userId"] + 지정한 속성에 + 대해서만 결과 값 리턴
resultType이 optional인 경우 + 필수
+
+
+
+

Response Parameter

+
resultType 쿼리 타입에 따라 리턴 항목이 다름.
- basic + : 기본 속성만 리턴 (아래 * 표시된 30개 항목)
- optional : body에 보낸 attributes 데이터만 리턴
+
+
+ + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1API 호출 성공 여부resultStringsuccess
fail
2현재 페이지currentPageint1
3총 결과 페이지 수totalPageint3
4검색된 임직원의 수totalCountint30
5임직원 정보employeesJSON String
6   계정신청상태   accountStatusStringAA: 아이디 승인
W: 아이디 + 신청
M: 아이디 미발급
7   사업장코드   busiCodeStringC60B0001
8   사업장명   busiNameString잠실동관
9   회사코드 *   companyCodeStringC60
10   회사명 *   companyNameString삼성SDS
11   국가   countryStringKR
12   기본소속구분코드   defaultCompanyCodeStringOO: 원소속
S: 파견소속
13   부서코드 *   departmentCodeStringC60AH959
14   부서명 *   departmentNameStringKnox개발그룹(솔루션개발)
15   담당업무 *   descriptionStringKnox Suite + 개발
16   이메일 + 주소 *   emailAddressStringknoxportal@samsung.com
17   사번 *   employeeNumberString123123
18   임직원 + 상태 *   employeeStatusStringBB: 재직
V: 휴직
19   임직원 + 구분   employeeTypeStringNN:정규직 (@samsung.com)
U:협력직 C:자회사 + T:임시직 (@partner.samsung.com)
X:협력직 Y:자회사 Z:임시직 + (@samsung.com)
20   영문 + 사업장명   enBusiNameStringSDS East Campus
21   영문 + 회사명 *   enCompanyNameStringSAMSUNG SDS
22   영문 + 부서명 *   enDepartmentNameStringKnox Development Group
23   영문 + 담당업무 *   enDiscriptionStringKnox Portal User Mgmt.
24   영문 + 성명 *   enFullNameStringSamsung Kim
25   영문 + 이름 *   enGivenNameStringSamsung
26   영문 + 직위명 *   enGradeNameStringManager
27   영문 + 회사주소   enOfficeAddressString123, Olympic-ro 35-gil, Songpa우편번호로 + 구분되는 회사주소
28   영문 + 지역명   enRegionNameStringJamsil
29   영문 파견 + 사업장명   enSendBusiNameStringJamsil
30   영문 파견 + 회사명   enSendCompanyNameStringSamsung Electronics
31   영문 파견 + 부서명   enSendDepartmentNameStringIT Service
32   영문 파견 + 직위명   enSendGradeNameStringLab Leader
33   영문 파견 + 지역명   enSendRegionNameStringSuwon
34   영문 파견 + 총괄명   enSendSubOrgNameString
35   영문 파견 + 직급명   enSendTitleNameStringE5
36   영문 + 성 *   enSirNameStringKim
37   영문 + 총괄명   enSubOrgNameString
38   영문 + 직급명 *   enTitleNameStringSenior Engineer
39   epId *   epIdStringD100118130308C600299
40   임원여부   executiveYnStringNY: 임원
N: 직원
41   외부 + 메일주소   externalEmailAddressStringknoxportal@gmail.com
42   성명 *   fullNameString김삼성
43   이름 *   givenNameString삼성
44   직위명 *   gradeNameString책임
45   직위직급 + 표시코드 *   gradeTitleIndiCodeStringBG: 직위
T: 직급
B: 직위/직급 모두
46   내부 + 부서코드   inDepartmentCodeStringRE_KO41
47   내부 + 부서명   inDepartmentNameStringSamsung Research
48   직무명 *   jobNameStringAEB
49   직무코드   jobCodeStringSystemS/W
50   현채인 + 여부   localStaffYnStringNY: 현채인
N: 현채인 아님
+
51   핸드폰   mobileString+82-10-1111-2222
52   닉네임   nickNameStringnick
53   근무지 + 주소   officeAddressString송파구 올림픽로35길 + 123
54   근무지 상세 + 주소   officeDetailAddressString동관 19층 + 상세 + 회사주소
55   근무지 + 팩스번호   officeFaxNumberString+82-2-2255-1999
56   근무지 + 우편번호   officeZipCodeString138-240
57   근무지 + 전화번호   officeTelNumberString82-70-9999-9999
58   선호언어   preferredLanguageStringko
59   실명 + 여부 *   realNameYnStringRR:실명
V:가명
60   지역코드   regionCodeString
61   지역명   regionNameString
62   보안등급 *   securityLevelString51:회장단(회장,부회장,비서실장)
2:사장단(사장,부사장,전무)
3:임원진(상무,이사,고문,감사)
4:간부(부,차,과장)
5:사원(대리,사원)
9:협력사 + 임직원
63   파견 + 사업장코드   sendBusiCdeString
64   파견 + 회사코드   sendCompanyCodeStringC10
65   파견 + 회사명   sendCompanyNameString삼성전자
66   파견 + 부서코드   sendDepartmentCodeStringC10CB04CB040060
67   파견 + 부서명   sendDepartmentNameStringIT Services
68   파견 + 직위명   sendGradeNameString
69   파견 + 직위직급 표시코드   sendGradeTitleIndiCodeString
70   파견 + 지역코드   sendRegionCodeString
71   파견 + 보안등급   sendSecurityLevelString51:회장단(회장,부회장,비서실장)
2:사장단(사장,부사장,전무)
3:임원진(상무,이사,고문,감사)
4:간부(부,차,과장)
5:사원(대리,사원)
9:협력사 + 임직원
72   파견 + 총괄코드   sendSubOrgCodeString
73   파견 + 총괄명   sendSubOrgNameString
74   파견 + 직급명   sendTitleNameString책임
75   파견 + 직급코드   sendTitleCodeStringE5
76   파견 직급 + 정렬 순서   sendTitleSortOrderString309
77   거점 *   serverLocationStringKRKR: 한국
GB: 구주
US: 미주
78    *   sirNameString
79   총괄코드   subOrgCodeString
80   총괄명   subOrgNameString
81   직급명 *   titleNameString책임
82   직급코드 *   titleCodeStringB2K
83   직급정렬순서 *   titleSortOrderString54
84   고유코드   openCodeString
85   로그인 + 아이디 *   userIdStringknoxportal
86   인터넷 + 전화번호   voipNumberString
87   퇴직/휴직일   withdrawDateString
88   ID + 유효기간   epIdExpiryDateString20201231
89   타임존   timeZoneStringAsia/Seoul이름으로 검색 + 시에는 제공하지 않음
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
(1)
/employees?departmentCode=C60AH959
{"resultType" :"basic"}


(2)
/employees?companyCode=C60&userIds=es.jen.cho,ye.chang
{"resultType" :"optional",
"attributes":["emailAddress","userId"]
}
+
+
+
(1)
* 기본 값으로 설정된 attributes값만 리턴
{"result":"success",
"currentPage":1,
"totalPage":2,
"totalCount":612,
"employees":[
{"fullname":"조은성",
"departmentname":"개발그룹(SC_인트라넷)",
"departmentcode":"C60AH959",...},
{"fullName":"김민정","departmentname".....}]
}


+(2)
* body에 설정된 attributes값만 리턴
{"result":"success",
"currentPage":1,
"totalPage":1,
"totalCount":2,
"employees":[{"emailAddress":"es.jen.cho@stage.samsung.com","userId":"es.jen.cho"},
{"emailAddress":"ye.chang@stage.samsung.com","userId":"ye.chang"}]
}
+
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400EM0001Search request with more than 100 list can not be proceeded.조회건수 100건 초과하여 에러 발생. + Parameter 추가하여 조회 건수 축소
400EM0004Please insert the search keyword.Parameter 누락 확인 +
400EM0005Search keyword length is not valid.Parameter 길이 확인 +
400EM0006Search keyword should be no longer than 100 characters.Parameter 길이 100자 이하로 + 작성
400EM0007Search keyword can not include the caracter.Parameter에 *, % 이 포함되어 + 있는지 확인
500EM0010EPWebservice.{} Abnormal.Parameter 누락 또는 잘못된 + 형식인지 확인
400EM0014Please enter {} as required.{} 필수값 누락
400EM0015Please enter {} according to the specified format.잘못된 형식으로 인한 오류 +
400EM0016Only one of {} can be selected.{} 중 한 개만 선택하여 검색 + 가능
400EM0017For the requested search conditions, paging is not possible.페이징 지원 불가
400EM0018Please remove the {} keyword from the requested search conditions and try + again.요청한 검색조건 중, {} 조건 제거 후 + 다시 시도 바랍니다.
+
+



+
+
조직도 조회
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter
Type
Data
Type
Sample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 아이디System-IDYHeaderStringC60REST0001
2회사코드companyCodeYQueryStringC602번 항목 단독 검색 또는
3~5번 항목 중 하나와 결합하여 + 검색
3상위부서코드uprDepartmentCodeNQueryStringC60AI572companyCode 쿼리와 함께 + 사용
(3~5번 중
한 가지만 선택 가능)
+
4부서코드departmentCodeQueryStringC60AH959companyCode 쿼리와 함께 사용 +
5부서명departmentNameQueryString123123companyCode 쿼리와 함께 사용 +
6페이지 번호pageNQueryString1companyCode로만 조회하는 경우에만
paging + 적용가능
page 입력 시 500건씩 조회
page 입력하지 않을 경우 최대 2,000건 조회

(companyCode로만
검색 시 + 필수)
+
+
+
+

Response Parameter

+
- 조회대상 회사의 조직정보만 리턴
- 조회대상 회사에 신청 회사 외 + 타사 등록 시 일부 속성(아래 * 표시한 11개 항목)만 조회 가능
+
+
+ + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1API 호출 성공 여부resultStringsuccess
fail
2현재 페이지currentPageint1
3총 결과 페이지 수totalPageint3
4검색된 조직정보의 수totalCountint30
5조직 정보 리스트organizationsJSON String
6   회사코드 *   companyCodestringC60
7   회사명 *   companyNamestring삼성SDS
8   부서코드 *   departmentCodestringC60AH959
9   부서레벨   departmentLevelstring3
10   부서명 *   departmentNamestringKnox개발그룹(솔루션개발)
11   부서간 + 순위   departmentOrderstring2
12   영문 + 회사명 *   enCompanyNamestringSAMSUNG SDS
13   영문 + 부서명 *   enDepartmentNamestringKnox Development Group
14   영문 부서장 + 직급   enManagerTitlestringPrincipal Engineer/Group Leader
15   영문 + 총괄명 *   enSubOrgCodestring
16   내부부서 + 코드 *   inDepartmentCodestring
17   하위 + 부서존재 유무   lowDepartmentYnstringTT: 존재함
F: 존재하지 않음
+
18   부서장 + 아이디   managerIdstringkch.jung
19   부서장 + 성명   managerNamestring정기철
20   부서장 + 직급   managerTitlestringPrincipal + Engineer/그룹장(Sr. SCP)
21   표현언어 *   preferredLanguagestringko
22   총괄코드 *   subOrgCodestring
23   총괄명 *   subOrgNamestring
24   상위 + 부서코드   uprDepartmentCodestringC60AJ336
25   영문 상위 + 부서명   enUprDepartmentNamestringSolution Development Team
26   상위 + 부서명   uprDepartmentNamestring솔루션개발팀 +
27   부서 숨김 + 여부   hiddenDepartmentYnstringFT: 비노출
F: 노출
28   법인코드   corpCodestringA001
29   법인명   corpNamestring영국법인
30   영문법인명   enCorpNamestringUK CORP +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/organizations?companyCode=C60&departmentCode=C60AH959
+													
+
+
{
"currentPage":"1",
"totalPage":"1",
"totalCount":"1",
"organizations":[{"companyCode":"C60",
"departmentname":"knox개발그룹",
"enDepartmentName":"Knox Development Group ",
...}]
}
+
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ORG0003Please insert the search keyword.Parameter 확인 +
400ORG0004Search keyword must be larger than 4 bytes.Parameter 길이 4자 이상으로 + 작성
400ORG0005Search keyword should be no longer than 100 characters.Parameter 길이 100자 이내로 + 작성
400ORG0006Search keyword can not include the caracter.Parameter에 *, % 이 포함되어 + 있는지 확인
500ORG0010ORGWebservice. {} Abnormal.Parameter 누락 또는 잘못된 + 형식인지 확인
400ORG0011Please enter {} as required.{} 필수값 누락
400ORG0012Please enter {} according to the specified format.잘못된 형식으로 인한 오류 +
400ORG0013Only one of {} can be selected.{} 중 한 개만 선택하여 검색 + 가능
400ORG0014For the requested search conditions, paging is not possible.페이징 지원 불가
+
+



+
+
직급정보 조회
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 아이디System-IDYHeaderStringC60REST0001
2회사코드companyCodeYQueryStringC60
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1API 호출 성공 여부 + resultStringsuccess
fail
2직급정보 배열titlesJSON String
3   회사코드   companyCodeStringC60
4   직급코드   titleCodeStringB3K
5   직급명   titleNameString책임
6   영문직급명   enTitleNameStringSenior Engineer
7   직급정렬 + 순서   sortOrderString1
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
/titles?companyCode=C60
+														
+
+
{
"result":"success",
"titles":[{"companyCode":"C60",
"titleCode":"J8",
"titleName":"사장",
"enTitleName":"CEO",
"sortOrder":"1"},
{"companyCode":"C60",
"titleCode":"J7",
"titleName":"상무",
"enTitleName":"상무",
"sortOrder":"2"},
...]
}
+
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ORG0003Please insert the search keyword.Parameter 확인 +
400ORG0005Search keyword should be no longer than 100 characters.Parameter 길이 100자 이내로 + 작성
400ORG0006Search keyword can not include the caracter.Parameter에 *, % 이 포함되어 + 있는지 확인
500ORG0010ORGWebservice. {} Abnormal.Parameter 누락 또는 잘못된 + 형식인지 확인
+
+
+
\ No newline at end of file diff --git a/lib/knox-api/employee/employee.ts b/lib/knox-api/employee/employee.ts new file mode 100644 index 00000000..885b5a3f --- /dev/null +++ b/lib/knox-api/employee/employee.ts @@ -0,0 +1,435 @@ +"use server" + +// Knox API 임직원 관련 서버 액션들 + +// 기본 설정 타입 +interface KnoxConfig { + baseUrl: string; + systemId: string; +} + +// 공통 응답 타입 +interface BaseResponse { + result: "success" | "fail"; +} + +// 임직원 조회 관련 타입 +interface EmployeeSearchParams { + companyCode?: string; + fullName?: string; + departmentCode?: string; + employeeNumber?: string; + name?: string; + epIds?: string; + userIds?: string; + emailAddresses?: string; + titleCode?: string; + page?: string; + resultType: "basic" | "optional"; + attributes?: string[]; +} + +interface Employee { + accountStatus?: string; + busiCode?: string; + busiName?: string; + companyCode: string; + companyName: string; + country?: string; + defaultCompanyCode?: string; + departmentCode: string; + departmentName: string; + description?: string; + emailAddress?: string; + employeeNumber?: string; + employeeStatus?: string; + employeeType?: string; + enBusiName?: string; + enCompanyName?: string; + enDepartmentName?: string; + enDiscription?: string; + enFullName?: string; + enGivenName?: string; + enGradeName?: string; + enOfficeAddress?: string; + enRegionName?: string; + enSendBusiName?: string; + enSendCompanyName?: string; + enSendDepartmentName?: string; + enSendGradeName?: string; + enSendRegionName?: string; + enSendSubOrgName?: string; + enSendTitleName?: string; + enSirName?: string; + enSubOrgName?: string; + enTitleName?: string; + epId: string; + executiveYn?: string; + externalEmailAddress?: string; + fullName: string; + givenName?: string; + gradeName?: string; + gradeTitleIndiCode?: string; + inDepartmentCode?: string; + inDepartmentName?: string; + jobName?: string; + jobCode?: string; + localStaffYn?: string; + mobile?: string; + nickName?: string; + officeAddress?: string; + officeDetailAddress?: string; + officeFaxNumber?: string; + officeZipCode?: string; + officeTelNumber?: string; + preferredLanguage?: string; + realNameYn?: string; + regionCode?: string; + regionName?: string; + securityLevel?: string; + sendBusiCde?: string; + sendCompanyCode?: string; + sendCompanyName?: string; + sendDepartmentCode?: string; + sendDepartmentName?: string; + sendGradeName?: string; + sendGradeTitleIndiCode?: string; + sendRegionCode?: string; + sendSecurityLevel?: string; + sendSubOrgCode?: string; + sendSubOrgName?: string; + sendTitleName?: string; + sendTitleCode?: string; + sendTitleSortOrder?: string; + serverLocation?: string; + sirName?: string; + subOrgCode?: string; + subOrgName?: string; + titleName?: string; + titleCode?: string; + titleSortOrder?: string; + openCode?: string; + userId?: string; + voipNumber?: string; + withdrawDate?: string; + epIdExpiryDate?: string; + timeZone?: string; +} + +interface EmployeeResponse extends BaseResponse { + currentPage: number; + totalPage: number; + totalCount: number; + employees: Employee[]; +} + +// 조직도 조회 관련 타입 +interface OrganizationSearchParams { + companyCode: string; + uprDepartmentCode?: string; + departmentCode?: string; + departmentName?: string; + page?: string; +} + +interface Organization { + companyCode: string; + companyName: string; + departmentCode: string; + departmentLevel?: string; + departmentName: string; + departmentOrder?: string; + enCompanyName?: string; + enDepartmentName?: string; + enManagerTitle?: string; + enSubOrgCode?: string; + inDepartmentCode?: string; + lowDepartmentYn?: string; + managerId?: string; + managerName?: string; + managerTitle?: string; + preferredLanguage?: string; + subOrgCode?: string; + subOrgName?: string; + uprDepartmentCode?: string; + enUprDepartmentName?: string; + uprDepartmentName?: string; + hiddenDepartmentYn?: string; + corpCode?: string; + corpName?: string; + enCorpName?: string; +} + +interface OrganizationResponse extends BaseResponse { + currentPage: number; + totalPage: number; + totalCount: number; + organizations: Organization[]; +} + +// 직급정보 조회 관련 타입 +interface TitleSearchParams { + companyCode: string; +} + +interface Title { + companyCode: string; + titleCode: string; + titleName: string; + enTitleName: string; + sortOrder: string; +} + +interface TitleResponse extends BaseResponse { + titles: Title[]; +} + +// 설정 가져오기 (환경변수 또는 설정에서) +const getKnoxConfig = (): KnoxConfig => { + return { + baseUrl: process.env.KNOX_API_BASE_URL || "https://api.knox.samsung.com", + systemId: process.env.KNOX_SYSTEM_ID || "C60REST0001" + }; +}; + +// 공통 헤더 생성 +const createHeaders = (systemId: string): Record => { + return { + "Content-Type": "application/json", + "System-ID": systemId + }; +}; + +/** + * 임직원 조회 API + * POST /employee/api/v2.0/employees + */ +export async function searchEmployees(params: EmployeeSearchParams): Promise { + const config = getKnoxConfig(); + + try { + // URL 파라미터 구성 + const searchParams = new URLSearchParams(); + + if (params.companyCode) searchParams.append("companyCode", params.companyCode); + if (params.fullName) searchParams.append("fullName", params.fullName); + if (params.departmentCode) searchParams.append("departmentCode", params.departmentCode); + if (params.employeeNumber) searchParams.append("employeeNumber", params.employeeNumber); + if (params.name) searchParams.append("name", params.name); + if (params.epIds) searchParams.append("epIds", params.epIds); + if (params.userIds) searchParams.append("userIds", params.userIds); + if (params.emailAddresses) searchParams.append("emailAddresses", params.emailAddresses); + if (params.titleCode) searchParams.append("titleCode", params.titleCode); + if (params.page) searchParams.append("page", params.page); + + // Body 데이터 구성 + const body = { + resultType: params.resultType, + ...(params.attributes && { attributes: params.attributes }) + }; + + const response = await fetch( + `${config.baseUrl}/employee/api/v2.0/employees?${searchParams.toString()}`, + { + method: "POST", + headers: createHeaders(config.systemId), + body: JSON.stringify(body) + } + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data as EmployeeResponse; + } catch (error) { + console.error("임직원 조회 오류:", error); + throw error; + } +} + +/** + * 조직도 조회 API + * GET /employee/api/v2.0/organizations + */ +export async function searchOrganizations(params: OrganizationSearchParams): Promise { + const config = getKnoxConfig(); + + try { + // URL 파라미터 구성 + const searchParams = new URLSearchParams(); + searchParams.append("companyCode", params.companyCode); + + if (params.uprDepartmentCode) searchParams.append("uprDepartmentCode", params.uprDepartmentCode); + if (params.departmentCode) searchParams.append("departmentCode", params.departmentCode); + if (params.departmentName) searchParams.append("departmentName", params.departmentName); + if (params.page) searchParams.append("page", params.page); + + const response = await fetch( + `${config.baseUrl}/employee/api/v2.0/organizations?${searchParams.toString()}`, + { + method: "GET", + headers: createHeaders(config.systemId) + } + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data as OrganizationResponse; + } catch (error) { + console.error("조직도 조회 오류:", error); + throw error; + } +} + +/** + * 직급정보 조회 API + * GET /employee/api/v2.0/titles + */ +export async function searchTitles(params: TitleSearchParams): Promise { + const config = getKnoxConfig(); + + try { + // URL 파라미터 구성 + const searchParams = new URLSearchParams(); + searchParams.append("companyCode", params.companyCode); + + const response = await fetch( + `${config.baseUrl}/employee/api/v2.0/titles?${searchParams.toString()}`, + { + method: "GET", + headers: createHeaders(config.systemId) + } + ); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + const data = await response.json(); + return data as TitleResponse; + } catch (error) { + console.error("직급정보 조회 오류:", error); + throw error; + } +} + +/** + * 편의 함수들 + */ + +/** + * 사번으로 임직원 조회 + */ +export async function getEmployeeByNumber(employeeNumber: string, companyCode?: string): Promise { + try { + const response = await searchEmployees({ + employeeNumber, + companyCode, + resultType: "basic" + }); + + if (response.result === "success" && response.employees.length > 0) { + return response.employees[0]; + } + return null; + } catch (error) { + console.error("사번으로 임직원 조회 오류:", error); + return null; + } +} + +/** + * 이메일로 임직원 조회 + */ +export async function getEmployeeByEmail(emailAddress: string, companyCode?: string): Promise { + try { + const response = await searchEmployees({ + emailAddresses: emailAddress, + companyCode, + resultType: "basic" + }); + + if (response.result === "success" && response.employees.length > 0) { + return response.employees[0]; + } + return null; + } catch (error) { + console.error("이메일로 임직원 조회 오류:", error); + return null; + } +} + +/** + * 부서 코드로 임직원 목록 조회 + */ +export async function getEmployeesByDepartment(departmentCode: string, page?: string): Promise { + try { + const response = await searchEmployees({ + departmentCode, + page, + resultType: "basic" + }); + + if (response.result === "success") { + return response.employees; + } + return []; + } catch (error) { + console.error("부서별 임직원 조회 오류:", error); + return []; + } +} + +/** + * 회사의 모든 부서 조회 + */ +export async function getDepartmentsByCompany(companyCode: string): Promise { + try { + const response = await searchOrganizations({ + companyCode + }); + + if (response.result === "success") { + return response.organizations; + } + return []; + } catch (error) { + console.error("회사별 부서 조회 오류:", error); + return []; + } +} + +/** + * 회사의 모든 직급 조회 + */ +export async function getTitlesByCompany(companyCode: string): Promise { + try { + const response = await searchTitles({ companyCode }); + + if (response.result === "success") { + return response.titles; + } + return []; + } catch (error) { + console.error("회사별 직급 조회 오류:", error); + return []; + } +} + +// 타입 export +export type { + EmployeeSearchParams, + Employee, + EmployeeResponse, + OrganizationSearchParams, + Organization, + OrganizationResponse, + TitleSearchParams, + Title, + TitleResponse +}; diff --git a/lib/knox-api/index.ts b/lib/knox-api/index.ts new file mode 100644 index 00000000..e1ef3d51 --- /dev/null +++ b/lib/knox-api/index.ts @@ -0,0 +1,6 @@ +export * from './approval/approval'; +export * from './employee/employee'; +export * from './mail/knox-mail'; +export * from './messenger/messenger'; +export * from './realtime-notification/realtime-notification'; + diff --git a/lib/knox-api/mail/knox-mail.ts b/lib/knox-api/mail/knox-mail.ts new file mode 100644 index 00000000..48ba6c16 --- /dev/null +++ b/lib/knox-api/mail/knox-mail.ts @@ -0,0 +1,312 @@ +'use server'; + +// Knox Mail API TypeScript Library for Next.js Server Actions +// Based on Knox Mail API Guide v2.0 + +export interface KnoxMailConfig { + baseUrl: string; + systemId: string; + userId: string; +} + +// 공통 타입 정의 +export interface KnoxMailResponse { + result: 'success' | 'error'; + mailId?: string; + data?: T; + error?: { + code: string; + message: string; + }; +} + +// 발신인 정보 +export interface Sender { + emailAddress: string; +} + +// 수신인 정보 +export interface Recipient { + emailAddress: string; + recipientType: 'TO' | 'CC' | 'BCC'; +} + +// 일반 메일 발신 요청 +export interface SendMailRequest { + subject: string; + contents: string; + contentType: 'TEXT' | 'HTML' | 'MIME'; + docSecuType: 'PERSONAL' | 'OFFICIAL'; + sender: Sender; + recipients: Recipient[]; + attachments?: File[]; + reservedTime?: string; // yyyy-MM-dd HH:mm 형식 +} + +// 대외비 메일 DRM 옵션 +export interface DrmOption { + validDays: string; + useCount: string; + canView: string; + canPrint: string; + notifyExternalUser: string; + notifyInternalUser: string; +} + +// 대외비 메일 발신 요청 +export interface SendSecuMailRequest extends Omit { + docSecuType: 'CONFIDENTIAL' | 'CONFIDENTIAL_STRICT'; + drmOption: DrmOption; +} + +// 메일 발신 취소 요청 +export interface CancelMailRequest { + recipients: string[]; +} + +// 메일 별 수신상태 조회 요청 +export interface DeliveryStatusCountRequest { + mailIds: string[]; +} + +// 수신상태 카운트 응답 +export interface DeliveryStatusCount { + mailId: string; + totalStatusCount: number; + sendingCount: number; + openCount: number; + unopenCount: number; + etcCount: number; + sendCancelCount: number; + sendCancelReqCount: number; + sendBlockCount: number; + sendFailCount: number; + drmProcessCount: number; + drmFailCount: number; + reserveCount: number; + reserveCancelCount: number; + unknownCount: number; +} + +// 수신인 별 수신상태 응답 +export interface RecipientDeliveryStatus { + name: string; + position: string; + enName: string; + enPosition: string; + company: string; + department: string; + enDepartment: string; + email: string; + userID: string; + recipientType: 'TO' | 'CC' | 'BCC'; + updateTime: { + month: number; + year: number; + dayOfMonth: number; + hourOfDay: number; + minute: number; + second: number; + }; + status: string; + needOpenNotify: boolean; + isDLAddr: boolean; +} + +// 내부 유틸리티 함수들 +function getHeaders(systemId: string): Record { + return { + 'System-ID': systemId, + 'Content-Type': 'application/json', + }; +} + +async function makeRequest( + config: KnoxMailConfig, + endpoint: string, + method: 'GET' | 'POST', + data?: unknown, + isMultipart = false +): Promise> { + const url = `${config.baseUrl}${endpoint}?userId=${config.userId}`; + + const headers = getHeaders(config.systemId); + if (isMultipart) { + delete headers['Content-Type']; // multipart/form-data는 브라우저가 자동으로 설정 + } + + try { + const response = await fetch(url, { + method, + headers, + body: data ? (isMultipart ? data as FormData : JSON.stringify(data)) : undefined, + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + return { + result: 'error', + error: { + code: response.status.toString(), + message: errorData.message || response.statusText, + }, + }; + } + + const result = await response.json(); + return { + result: 'success', + ...result, + }; + } catch (error) { + return { + result: 'error', + error: { + code: 'NETWORK_ERROR', + message: error instanceof Error ? error.message : 'Unknown error', + }, + }; + } +} + +function createFormData(mailData: Record, attachments?: File[]): FormData { + const formData = new FormData(); + + // 메일 데이터를 JSON으로 추가 + formData.append('mail', JSON.stringify(mailData)); + + // 첨부파일이 있으면 추가 + if (attachments && attachments.length > 0) { + attachments.forEach(file => { + formData.append('attachments', file); + }); + } + + return formData; +} + +// Next.js 서버 액션 함수들 + +/** + * 일반 메일 발신 서버 액션 + * @param config Knox Mail API 설정 + * @param request 메일 발신 요청 데이터 + * @returns 발신 결과 (mailId 포함) + */ +export async function sendMail( + config: KnoxMailConfig, + request: SendMailRequest +): Promise> { + const { attachments, ...mailData } = request; + + if (attachments && attachments.length > 0) { + const formData = createFormData(mailData, attachments); + return makeRequest<{ mailId: string }>(config, '/mail/api/v2.0/mails/send', 'POST', formData, true); + } else { + return makeRequest<{ mailId: string }>(config, '/mail/api/v2.0/mails/send', 'POST', mailData); + } +} + +/** + * 대외비 메일 발신 서버 액션 + * @param config Knox Mail API 설정 + * @param request 대외비 메일 발신 요청 데이터 + * @returns 발신 결과 (mailId 포함) + */ +export async function sendSecuMail( + config: KnoxMailConfig, + request: SendSecuMailRequest +): Promise> { + const { attachments, ...mailData } = request; + + if (attachments && attachments.length > 0) { + const formData = createFormData(mailData, attachments); + return makeRequest<{ mailId: string }>(config, '/mail/api/v2.0/mails/secu-send', 'POST', formData, true); + } else { + return makeRequest<{ mailId: string }>(config, '/mail/api/v2.0/mails/secu-send', 'POST', mailData); + } +} + +/** + * 메일 발신 취소 서버 액션 + * @param config Knox Mail API 설정 + * @param mailId 취소할 메일 ID + * @param request 취소 요청 데이터 (수신인 목록) + * @returns 취소 결과 + */ +export async function cancelMail( + config: KnoxMailConfig, + mailId: string, + request: CancelMailRequest +): Promise { + return makeRequest(config, `/mail/api/v2.0/mails/${mailId}/cancel`, 'POST', request); +} + +/** + * 메일 별 수신상태 조회 서버 액션 + * @param config Knox Mail API 설정 + * @param request 조회할 메일 ID 목록 + * @returns 메일별 수신상태 카운트 목록 + */ +export async function getDeliveryStatusCount( + config: KnoxMailConfig, + request: DeliveryStatusCountRequest +): Promise> { + return makeRequest(config, '/mail/api/v2.0/mails/deliverystatus/count', 'POST', request); +} + +/** + * 수신인 별 수신상태 조회 서버 액션 + * @param config Knox Mail API 설정 + * @param mailId 조회할 메일 ID + * @returns 수신인별 수신상태 목록 + */ +export async function getRecipientDeliveryStatus( + config: KnoxMailConfig, + mailId: string +): Promise> { + return makeRequest(config, `/mail/api/v2.0/mails/${mailId}/deliverystatus`, 'GET'); +} + +// 편의 함수들 +export async function createKnoxMailConfig( + baseUrl: string, + systemId: string, + userId: string +): Promise { + return { + baseUrl, + systemId, + userId, + }; +} + +// 에러 코드 상수 +export const KNOX_MAIL_ERROR_CODES = { + ML1001: '필수값 중 입력되지 않은 값이 있습니다.', + ML1002: '사용자 정보가 존재하지 않습니다.', + ML1003: '요청하신 데이터가 존재하지 않습니다.', + ML1101: '본문 (content) 값이 입력되지 않았습니다.', + ML1102: '첨부 파일 처리 중 에러가 발생했습니다.', + ML1104: '일반 메일 발신 중 docSecuType 값이 유효하지 않습니다.', + ML1107: '대외비/극비 보안 옵션 값이 유효하지 않습니다.', + ML1108: '대외비/극비 메일 contentType 값이 유효하지 않습니다.', + ML1109: '대외비/극비 메일 docSecuType 값이 유효하지 않습니다.', + ML1110: '극비 메일일 경우에는 내부 수신인에게만 메일 발신이 가능합니다.', + ML1111: '대외비/극비 메일에서 허용되지 않는 첨부 파일의 확장자가 있습니다.', + ML1112: '메일 제목 크기가 300 bytes를 초과하였습니다.', + ML1114: '메일 발신 API에서 허용되는 content 크기를 초과하였습니다.', + ML1115: '일반 메일 contentType 값이 유효하지 않습니다.', + ML1117: '메일 발신 API에서 발신가능한 최대 수신인을 초과하였습니다.', + ML1118: '수신자의 수신 타입이 잘못 설정되었습니다.', + CO400: '잘못된 요청입니다.', +} as const; + +// 타입 가드 함수들 +export function isKnoxMailError(response: KnoxMailResponse): response is KnoxMailResponse & { error: { code: string; message: string } } { + return response.result === 'error' && !!response.error; +} + +export function isKnoxMailSuccess(response: KnoxMailResponse): response is KnoxMailResponse & { result: 'success' } { + return response.result === 'success'; +} diff --git a/lib/knox-api/mail/mail-guide.html b/lib/knox-api/mail/mail-guide.html new file mode 100644 index 00000000..5e38d3a7 --- /dev/null +++ b/lib/knox-api/mail/mail-guide.html @@ -0,0 +1,2114 @@ +
+
+

메일

+
+
+

메일 연계 API 이용을 위한 상세 개발 가이드입니다.
메일 API는 메일 발신, 발신 취소, 상태 조회 세 가지 유형으로 나누어져 있습니다.

+
+
[정책 및 제약사항]
+
+
+
1. 발신인 정보는 녹스포탈 임직원만 지정 가능하며, 발신자의 거점으로 연계 호출해야 + 합니다.
+
2. 본문 사이즈는 최대 1MB 를 넘을 수 없습니다.
+
3. 한번에 10개의 첨부파일을 포함하여 발송할 수 있으며, 전체 첨부 사이즈는 10MB 를 넘을 + 수 없습니다.
+
4. 수신인은 최대 200명까지 지정이 가능합니다.
+
+
+
[API 목록]    테스트 페이지로 이동(Swagger)*Chrome Browser만 이용 가능합니다.
+
+
+ + + + + + + + + + + + + + + +
APIURIMethodDescription
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
일반 메일 + 발신/mail/api/v2.0/mails/send?userId=Knox아이디 + POSTKnox 메일을 + 발신한다.
대외비 + 메일 발신/mail/api/v2.0/mails/secu-send?userId=Knox아이디 + POSTKnox 대외비 메일을 + 발신한다.
메일 발신 + 취소/mail/api/v2.0/mails/{mailId}/cancel?userId=Knox아이디 + POSTKnox 내부로 발신한 메일을 + 발신 취소한다.
메일 별 수신상태 조회 + /mail/api/v2.0/mails/deliverystatus/count?userId=Knox아이디 + POST해당하는 + 메일에 대해서 전체 수신 상태를 조회한다.
수신인 별 수신상태 조회/mail/api/v2.0/mails/{mailId}/deliverystatus?userId=Knox아이디 + GET해당하는 메일에 + 대해서 수신인 별 수신 상태를 조회한다.
+
+

+
+
일반 메일 발신 +
+
+

/mail/api/v2.0/mails/send?userId=Knox아이디

+
+
+

삼성 그룹사 임직원 뿐만 아니라 외부수신인을 포함하여 메일 발신이 가능하며, 발신된 메일을 발신함에 + 저장됩니다.

+

주 1. 발신자의 메일>환경설정> 발신메일저장옵션에 따라 다를 수 있습니다.

+

주 2. Multipart/form-data 구성시 아래 Sample Request 와 같이 각 파트를 + 구분하여 form-data 의 name 값을 ‘mail’ , ‘attachments’ 로 호출해야 합니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + 아이디System-IDYHeaderStringC60LD0001 +
2유저 아이디 + userId + YQueryStringknoxportal +
3메일 제목 + subject + YBodyString메일 제목입니다. +
4문서 + 타입docSecuTypeYBodyStringPERSONAL + 1) PERSONAL : 개인
2) OFFICIAL : + 공문
5메일 본문 + contents + YBodyString안녕하세요, 테스트 + 메일입니다.
6컨텐츠 + 타입contentTypeYBodyStringTEXT + 1) TEXT : 텍스트
2) MIME : + 마임
3) HTML : HTML
7발신인sender + YBodyJSON Object
8발신인 + 이메일emailAddressYBodyStringknoxportal@samsung.com + 1) 운영 환경 : knoxportal@samsung.com
2) 스테이지 환경 : knoxportal@stage.samsung.com
9수신인 + recipientsYBodyJSON List
10수신인 + 이메일emailAddress + YBodyStringknoxportal@samsung.com + 1) 운영 환경 : knoxportal@samsung.com
2) 스테이지 환경 : knoxportal@stage.samsung.com
11수신 + 타입recipientTypeYBodyStringTO + 1) 수신 : TO
2) 참조 : + CC
3) 비밀참조 : BCC
12첨부 + 파일attachmentsNBodymultipart/form-data + multipart/form-data로 변환된 바이너리 + 파일 및 파일명
13예약 + 발신reservedTimeNBodyStringyyyy-MM-dd HH:mm
ex)"2023-10-25 + 15:00"
10분 단위 설정 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 성공 + 여부result + Stringsuccess
메일 아이디 + mailId + String20190409043651epcms1s110a09b3ca1b6c8d754ee1c28a182d8d5 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
/mail/api/v2.0/mails/send?userId=knoxportal
body :

Content-Disposition: form-data; name="mail"
{
   "subject" : + "EMAIL SUBJECT (이메일 제목)",
   "contents" : "EMAIL BODY (이메일 + 본문)",
   "contentType" : + "TEXT",
   "docSecuType" : + "PERSONAL",
   "sender" + :
      {
         "emailAddress" + : "knoxportal@samsung.com"
      },
   "recipients" :
      [
         {
            "emailAddress" + : "knoxportal@samsung.com",
            "recipientType" + : "TO"
         }
      ]
}
Content-Disposition: form-data; + name="attachments"; filename="db변경.JPG"
Content-Type: image/jpeg
Content-Disposition: form-data; name="attachments"; filename="2 - + 복사본 (2).jpg"
Content-Type: + image/jpeg
{
   "mailId": + "20190531015540hdp_101d2782e07bbad98034606076da1e299b05",
   "result": "success"
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ML1001필수값 중 입력되지 않은 값이 있습니다. + 모든 필수값이 + 입력되었는지 확인이 필요합니다. 또, 에러 메시지에 null인 parameter 명이 리턴된다면, 해당 값을 우선적으로 확인해야 합니다.
400ML1002사용자 정보가 존재하지 않습니다.호출 시 입력하는 + URI 상의 Knox Id, 혹은 메일 발신자 knox 이메일 addresss가 정상적인지 확인이 필요합니다.
400ML1104일반 메일 발신 중 docSecuType 값이 유효하지 + 않습니다.일반 메일의 + docSecuType은 PERSONAL(개인), OFFICIAL(공문) 두 값만 허용됩니다.
400ML1112메일 제목 크기가 300 bytes를 + 초과하였습니다.제목의 사이즈 확인이 + 필요합니다.
400ML1114메일 발신 API에서 허용되는 content 크기를 + 초과하였습니다.발신 API에서 본문 + 사이즈는 최대 1mb까지 입력이 가능합니다. 해당 크기를 초과하는 내용에 대해서는 가급적 첨부 파일 등을 이용 부탁드립니다.
400ML1115일반 메일 contentType 값이 유효하지 + 않습니다일반 메일의 + contentType 값은 HTML, MIME, TEXT 세 개의 값만 허용됩니다.
400ML1117메일 발신 API에서 발신가능한 최대 수신인을 + 초과하였습니다.입력 가능한 최대 + 수신인 수는 100명입니다.
400ML1118수신자의 수신 타입이 잘못 설정되었습니다. + 수신 타입은 + TO(수신), CC(참조), BCC(비밀참조) 세 개의 값만 허용됩니다.
403ML1102첨부 파일 처리 중 에러가 발생했습니다. + 첨부 파일의 + Multipart/form-data 형식 확인이 필요합니다.
400CO400잘못된 요청입니다.요청 파라미터를 + 확인해주세요. 특히 userId, docSecuType 이 누락되었는지 확인해주세요.
+
+

+
+
대외비 메일 + 발신
+
+

/mail/api/v2.0/mails/secu-send?userId=Knox아이디

+
+
+

대외비, 극비로 설정하여 보안 메일을 발송할 수 있습니다.
보안 메일 옵션을 설정할 수 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + 아이디System-IDYHeaderStringC60LD0001 +
2유저 아이디 + userId + YQueryStringknoxportal +
3메일 제목 + subject + YBodyString메일 제목입니다. +
4문서 + 타입docSecuTypeYBodyStringPERSONAL + 1) PERSONAL : 개인
2) OFFICIAL : + 공문
5메일 본문 + contents + YBodyString안녕하세요, 테스트 + 메일입니다.
6컨텐츠 + 타입contentTypeYBodyStringTEXT1) TEXT : 텍스트
2) MIME : + 마임
3) HTML : HTML
7발신인sender + YBodyJSON Object
8발신인 + 이메일emailAddressYBodyStringknoxportal@samsung.com + 1) 운영 환경 : knoxportal@samsung.com
2) 스테이지 환경 : knoxportal@stage.samsung.com
9수신인 + recipientsYBodyJSON List
10수신인 + 이메일emailAddress + YBodyStringknoxportal@samsung.com + 1) 운영 환경 : knoxportal@samsung.com
2) 스테이지 환경 : knoxportal@stage.samsung.com
11수신 + 타입recipientTypeYBodyStringTO + 1) 수신 : TO
2) 참조 : + CC
3) 비밀참조 : BCC
12첨부 + 파일attachmentsNBodymultipart/form-data + multipart/form-data로 변환된 바이너리 + 파일 및 파일명
13대외비 옵션 + drmOptionYJSON ObjectString
14대외비 메일 조회 가능 + 일 수validDaysYBodyString3
15대외비 개봉 가능 + 횟수useCount + YBodyString3
16대외비 수신인 조회 가능 + 여부canView + YBodyString0
17대외비 인쇄 가능 + 여부canPrint + YBodyString0
18대외비 + 외부 수신인의 개봉 알림 여부notifyExternalUser + YBodyString0 + +
19대외비 + 내부 수신인의 개봉 알림 여부notifyInternalUser + YBodyString0 + +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 성공 + 여부result + Stringsuccess
mailId + 메일 아이디 + String20190409043651epcms1s110a09b3ca1b6c8d754ee1c28a182d8d5 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
/mail/api/v2.0/mails/send?userId=knoxportal
body :

Content-Disposition: form-data; name="mail"
{
   "subject" : + "EMAIL SUBJECT (이메일 제목)",
   "contents" : "EMAIL BODY (이메일 + 본문)",
   "contentType" : + "TEXT",
   "docSecuType" : + "PERSONAL",
   "sender" + :
      {
         "emailAddress" + : "knoxportal@samsung.com"
      },
   "recipients" :
      [
         {
            "emailAddress" + : "knoxportal@samsung.com",
            "recipientType" + : "TO"
         }
      ],
   "drmOption" :
      {
         "validDays":"3",
         "useCount":"3",
         "canView":"0",
         "canPrint":"0",
         "notifyExternalUser":"0",
         "notifyInternalUser":"0"
      }
}
Content-Disposition: form-data; + name="attachments"; filename="db변경.JPG"
Content-Type: image/jpeg
Content-Disposition: form-data; name="attachments"; filename="2 - + 복사본 (2).jpg"
Content-Type: + image/jpeg
{
   "mailId": + "20190531015540hdp_101d2782e07bbad98034606076da1e299b05",
   "result": "success"
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ML1001필수값 중 입력되지 않은 값이 있습니다. + 모든 필수값이 + 입력되었는지 확인이 필요합니다. 또, 에러 메시지에 null인 parameter 명이 리턴된다면, 해당 값을 우선적으로 확인해야 합니다.
400ML1002사용자 정보가 존재하지 않습니다.호출 시 입력하는 + URI 상의 Knox Id, 혹은 메일 발신자 knox 이메일 addresss가 정상적인지 확인이 필요합니다.
400ML1101본문 (content) 값이 입력되지 + 않았습니다.메일 발신 관련 + API에서 본문 (content) 값이 정상적으로 입력되었는지 확인이 필요합니다.
400ML1107대외비/극비 보안 옵션 값이 유효하지 않습니다. 옵션 + 값을 확인해주세요.대외비/극비의 보안 + 옵션 설정 유효 값을 가이드를 통해 확인 후 입력이 필요합니다.
400ML1108대외비/극비 메일 contentType 값이 유효하지 + 않습니다.대외비/극비 메일에서 + contentType은 HTML과 TEXT 타입만 허용됩니다.
400ML1109대외비/극비 메일 docSecuType 값이 유효하지 + 않습니다.대외비/극비 메일의 + docSecuType은 CONFIDENTIAL(대외비), CONFIDENTIAL_STRICT(극비) 두 값만 허용됩니다.
400ML1110극비 메일일 경우에는 내부 수신인에게만 메일 발신이 + 가능합니다.외부 수신인 혹은 + 유효하지 않은 Knox 이메일 계정이 수신인에 포함되지 않았는지 확인이 필요합니다.
400ML1111대외비/극비 메일에서 허용되지 않는 첨부 파일의 + 확장자가 있습니다.txt, doc, + ppt, xls, pdf, jpg, jpeg, gif, bmp, docx, pptx, xlsx, mht, gul 확장자만 허용됩니다.
400ML1112메일 제목 크기가 300 bytes를 + 초과하였습니다.제목의 사이즈 확인이 + 필요합니다.
400ML1114메일 발신 API에서 허용되는 content 크기를 + 초과하였습니다.발신 API에서 본문 + 사이즈는 최대 1mb까지 입력이 가능합니다. 해당 크기를 초과하는 내용에 대해서는 가급적 첨부 파일 등을 이용 부탁드립니다.
400ML1117메일 발신 API에서 발신가능한 최대 수신인을 + 초과하였습니다.입력 가능한 최대 + 수신인 수는 100명입니다.
400ML1118수신자의 수신 타입이 잘못 설정되었습니다. + 수신 타입은 + TO(수신), CC(참조), BCC(비밀참조) 세 개의 값만 허용됩니다.
403ML1102첨부 파일 처리 중 에러가 발생했습니다. + 첨부 파일의 + Multipart/form-data 형식 확인이 필요합니다.
+
+

+
+
메일 발신 취소 +
+
+

/mail/api/v2.0/mails/{mailId}/cancel?userId=Knox아이디 +

+
+
+

Knox 사용자가 발신한 메일을, 수신자의 수신 메일함에서 삭제하는 + 기능입니다.
(주) Knox 외부로 보낸 메일에 대해서는 발신 취소가 + 불가능합니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + 아이디System-IDYHeaderStringC60LD0001 +
2메일 아이디 + {mailId} + YPathString20190623111845epcms1v2dd0e6bfd951d8f03bd75cd90afacdf8a + 발신된 모든 메일은 메일아이디라는 고유값을 가지며, 메일 발신이 성공하면 메일아이디를 전달받습니다. +
전달받은 메일아이디를 활용하여 발신취소 또는 수신상황 조회를 할 수 + 있습니다.
3유저 아이디 + userId + YQueryStringknoxportal +
4수신인 + recipientsYBodyString
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + +
API 호출 성공 + 여부result + Stringsuccess
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
/mail/api/v2.0/mails/20190623111845epcms1v2dd0e6bfd951d8f03bd75cd90afacdf8a/cancel?userId=knoxportal
Content-Type : application/json;
body :
{
   "recipients" : + ["sample.id@samsung.com","knoxportal@samsung.com"]
}
{
   "result": + "success"
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ML1001필수값 중 입력되지 않은 값이 있습니다. + 모든 필수값이 입력되었는지 확인이 필요합니다. 또, + 에러 메시지에 null인 parameter 명이 리턴된다면, 해당 값을 우선적으로 확인해야 합니다.
400ML1002사용자 정보가 존재하지 않습니다.호출 시 입력하는 URI 상의 Knox Id, 혹은 + 메일 발신자 knox 이메일 addresss가 정상적인지 확인이 필요합니다.
404ML1003요청하신 데이터가 존재하지 않습니다. + 호출 시 입력한 MailId에 해당되는 메일 데이터가 + 존재하지 않습니다. 발신취소 및 상태조회 하고자 하는 발신자/수신자 정보 확인이 필요합니다.
+
+

+
+
메일 + 별 수신상태 조회
+
+

/mail/api/v2.0/mails/deliverystatus/count?userId=Knox아이디 +

+
+
+

전달받은 메일 ID 리스트에 대해서, 각각의 전체적인 수신상태를 조회할 수 + 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + 아이디System-IDYHeaderStringC60LD0001 +
2유저 아이디 + userId + YQueryStringknoxportal +
3메일 아이디 + 리스트mailIds + YBodyString20190623111845epcms1v2dd0e6bfd951d8f03bd75cd90afacdf8a +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
메일 아이디 + mailId + String20190409043651epcms1s110a09b3ca1b6c8d754ee1c28a182d8d5 +
전체 + 카운트totalStatusCount + int8 + +
배달중sendingCountint0
개봉 + openCountint1
미개봉 + unopenCountint7
기타 + etcCountint0
발신취소sendCancelCount + int0 +
발신취소 요청중 + sendCancelReqCount + int0 +
발신차단sendBlockCount + int0 +
발신실패sendFailCount + int0 +
대외비 + 변환중drmProcessCount + int0 +
대외비 변환 + 실패drmFailCountint0
예약 + reserveCountint0
예약 + 취소reserveCancelCount + int0 +
알수없음unknownCountint0
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ML1001필수값 중 입력되지 않은 값이 있습니다. + 모든 필수값이 입력되었는지 확인이 필요합니다. 또, + 에러 메시지에 null인 parameter 명이 리턴된다면, 해당 값을 우선적으로 확인해야 합니다.
400ML1002사용자 정보가 존재하지 않습니다.호출 시 입력하는 URI 상의 Knox Id, 혹은 + 메일 발신자 knox 이메일 addresss가 정상적인지 확인이 필요합니다.
404ML1003요청하신 데이터가 존재하지 않습니다. + 호출 시 입력한 MailId에 해당되는 메일 데이터가 + 존재하지 않습니다. 발신취소 및 상태조회 하고자 하는 발신자/수신자 정보 확인이 필요합니다.
+
+

+
+
수신인 별 + 수신상태 조회
+
+

/mail/api/v2.0/mails/{mailId}/deliverystatus?userId=Knox아이디 +

+
+
+

전달받은 메일 ID에 대해서, 해당 메일의 수신인 별 수신 상태를 조회할 수 + 있습니다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 + 아이디System-IDYHeaderStringC60LD0001 +
2메일 아이디 + {mailId} + YPathString20190623111845epcms1v2dd0e6bfd951d8f03bd75cd90afacdf8a + 발신된 모든 메일은 메일아이디라는 고유값을 가지며, 메일 발신이 성공하면 메일아이디를 전달받습니다. +
전달받은 메일아이디를 활용하여 발신취소 또는 수신상황 조회를 할 수 + 있습니다.
3유저 아이디 + userId + YQueryStringknoxportal +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
이름nameStringKnoxPortal +
직급 + positionStringSenior + Engineer
영문 성명 + enName + StringKnoxPortal + ServiceDesk
영문 + 직급enPositionStringSenior + Engineer
회사명 + company + String삼성SDS
부서명 + departmentString사업그룹(Knox + Portal)
영문 + 부서명enDepartmentStringBusiness + Group
이메일 주소 + emailStringknoxportal@samsung.com
유저 ID + userID + Stringknoxportal +
수신타입recipientType + StringTO +
수신상태가 업데이트된 + 시간updateTimeCalendar{"month":6,"year":2019,"dayOfMonth":7,"hourOfDay":5,"minute":48,"second":16} +
개봉상태 + status + StringUNOPEN
수신자가 메일 + 개봉시 발신자에게 알림 여부needOpenNotify + booleanfalse
DL 메일주소 + 여부값isDLAddrbooleanfalse
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
400ML1001필수값 중 입력되지 않은 값이 있습니다. + 모든 필수값이 입력되었는지 확인이 필요합니다. 또, + 에러 메시지에 null인 parameter 명이 리턴된다면, 해당 값을 우선적으로 확인해야 합니다.
400ML1002사용자 정보가 존재하지 않습니다.호출 시 입력하는 URI 상의 Knox Id, 혹은 + 메일 발신자 knox 이메일 addresss가 정상적인지 확인이 필요합니다.
404ML1003요청하신 데이터가 존재하지 않습니다. + 호출 시 입력한 MailId에 해당되는 메일 데이터가 + 존재하지 않습니다. 발신취소 및 상태조회 하고자 하는 발신자/수신자 정보 확인이 필요합니다.
+
+
+
\ No newline at end of file diff --git a/lib/knox-api/messenger/messenger-guide.html b/lib/knox-api/messenger/messenger-guide.html new file mode 100644 index 00000000..d91167ea --- /dev/null +++ b/lib/knox-api/messenger/messenger-guide.html @@ -0,0 +1,9422 @@ +
+
+

메신저

+
+
+

사전에 생성하신 Knox Portal 비실명계정을 발신자로 하여 Knox Messenger 내에서 + 대화방을 생성하고 메시지를 발신할 수 있습니다.
발신계정을 챗봇 타입으로 생성하시고 수신API 구축하시면 메시지를 수신하실 수도 있습니다..

+

+
[정책 및 제약사항]
+
+
+
1. 토큰 발급부터 메시지 발송까지 필수 작업 순서는 아래와 같습니다. +
+
 1) 메신저 API 신청을 통해 Access Token을 + 획득합니다.
+
 2) 디바이스 등록 API 수행 (GET + /messenger/contact/api/v1.0/device/o1/reg)을 통해 Devide ID를 획득합니다.
+
 3) 암호화 키 조회 API 수행 (GET + /messenger/msgctx/api/v1.0/key/getkeys)을 통해 key value를 획득합니다.
+
 4) 위의 1),2),3) 에서 획득한 파라미터를 사용하여 대화방 생성 + API(/messenger/message/api/v1.0/message/createChatroomRequest), 메시지 발신 + API(/messenger/message/api/v1.0/message/chatRequest) 호출합니다.
+
2. 메신저 API는 다음과 같은 연속호출 제한조건이 있으니 반드시 준수하여 주시기 + 바랍니다.
+
 - ShortTerm 정책: 1초당 50건 초과 시 해당 계정으로의 요청이 + 1초 간 차단
+
 - LongTerm 정책: 15분당 20,000건 초과 시 해당 계정으로의 + 요청이 12시간 동안 차단
+
3. 1회 발송 가능한 최대 메시지 길이는 유형별로 상이합니다.
+
 - 0 (Text type) : 3300 자
+
 - 1 (Media type), 8 (Ncustom type) : + 40,000 byte
+
4. 전송가능 파일 확장자는 아래와 같습니다.
+
 - IMAGE : jpg,jpeg,png,gif
+
 - VIDEO : + mp4,3gp,mov,flv,wmv,mkv,mpg,avi,3g2,m4v,ts,webm
+
 - AUDIO : + mp3,aac,m4a,amr,3ga,wma,imy,mid,mpeg,flac,ogg,wav
+
 - FILE : + pdf,gul,hwp,ppt,pptx,doc,docx,rtf,xls,xlsx,txt,snb,scc,spd,zip,ics
+
+

+
[API 목록]
+
+
+ + + + + + + + + + + + + + + +
APIURIMethodDescription
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
메신저 연락처 + 추가/messenger/contact/api/v1.0/contact/o1/user + POST메신저 연락처에 친구를 + 등록한다.
메신저 연락처 + 삭제/messenger/contact/api/v1.0/contact/o1/user/delete + POST메신저 연락처에 친구를 + 삭제한다.
메신저 연락처 리스트 + 조회/messenger/contact/api/v1.0/contact/o1/list + GET메신저 연락처 등록된 리스트를 + 조회한다.
메신저 User ID + 검색/messenger/contact/api/v1.0/profile/o1/search/loginid + POSTKnox Portal ID로 메신저 + 내부 User ID를 검색한다.
메신저 Device + 등록/messenger/contact/api/v1.0/device/o1/reg + GET연계시스템 발신계정에 대한 메신저 + Device를 등록한다.
메신저 Device + 해지/messenger/contact/api/v1.0/device/o1/delete + POST연계시스템 발신계정에 대한 메신저 + Device를 해지한다.
메신저 Device + 사용정보 조회/messenger/contact/api/v1.0/device/o1/use/info + POST본인 또는 타인의 메신저 Device별 + 사용정보를 조회한다.
파일서버 암호화 Key + 조회/messenger/file/api/v1.0/file/v1/getCurrentTime + GET파일 업로드/다운로드 API 사용을 + 위한 암호화 Key를 조회한다.
파일 + 업로드/messenger/file/api/v1.0/file/v1s/file/{filename} + PUT첨부파일을 업로드한다. +
파일 + 다운로드/messenger/file/api/v1.0/file/v1s/file/{file_id} + GET첨부파일을 다운로드한다. +
메시지서버 암호화 + Key 조회/messenger/msgctx/api/v1.0/key/getkeys + GET메시지서버의 Body 암호화용 Key를 + 조회한다.
대화방 참여자정보 + 조회/messenger/msgctx/api/v1.0/chat/activemember + GET특정 대화방의 참여자수와 User + ID를 조회한다.
대화방 + 생성/messenger/message/api/v1.0/message/createChatroomRequest + POST신규 대화방을 생성한다. +
메시지 + 발신/messenger/message/api/v1.0/message/chatRequest + POST대화방에 메시지를 + 발신한다.
대화상대 + 초대/messenger/message/api/v1.0/message/inviteRequest + POST대화방에 대화상대를 + 초대한다.
대화상대 + 내보내기/messenger/message/api/v1.0/message/removeMemberRequest + POST대화방에서 대화상대를 + 내보낸다.
대화방 + 삭제/messenger/message/api/v1.0/message/destroyChatroomRequest + POST대화방을 삭제한다. +
메시지 + 발신취소/messenger/message/api/v1.0/message/recallMessageRequest + POST발신된 메시지를 + 발신취소한다.
대화방명 + 변경/messenger/message/api/v1.0/message/changeChatroomMetaRequest + POST대화방 이름을 변경한다. (방장만 + 가능)
방장 + 변경/messenger/message/api/v1.0/message/changeOwnerRequest + POST대화방의 방장을 변경한다. (방장만 + 가능)
대화방 + 나가기/messenger/message/api/v1.0/message/endChatRequest + POST대화방을 나간다.
메시지 읽음 + Count 조회/messenger/message/api/v1.0/message/messageReadCountRequest + POST발신된 메시지의 읽음 Count를 + 조회한다.
+
+



+
+
Add user +
+
+

/messenger/contact/api/v1.0/contact/o1/user

+
+
+

연락처에 친구 추가. 자통법 대상자는 친구 추가 불가 및 blocklist로 결과 + 반환.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
6연락처에 등록할 + contactListcontactList + yBodyList +
7연락처에 등록할 + userIDcontactList.userID + yBodyLong1010101010101 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
연락처에 등록된 + userID 리스트contactList + List + +
연락처에 + 등록된 userIDuserID + Long + 1010101010103 + +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +

POST + /messenger/contact/api/v1.0/contact/o1/user HTTP/1.1
Host : yyy.xxxxxx.com

{
    “contactList” : [
         { “userID” : + 10101010101 },
         { “userID” : + 10101010102 }
    ]
}

{
    “contactList” : [
         { “userID” : + 10101010101 }
    ],    “blockedUserIDList” + : [
         { “userID” : + 10101010102 }
    ]
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400 + CFC-100002 + Group + is not exist +
400 + CFC-200001 + Contact + is already added +
400 + CFC-200003 + parameter + userID is invalid userID +
400 + CFC-200004 + Blocked + Group Relation +
400 + CFC-200005 + Exceeded + max contact member limit +
+
+

+
+
Delete + user
+
+

/messenger/contact/api/v1.0/contact/o1/user/delete +

+
+
+

연락처에서 친구를 삭제.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
6연락처에서 제거할 + contactListcontactList + yBodyList +
7연락처에서 제거할 + userIDcontactList.userID + yBodyLong1010101010101 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + +
-----
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +

POST + /messenger/contact/api/v1.0/contact/o1/user/delete HTTP/1.1
Host : yyy.xxxxxx.com

{
    “contactList” : [
         { “userID” : + 10101010101 },
         { “userID” : + 10101010102 }
    ]
}
-
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + +
400 + CFC-100002 + Group + is not exist +
400 + CFC-200002 + parameter + userid is not exist in contactlist +
+
+

+
+
Contact + list
+
+

GET + /messenger/contact/api/v1.0/contact/o1/list

+
+
+

등록된 연락처 목록을 조회횐다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
동기화시간 + syncTime + long + 1480489063661 + Returns + sync time which will be used at next API call.
연락처 + 목록contactList + List + [
{"userID": + 753912291915206657},
{"userID": + 753912292411707393},
{"userID": + 753912844722900993},
{"userID": + 753913660166377473}
]
Returns + contact list
사용자ID + contactList:userID + long + 753912291915206657 + Returns + userID of contact.
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
/messenger/contact/api/v1.0/contact/o1/list + {
"syncTime": + 1480489063661",
"contactList": [
{"userID": 753912291915206657},
{"userID": 753912292411707393},
{"userID": 753912844722900993},
{"userID": 753913660166377473}
]
}
+
+

+
+
Login ID + List Search
+
+

POST + /messenger/contact/api/v1.0/profile/o1/search/loginid

+
+
+

SingleID (Knox Portal ID)를 이용한 사용자 + 검색

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
6검색할 + 사용자 리스트singleIdList + yBodyList[
{"singleId" : + "test1.kim"},
{"singleId" : + "test2.lee"},
{"singleId" : + "test3.park"}
]
검색할 사용자 + 리스트
7검색할 + 사용자의 Knox Portal IDsingleIdList:singleId + yBodyStringtest1.kim + 검색할 사용자의 + Knox Portal ID
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
사용자조회결과 + userSearchResult + Object + + Returns + profile search result.
조회결과목록 + searchResultList + List + + Returns + users userID
사용자ID + userID + long + 753913659651002369 + Returns + users userID.
싱글ID + singleID + String + test1.kim + Returns + users Knox Suite ID
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/contact/api/v1.0/profile/o1/search/loginid HTTP/1.1 +
{
"singleIdList" : + [
{"singleId" : "test1.kim"},
{"singleId" : "test2.lee"},
{"singleId" : "test3.park"}
]
}
{
"userSearchResult": + {
"searchResultList": [
{
"userID": + 753913659651002369,
"singleID": + "test1.kim"
}
{
"userID": + 753913660166377473,
"singleID": + "test3.park"
}
],
"hasMore": + false

}
}
+
+

+
+
Device + registration
+
+

GET + /messenger/contact/api/v1.0/device/o1/reg

+
+
+

사용 기기를 등록 및 Knox Messenger 기기 인증에 + 사용될 x-device-id값 제공.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Content Type + Content-Type + yHeaderStringapplication/json + +
4AcceptAcceptyHeaderStringapplication/json
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
디바이스서버ID + deviceServerID + long + 22222 + 등록된 + deviceID.
등록된 + 기기의 사용자IDuserID + long + 110101010 + Returns + users userID.
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
GET + /messenger/contact/api/v1.0/device/o1/reg HTTP/1.1{
“deviceServerID” : + 22222,
“userID” : 110101010
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
403 + CFC-900003 + device + type is not invalid +
403 + CFC-900008 + exceeded + device reg limit +
403 + CFC-900009 + exceeded + device model length limit +
403 + CFC-900010 + Device + reg is not allowed +
+
+

+
+
Device + deregistration
+
+

/messenger/contact/api/v1.0/device/o1/delete +

+
+
+

등록된 기기를 해지. 접속 중인 기기를 해지할 경우 미인증 단말로 + 인식.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
6등록 해지된 + deviceID.deviceServerID + yBodyLong10101010101 +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + +
API 호출 성공 + 여부resultStringsuccess, + fail
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
{
POST + /messenger/contact/api/v1.0/device/o1/delete HTTP/1.1
Host : yyy.xxxxxx.com

{
“deviceList” : [
     { “deviceServerID” : 10101010101 + },
     { “deviceServerID” : + 10101010102 }
]
}}
-
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
400CFC-900006parameter + deviceID is not registeredparameter + deviceID is not registered
+
+

+
+
Device use + Info
+
+

/messenger/contact/api/v1.0/device/o1/use/info +

+
+
+

본인 및 타인의 기기별 마지막 사용시간 조회.(Open API 기기 + 제외)

+

singleIdList는 최대 600개까지 입력 가능함.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorizationyHeaderStringBearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + Typex-device-type + yHeaderStringrelation +
3Device + IDx-device-idyHeaderString1234 + +
4Content Type + Content-Type + yHeaderStringapplication/json + +
5AcceptAcceptyHeaderStringapplication/json
6조회할 사용자 + 리스트.singleIdList + yBodyList[] + +
7조회할 사용자의 + Knox Suite IDsingleIdList.singleId + yBodyString[] + +
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
API 호출 성공 + 여부resultString + success, + fail +
사용자별 검색 + 결과userDeviceList + String + [ + ] +
사용자의 + userIDuserIDLong + 10101010101 +
사용자의 Knox + Suite IDsingleIDString + test1.kim +
사용자의 + deviceListdeviceList + List + [ + ] +
사용자의 + deviceIDdeviceServerID + Long + 20490 +
마지막 + 접속시간conn_date + String + 2016-06-22 PM + 04:22:46 +
OS + TypedeviceOsType + String + Windows, + Android,iOS +
Device + TypedeviceType + String + pc, + mobile +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
{
POST + /messenger/contact/api/v1.0/device/o1/use/info HTTP/1.1

{
     "singleIdList" : [
         {"singleId" : + "test1.kim"},
         {"singleId" : + "test2.lee"},
         {"singleId" : + "test3.park"}
     + ]
}
Host : + yyy.xxxxxx.com}}
{
{
     "userDeviceList": [
     {
         "userID": + 761258979308365297,
         "singleID": + "test1.kim",
         "deviceList": + [
         + {
             + "deviceServerID": 1000003610,
             + "conn_date": "2016-06-22 PM 04:22:46",
             + "deviceType": "pc",
             + “deviceOsType”: “Windows”
         }
         ]
     },
     {
     "userID": + 755053073097855041,
     + "singleID": "test2.lee",
     + "deviceList": [
     + {
         + "deviceServerID": 20490,
         "deviceType": + "mobile",
“deviceOsType”: “Android”
     },
+      {
     + "deviceServerID": 1000006058,
+      "deviceType": "mobile"
“deviceOsType”: “iOS”
+      }
+      ]
     + },
     {
     "userID": + 755053029387931649,
     + "singleID": "test3.park",
     + "deviceList": []
}
]
}
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
+
+

+
+
FILE + SERVER TIME(KEY)
+
+

GET + /messenger/file/api/v1.0/file/v1/getCurrentTime

+
+
+

Secure API 호출 시 사용되는 x-request-time에 대입할 서버 + 측 현재 시간(UTC) 및 암호화 키를 반환한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1AcceptAcceptHeaderStringapplication/json + application/json +
2Access + tokenAuthorization + yHeaderStringBearer + ce1d72e2a6c96cc09db7c837b1e44fc1[평문] Access + Token.
3Access + tokenx-access-token + yHeaderStringce1d72e2a6c96cc09db7c837b1e44fc1 + [평문] Access + Token - Authorization과 동일한 값이나 Bearer는 제외
4Device ID + x-device-id + yHeaderString131314850 + [평문] Device + registration API를 통해 얻은 deviceServerID를 사용
5Device + Typex-device-type + yHeaderStringrelation + [평문] Device type을 + 사용. - Valid Values: [relation]
6키문자열(파일명)wordyPathStringr1234562312121.gif + [평문] 파일명을 이용해서 암호화 키 문자열로 사용
- + Upload : [file name] Download : [fileid]
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
서버시간serverTime + String1487298788653 + 서버측 현재 + 시간(UTC)
암호키값wordString!2#4%6&8(0gif.gif1@3$5^7*9)!2#4% + 암호키값
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
GET + /messenger/file/api/v1.0/file/v1/getCurrentTime HTTP/1.1 Host : File + Server Authorization: Bearer f5fe27195fb2523cee1758c162a9f60 x-access-token: + f5fe27195fb2523cee1758c162a9f60 x-device-id: 131314850 x-device-type: + relation  [Upload] GET + /messenger/file/api/v1.0/file/v1/getCurrentTime?word=r1234562312121.gif + HTTP/1.1 Host : File Server Authorization: Bearer + f5fe27195fb2523cee1758c162a9f60 x-access-token: + f5fe27195fb2523cee1758c162a9f60 x-device-id: 131314850 x-device-type: + relation  [Download] GET + /messenger/file/api/v1.0/file/v1/getCurrentTime?word=70wT1NHM0y0TF HTTP/1.1 Host : + File Server Authorization: Bearer + f5fe27195fb2523cee1758c162a9f60 x-access-token: + f5fe27195fb2523cee1758c162a9f60 x-device-id: 131314850 x-device-type: + relation[success] HTTP/1.1 + 200 OK Content-Type: application/json Server: File + Server { "serverTime": "1487298788653", "word": + "!2#4%6&8(0gif.gif1@3$5^7*9)!2#4%" }  [error] HTTP/1.1 400 Bad + Request Content-Type: application/json Content-Length: 97 Server: File + Server Connection: close  { "svrTime": "2016-02-11 + 12:34:03.997", "errorCode": "CFI-10001", "errorMessage": " x-device-id is + mandatory" }
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
200Success +
204No + Content +
301Moved + Permanently +
302Found +
307Temporary + redirect +
400CFI-10001{argument} is + mandatory +
400CFI-10002{argument} is + invalid +
400BLUE-999999Device is not + registered +
400BLUE-444401Email address is not + verified +
401Unauthorized +
403Forbidden +
500Internal + Server Error +
+
+

+
+
SECURE + UPLOAD FILE
+
+

PUT + /messenger/file/api/v1.0/file/v1s/file/{filename}

+
+
+

파일 서버에 파일이 업로드 되고 해당 파일을 다운로드 받을 수 있는 URL을 + 반환한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1AcceptAcceptHeaderStringapplication/json + 응답에 허용되는 특정 미디어 + 유형을 지정. - Default: application/json - Valid Values: [application/json, + application/xml]
2Content-Type + Content-Type + HeaderStringbinary/octet-stream + Content-Type - + Default: binary/octet-stream - Valid Values: MIME types
3Content-Length + Content-Length + yHeaderString32121 + 업로드 할 파일의 크기 + (bytes) Valid Values: decimal number
4Access + tokenAuthorization + yHeaderStringBearer + ce1d72e2a6c96cc09db7c837b1e44fc1[평문] Access + Token
5Access + tokenx-access-token + yHeaderStringBublCtBL1kiiUfArCc1ECFChhKGKrdc5liIrsFEuc1kh2pgPShAar9x81edAn1zd + [암호화] Access + Token을 aes256으로 암호화 해야함 - Token type (“Bearer”)를 제외한 Token Value만 Encrypt 처리 +
6Device ID + x-device-id + yHeaderStringwsXERf15w7AZy9m0xJVg+g== + [암호화] Device + registration API를 통해 얻은 deviceServerID를 AES256으로 암호화해서 사용
7Device + Typex-device-type + yHeaderString9JtF6T25SvaSnkgmbkIZsA== + [암호화] Device type을 + AES256으로 암호화해서 사용. - Valid Values: [relation]
8Server + Timex-request-time + yHeaderStringJVdr5iiTe6ogMBoGnwkhOg== + [암호화] File Server + Time(key) API를 통해 얻은 serverTime을 AES256으로 암호화해서 사용
9File + NamefilenameyHeaderStringr1500944966271.jpg + [평문] 업로드 시 파일이름은 + 반드시 다음의 Rule을 준수해서 지정. - Rule : “r” + TimeStamp + Extension
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + +
다운로드 경로 + download_url + Stringhttps://yyy.xxxxxx.com/file/v1s/file/70wT1NHM0y0TF + 파일 다운로드 경로 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
PUT + /messenger/file/api/v1.0/file/v1s/file/ r1500944966271.jpg HTTP/1.1 Host : File + Server Content-Length: 11434 Authorization: Bearer + f5fe27195fb2523cee1758c162a9f60 x-access-token: + BublCtBL1kiiUfArCc1ECFChhKGKrdc5liIrsFEuc1kh2pgPShAar9x81edAn1zd x-device-id: + wsXERf15w7AZy9m0xJVg+g== x-device-type: + 9JtF6T25SvaSnkgmbkIZsA== x-request-time: JVdr5iiTe6ogMBoGnwkhOg==  [11434 + bytes of object data][success] HTTP/1.1 + 200 OK Content-Type: application/json Server: File + Server { "download_url": + "https://yyy.xxxxxx.com/file/v1s/file/70wT1NHM0y0TF" }  [error] HTTP/1.1 + 400 Bad Request Content-Type: application/json Content-Length: 98 Server: + File Server Connection: close { "svrTime": "2015-02-11 + 12:32:30.234", "errorCode": "CFI-10002", "errorMessage": "filename is + invalid" }
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
200Success +
204No + Content +
301Moved + Permanently +
302Found +
307Temporary + redirect +
400CFI-10001{argument} is + mandatory +
400CFI-10002{argument} is + invalid +
400CFI-10003File size is + overflow +
400CFI-10004File size is + empty +
400CFI-10005File format is + error +
400CFI-10006File format is not + supported +
400CFI-10011Infected File + +
400CFI-10013No + permission to upload a file +
400BLUE-999999Device is not + registered +
400BLUE-444401Email address is not + verified +
401Unauthorized +
403Forbidden +
500Internal + Server Error +
+
+

+
+
SECURE DOWNLOAD FILE
+
+

GET + /messenger/file/api/v1.0/file/v1s/file/{file_id}

+
+
+

파일 서버에서 파일을 다운로드 한다. 만약 파일을 다운로드 하려면, + 당신의 application은 반드시 302 code responses를 취급해야 한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorization + yHeaderStringBearer + ce1d72e2a6c96cc09db7c837b1e44fc1[평문] Access + Token
2Access + tokenx-access-token + yHeaderStringBublCtBL1kiiUfArCc1ECFChhKGKrdc5liIrsFEuc1kh2pgPShAar9x81edAn1zd + [암호화] Access + Token을 aes256으로 암호화 해야함 - Token type (“Bearer”)를 제외한 Token Value만 Encrypt 처리 +
3Device ID + x-device-id + yHeaderStringwsXERf15w7AZy9m0xJVg+g== + [암호화] 기기 등록을 통해 + 얻은 deviceServerID를 aes256으로 암호화 해야함.
4Device + Typex-device-type + yHeaderString9JtF6T25SvaSnkgmbkIZsA== + [암호화] 기기 타입을 + aes256으로 암호화 해야함. - Valid Values: [relation]
5Server + Timex-request-time + yHeaderStringJVdr5iiTe6ogMBoGnwkhOg== + [암호화] 파일 서버에서 받은 + 서버시간을 AES256 Encrypt 처리하여 지정
6파일IDfile_idyPathString70wT1NHM0y0TF + [암호화] Secure + Upload File API를 통해 얻은 download_url의 맨 뒤 file ID값을 AES256으로 암호화해서 사용
7썸네일 + 크기thumbParameter + String160x160 + 다운로드 할 썸네일의 사이즈 + 지정. - Valid Values: [160x160]
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + +
(데이터) + (payload) + Binary + 파일 바이너리 + 데이터
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
GET + /messenger/file/api/v1.0/file/v1s/file/70wT1NHM0y0TF?thumb=160x160 HTTP/1.1 Host : + File Server Authorization: Bearer + f5fe27195fb2523cee1758c162a9f60 x-access-token: + BublCtBL1kiiUfArCc1ECFChhKGKrdc5liIrsFEuc1kh2pgPShAar9x81edAn1zd x-device-id: + wsXERf15w7AZy9m0xJVg+g== x-device-type: + 9JtF6T25SvaSnkgmbkIZsA== x-request-time: JVdr5iiTe6ogMBoGnwkhOg==[success] HTTP/1.1 + 200 OK Content-Length: 434234 Content-Type: image/jpeg Connection: + close Server: File Server  [434234 bytes of object + data]  [error] HTTP/1.1 400 Bad Request Content-Type: + application/json Content-Length: 97 Server: File Server Connection: + close {"svrTime": "2015-02-11 12:34:03.997","errorCode": "CFI-10002", + "errorMessage": "file_id is invalid"}
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
200Success +
204No + Content +
301Moved + Permanently +
302Found +
307Temporary + redirect +
400CFI-10001{argument} is + mandatory +
400CFI-10002{argument} is + invalid +
400CFI-10007File has expired + +
400CFI-10012V7 + Empsearch API error +
400BLUE-999999Device is not + registered +
400BLUE-444401Email address is not + verified +
401Unauthorized +
403Forbidden +
500Internal + Server Error +
+
+

+
+
Get Keys +
+
+

/messenger/msgctx/api/v1.0/key/getkeys

+
+
+

Device의 channel auth Key and device key를 조회한다. +

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorization + yHeader + String + Bearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + IDx-device-id + yHeader + Long1234 +
3Content + TypeContent-Type + nHeader + String + application/json +
4AcceptAcceptnHeader + Stringapplication/json + +
5Device Type + x-device-type + nHeader + Stringmobilemobile or pc or + relation
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Device의 + Message keykey + String4cc5d9fa5d44819357618b8a8d8c21326df20fa95cd5fd6da0f9cdd030d1a9b7c31df7eb7080b9c3b62ee0348eb1d86b + +
Device의 Expired + message keyexpiredkey + String + 4cc5d9fa5d44819357618b8a8d8c21326df20fa95cd5fd6da0f9cdd030d1a9b7c31df7eb7080b9c3b62ee0348eb1d86b + optional
Channel Auth + keychannelauthkey + String + 537461636b5472616365456c656d656e745b5d20656c656d73203d2065782e67696e742066696e616c4c656e203d2070 +
Message + key의 expiring Timestamp 값keyexpirationtimestamp + Long + 1718094662042 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
GET /messenger/msgctx/api/v1.0/key/getkeys
HTTP/1.1
Host : + yyy.xxxxxx.com
Content-type: + application/json
Accept: + application/json
x-device-type : + mobile
x-device-id : 1234
Authorization : Bearer fc55e83b7dea72ebe8f4f0dee2a2c4
+
HTTP/1.1 200 OK
{
    “key” : + “4cc5d9fa5d44819357618b8a8d8c21326df20fa95cd5fd6da0f9cdd030d1a9b7c31df7eb7080b9c3b62ee0348eb1d86b”,
    “channelauthkey” : + “537461636b5472616365456c656d656e745b5d20656c656d73203d2065782e67696e742066696e616c4c656e203d2070”
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + +
400 + BLUE-999999 + Not exist + deviceId +
400 + BMC-300150 + Not Exist + Channel Auth Key. +
+
+

+
+
Chat + Active Member
+
+

/messenger/msgctx/api/v1.0/chat/activemember +

+
+
+

채팅방의 참여자 수와 User ID를 조회한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1Access + tokenAuthorization + y + Header + String + Bearer + fc55e83b7dea72ebe8f4f0dee2a2c4
2Device + IDx-device-id + y + Header + Long + 1234 +
3Content + TypeContent-Type + n + Header + String + application/json +
4Accept + Accept + n + Header + String + application/json +
5Device + Typex-device-type + n + Header + String + mobile + mobile or pc or + relation
6Chatroom + Idchatroomid + y + Query + Long + 332321144605 + max 19 number + string
+
+
+
+

Response Parameter

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
현재 + 대화방에 참여중인 멤버의 수activemembercount + Integer + 10 + +
현재 + 대화방에 참여중인 멤버의 User ID List.activememberlist + Long + + List +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
GET + /messenger/msgctx/api/v1.0/chat/activemember?chatroomid=1221232323
HTTP/1.1
Host : + yyy.xxxxxx.com
Content-type: + application/json
Accept: + application/json
x-device-type : + mobile
x-device-id : 1234
Authorization : Bearer fc55e83b7dea72ebe8f4f0dee2a2c4
+
HTTP/1.1 200 OK
{
    “activemembercount”:5,
    “activememberlist” : [
        753913371694206977,
        753915435136061441,
        753915446684553217,
        753916848394735617,
        753916967328419841
    ]
}
+
+
+
Error Code
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + +
400 + BLUE-999999 + Not + exist deviceId +
+
+

+
+
메시지 + API 공통 포맷
+
+

아래 목록의 API들은 메시지군의 API들로써 공통적인 포맷을 + 갖는다. (payload data 암호화, 공통 error 코드)
- 대화방 생성
- 메시지 발신
- 대화상대 초대
- 대화상대 내보내기
- 대화방 + 삭제
- 메시지 발신취소
- 대화방명 변경
- 방장 변경
- 대화방 나가기
- 메시지 읽음 Count 조회

+
+
+

payload data 암호화

+
+
+

API호출에 사용되는 Request Payload data와 + Response Payload data는 암호된 값을 사용한다.
각 API 기능별로 Payload 내에 적재된 RequestBody와 ResponseBody내용을 전송단에서 + Aes256암호화 > Base64암호화를 거쳐 데이터를 보내며, 수신단에서 Base64복호화 > Aes256복호화를 거쳐 암호화를 해제함으로써 데이터 추출할 수 + 있다.
기능별 API 명세에서는 각 API별로, 암호화가 해제된 평문 기준의 RequestBody, ResponseBody 명세에 대한 설명이 기재되어 있다.

+

+
+
+

연계 시스템측에서 사용하게 되는 RequestBody 암호화 및 + ResponseBody 복호화에 대한 예시는 아래와 같다.

+
+
+
+ + + + + + + + + + + +
[RequestBody + 암호화 예시][ResponseBody + 복호화 예시]
+
+
+ + + + + + + + + + + +
적용전 (RequestBody평문): {"requestId": 1578016699286727, "chatroomId": + 99343295704997888}
암호화 1단계: AES256 + 인코딩
암호화 2단계: BASE64 인코딩
적용후 (RequestBody암호문): + IN/WslquK+4b3I+I3lJF1UyiYksAhZRncHL5axCGpJur9U/LabuKIIo7OKEQe1JOSaCb3szhWphL2Ufhj86dcClTXz5b+AVYDq6LRbd4zBQ=
+
적용전 (ResponseBody-암호문): + 7Q9FCL95U+5FIFGcZbG9Y6wvpod95dfH+pxDZVb3HnJzz/U+nZAG3tQ+NPOUprKaMZ3rTEPbYsMr89KIWEdpog== +
복호화 1단계: AES256 디코딩
복호화 2단계: AES256 디코딩
적용후 + (ResponseBody-평문): { "code": 3003, "msg": "All receivers are invalid." + }
+
+
+
+

※ 예시에 사용된 메시지 키 값은 아래와 같으며, 실사용시 메시지 + 키값을 "메시지서버 암호화 Key 조회" api로 조회하여 사용하여야 한다.(메시지 key값은 단말별로 부여됨)
- 예시에 사용된 메시지 key: + "b6d06ce799b97b58aa606e393c6a18ee1f6008726b59072036207ccafe6443b9b3c546f665fdae562a7d8d35f4bca16e"
+

+

+

※ 암복호화 모듈 구현은 샘플 코드를 참고 바람.

+
+
+

메시지 공통 Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
2001000Success +
2001001Detected + some invalid receivers. (Success partial) +
204No + Content +
4002001Wrong + token +
4002002Not + registered requester. +
4003003Invalid + receiver. +
4003004Receiver is + not enabled. +
4003005Exceeded + chatroom count limit. +
4003009Membership + violation detected. +
4003106All + receivers are invalid. +
4004001Wrong + parameter value. +
4004003Wrong body! (Fail decrypt about message body.)
해당 에러 발생 시 6.1 GET Keys API를 수행하여 최신 Key value를 response 받아서 + RequestBody 암호화를 수행할 것을 권장함.
+
4006001General DAO + error +
4007001Not bounded + device. +
4009000Internal + server error. +
4009001Exceeded + session count limit. +
4009002Short Term + DDoS detected. +
4009003Long Term DDoS detected.
(정책 시간 동안 + api 사용 금지 ex. 12시간)
+
401Unauthorized +
403Forbidden +
500Internal + Server Error +
+
+

+
+
대화방 + 생성
+
+

POST + /messenger/message/api/v1.0/message/createChatroomRequest

+
+
+

신규 대화방을 생성한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY:requestId + yLong1302575819285 + Packet별로 + Unique한 Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방유형 + BODY:chatType + yInteger2Chat Type, 대화방 유형
“단방향(공지type)” + 외부연계 사용 시 2,5만 사용

0: (SINGLE) – 1:1 대화
1: (GROUP) – + Group 대화
2: (BROADCAST GROUP) Group + 공지방(2인이상)
5: (BROADCAST SINGLE) 1:1 + 공지방
(3)참여자목록 + BODY:receivers + yList + [753917009235808257,753916848517419009] + 채팅 참여자들의 User + Id를 리스트 형태로 작성
(4)대화방이름 + BODY:chatroomTitle + String"dev server + team"최대 길이 128 자 + (utf8mb4)
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
결과 + result + 결과
결과:코드 + result:code + Integer1000 + 결과 코드 +
결과:(에러)내용 + result:msg + String"Detected + some invalid receivers."결과 내용 +
결과:참여불가상세 + result:wrongReceiverDetail +
결과:참여불가상세:잘못된 + 사용자 목록result: + wrongReceiverDetail: invalidReceiversList + [897548937598437953, + 89754354568789456]잘못된 유저정보로 대화방에 입장할 수 없는 사용자
* 결과 + 코드 1001/3003 리턴
결과:참여불가상세:정책상 + 불허된 목록result: + wrongReceiverDetail: organizationViolatedList + [897548937598437953, + 89754354568789456]정책상 대화할 수 없는 사용자 (회사가 다르면 대화가 불가함)
* 결과 코드 1001/3003 리턴
결과:참여불가상세:단말 + 미등록자 목록result: + wrongReceiverDetail: disabledReceiversList + [897548937598437953, + 89754354568789456]등록된 단말이 없어서 대화에 참여할 수 없는 사용자
* 결과 + 코드 1001/3003 리턴
결과:참여불가상세:자통법상 + 차단된 목록result: + wrongReceiverDetail: blockedGroupList + [897548937598437953, + 89754354568789456]자본시장통합법에 의거 대화를 할 수 없는 관계의 사용자
* + 결과 코드 1001/3003 리턴
대화방 + 생성시간createTimeMillis + Long1578386757248 + 대화방 + 생성시간
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/createChatroomRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전): {"chatType": 2, + "requestId": 1578016699286727, + "receivers":[753917009235808257,753916848517419009]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId": 1578016699286727, "chatroomId": 99343295704997888, + "result": {"code": 1000, "wrongReceiverDetail": {}}, createTimeMillis": + 1578016699269}
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
메시지 + 발신
+
+

POST + /messenger/message/api/v1.0/message/chatRequest

+
+
+

메시지를 발송한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY: + requestIdyLong# + {"requestId": 15784605065976949, "chatroomId": 99343295704997888, "chatMessageParams": + [{"msgId": 15784605065976949, "msgType": 0, "chatMsg": "blah~ blah~", "msgTtl": + 7200}]}Packet별로 Unique한 + Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY: + chatroomIdyLong99343295704997888 + 대화방 ID
(3)BODY: + chatMessageParamsyList + 최대 10개
(3-1)BODY: + chatMessageParam: msgIdyLong1578409921352 + 메시지별 Unique한 ID, + Milliseconds 형식 (ex. 1302575819285 )
(3-2)BODY: + chatMessageParam: msgTypeyInteger0Msg Type, 메시지 유형

0: (TEXT) ? Common text message
1: + (MEDIA) ? MultiMedia message (file, video)
7: (RTF) + - Excel message
8: (NCUSTOM) - Message with json + format
(3-3)BODY: + chatMessageParam: chatMsgyString"Hello + world!"메시지 내용 (최대 + 3,300자)
(3-4)BODY: + chatMessageParam: msgTtlInteger7200메시지 서버 저장 기간 (Min : 3600 sec / Max : according to company policy / + Default : 259200 sec)
* If an unacceptable value is + entered, the default value
+
+
+
+

# {"requestId": + 15784605065976949, "chatroomId": 99343295704997888, "chatMessageParams": [{"msgId": 15784605065976949, + "msgType": 0, "chatMsg": "blah~ blah~", "msgTtl": 7200}]}

+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 Id +
결과 + result + Result
* If Nth message in 10 is + failed, It is cause of failure for the message.
결과: 코드 + result: + codeInteger1000 + Result + code
결과: + (에러)내용result: + msgStringResult + message
결과: + 메시지처리상세result: + processedMessageEntriesList +
결과: 메시지처리상세: + 메시지IDresult: + processedMessageEntrie: msgIdLong전달된 메시지 ID +
결과: 메시지처리상세: + 전달시간result: + processedMessageEntrie: sentTimeLong1578449866003 + 전달시간 (서버 기준)
* If it is failed to + sending message, returns 0
결과: + 참여불가상세result: + wrongReceiverDetail
결과: 참여불가상세: + 잘못된 사용자 목록result: + wrongReceiverDetail: invalidReceiversList + [897548937598437953, + 89754354568789456]잘못된 유저 정보로 메시지를 전달할 수 없는 사용자
* It + is available for ResultCode 1001/3003
결과: 참여불가상세: + 단말 미등록자 목록result: + wrongReceiverDetail: disabledReceiversList + [897548937598437953, + 89754354568789456]등록된 단말이 없어서 메시지를 전달할 수 없는 사용자
* It + is available for ResultCode 1001/1003
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/chatRequest + HTTP/1.1
headers: {"Accept": "application/json", + "Authorization": "Bearer ed114dc382ca16d5b43154fe5832a7", "Content-Type": + "application/json", "x-device-id": "1000145874", "Content-Length": + "172"}

body(암호화전): {"requestId": 15784605065976949, "chatroomId": + 99343295704997888, "chatMessageParams": [{"msgId": 15784605065976949, "msgType": 0, + "chatMsg": "blah~ blah~", "msgTtl": 7200}]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId":15784605065976949,"chatroomId":99343295704997888,"result":{"code":1000,"wrongReceiverDetail":{}},"processedMessageEntries":[{"msgId":15784605065976949,"sentTime":1578460506612}]}
+
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
대화상대 + 초대
+
+

POST + /messenger/message/api/v1.0/message/inviteRequest

+
+
+

대화 상대를 초대한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY: + requestIdyLong1302575819285 + Packet별로 Unique한 + Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY: + chatroomIdyLong99343295704997888 + 대화방 ID +
(3)초대자목록 + BODY: + invitingMembersyList + [773887412433063937, + 74124330639377655]초대 대상자 User + Id
+
+
+
+

# {"requestId": 15784506666772442, + "chatroomId": 99343295704997888, "invitingMembers": [773887412433063937]}

+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
초대받은시간 + sentTime + Long1578450666592 + 서버로부터 초대받은 + 시간
결과 + result + Result
* If Nth message in 10 is + failed, It is cause of failure for the message.
결과: + 코드result: + codeInteger1000 + Result + code
결과: + (에러)내용result: + msgStringResult + message
결과: + 참여불가상세result: + wrongReceiverDetail
결과: 참여불가상세: + 잘못된 사용자 목록result: + wrongReceiverDetail: invalidReceiversList + [897548937598437953, + 89754354568789456]잘못된 유저 정보로 메시지를 전달할 수 없는 사용자
* It + is available for ResultCode 1001/3003
결과: 참여불가상세: + 정책상 불허된 목록result: + wrongReceiverDetail: organizationViolatedList + [897548937598437953, + 89754354568789456]정책상 대화할 수 없는 사용자 (회사가 다르면 대화가 불가함)
* It is available for ResultCode 1001/3003
결과: + 참여불가상세: 단말 미등록자 목록result: + wrongReceiverDetail: disabledReceiversList + [897548937598437953, + 89754354568789456]등록된 단말이 없어서 메시지를 전달할 수 없는 사용자
* + It is available for ResultCode 1001/1003
결과: + 참여불가상세: 이미 참여한 목록result: + wrongReceiverDetail: existingList + [897548937598437953, + 89754354568789456]이미 대화방에 참여중인 사용자
* It is available + for ResultCode 1001/3003
결과: + 참여불가상세: 인원제한으로 누락된 목록result: + wrongReceiverDetail: interruptedReceiversList + [897548937598437953, + 89754354568789456]대화방의 멤버가 최대 인원을 넘어서 초대할 수 없는 사용자
* + It is available for ResultCode 1001/3003
결과: + 참여불가상세: 자통법상 차단된 목록result: + wrongReceiverDetail: blockedGroupList + [897548937598437953, + 89754354568789456]자본시장통합법에 의거 대화를 할 수 없는 관계의 사용자
* + It is available for ResultCode 1001/3003
+
+
+
+

# + {"requestId":15784506666772442,"chatroomId":99343295704997888,"result":{"code":1000,"wrongReceiverDetail":{}},"sentTime":1578450666592} +

+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/inviteRequest + HTTP/1.1
headers: {"Accept": "application/json", + "Authorization": "Bearer ed114dc382ca16d5b43154fe5832a7", "Content-Type": + "application/json", "x-device-id": "1000145874", "Content-Length": + "172"}
body(��ȣȭ��): {"requestId": + 15784506666772442, "chatroomId": 99343295704997888, "invitingMembers": + [773887412433063937]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server
{"requestId":15784506666772442,"chatroomId":99343295704997888,"result":{"code":1000,"wrongReceiverDetail":{}},"sentTime":1578450666592}
+
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
대화상대 + 내보내기
+
+

POST + /messenger/message/api/v1.0/message/removeMemberRequest

+
+
+

대화 상대를 방출한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY:requestId + yLong1302575819285 + Packet별로 Unique한 + Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY:chatroomId + yLong99343295704997888 + 대화방 ID +
(3)방출자 목록 + BODY:removingMembers + yList + [753917009235808257,753916848517419009] + 방출할 대상자 User Id를 + 리스트 형태로 작성
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
요청시간 + + 1578450666592 + 서버로 요청받은 + 시간
결과 + result + 결과
결과:코드 + result:code + Integer1000 + 결과 코드 +
결과:(에러)내용 + result:msg + String결과 내용 +
결과:비정상수신자상세 + result:wrongReceiverDetail +
결과:비정상수신자상세:미참여 + result: + wrongReceiverDetail:notExistingList + [897548937598437953, + 89754354568789456]내보내기 대상자 중 대화방 멤버가 아닌 사용자
* 결과 코드 + 1001/3003 리턴
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/removeMemberRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전): {"requestId": + 15784562811364493, "chatroomId": 99343295704997888, "removingMembers": + [773887412433063937]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId":15784562811364493,"chatroomId":99343295704997888,"result":{"code":1000},"sentTime":1578456281137}
+
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
대화방 + 삭제
+
+

POST + /messenger/message/api/v1.0/message/destroyChatroomRequest

+
+
+

대화방을 삭제한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY:requestId + yLong1302575819285 + Packet별로 + Unique한 Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY:chatroomId + yLong99343295704997888 + 대화방 ID +
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
결과 + result + + 결과 +
결과:코드 + result:code + Integer1000 + 결과 코드 +
결과:(에러)내용 + result:msg + String + 결과 내용 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/destroyChatroomRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전){"requestId": + 15784562811364493, "chatroomId": 99343295704997888}
HTTP/1.1 200 OK Content-Type: application/json Server: Message + Server
{"requestId":15784562811364493,"chatroomId":99343295704997888,"result":{"code":1000}}
+
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
메시지 + 발신취소
+
+

POST + /messenger/message/api/v1.0/message/recallMessageRequest

+
+
+

발송된 메시지를 취소한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY:requestId + yLong1302575819285 + Packet별로 Unique한 + Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY:chatroomId + yLong99343295704997888 + 대화방 ID +
(3)메시지ID + BODY:msgId + yLong15784605065976949 + 발신 취소 대상 메시지 + ID
(4)원본메시지 + 발송시간BODY:sentTime + yLong1578460506612 + 원본 메시지 발송시간 + (메시지 발송 ChatReply 의 sentTime)
(5)미디어정보 + BODY:mediaInfo + String"http:// + sqaproxy.samsung.net/file/v1/file/esK93SYcoqeE8ETvJgUdeg"발신취소 대상 메시지가 + MEDIA 타입인 경우 삭제 대상 파일의 "download url"
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
결과 + result + 결과
결과:코드 + result:code + Integer1000 + 결과 코드 +
결과:(에러)내용 + result:msg + String결과 내용 +
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/recallMessageRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전): {"requestId": + 15784610001948974, "chatroomId": 99343295704997888, "msgId": 15784605065976949, + "sentTime": 1578460506612}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId":15784610001948974,"chatroomId":99343295704997888,"result":{"code":1000}}
+
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
대화방명 변경
+
+

POST + /messenger/message/api/v1.0/message/changeChatroomMetaRequest

+
+
+

대화방의 Meta 정보를 변경한다. (대화방명 변경만 + 가능)

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY: + requestIdyLong1302575819285 + Packet별로 + Unique한 Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY: + chatroomIdyLong99343295704997888 + 대화방 + ID
(3)대화방 + 이름BODY: + titleString"dev + server team"변경하고자 하는 + 대화방명
+
+
+
+

# {"requestId": + 15784610001948974, "chatroomId": 99343295704997888, "title": "메시지 테스트방1"}

+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
결과 + result + + Result +
결과: + 코드result: + codeInteger1000 + Result + code
결과: + (에러)내용result: + msgString + Result + message
대화방 + 변경시간changeTimeMillis + Long1578386757248 + 대화방 + 속성(이름)이 변경된 시간
+
+
+
+

# {"requestId": + 15784610001948974, "chatroomId": 99343295704997888, "result": {"code": 1000}, changeTimeMillis": + 1578016699269}

+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/changeChatroomMetaRequest + HTTP/1.1
headers: {"Accept": "application/json", + "Authorization": "Bearer ed114dc382ca16d5b43154fe5832a7", "Content-Type": + "application/json", "x-device-id": "1000145874", "Content-Length": + "172"}

body(암호화전): {"requestId": 15784610001948974, "chatroomId": + 99343295704997888, "title": "메시지 테스트방1"}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId": 15784610001948974, "chatroomId": 99343295704997888, + "result": {"code": 1000}, changeTimeMillis": 1578016699269}
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
방장 + 변경
+
+

POST + /messenger/message/api/v1.0/message/changeOwnerRequest

+
+
+

대화방의 방장을 변경한다. (ChatType이 0: (1:1 + 대화방), 1: (Group 대화방)에서만 지원됨)

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY: + requestIdyLong# + {"requestId": 15784610001948974, "chatroomId": 99343295704997888, "newOwner": + 753917009235808257}Packet별로 + Unique한 Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY: + chatroomIdyLong99343295704997888 + 대화방 + ID
(3)새방장ID + + Long753917009235808257 + 새로운 + 방장ID
+
+
+
+

# {"requestId": + 15784610001948974, "chatroomId": 99343295704997888, "newOwner": 753917009235808257}

+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 생성된 대화방 + Id
결과 + result + + Result +
결과: + 코드result: + codeInteger1000 + Result + code
결과: + (에러)내용result: + msgString + Result + message
요청시간 + sentTime + Long1578386757248 + 서버에서 해당 + Request를 받은 시간
+
+
+
+

{"requestId": + 15784610001948974, "chatroomId": 99343295704997888, newOwner": 753917009235808257}

+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/changeOwnerRequest + HTTP/1.1
headers: {"Accept": "application/json", + "Authorization": "Bearer ed114dc382ca16d5b43154fe5832a7", "Content-Type": + "application/json", "x-device-id": "1000145874", "Content-Length": + "172"}

body(암호화전): {"requestId": 15784610001948974, "chatroomId": + 99343295704997888, "newOwner": 753917009235808257}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId": 15784610001948974, "chatroomId": 99343295704997888, + "result": {"code": 1000}, newOwner": 753917009235808257}
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
대화방 나가기 +
+
+

POST + /messenger/message/api/v1.0/message/endChatRequest

+
+
+

대화방에서 퇴장한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청IDBODY:requestId + yLong1302575819285 + Packet별로 Unique한 Id + Milliseconds 형식 (ex. 1302575819285 )
(2)BODY:endChatEntries + yList +
(2-1)퇴장할 + 대화방 IDBODY:endChatEntriy:chatroomId + yLong99343295704997888 + 퇴장할 대화방 ID
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청IDrequestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
결과result + 결과
결과:코드result:code + Integer1000결과 코드
결과:(에러)내용 + result:msg + String결과 내용
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/endChatRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전): {"requestId": + 15784610001948974, "endChatEntries":[{"chatroomId": + 99343295704997888}]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId": 15784610001948974, "result": {"code": + 1000}}
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+

+
+
메시지 읽음 + Count 조회
+
+

POST + /messenger/message/api/v1.0/message/messageReadCountRequest

+
+
+

발신 메시지를 읽은 사용자의 수를 조회한다.

+
+
+

Request Parameter

+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Parameter TypeNo.PropertiesAttributeMandatoryData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Header1응답 허용 + 타입Accept + String"application/json" + Default: application/json
Valid + Values: [application/json, application/xml]
2첨부데이터타입 + Content-Type + yString"application/json" + Payload의 content type 명시
ex) + application/json
3인증토큰 + Authorization + yString"Bearer + f5fe27195fb2523cee1758c162a9f60"[평문] Access Token (발급 + 받은 Access Token)
4단말IDx-device-id + yString"104032854"[평문] + 연계시스템용으로 등록한 단말 ID ("메신저 Device 등록" 부분 참조)
5단말종류x-device-type + yString"relation" + [평문] 단말 타입, “relation” 으로 고정
※ + relation: 외부연계 시스템
PayloadBodyyString"/6Fz+KIhVzmyhiBpMrLNJp+0saSg7b7XlZp3tlXrnRLVaCHDD4XqV9dGVh6hmri7hR3dJdTps1qO3gDH1XccTj3Qmy3X4MsMBFP8AW3uIGk7QdlBp0wMi8FBrHExUR/h" + [암호화] Payload 데이터
※ 평문 + 상태(json문자열)의 BODY항목을 2단계 암호화를 거친 암호화된 문자열 값.
1단계: + Aes256암호화 (암호화키는 "메시지서버 암호화 Key 조회" 부분 참조)
2단계: + Base64암호화
(1)요청ID + BODY:requestId + yLong1302575819285 + Packet별로 Unique한 + Id Milliseconds 형식 (ex. 1302575819285 )
(2)대화방ID + BODY:chatroomId + yLong99343295704997888 + 대화방 ID +
(3)메시지정보 + BODY:messageEntry + yList +
(3-1)메시지ID + BODY:messageEntry: + msgIdyLong38635452485935 + 카운트 조회를 하고자 하는 + 메시지의 ID
(3-2)원본메시지 + 발송시간BODY:endChatEntriy:messageEntry: + sentTimeLong1472639462088 + 카운트 조회를 하고자 하는 + 메시지의 sent time
+
+
+
+

Response Parameter [Encrypted]

+
+
+
+ + + + + + + + + + + + + + + + + +
PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
요청ID + requestId + Long15783867572942564 + Packet별로 Unique한 Id (Milliseconds 형식)
※ 요청시 사용한 requestId 값과 동일
대화방ID + chatroomId + Long99536308621824000 + 대화방 Id +
결과 + result + 결과
결과:코드 + result:code + Integer1000 + 결과 코드 +
결과:(에러)내용 + result:msg + String결과 내용 +
결과:카운트 조회 + 목록result:messageEntry + List +
결과:카운트 조회 + 목록:메시지IDresult:messageEntry:msgId + Long카운트 조회한 메시지의 + ID
결과:카운트 조회 + 목록:메시지발송시간result:messageEntry:sentTime + Long카운트 조회한 메시지의 + sent time
결과:카운트 조회 + 목록:읽음 카운트result:messageEntry:readCount + Integer해당 메시지에 대한 읽음 + 카운트
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
POST /messenger/message/api/v1.0/message/messageReadCountRequest + HTTP/1.1

headers: + {"Accept": "application/json", "Authorization": "Bearer + ed114dc382ca16d5b43154fe5832a7", "Content-Type": "application/json", "x-device-id": + "1000145874", "Content-Length": "172"}

body(암호화전): {"requestId": + 15784610001948974, "chatroomId": 99343295704997888, "messageEntry":[{"msgId": + 38635452485935, "sentTime":1472639462088}]}
HTTP/1.1 200 OK
Content-Type: + application/json
Server: Message + Server

{"requestId": 15784610001948974, "chatroomId": 99343295704997888, + "result": {"code": 1000}, "messageEntry":[{"msgId": 38635452485935, + "sentTime":1472639462088, "readCount":0}]}
+
+
+
+

Error Code

+
+
+

"메시지 API 공통 포맷" 부분 참조 (에러코드 부분)

+
+
\ No newline at end of file diff --git a/lib/knox-api/messenger/messenger.ts b/lib/knox-api/messenger/messenger.ts new file mode 100644 index 00000000..58611621 --- /dev/null +++ b/lib/knox-api/messenger/messenger.ts @@ -0,0 +1,925 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +"use server" + +import { z } from 'zod'; + +// 환경 변수 타입 정의 +const MESSENGER_BASE_URL = process.env.MESSENGER_BASE_URL || 'https://api.messenger.com'; +const ACCESS_TOKEN = process.env.MESSENGER_ACCESS_TOKEN; +const DEVICE_ID = process.env.MESSENGER_DEVICE_ID; + +// 공통 헤더 생성 함수 +function createHeaders(additionalHeaders?: Record) { + const headers: Record = { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${ACCESS_TOKEN}`, + 'x-device-id': DEVICE_ID!, + 'x-device-type': 'relation', + ...additionalHeaders + }; + + return headers; +} + +// 응답 타입 정의 +type ApiResponse = { + success: boolean; + data?: T; + error?: string; + statusCode?: number; +}; + +// 에러 핸들링 함수 +function handleApiError(error: any, endpoint: string): ApiResponse { + console.error(`Knox Messenger API Error (${endpoint}):`, error); + + return { + success: false, + error: error.message || `Failed to call ${endpoint}`, + statusCode: error.status || 500 + }; +} + +// ============================================================================= +// 연락처 관리 API +// ============================================================================= + +// 연락처 추가 스키마 +const addContactSchema = z.object({ + contactList: z.array(z.object({ + userID: z.number() + })) +}); + +// 연락처 추가 +export async function addContact(data: z.infer): Promise> { + try { + const validated = addContactSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/contact/o1/user`, { + method: 'POST', + headers: createHeaders(), + body: JSON.stringify(validated) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to add contact', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'addContact'); + } +} + +// 연락처 삭제 스키마 +const deleteContactSchema = z.object({ + contactList: z.array(z.object({ + userID: z.number() + })) +}); + +// 연락처 삭제 +export async function deleteContact(data: z.infer): Promise> { + try { + const validated = deleteContactSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/contact/o1/user/delete`, { + method: 'POST', + headers: createHeaders(), + body: JSON.stringify(validated) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to delete contact', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'deleteContact'); + } +} + +// 연락처 목록 조회 +export async function getContactList(): Promise> { + try { + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/contact/o1/list`, { + method: 'GET', + headers: createHeaders() + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get contact list', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getContactList'); + } +} + +// 사용자 검색 스키마 +const searchUserSchema = z.object({ + singleIdList: z.array(z.object({ + singleId: z.string() + })) +}); + +// 사용자 검색 +export async function searchUserByLoginId(data: z.infer): Promise> { + try { + const validated = searchUserSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/profile/o1/search/loginid`, { + method: 'POST', + headers: createHeaders(), + body: JSON.stringify(validated) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to search user', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'searchUserByLoginId'); + } +} + +// ============================================================================= +// 장치 관리 API +// ============================================================================= + +// 장치 등록 +export async function registerDevice(): Promise> { + try { + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/device/o1/reg`, { + method: 'GET', + headers: createHeaders() + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to register device', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'registerDevice'); + } +} + +// 장치 해지 스키마 +const deregisterDeviceSchema = z.object({ + deviceServerID: z.number() +}); + +// 장치 해지 +export async function deregisterDevice(data: z.infer): Promise> { + try { + const validated = deregisterDeviceSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/device/o1/delete`, { + method: 'POST', + headers: createHeaders(), + body: JSON.stringify(validated) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to deregister device', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'deregisterDevice'); + } +} + +// 장치 사용 정보 조회 스키마 +const getDeviceUseInfoSchema = z.object({ + singleIdList: z.array(z.object({ + singleId: z.string() + })) +}); + +// 장치 사용 정보 조회 +export async function getDeviceUseInfo(data: z.infer): Promise> { + try { + const validated = getDeviceUseInfoSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/contact/api/v1.0/device/o1/use/info`, { + method: 'POST', + headers: createHeaders(), + body: JSON.stringify(validated) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get device use info', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getDeviceUseInfo'); + } +} + +// ============================================================================= +// 파일 관리 API +// ============================================================================= + +// 파일 서버 시간 및 키 조회 스키마 +const getFileServerTimeSchema = z.object({ + word: z.string() +}); + +// 파일 서버 시간 및 키 조회 +export async function getFileServerTime(data: z.infer): Promise> { + try { + const validated = getFileServerTimeSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/file/api/v1.0/file/v1/getCurrentTime?word=${validated.word}`, { + method: 'GET', + headers: createHeaders({ + 'x-access-token': ACCESS_TOKEN! + }) + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get file server time', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getFileServerTime'); + } +} + +// 파일 업로드 스키마 +const uploadFileSchema = z.object({ + filename: z.string(), + fileData: z.instanceof(FormData).or(z.any()) +}); + +// 파일 업로드 +export async function uploadFile(data: z.infer): Promise> { + try { + const validated = uploadFileSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/file/api/v1.0/file/v1s/file/${validated.filename}`, { + method: 'PUT', + headers: createHeaders({ + 'x-access-token': ACCESS_TOKEN!, + 'Content-Type': 'multipart/form-data' + }), + body: validated.fileData + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to upload file', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'uploadFile'); + } +} + +// 파일 다운로드 스키마 +const downloadFileSchema = z.object({ + fileId: z.string() +}); + +// 파일 다운로드 +export async function downloadFile(data: z.infer): Promise> { + try { + const validated = downloadFileSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/file/api/v1.0/file/v1s/file/${validated.fileId}`, { + method: 'GET', + headers: createHeaders({ + 'x-access-token': ACCESS_TOKEN! + }) + }); + + if (!response.ok) { + return { + success: false, + error: 'Failed to download file', + statusCode: response.status + }; + } + + const blob = await response.blob(); + + return { + success: true, + data: blob + }; + } catch (error) { + return handleApiError(error, 'downloadFile'); + } +} + +// ============================================================================= +// 메시지 관리 API +// ============================================================================= + +// 메시지 서버 키 조회 +export async function getMessageServerKeys(): Promise> { + try { + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/msgctx/api/v1.0/key/getkeys`, { + method: 'GET', + headers: createHeaders() + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get message server keys', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getMessageServerKeys'); + } +} + +// 대화방 참여자 정보 조회 스키마 +const getChatMembersSchema = z.object({ + chatroomId: z.number() +}); + +// 대화방 참여자 정보 조회 +export async function getChatMembers(data: z.infer): Promise> { + try { + const validated = getChatMembersSchema.parse(data); + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/msgctx/api/v1.0/chat/activemember?chatroomId=${validated.chatroomId}`, { + method: 'GET', + headers: createHeaders() + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get chat members', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getChatMembers'); + } +} + +// 대화방 생성 스키마 +const createChatroomSchema = z.object({ + requestId: z.number(), + chatType: z.number(), // 0: 1:1, 1: GROUP, 2: BROADCAST GROUP, 5: BROADCAST SINGLE + receivers: z.array(z.number()), + chatroomTitle: z.string().optional() +}); + +// 대화방 생성 +export async function createChatroom(data: z.infer): Promise> { + try { + const validated = createChatroomSchema.parse(data); + + // TODO: 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/createChatroomRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to create chatroom', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'createChatroom'); + } +} + +// 메시지 발송 스키마 +const sendMessageSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + chatMessageParams: z.array(z.object({ + msgId: z.number(), + msgType: z.number(), // 0: TEXT, 1: MEDIA, 7: RTF, 8: NCUSTOM + chatMsg: z.string(), + msgTtl: z.number().optional() + })) +}); + +// 메시지 발송 +export async function sendMessage(data: z.infer): Promise> { + try { + const validated = sendMessageSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/chatRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to send message', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'sendMessage'); + } +} + +// 대화상대 초대 스키마 +const inviteUserSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + invitingMembers: z.array(z.number()) +}); + +// 대화상대 초대 +export async function inviteUser(data: z.infer): Promise> { + try { + const validated = inviteUserSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/inviteRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to invite user', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'inviteUser'); + } +} + +// 대화상대 내보내기 스키마 +const removeUserSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + removingMembers: z.array(z.number()) +}); + +// 대화상대 내보내기 +export async function removeUser(data: z.infer): Promise> { + try { + const validated = removeUserSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/removeMemberRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to remove user', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'removeUser'); + } +} + +// 대화방 삭제 스키마 +const deleteChatroomSchema = z.object({ + requestId: z.number(), + chatroomId: z.number() +}); + +// 대화방 삭제 +export async function deleteChatroom(data: z.infer): Promise> { + try { + const validated = deleteChatroomSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/destroyChatroomRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to delete chatroom', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'deleteChatroom'); + } +} + +// 메시지 발신취소 스키마 +const recallMessageSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + msgId: z.number() +}); + +// 메시지 발신취소 +export async function recallMessage(data: z.infer): Promise> { + try { + const validated = recallMessageSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/recallMessageRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to recall message', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'recallMessage'); + } +} + +// 대화방명 변경 스키마 +const changeChatroomNameSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + chatroomTitle: z.string() +}); + +// 대화방명 변경 +export async function changeChatroomName(data: z.infer): Promise> { + try { + const validated = changeChatroomNameSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/changeChatroomMetaRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to change chatroom name', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'changeChatroomName'); + } +} + +// 방장 변경 스키마 +const changeOwnerSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + newOwnerUserId: z.number() +}); + +// 방장 변경 +export async function changeOwner(data: z.infer): Promise> { + try { + const validated = changeOwnerSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/changeOwnerRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to change owner', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'changeOwner'); + } +} + +// 대화방 나가기 스키마 +const leaveChatroomSchema = z.object({ + requestId: z.number(), + chatroomId: z.number() +}); + +// 대화방 나가기 +export async function leaveChatroom(data: z.infer): Promise> { + try { + const validated = leaveChatroomSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/endChatRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to leave chatroom', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'leaveChatroom'); + } +} + +// 메시지 읽음 카운트 조회 스키마 +const getMessageReadCountSchema = z.object({ + requestId: z.number(), + chatroomId: z.number(), + msgId: z.number() +}); + +// 메시지 읽음 카운트 조회 +export async function getMessageReadCount(data: z.infer): Promise> { + try { + const validated = getMessageReadCountSchema.parse(data); + + // 실제 구현에서는 메시지 서버 키를 사용하여 암호화해야 함 + const encryptedBody = JSON.stringify(validated); // 임시로 평문 사용 + + const response = await fetch(`${MESSENGER_BASE_URL}/messenger/message/api/v1.0/message/messageReadCountRequest`, { + method: 'POST', + headers: createHeaders(), + body: encryptedBody + }); + + const result = await response.json(); + + if (!response.ok) { + return { + success: false, + error: result.message || 'Failed to get message read count', + statusCode: response.status + }; + } + + return { + success: true, + data: result + }; + } catch (error) { + return handleApiError(error, 'getMessageReadCount'); + } +} + +// ============================================================================= +// 유틸리티 함수 +// ============================================================================= + +// 현재 시간을 밀리초로 반환 (requestId 생성용) +export async function generateRequestId(): Promise { + return Date.now(); +} + +// 메시지 ID 생성 (각 메시지마다 고유한 ID 필요) +export async function generateMessageId(): Promise { + return Date.now() + Math.floor(Math.random() * 1000); +} + +// 헬퍼 함수 - 간단한 텍스트 메시지 발송 +export async function sendTextMessage(chatroomId: number, message: string): Promise> { + const requestId = await generateRequestId(); + const msgId = await generateMessageId(); + + return sendMessage({ + requestId, + chatroomId, + chatMessageParams: [{ + msgId, + msgType: 0, // TEXT + chatMsg: message, + msgTtl: 7200 // 2시간 + }] + }); +} + +// 헬퍼 함수 - 그룹 대화방 생성 +export async function createGroupChatroom(userIds: number[], title?: string): Promise> { + const requestId = await generateRequestId(); + + return createChatroom({ + requestId, + chatType: 2, // BROADCAST GROUP + receivers: userIds, + chatroomTitle: title + }); +} + +// 헬퍼 함수 - 1:1 대화방 생성 +export async function createPrivateChatroom(userId: number): Promise> { + const requestId = await generateRequestId(); + + return createChatroom({ + requestId, + chatType: 5, // BROADCAST SINGLE + receivers: [userId] + }); +} diff --git a/lib/knox-api/realtime-notification/realtime-notification-guide.html b/lib/knox-api/realtime-notification/realtime-notification-guide.html new file mode 100644 index 00000000..728df9c1 --- /dev/null +++ b/lib/knox-api/realtime-notification/realtime-notification-guide.html @@ -0,0 +1,764 @@ +
+
+

실시간알림

+
+
+

Knox Suite을 통해 토스트 알림을 전송합니다.

+


+
[정책 및 제약사항]
+
+
+
1. 토스트알림은 Knox Suite 로그인 사용자에게만 전송가능합니다.
+
2. 토스트알림에 포함 된 링크는 호출 시 사전 확인 필요합니다.
+
3. 토스트알림 최대 수신인은 100명을 초과할 수 없습니다.
+
+


+
[API 목록]    테스트 페이지로 이동(Swagger)*Chrome Browser만 이용 가능합니다.
+
+
+ + + + + + + + + + + + + + + +
APIURIMethodDescription
+
+
+ + + + + + + + + + + + + + + +
알림 전송/sendnotificationPOST실시간 토스트 알림 전송
+
+



+


+
알림 전송
+
+

Request Parameter

URL : + /notification/api/v2.0/sendnotification +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeMandatoryParameter TypeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1연계 시스템 ID +    System-IDYHeaderStringC60REST0001발급받은 + 연계 ID
2수신계정   targetAddressYBodyString Array["knoxportal@samsung.com"]알림수신인 + 메일계정
3이벤트속성   ntypeYBodyStringNEW이벤트의 + 속성
4시스템이름   systemnameYBodyStringPush service외부 + 시스템 식별 Name
5알림표시명   fromYBodyString녹스포털 테스트외부 + 시스템 Toast 표시명(Local)
6알림표시명(영) +    fromGlobalYBodyStringKnox Portal Test외부 + 시스템 Toast 표시명(Global)
7Visual속성 +    exVisualVOYBodyJsonStringN/A알림 + Visual 속성
8토스트이름   templateNBodyStringdefault templatePre-Defined된 Toast + 이름
9로고이미지   skinNBodyStringdefault skinBackground 와 기본제공 + Logo 이미지
10영문사용여부 +    globalNBodyStringNText에 + 설정된 global 사용여부
11로고표시여부 +    logoNBodyStringYlogo + 표시여부
12로고이미지URL +    logourlNQueryStringhttp://www.samsung.net/logo.jpg불러올 + logo 표시 이미지 url
13Text속성 +    exTextVOYQueryJsonStringArrayN/A알림 + Text 속성
14표시문자열   contentYBodyString한글기준 10자이내, 30byte 이내표시 + 문자열
15표시문자열(영) +    contentglobalNBodyStringToast Title표시 + 문자열 Global
16표시문자크기 +    sizeNBodyInt512표시 + 문자열 문자 크기
17표시문자위치 +    posYBodyInt2표시 + 문자열 위치
18표시문자스타일 +    styleNBodyStringBOLD표시 + 문자열 문자 스타일
19Color속성 +    exColorVONBodyJsonStringN/A표시 + 문자열 문자 색상
20표시문자Red +    rYBodyInt255RGB + 값중 red 값
21표시문자Green +    gYBodyInt255RGB + 값중 green 값
22표시문자Blue +    bYBodyInt0RGB + 값중 blue 값
23Action속성 +    exActionsVOYBodyJsonStringN/A알림 + Action 속성
24팝업여부   popupNBodyStringYToast + 클릭 시 links 값 중 rel 이 popup인 href 호출
25클릭허용여부 +    clickableNBodyStringYToast + 영역 클릭 허용 여부
26Link속성 +    exLinksVONBodyJsonStringN/A알림 + Link 속성
27링크속성값   relNBodyStringpopup링크 식별 + 값
28링크URL   hrefNBodyStringhttp://www.samsung.netlink + URL
29부가 옵션   hintYHeaderStringmultibrowsermultibrowser값 지정 시 녹스포털을 로그인한 브라우저의 Tab으로 href URL을 로딩 +
* IE 는 Popup으로 표시됨
+
+
+
+

Response Parameter

+
호출 성공여부 및 알림의 키 값(UID)을 리턴합니다. +
+
+ + + + + + + + + + + + + + + + + + + +
No.PropertiesAttributeData TypeSample DataNote
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
1API 호출 + 성공여부   ResultStringSuccess실시간알림 연계 + 성공여부
2에러코드   ErrorCodeStringnull에러발생 + 시 코드 값
3응답메시지 및 알림 + ID   Message and IDStringAlarm Created, uid : 3cd8085ff2c4420bb4cf1828d6369ea4응답 + 메시지 및 알림 ID
+
+
+
+

Sample

+
+
+
+ + + + + + + + + + + +
RequestResponse
+
+
+ + + + + + + + + + + +
+
{
"targetAddress" : ["knoxportal@samsung.com"],
"ntype": "NEW",
"messageid": "EXT201804030305581008775022",
"systemname" : "push service",
"from" :"외부 알림 테스트",
"fromGlobal" : "External Notification Test ",
"exVisualVO": {
"template": "content",
"skin": "White",
"global": "N",
"logo": "Y",
"logourl": "",
"exTextVOList": [
{
"content": "제목",
"contentglobal": "Title",
"size": 14,
"pos": 1,
"exColorVO": {
"r": 0,
"g": 0,
"b": 0
},
"style": "BOLD"
}
]
},
"exActionsVO": {
"popup": "Y",
"snooze": "N",
"clickable": "Y",
"hint": "multibrowser",
"exLinksVOList":
[
{
"rel": "popup",
"href": "http://naver.com",
"args" : ""
}
]
}
}
+
+
+
{
"result": "OK",
"errorCode": null,
"message": "Alarm Created, uid : 3cd8085ff2c4420bb4cf1828d6369ea4"
}
+
+
+
+
+
+

Error Code

+
+
+
+ + + + + + + + + + + + + + + +
HTTP응답코드에러코드에러메시지조치방안
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
400EX001Notification information is null.알림 인풋 + 전체가 NULL일 경우 발생
400EX002[ntype] value is NEW or RECALL.ntype + 값이 NEW이거나 RECALL이지 않은 경우 발생
400EX003[from] is mendentory.from값이 + 입력되지 않은 경우 발생
400EX004[fromGlobal] is mendentory.fromGlobal값이 입력되지 않은 경우 + 발생
400EX006[systemname] is mendentory.systemname값이 입력되지 않은 경우 + 발생
400EX007[exVisualVO] is mendentory.exVisualVO값이 입력되지 않은 경우 + 발생
400EX008[exActionsVO] is mendentory.exActionsVO값이 입력되지 않은 경우 + 발생
400EX009The length of [template] is max 10 characters.template 값이 10자 이상 입력될 경우 + 발생
400EX010The length of [skin] is max 10 characters.skin 값이 + 10자 이상 입력될 경우 발생
400EX011The value of [global] value is not Y or N.global + 값이 Y혹은 N이 입력되지 않는 경우 발생
400EX012The value of [logo] value is not Y or N.logo 값이 + Y 혹은 N이 입력되지 않는 경우 발생
400EX013The value of [logourl] must start with url pattern(http://).Logourl값이 정상적인 URL이 아닌 경우 + 발생(http://로 시작필요)
400EX014[exTextVO] is mendentory.exTextVO 값이 입력되지 않은 경우 + 발생
400EX015[content] is mendentory.content + 값이 입력되지 않은 경우 발생
400EX016[R,G,B] value range is 0 to 255.R,G,B + 값이 0~255범위에서 벗어나는 경우 발생
400EX017For the requested search conditions, paging is not possible.href 값이 + 정상적인 URL이 아닌 경우 발생(http://로 시작필요)
400EX018The value of [template] encoding is supported UTF-8.Template 값이 UTF-8로 인코딩 되지 + 않은 경우 발생
400EX019The value of [skin] encoding is supported UTF-8.Skin 값이 + UTF-8로 인코딩 되지 않은 경우 발생
400EX020The value of [rel] is max 10 characters.Rel 값이 + 10자 이상 입력될 경우 발생
400EX021The value of [rel] encoding is supported UTF-8.rel 값이 + UTF-8로 인코딩 되지 않은 경우 발생
400EX022[targetAddress] is invalid. Check if an on-leave or retired person.targetAddress 값의 임직원 정보가 없는 + 경우 발생
400EX023[size] value range is 0 to 1024.size 값이 + 0~1024범위에서 벗어나는 경우 발생
400EX024[pos] value range is 1 to 3.pos 값이 + 1~3위에서 벗어나는 경우 발생
+
+


+
\ No newline at end of file diff --git a/lib/knox-api/realtime-notification/realtime-notification.ts b/lib/knox-api/realtime-notification/realtime-notification.ts new file mode 100644 index 00000000..a26f5b55 --- /dev/null +++ b/lib/knox-api/realtime-notification/realtime-notification.ts @@ -0,0 +1,333 @@ +"use server" + +import { z } from "zod" + +// 타입 정의 +const ColorSchema = z.object({ + r: z.number().min(0).max(255), + g: z.number().min(0).max(255), + b: z.number().min(0).max(255), +}) + +const TextSchema = z.object({ + content: z.string().min(1), + contentglobal: z.string().optional(), + size: z.number().min(0).max(1024).optional(), + pos: z.number().min(1).max(3), + exColorVO: ColorSchema.optional(), + style: z.string().optional(), +}) + +const LinkSchema = z.object({ + rel: z.string().max(10).optional(), + href: z.string().url().optional(), + args: z.string().optional(), +}) + +const VisualSchema = z.object({ + template: z.string().max(10).optional(), + skin: z.string().max(10).optional(), + global: z.enum(["Y", "N"]).optional(), + logo: z.enum(["Y", "N"]).optional(), + logourl: z.string().url().optional(), + exTextVOList: z.array(TextSchema), +}) + +const ActionsSchema = z.object({ + popup: z.enum(["Y", "N"]).optional(), + snooze: z.enum(["Y", "N"]).optional(), + clickable: z.enum(["Y", "N"]).optional(), + hint: z.string().optional(), + exLinksVOList: z.array(LinkSchema).optional(), +}) + +const NotificationRequestSchema = z.object({ + targetAddress: z.array(z.string().email()).max(100), + ntype: z.enum(["NEW", "RECALL"]), + messageid: z.string().optional(), + systemname: z.string().min(1), + from: z.string().min(1), + fromGlobal: z.string().min(1), + exVisualVO: VisualSchema, + exActionsVO: ActionsSchema, +}) + +export type NotificationRequest = z.infer +export type NotificationColor = z.infer +export type NotificationText = z.infer +export type NotificationLink = z.infer +export type NotificationVisual = z.infer +export type NotificationActions = z.infer + +// 응답 타입 +export interface NotificationResponse { + result: string + errorCode: string | null + message: string +} + +// 에러 타입 +export interface NotificationError { + httpStatus: number + errorCode: string + message: string +} + +// 환경 변수 검증 +const getApiConfig = () => { + const baseUrl = process.env.KNOX_API_BASE_URL + const systemId = process.env.KNOX_SYSTEM_ID + + if (!baseUrl || !systemId) { + throw new Error("Knox API configuration missing: KNOX_API_BASE_URL and KNOX_SYSTEM_ID are required") + } + + return { baseUrl, systemId } +} + +/** + * Knox Suite 실시간 토스트 알림 전송 + */ +export async function sendNotification( + request: NotificationRequest +): Promise { + try { + // 요청 데이터 검증 + const validatedRequest = NotificationRequestSchema.parse(request) + + const { baseUrl, systemId } = getApiConfig() + + const response = await fetch(`${baseUrl}/notification/api/v2.0/sendnotification`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "System-ID": systemId, + "hint": validatedRequest.exActionsVO.hint || "multibrowser", + }, + body: JSON.stringify(validatedRequest), + }) + + if (!response.ok) { + const errorData = await response.json() + throw new Error(`API Error: ${errorData.message || response.statusText}`) + } + + const result: NotificationResponse = await response.json() + return result + + } catch (error) { + console.error("Knox notification error:", error) + throw error + } +} + +/** + * 간단한 토스트 알림 전송 (기본 설정 사용) + */ +export async function sendSimpleNotification( + targetEmails: string[], + title: string, + titleGlobal: string, + systemName: string, + link?: string +): Promise { + const notification: NotificationRequest = { + targetAddress: targetEmails, + ntype: "NEW", + systemname: systemName, + from: title, + fromGlobal: titleGlobal, + exVisualVO: { + template: "content", + skin: "White", + global: "N", + logo: "Y", + logourl: "", + exTextVOList: [ + { + content: title, + contentglobal: titleGlobal, + size: 14, + pos: 1, + exColorVO: { + r: 0, + g: 0, + b: 0, + }, + style: "BOLD", + }, + ], + }, + exActionsVO: { + popup: "Y", + clickable: "Y", + hint: "multibrowser", + exLinksVOList: link ? [ + { + rel: "popup", + href: link, + args: "", + }, + ] : [], + }, + } + + return await sendNotification(notification) +} + +/** + * 알림 취소 (RECALL) + */ +export async function recallNotification( + targetEmails: string[], + systemName: string, + messageId: string +): Promise { + const notification: NotificationRequest = { + targetAddress: targetEmails, + ntype: "RECALL", + messageid: messageId, + systemname: systemName, + from: "알림 취소", + fromGlobal: "Notification Recall", + exVisualVO: { + template: "content", + skin: "White", + global: "N", + logo: "Y", + logourl: "", + exTextVOList: [ + { + content: "알림이 취소되었습니다", + contentglobal: "Notification has been recalled", + size: 14, + pos: 1, + exColorVO: { + r: 255, + g: 0, + b: 0, + }, + style: "BOLD", + }, + ], + }, + exActionsVO: { + popup: "N", + clickable: "N", + hint: "multibrowser", + }, + } + + return await sendNotification(notification) +} + +/** + * 사용자 정의 스타일 토스트 알림 + */ +export async function sendCustomNotification( + targetEmails: string[], + systemName: string, + title: string, + titleGlobal: string, + options: { + template?: string + skin?: string + logoUrl?: string + textColor?: NotificationColor + textSize?: number + textStyle?: string + link?: string + linkRel?: string + } = {} +): Promise { + const notification: NotificationRequest = { + targetAddress: targetEmails, + ntype: "NEW", + systemname: systemName, + from: title, + fromGlobal: titleGlobal, + exVisualVO: { + template: options.template || "content", + skin: options.skin || "White", + global: "N", + logo: options.logoUrl ? "Y" : "Y", + logourl: options.logoUrl || "", + exTextVOList: [ + { + content: title, + contentglobal: titleGlobal, + size: options.textSize || 14, + pos: 1, + exColorVO: options.textColor || { + r: 0, + g: 0, + b: 0, + }, + style: options.textStyle || "BOLD", + }, + ], + }, + exActionsVO: { + popup: options.link ? "Y" : "N", + clickable: options.link ? "Y" : "N", + hint: "multibrowser", + exLinksVOList: options.link ? [ + { + rel: options.linkRel || "popup", + href: options.link, + args: "", + }, + ] : [], + }, + } + + return await sendNotification(notification) +} + +/** + * 헬퍼 함수: 알림 ID 추출 + */ +export async function extractNotificationId(response: NotificationResponse): Promise { + if (response.result === "OK" && response.message) { + const match = response.message.match(/uid\s*:\s*([a-f0-9]+)/i) + return match ? match[1] : null + } + return null +} + +/** + * 헬퍼 함수: 여러 사용자에게 배치 알림 전송 + */ +export async function sendBatchNotifications( + notifications: Array<{ + targetEmails: string[] + title: string + titleGlobal: string + systemName: string + link?: string + }> +): Promise { + const results: NotificationResponse[] = [] + + for (const notification of notifications) { + try { + const result = await sendSimpleNotification( + notification.targetEmails, + notification.title, + notification.titleGlobal, + notification.systemName, + notification.link + ) + results.push(result) + } catch (error) { + console.error("Batch notification error:", error) + results.push({ + result: "ERROR", + errorCode: "BATCH_ERROR", + message: error instanceof Error ? error.message : "Unknown error", + }) + } + } + + return results +} -- cgit v1.2.3