腾讯聊天与Salesforce集成:开发者的综合指南

10 분 읽기
May 7, 2025

시나리오 개요

이 튜토리얼은 Salesforce의 워크플로우에 Chat SDK를 통합하는 접근 방식을 시연하여 Salesforce 에이전트와 최종 사용자 간의 커뮤니케이션을 활용하는 것을 목표로 합니다.

적용된 제품

채팅

기본 통합 지침

사전 준비

1. Tencent RTC에 가입하고, 앱을 생성하고 채팅 서비스를 등록합니다. 가이드라인를 참조하세요.

2. Salesforce 개발자 계정에 가입합니다. 계정이 없다면 여기 클릭하세요.

로드맵

목표를 달성하기 위해 세 가지 부분이 필수적입니다.

1. 최종 사용자가 대화를 시작할 수 있는 애플리케이션.

2. Salesforce 사례를 생성하고 채팅 그룹을 만드는 온라인 서버. 또한 Salesforce 에이전트를 그룹에 초대/삭제하고 사례가 종료될 때 그룹을 해체하는 API를 제공합니다.

3. Salesforce 내에서 통신하기 위한 맞춤형 Salesforce 유틸리티 컴포넌트.

다음은 통합 맵입니다:

통합 맵입니다:

- 최종 사용자가 실시간 통신을 통해 웹 서버와 상호 작용합니다.
- 최종 사용자가 웹 서버에서 티켓을 생성합니다.

최종 사용자 애플리케이션

Chat은 가장 인기 있는 플랫폼에 대한 다양한 SDK를 제공하며, 원하는 플랫폼의 SDK를 선택할 수 있습니다. SDK를 확인하려면 안드로이드, iOS, , Flutter, Windows, Unity, Unreal Engine. 애플리케이션을 처음부터 구축하는 추천 방법은 TUIKit을 사용하여 인터페이스를 레이어링하는 것입니다. 자세한 내용은 안드로이드, iOS, , Flutter.

온라인 서버 중계

여기서는 최종 사용자가 Salesforce 사례를 제출하고 채팅 그룹을 생성할 수 있도록 웹 서버를 단계별로 만드는 방법을 안내합니다. 또한 Salesforce 에이전트를 채팅 그룹에 초대하거나 제거하고, 사례가 종료되면 그룹을 삭제할 수 있습니다.

에이전트 채팅 인터페이스

이 튜토리얼에서는 Salesforce에서 채팅 인터페이스를 만들고 에이전트를 채팅 그룹에 초대하는 방법을 제공합니다. 또한 UIKit을 사용하여 이 플러그인 위젯을 구축할 수 있습니다.

시나리오별 구현

온라인 서버 생성

온라인 서버는 Salesforce와 Chat을 연결하고 최종 사용자가 Salesforce 사례를 생성하고 해당 채팅 그룹을 생성할 수 있도록 하기 위한 것입니다. 다음은 예제 Node 서버입니다:

const express = require("express")
const axios = require("axios")
var TLSSigAPIv2 = require("tls-sig-api-v2") // Chat용 UserSig 생성
const sf = require("node-salesforce") // Node.js 애플리케이션용 Salesforce API 연결 라이브러리

const YOUR_SDKAPPID = 1400000000
const YOUR_SECRET = ""
const ADMIN_USERID = ""

const app = express()
app.use(express.json())

const port = process.env.PORT || 3000

app.use(express.json())

app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "https://YOUR_DOMAIN")
  res.header("Access-Control-Allow-Headers", "*")
  next()
})

// 최종 사용자가 /createticket을 호출하여 Salesforce 사례와 Chat 채팅 그룹을 생성합니다. Salesforce 에이전트가 그룹에 참여하기를 기다립니다.
app.post("/createticket", async (req, res) => {
  const { userId, caseInfo } = req.body
  if (!userId) return res.status(500).send("userId가 누락되었습니다.")

  const auth = await getSalesforceAccessToken()
  if (auth.error) return res.status(500).send("Salesforce 인증 오류")

  const salesforceCase = await createCase(auth.token, caseInfo)
  if (!salesforceCase.success)
    return res.status(500).send("사례 생성 실패")

  const groupName = salesforceCase.id
  const result = await createGroup(groupName, userId)
  if (result.ErrorCode !== 0)
    return res.status(500).send("그룹 생성 실패")

  res.status(200).send(result)
})

// 그룹에 새 에이전트가 할당되면 Salesforce가 이 에이전트를 채팅 그룹에 추가하라는 요청을 보냅니다.
app.post("/joingroup", async (req, res) => {
  const { groupId, userId } = req.body
  if (!userId) return res.status(500).send("userId가 누락되었습니다.")
  if (!groupId) return res.status(500).send("groupId가 누락되었습니다.")

  const result = await joinGroup(groupId, userId)
  if (result.ErrorCode !== 0)
    return res.status(500).send("그룹 참여 실패")

  res.status(200).send(result)
})

// 에이전트가 그룹에서 제거되면 Salesforce가 이 에이전트를 채팅 그룹에서 제거하라는 요청을 보냅니다.
app.post("/leavegroup", async (req, res) => {
  const { groupId, userId } = req.body
  if (!userId) return res.status(500).send("userId가 누락되었습니다.")
  if (!groupId) return res.status(500).send("groupId가 누락되었습니다.")

  const result = await leaveGroup(groupId, userId)
  if (result.ErrorCode !== 0)
    return res.status(500).send("그룹 탈퇴 실패")

  res.status(200).send(result)
})

app.post("/deletegroup", async (req, res) => {
  const { groupId } = req.body
  if (!groupId) return res.status(500).send("groupId가 누락되었습니다.")

  const result = await deleteGroup(groupId)
  if (result.ErrorCode !== 0)
    return res.status(500).send("그룹 삭제 실패")

  res.status(200).send(result)
})

const getSalesforceAccessToken = async function () {
  const url = "https://{your_instance}.salesforce.com"
  const conn = new sf.Connection({ loginUrl: url })
  try {
    await conn.login("SF_EMAIL", "SF_PASSWORDSF_TOKEN")
    return { error: undefined, token: conn.accessToken }
  } catch (e) {
    return { error: e, token: undefined }
  }
}

const createCase = async function (token, caseInfo) {
  const { subject, desc, name, email } = caseInfo
  const body = {
    Subject: subject,
    Description: desc,
    SuppliedName: name,
    SuppliedEmail: email,
  }
  const headers = {
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer " + token,
    },
  }
  const url =
    "https://{your_instance}.salesforce.com/services/data/v{api_version}/sobjects/Case"
  try {
    const result = await axios.post(url, body, headers)
    return result.data
  } catch (e) {
    return { id: undefined, success: false, error: e }
  }
}

const generateUserSig = function () {
  const expires = 600
  const api = new TLSSigAPIv2.Api(YOUR_SDKAPPID, YOUR_SECRET)
  return api.genSig(ADMIN_USERID, expires)
}

const generateRandom = function () {
  return Math.floor(Math.random() * 4294967295)
}

const createGroup = async function (groupName, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  // salesforceCase.id를 그룹 ID로 사용
  const data = { Owner_Account: userId, Type: "Public", Name: groupName, GroupId: groupName }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/create_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
    const groupRes = await axios.post(url, data)
    return groupRes.data
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e }
  }
}

const joinGroup = async function (groupId, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId, MemberList: [{ Member_Account: userId }] }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/add_group_member?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
    const groupRes = await axios.post(url, data)
    return groupRes.data
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e }
  }
}

const leaveGroup = async function (groupId, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId, MemberToDel_Account: [userId] }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/delete_group_member?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
    const groupRes = await axios.post(url, data)
    return groupRes.data
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e }
  }
}

const deleteGroup = async function (groupId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/destroy_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
    const groupRes = await axios.post(url, data)
    return groupRes.data
  } catch (e) {
    return { ErrorCode: -1, ErrorInfo: e }
  }
}

app.listen(process.env.PORT || port, () =>
  console.log(`예제 앱이 포트 ${port}에서 실행 중입니다!`)
)

서버는 최종 사용자가 Salesforce에서 사례를 생성하고 채팅에서 그룹을 생성할 수 있는 /createticket 경로를 지원합니다. 여기서 우리는 다음을 수행합니다:

1. 먼저 Salesforce에서 accessToken을 가져옵니다. 더 많은 정보는 SF_TOKEN를 참조하세요.

const getSalesforceAccessToken = async function () {
  const url = "https://{your_instance}.salesforce.com"
  const conn = new sf.Connection({ loginUrl: url })
  try {
 await conn.login("SF_EMAIL", "SF_PASSWORDSF_TOKEN")
 return { error: undefined, token: conn.accessToken }
  } catch (e) {
 return { error: e, token: undefined }
  }
}

2. Salesforce 사례를 생성합니다.

const createCase = async function (token, caseInfo) {
  const { subject, desc, name, email } = caseInfo
  const body = {
 Subject: subject,
 Description: desc,
 SuppliedName: name,
 SuppliedEmail: email,
  }
  const headers = {
 headers: {
   "Content-Type": "application/json",
   Authorization: "Bearer " + token,
 },
  }
  const url =
 "https://{your_instance}.salesforce.com/services/data/v{api_version}/sobjects/Case"
  try {
 const result = await axios.post(url, body, headers)
 return result.data
  } catch (e) {
 return { id: undefined, success: false, error: e }
  }
}

3. Chat을 위한 UserSig을 생성합니다.

 const generateUserSig = function () {
  const expires = 600
  const api = new TLSSigAPIv2.Api(YOUR_SDKAPPID, YOUR_SECRET)
  return api.genSig(ADMIN_USERID, expires)
}

4. 사례 ID와 사용자 ID로 Chat 그룹을 생성합니다.

const createGroup = async function (groupName, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { Owner_Account: userId, Type: "Public", Name: groupName }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/create_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
 const groupRes = await axios.post(url, data)
 return groupRes.data
  } catch (e) {
 return { ErrorCode: -1, ErrorInfo: e }
  }
}

또한 웹 서버는 사례 ID 및 에이전트 ID로 채팅 그룹에 참여/탈퇴/삭제할 수 있는 경로를 제공합니다. 이는 Salesforce 트리거가 사례 에이전트의 변경을 감지할 때 사용됩니다. 자세한 내용은 3단계에서 논의됩니다.

const joinGroup = async function (groupId, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId, MemberList: [{ Member_Account: userId }] }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/add_group_member?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
 const groupRes = await axios.post(url, data)
 return groupRes.data
  } catch (e) {
 return { ErrorCode: -1, ErrorInfo: e }
  }
}

const leaveGroup = async function (groupId, userId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId, MemberToDel_Account: [userId] }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/delete_group_member?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
 const groupRes = await axios.post(url, data)
 return groupRes.data
  } catch (e) {
 return { ErrorCode: -1, ErrorInfo: e }
  }
}

const deleteGroup = async function (groupId) {
  const sig = generateUserSig()
  const random = generateRandom()
  const data = { GroupId: groupId }
  const url = `https://console.tim.qq.com/v4/group_open_http_svc/destroy_group?sdkappid=${YOUR_SDKAPPID}&identifier=${ADMIN_USERID}&usersig=${sig}&random=${random}&contenttype=json`
  try {
 const groupRes = await axios.post(url, data)
 return groupRes.data
  } catch (e) {
 return { ErrorCode: -1, ErrorInfo: e }
  }
}

이것으로 웹 서버 측 설정이 완료됩니다. 서버를 설정한 후 /createticket 엔드포인트를 호출하고:

  1. Salesforce에서 사례가 생성되었는지 확인합니다.
  2. Chat 콘솔에서 그룹이 사례 ID로 생성되었는지 확인합니다.

Chat Web UI Kit을 사용하여 Salesforce 유틸리티 컴포넌트 구축

여기에서는 Chat UI Kit을 사용하여 Salesforce 유틸리티 컴포넌트를 만드는 단계를 보여줍니다. Salesforce에서는 Lightning Container를 사용하여 제3자 i-frame을 정적 리소스로 업로드하고, Aura 구성 요소를 사용하여 내용을 호스팅합니다. 그리고 Chat Web UIKit을 사용하여 에이전트 채팅 컴포넌트를 구축하고, 이를 Lightning Container로 배치하여 Salesforce 유틸리티 바 위젯으로 표시합니다.

1. 먼저 Chat Web UIKit을 사용하여 채팅 컴포넌트를 개발합니다. 루트 index.html로 정적 리소스로 구축하고 zip 파일로 압축합니다. 사례 에이전트의 ID는 채팅 컴포넌트에 전달되며, 해당 ID를 사용하여 채팅에서 초기화 및 로그인합니다.

채팅 컴포넌트 개발
UI Kit 사용
정적 리소스 압축
에이전트 ID 전송
초기화 및 로그인

2. 컴포넌트를 위한 Lightning Container를 생성합니다. 자세한 내용은 여기.

    2.1 Salesforce 개발자 콘솔에 들어갑니다. 

    2.2 파일 -> 새로 만들기 -> Lightning Component를 클릭합니다. 

    2.3 이름 = "tim_utilities_bar" 

    2.4 제출을 클릭합니다.

3. 사용자 정의 컴포넌트를 유틸리티 바 위젯에 렌더링합니다. 3.1 aura:component를 유틸리티 바로 설정하고 aura:id를 제공합니다.

<!-- tim_utilities_bar.cmp -->
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  <lightning:utilityBarAPI aura:id='utilitybar'" />
</aura:component>

3.2 정적 리소스를 Lightning Container에 업로드합니다.

a. Salesforce 정적 리소스로 가서 "tim_bar"라는 새로운 리소스를 생성합니다.

b. 리소스의 zip 파일을 업로드하고 "캐시 제어"를 "공개"로 설정합니다. 

c. 저장을 클릭합니다.

노트:

  • index.html은 항상 .zip 파일의 루트 수준에 있어야 합니다.
  • 파일을 업로드한 후 반드시 "저장"을 클릭해야 합니다.
  • Salesforce는 리소스 이름을 저장하며, .zip 파일의 이름은 저장하지 않습니다.
  • Lightning Component에서 사용하는 모든 코드와 자산은 .zip 파일에 포함되어야 합니다. CSP 신뢰된 사이트 목록에 화이트리스트가 있는 외부 코드 종속성은 작동하지 않습니다.

3.3 유틸리티 바 위젯에서 정적 리소스 "tim_bar"를 참조합니다.

a. 유틸리티 바 위젯에 lightning:container 태그를 추가합니다. aura:id는 "TIM_Bar"이어야 합니다. b. 정적 리소스를 참조합니다. "{!$Resource.tim_bar + '/index.html'}" . tim_bar는 저장된 "정적 리소스"이며, 업로드된 .zip 파일의 이름이 아닙니다.

<!-- tim_utilities_bar.cmp -->
<aura:component implements="flexipage:availableForAllPageTypes" access="global">
  <lightning:utilityBarAPI aura:id='utilitybar'" />
  <aura:attribute name="recordId" type="String" />
  <aura:attribute name="data" type="String" />
  <lightning:navigation aura:id='navService'" />
  <lightning:container
    aura:id='TIM_Bar'"
    src="{!$Resource.tim_bar + '/index.html'}"
  />
</aura:component>

3.4 Salesforce에 표시되도록 유틸리티 바 위젯을 추가합니다. 

  1. "설정" 클릭 후 "앱 관리자" 검색하여 유틸리티 바 위젯이 나타날 위치를 설정합니다. 
  2. 서비스 콘솔 앱에서 "▾" 클릭 후 "편집"을 클릭합니다. 
  3. 앱 설정에서 "유틸리티 항목(데스크탑 전용)"을 클릭합니다. 
  4. "유틸리티 항목 추가"를 클릭합니다. 
  5. "tim_utilities_bar"를 선택합니다. 
  6. 너비와 높이를 설정합니다. 
  7. "자동 시작"을 체크합니다. 
  8. "저장"을 클릭합니다.

3.5 Salesforce CSP 파일을 업데이트하여 Salesforce에서 Chat에 접근할 수 있는 권한을 부여합니다. 

  1. Salesforce -> 설정 -> 검색 -> "CSP 신뢰된 사이트"로 이동합니다. 
  2. "새 신뢰된 사이트 추가"(모든 CSP 지시문 허용): wss://wss.im.qcloud.com 
  3. Salesforce -> 설정 -> 검색 -> "CORS"로 이동합니다. 
  4. "새 허용된 출처 목록" 추가: https://.qq.com https://.qcloud.com 
  5. Salesforce -> 설정 -> 검색 -> ""로 이동합니다. 
  6. "새 원격 사이트" 목록 추가: 웹 서버의 URL!

4. Lightning Container를 초기화합니다.

  • Lightning Container가 준비되면 LLC 메시지를 보내 알립니다. 
  • 유틸리티 바 위젯은 에이전트의 ID를 우리 컴포넌트에 전송해야 합니다. 
  • 유틸리티 바 위젯에서 받은 메시지를 기반으로 UIKit을 렌더링합니다.

다음 코드를 따라 하세요:

// tim_utilities_barController.js
({
handleMessage: function(component, message, helper) {
var payload = message.getParams().payload
// 컨테이너가 준비되면 initUIKit
if (payload === "READY") helper.initUIKit(component, message, helper)
}
});
({
initUIKit: function (component, message, helper) {
// 에이전트의 ID 가져오기
var userId = $A.get("$SObjectType.CurrentUser.Id")
var message = { userId: userId }
try {
// ID를 컴포넌트에 전송합니다.
component.find("TIM_Bar").message(message)
} catch (err) {
console.error("유틸리티 바에서 오류 발생:", err)
}
},
})

유틸리티 바 위젯에 onMessage 핸들러를 추가합니다:

<!-- tim_utilities_bar.cmp -->
<lightning:container
aura:id='TIM_Bar'"
src="{!$Resource.tim_bar + '/index.html'}"
onmessage="{!c.handleMessage}"
/>

스크립트에서 LLC 패키지 를 사용하여 Lightning Container가 로드되었을 때 앱을 렌더링합니다.

// index.js
try {
const clientState = "READY";
LLC.sendMessage(clientState);
console.warn("Lightning Container --> Salesforce --> 전송됨:", clientState);
} catch (e) {
console.error("LLC 작동하지 않음", e);
}
try {
LLC.addErrorHandler((error) => console.log("LLC 오류:", error));
LLC.addMessageHandler((salesforceMessage) => {
console.warn("Salesforce --> Lightning Container --> 도착:", salesforceMessage);
const app = createApp(App, {
user: salesforceMessage
});
app
.use(store)
.use(router)
.use(TUIKit)
.use(Aegis)
.use(ElementPlus)
.mount('#app');
});
} catch (e) {
console.error("LLC에서 오류 발생!!", e);
}

Salesforce 사례 할당을 듣고 Chat 그룹 멤버 설정

Salesforce에서는 사례가 수동 또는 자동으로 에이전트에게 할당됩니다. 따라서 새 에이전트를 그룹에 초대하고 이전 에이전트를 그룹에서 제거해야 합니다. Salesforce Apex 호출을 사용하여 사례 에이전트 할당 변경을 듣습니다. 다음은 Salesforce Apex 호출을 호출하여 수행해야 할 작업입니다.

1. 수동 사례 할당 듣기

지정된 에이전트가 한 사례로 변경되면 Apex 사례 변경 트리거가 Apex 호출을 호출합니다. 호출에서 a. 이전 에이전트를 Chat 그룹에서 삭제하고 b. 새 에이전트를 그룹에 초대합니다. 사례가 삭제되면 채팅 그룹도 해체합니다.

Salesforce 개발자 콘솔로 이동 -> 새로 만들기 -> Apex Trigger -> 이름 = "AssignAgent" & sObject = "Case"

// AssignAgent.apxt
trigger AssignAgent on Case (after update, after delete) {
     if(trigger.isUpdate){
       // 사례가 업데이트되고 있습니다.
       System.debug('사례 업데이트 발화:');
       for(Case a : trigger.new){
         Case oldCase = trigger.oldMap.get(a.ID);
         if(String.valueOf(a.OwnerId).substring(0, 3) == '005'){
           // 소유자 에이전트 ID가 변경되었습니다. 005 접두사는 에이전트 ID를 의미합니다.
           System.debug('초대된 에이전트 :' + a.OwnerId);
           // Chat 그룹에 새 소유자를 할당합니다.
           String[] data = new String[2];
           data[0] = a.Id; // 사례 ID는 그룹 ID입니다.
           data[1] = a.OwnerId;
           TimCallouts.joinGroup(data); // 사용자 정의 호출 클래스
         }
         // 새 사례 에이전트가 현재 에이전트와 다릅니다.
         if(String.valueOf(oldCase.OwnerId).substring(0, 3) == '005' && oldCase.OwnerId != a.OwnerId && String.valueOf(a.OwnerId).substring(0, 3) == '005'){
           // 그룹에서 이전 에이전트를 삭제합니다.
           // 주의: 사례의 첫 번째 소유자는 시스템 소유자가 됩니다.
           System.debug('이전 에이전트가 그룹에서 제거됩니다.' + a.Id);
           System.debug('leaveGroup: ' + oldCase.OwnerId);
           String[] removeData = new String[2];
           removeData[0] = a.Id; // 사례 ID는 그룹 ID입니다.
           removeData[1] = oldCase.OwnerId;
           TIMCallouts.leaveGroup(removeData);
         }
       }
   }
   if(trigger.isDelete ){
     // 사례가 삭제되고 있습니다.
     System.debug('사례 삭제 발화:');
     for(Case a : trigger.old){
       if(String.valueOf(a.OwnerId).substring(0, 3) == '005'){
         System.debug('그룹 삭제 :' + a.Id);
         String[] data = new String[1];
         data[0] = a.Id;
         TimCallouts.deleteGroup(data); // 사용자 정의 호출 클래스
       }
     }
   }
 }

2. Salesforce 옴니 채널에 의한 자동 사례 할당 듣기

옴니 채널은 사례 할당을 감지하고 Salesforce는 자동으로 AgentWork 객체를 생성합니다. 에이전트가 할당을 수락하면 AgentWork 트리거가 Salesforce 호출을 사용하여 그룹에 참여하도록 할 수 있습니다.

Salesforce 개발자 콘솔로 이동 -> 새로 만들기 -> Apex Trigger -> 이름 = "AgentOmniChannel" & sObject = "AgentWork"

// AgentOmniChanne.apxt
trigger AgentOmniChannel on AgentWork (after update, after insert) {
    if(Trigger.isUpdate){
      for(AgentWork a : Trigger.new){
            AgentWork oldCase = Trigger.oldMap.get(a.ID);
            if(a.Status == 'Opened' && String.valueOf(a.OwnerId).substring(0, 3) == '005' ){
              String[] data = new String[2];
              data[0] = a.WorkItemId;
              data[1] = a.OwnerId;
              TIMCallouts.joinGroup(data);
            }
      }
    }
}

3. 에이전트를 초대/제거하기 위한 Salesforce 호출 설정

Salesforce 개발자 콘솔로 이동 -> 새로 만들기 -> Apex Class -> 이름 = "TIMCallOuts"

// TIMCallOuts.apxc
public class TIMCallouts {
  @future(callout=true)
  public static void joinGroup(String[] data) {
    String groupId = data[0];
    String userId = data[1];
    Http http = new Http();
    HttpRequest request = new HttpRequest();
    request.setEndpoint('https://{your_web_server}/joingroup');
    request.setMethod('POST');
    request.setHeader('Content-Type', 'application/json;charset=UTF-8');
    request.setBody('{"userId":"'+ userId +'", "groupId":"'+ groupId +'"}');
    HttpResponse response = http.send(request);
    // JSON 응답 파싱
      if (response.getStatusCode() != 200) {
        System.debug('그룹 참여 실패: '+response.getStatusCode()+' '+response.getStatus());
      } else {
        System.debug('Tencent Chat 응답: ' + response.getBody());
      }
  }

  @future(callout=true)
  public static void leaveGroup(String[] data) {
      String groupId = data[0];
      String userId = data[1];
      Http http = new Http();
      HttpRequest request = new HttpRequest();
      request.setEndpoint('https://{your_web_server}/leavegroup');
      request.setMethod('POST');
      request.setHeader('Content-Type', 'application/json;charset=UTF-8');
      // 본문을 JSON 객체로 설정
      request.setBody('{"userId":"'+ userId +'", "groupId":"'+ groupId +'"}');
      HttpResponse response = http.send(request);
      // JSON 응답 파싱
      if (response.getStatusCode() != 200) {
        System.debug('그룹 탈퇴 실패: ' + response.getStatusCode() + ' ' + response.getStatus());
      } else {
        System.debug('Tencent Chat 응답: ' + response.getBody());
      }
    }

    @future(callout=true)
    public static void deleteGroup(String data) {
      String groupId = data;
      Http http = new Http();
      HttpRequest request = new HttpRequest();
      request.setEndpoint('http://{your_web_server}/deletegroup');
      request.setMethod('POST');
      request.setHeader('Content-Type', 'application/json;charset=UTF-8');
      // 본문을 JSON 객체로 설정
      request.setBody('{"groupId":"'+ groupId + '}');
      HttpResponse response = http.send(request);
      // JSON 응답 파싱
      if (response.getStatusCode() != 200) {
        System.debug('그룹 삭제 실패: ' + response.getStatusCode() + ' ' + response.getStatus());
      } else {
        System.debug('Tencent Chat 응답: ' + response.getBody());
      }
    }
}

이제 최종 사용자가 어떤 애플리케이션에서도 Salesforce 에이전트와 채팅을 시작할 수 있도록 하는 모든 정보를 알고 있습니다. 추가 질문이 있으시면 이메일(info_rtc@tencent.com)로 문의해 주세요. 솔루션이나 현대적인 실시간 통신 시스템 구축에 대해 더 많은 세부정보를 제공해 드리겠습니다.

지금 주문하기

클릭하여 여기 빠르게 구매 페이지로 이동하십시오.