채팅 Webhook
Photon Cloud에서 webhook를 사용하여 채팅 어플리케이션을 더 많이 제어할 수 있습니다.
채널 이력 저장, 메시지 필터, 채널 생성 취소와 특정 플레이어가 채팅 룸을 구독하는 것도 금지 할 수 있습니다.
Photon 채팅 webhook는 Photon Cloud가 특정 URL로 전송하는 이벤트-기반의 HTTP POST 요청입니다.
개별 Photon 채팅 webhook는 소유자 트리거, 데이터와 목적지 경로에 의해 정의됩니다.
설정
기본 설정
- BaseUrl (필수)
 호크 서비스 호스팅을 위한 URL입니다.
 슬래시로 끝나면 안됩니다.
 구성된 후크의 상대 경로 URI에서 콜백이 수신됩니다.
- CustomHttpHeaders
 구성된 웹 서비스에 대한 요청에서 HTTP 헤더로 설정되어야하는 키/값의 쌍으로 이루어진 JSON 객체입니다.
Paths
호스트에서 식별되는 URI에서 이벤트를 수신하도록 각 경로를 구성합니다.
빈 경로는 히트되지 않으며 해당 Webhook에서 콜백을 수신 받지 않습니다.
- PathChannelCreate
 신규 채널이 생성되거나 채널의 상태가 외부 서비스로부터 로드될 필요가 있을 때 호출됩니다.
- PathChannelDestroy
 채널이 Photon 서버 메모리상에서 제거되었을 때 호출됩니다.
 IsPersistent가 true로 설정되어 있는 경우에는 채널 상태가 전송됩니다.
- PathChannelSubscribe
 플레이어가 이미 생성되어 있는 채널을 구독할 때 호출 됩니다.
- PathChannelUnsubscribe
 플레이어가 채널을 구독을 해지할 때 호출 됩니다.
- PathPublishMessage
 클라이언트가 채널에 메시지를 게시했을 때 호출 됩니다.
옵션
이러한 옵션을 통해 채팅 webhook 동작을 조정하세요.
옵션은 설정되지 않았거나 값이 없는 경우 구성되지 않은 것으로 간주됩니다.
- FailIfUnavailable 
 - true로 설정하면 채널 생성, 구독과 메시지 게시 오퍼레이션은 상응하는 후크의 구성된 엔드포인트를 사용 할 수 없을 때 실패할 것 입니다.
 엔드 포인트는 HTTP 요청 처리동안에 오류가 발생하거나 HTTP 응답이 성공하지 않았을 때 사용할 수 없는 것으로 간주됩니다.
 기본값은- false입니다.
- IsPersistent 
 - true로 설정하면, Photon Cloud는 채널을 없애기전 채널 상태를 전송합니다. 이 옵션은 PathChannelCreate 및 PathChannelDestory 두개 모두 올바르게 구성되어 있고 MaxChannelHistory 가 0보다 큰 경우에만 유효합니다.
 자세한 내용은 ChannelCreate 와 ChannelDestroy webhook의 내용을 참조하시기 바랍니다.
 기본값은- false입니다.
- MaxChannelHistory 
 MaxChannelHistory는 채널당 지속될 최대 메시지수 입니다. 1에서 100 사이의 값입니다.
 기본값은 100 입니다.
- HasErrorInfo 
 HasErrorInfo- true로 설정되어 있는 경우 채팅 클라이언트들은 후크 엔드포인트를 사용 할 수 없을 때 오류 메시지와 같이 알림을 받게되지만, FailIfUnavailable 는- false로 설정됩니다. 기본값은- false입니다.
- SkipPostCreationFailure 
 SkipPostCreationFailure 이- true로 설정되어 있는 경우, PathUnsubscribe 와 PathChannelDestory webhook 는 채널 생성 실패 이후 전송되지 않을 것 입니다.
 기본값은- false입니다.
공통 기준
모든 Webhook에 대한 공통 인수
AppId:
관리화면에서 찾을 수 있는 게임 클라이언트에서 설정된 어플리케이션의 AppId.
AppVersion:
게임 클라이언트에서 설정된 어플리케이션의 버전.
Region:
게임 클라이언트가 연결된 지역과 해당 룸이 속한 지역.
ChannelName:
후크가 트리거되는 채널의 이름.
ChannelDestroy를 제외한 모든 Webhook에 대한 공통 인수
UserId:
후크를 트리거하는 플레이어의 UserID.
ChannelCreate를 제외한 모든 Webhook에 대한 공통 인수
HistoryCount:
채널 이력내에 있는 현재의 메시지 개수.
인수 목록
이 테이블은 각 webhook에서 사용 할 수 있는 인수들을 보여줍니다:
| 인수 | ChannelCreate / ChannelSubscribe | ChannelDestroy | PublishMessage | ChannelUnsubscribe | 
|---|---|---|---|---|
| AppId | ||||
| AppVersion | ||||
| Region | ||||
| ChannelType ("Public") | ||||
| ChannelName | ||||
| HistoryLen | ||||
| HistoryCount | ||||
| UserId | ||||
| ChannelState | 
세부 경로
ChannelCreate
이 webhook는 Photon 서버에서 채널을 만들려고 할 때 전송됩니다. 이전에 ChannelState 를 저장 한 경우 webhooks 응답으로 반환하여 내역을 로드해야합니다. 예를 보려면 "반환 값"을 참조하십시오.
특별한 인수
HistoryLen:
구독 오퍼레이션에서 클라이언트가 설정한 동일한 이름의 인수를 전달합니다.
클라이언트가 요청한 이력의 메시지 수를 포함 합니다.
샘플 호출
text
{
   "AppId":"00000000-0000-0000-0000-000000000000",
   "AppVersion":"1.0",
   "Region":"EU",
   "ChannelName":"PersistentChannel",
   "HistoryLen":10,
   "UserId":"testClient1"
}
ChannelDestroy
Photon 서버에서 채널이 파괴되려고 할 때 이 webhook이 전송됩니다.
이 Webhook는 빈 채널이 타임아웃 될 때 발생합니다.
채널에 가입자가 떠나 아무도 남아 있지 않았을 때 채널은 비어있는 것으로 간주됩니다.
빈 채널 타임아웃 기본값은 5초입니다.
IsPersistent 를 true 로 설정하고 _PathChannelDestory_를 올바르게 구성하면 ChannelState 가 webhook 본문으로 전송됩니다.
ChannelState에서 History 객체는 디버깅 목적으로만 사용됩니다. 폐기 할 수도 있습니다.
Photon 서버는 BinaryHistory를 사용하여 데이터 형식을 유지합니다.
나중에 채널 이력을 로드하려면 _현재 값_을 저장해야합니다.
샘플 호출
text
{
   "AppId":"00000000-0000-0000-0000-000000000000",
   "AppVersion":"1.0",
   "Region":"EU",
   "ChannelName":"PersistentChannel",
   "HistoryCount":2,
   "ChannelState":{
      "ChannelHistoryCapacity":100,
      "BinaryHistory": "RGl6AAEAAAAAAAN6AANp..",
      "History":{
         "MessageIdBase":2,
         "Entries":[
            {
               "Message":"msg1",
               "Sender":"testClient1",
               "MsgId":1
            },
            {
               "Message":"msg2",
               "Sender":"testClient2",
               "MsgId":2
            }
         ]
      }
   }
}
ChannelSubscribe
이 webhook은 이미 생성된 채널에 클라이언트 구독에 의해 트리거됩니다.
클라이언트는 다음 중 하나입니다:
- 첫 번째의 구독자가 아닙니다. 이것은 가장 많이 발생하는 사례이어야 합니다.
- 채널이 비어있고 타임아웃이 일어나지 않을 때 첫 번째 구독자입니다. 작은 창이기 때문에 가능성이 희박합니다.
특별한 인수
HistoryLen:
구독 오퍼레이션에서 클라이언트가 설정한 동일한 이름의 인수를 전달합니다.
클라이언트가 요청한 이력 메시지 개수를 포함합니다.
샘플 호출
text
{
   "AppId":"00000000-0000-0000-0000-000000000000",
   "AppVersion":"1.0",
   "Region":"EU",
   "ChannelName":"PersistentChannel",
   "HistoryLen":-1,
   "HistoryCount": 1,
   "UserId":"testClient2"
}
ChannelUnsubscribe
이 webhook는 다음의 사유들중 하나에 의해서 클라이언트가 채널에서 연결해제 되었을 때 트리거 됩니다:
- 구독 해지 오퍼레이션에 대한 명시적 호출.
- 명시적인 연결해제.
- 타임아웃 연결해제.
- 채널 생성 실패와 SkipPostCreationFailure 이 false로 설정
- 구독 실패.
샘플 호출
text
{
   "AppId":"00000000-0000-0000-0000-000000000000",
   "AppVersion":"1.0",
   "Region":"EU",
   "ChannelName":"PersistentChannel",
   "HistoryCount":2,
   "UserId":"testClient2"
}
PublishMessage
이 webhook는 클라이언트가 채널에 메시지를 게시했을 때 트리거 됩니다.
Specific Arguments
Message: 채널의 모든 구독자에게 게시하는 메시지. 클라이언트로부터 전송되는 것처럼 전달됩니다.
샘플 호출
text
{
   "AppId":"00000000-0000-0000-0000-000000000000",
   "AppVersion":"1.0",
   "Region":"EU",
   "ChannelName":"PersistentChannel",
   "HistoryCount":1,
   "UserId":"testClient2",
   "Message":"msg2"
}
반환 값
모든 webhook는 JSON 객체를 담고 있으며 ResultCode 값은 다음과 같습니다:
- 성공시에는 0.
성공 응답 샘플
text
{
   "ResultCode":0,
   "Message":"OK"
}
- 이외 다른 정수값은 실패입니다.
실패 응답 샘플
text
{
   "ResultCode":1,
   "Message":"A nice self explained error message"
}
"ChannelCreate" webhook는 ChannelState 인 웹서버로부터 추가 속성을 수신 할 수도 있습니다.
샘플 "Full" ChannelCreate 응답
text
{
   "ResultCode":0,
   "Message":"ChannelState Loaded Successfully",
   "ChannelState":{
      "ChannelHistoryCapacity":100,
      "BinaryHistory": "RGl6AAEAAAAAAAN6AANp..",
      "History":{
         "MessageIdBase":2,
         "Entries":[
            {
               "Message":"msg1",
               "Sender":"testClient1",
               "MsgId":1
            },
            {
               "Message":"msg2",
               "Sender":"testClient2",
               "MsgId":2
            }
         ]
      }
   }
}
"History" 는 상태 불러오기에는 필수가 아니기 때문에 디버깅에 매우 유용합니다. 상태 저장 또는 상태를 불러올 때는 무시 할 수도 있습니다.
샘플 "Stripped" ChannelCreate 응답
text
{
   "ResultCode":0,
   "Message":"ChannelState Loaded Successfully",
   "ChannelState":{
      "ChannelHistoryCapacity":100,
      "BinaryHistory": "RGl6AAEAAAAAAAN6AANp.."
   }
}
다음 사항들에 대한 모법 사례로 간주됩니다.:
- 사용자정의 오류 유형별 예약 ResultCode 값의 목록을 갖을 때.
- 디버깅시에 유용하게 사용하는 메시지 문자열을 리턴할 때.
아래 표는 webhook을 사용하여 취소하거나 중단 할 수 있는 채팅 오퍼레이션을 보여줍니다.
그렇게 하려면 0이 아닌 ResultCode를 리턴해야하며 선택적으로 OperationResponse의 DebugMessage에서 찾을 수있는 Message를 리턴해야 합니다.
| Webhook | 취소될 수 있음 | 
|---|---|
| ChannelCreate | |
| ChannelDestory | |
| ChannelSubscribe | |
| ChannelUnsubscribe | |
| PublishMessage | 
URL 태그
대시보드에서 Webhooks 또는 WebRpc 의 기준 URL을 설정 할 때 하나 이상의 "동적 변수"를 설정 할 수 있습니다.
이러한 변수들은 요청을 전송하기 전에 백엔드에서 상응하는 값들로 교체 되게 됩니다.
어플리케이션에서 사용자들을 서로 다르게 분리하여 처리를 원할 때 URL 태그는 매우 간편합니다.
Photon 은 다음의 URL 태그들을 지원합니다:
- {AppVersion}은 클라이언트에서 설정된 어플리케이션 버전을 전달 합니다.
- {AppId}는 어플리케이션의 ID 를 전달 합니다.
- {Region}은 클라이언트가 접속된 클라우드 지역에 대한 토큰을 전달 합니다. 예, "eu".
- {Cloud}는 클라이언트가 연결된 클라우드의 이름을 전달 합니다. 예, "public" 또는 "enigmaticenterprise".
URL 태그 유즈케이스의 예제
- https://{Region}.mydomain.com/{AppId}?version={AppVersion}&cloud={Cloud}
- https://mydomain.com/{Cloud}/{Region}/{AppId}/{AppVersion}
데이터 타입 변환
이 섹션에서는 Photon 서버와 웹 서비스간의 데이터 교환의 타입에 대해서만 설명합니다.
클라이언트와 Photon 서버간의 데이터 타입에 대해서는  Photon 의 직렬화 페이지를 참고 하시기 바랍니다.
Photon 서버 -> 웹 서비스
| C# / .NET (Photon 지원 타입) | JavaScript / JSON | 
|---|---|
| byte | number | 
| short | |
| int | |
| long | |
| double | |
| bool | bool | 
| string | string | 
| byte[](byte 배열 length <short.MaxValue) | string (Base64 encoded) | 
| T[](array of supported type T, length <short.MaxValue) | array | 
| Hashtable(of supported types, count <short.MaxValue, preferably Photon implementation) | object | 
| Dictionary(keys and values of supported types, count <short.MaxValue) | object | 
| null | null | 
샘플 요청 데이터 (타입들이 연결되어 있습니다)
Photon 서버 전송:
JavaScript
{
    "(Dictionary<String,Object>)Dictionary":{
        "(Int32)dk_int":"1",
        "(String)dk_str":"dv2",
        "(Boolean)dk_bool":"True"
    },
    "(Hashtable)Hashtable":{
        "(Byte)hk_byte":"255",
        "(Object[])hk_array":[
            "(Object)0",
            "(Object)xy",
            "(Object)False"
        ],
        "hk_null":"null"
    },
    "null":"null",
    "(String[])string[]":[
        "(String)PUN",
        "(String)TB",
        "(String)RT",
        "(String)Bolt",
        "(String)Chat"
    ],
    "(Byte[])byte[]":[
        "(Byte)255",
        "(Byte)0"
    ],
    "(Int16[])short[]":[
        "(Int16)-32768",
        "(Int16)32767"
    ],
    "(Int32[])int[]":[
        "(Int32)-2147483648",
        "(Int32)2147483647"
    ],
    "(Int64[])long[]":[
        "(Int64)-9223372036854775808",
        "(Int64)9223372036854775807"
    ],
    "(Single[])float[]":[
        "(Single)-3.402823E+38",
        "(Single)3.402823E+38"
    ],
    "(Double[])double[]":[
        "(Double)-1.79769313486232E+308",
        "(Double)1.79769313486232E+308"
    ],
    "(Boolean[])bool[]":[
        "(Boolean)True",
        "(Boolean)False"
    ]
}
Web 서비스 수신:
JavaScript
{
    "(object)Dictionary":{
        "dk_int":"(number)1",
        "dk_str":"(string)dv2",
        "dk_bool":"(boolean)true"
    },
    "(object)Hashtable":{
        "hk_byte":"(number)255",
        "hk_null":null,
        "hk_array":[
            "(number)0",
            "(string)xy",
            "(boolean)false"
        ]
    },
    "null":null,
    "(array)string[]":[
        "(string)PUN",
        "(string)TB",
        "(string)RT",
        "(string)Bolt",
        "(string)Chat"
    ],
    "byte[]":"(string)/wA=",
    "(array)short[]":[
        "(number)-32768",
        "(number)32767"
    ],
    "(array)int[]":[
        "(number)-2147483648",
        "(number)2147483647"
    ],
    "(array)long[]":[
        "(number)-9223372036854776000",
        "(number)9223372036854776000"
    ],
    "(array)float[]":[
        "(number)-3.40282347e+38",
        "(number)3.40282347e+38"
    ],
    "(array)double[]":[
        "(number)-1.7976931348623157e+308",
        "(number)1.7976931348623157e+308"
    ],
    "(array)bool[]":[
        "(boolean)true",
        "(boolean)false"
    ]
}
웹 서비스 -> Photon 서버
C#/.Net 에서 JavaScript/JSON 타입과 각각 대응하는 테이블입니다.
Here is a table that matches each JavaScript/JSON type to its equivalent one in C#/.Net :
| JavaScript / JSON | C# / .Net | 
|---|---|
| object | Dictionary | 
| array | object[](array of objects) | 
| number (integral) | long | 
| number (floating) | double | 
| string | string | 
| boolean | bool | 
| null(not a type) | null | 
| undefined(when sent) | null | 
응답 데이터 샘플 (타입들이 연결되어 있습니다)
Web Service 전송:
JavaScript
{
    "(object)number": {
        "MAX_VALUE": "(number)1.7976931348623157e+308",
        "MIN_VALUE": "(number)5e-324"
    },
    "(object)object": {
        "string": "(string)xyz",
        "null": null,
        "bool": "(boolean)false",
        "undefined": "(undefined)undefined",
        "number": "(number)-3.14"
    },
    "(array)array": [
        "(string)xyz",
        "(number)0",
        "(boolean)true",
        null,
        "(undefined)undefined"
    ]
}
Photon Server 수신:
JavaScript
{
    "(Dictionary<String,Object>)number":{
        "(Double)MAX_VALUE":"1.79769313486232E+308",
        "(Double)MIN_VALUE":"4.94065645841247E-324"
    },
    "(Dictionary<String,Object>)object":{
        "(String)string":"xyz",
        "null":"null",
        "(Boolean)bool":"False",
        "(Double)number":"-3.14"
    },
    "(Object[])array":[ 
        "(Object)xyz",
        "(Object)0",
        "(Object)True",
        "null",
        "null"
    ]
}