本件は、CLUe API を使用して CLUe Server からイベントログを取得する方法についての簡単なガイドです。
以下の例では、cURL と C# WPF .NET を使用しています。
内容
前提条件
CLUe APIを使用するには、以下の情報が必要です。
- 店舗のPlaceID
- ログイン情報
- APIアクセストークン - CLUeにログインすると取得できます。
ログイン
CLUe APIを利用するには、アクセストークンが必要です。
このアクセストークンは、ログイン情報を使ってCLUeにログインすることで取得できます。
1. API endpoint and Parameters
[POST] https://api.moon.supremainc.com/v1/accounts/login/phone
2. Request Body
下記の情報をSuprema代理店にご請求ください。
Field | Type | Required | Description |
---|---|---|---|
countryCode | string | yes | country code |
phone | string | yes | login id |
password | string | yes | password |
accountType | string | yes | account type |
authDeviceType | string | yes | authentication device type |
curl --location 'https://api.moon.supremainc.com/v1/accounts/login/phone' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --data '{ "countryCode" : "kr", "phone" : "0123456789", "password" : "Pa$sw0rd", "accountType" : "BUSINESS_OWNER", "authDeviceType" : "MOBILE_APP" } '
3. Response Body
Field | Type | Nullable | Description |
---|---|---|---|
code | Number | false | API response code |
status | Boolean | false | API response status |
message | String | false | API response message |
data.accountId | Number | false | account id |
data.accountType | String | false | USER / SUPREMA_MANUFACTURE / SERVICE_PROVIDER/ SERVICE_OPERATOR / BUSINESS_PROVIDER/ BUSINESS_OWNER |
data.accountStatus | String | false | INACTIVE ACTIVE AUTH_CODE_LOCKED AUTH_CODE_TOO_MANY_SEND PASSWORD_LOCKED PASSWORD_EXPIRED DELETE_RESERVE |
data.name | String | false | account name |
data.countryCode | String | false | account countryCode |
data.phone | String | false | account phone number |
data.accessToken | String | false | API accessToken |
data.refreshToken | String | false | API refreshToken |
HTTP/1.1 200 OK Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/json Content-Length: 626 { "code" : 200, "status" : true, "message" : "OK", "data" : { "accountId" : 1, "accountType" : "BUSINESS_OWNER", "accountStatus" : "ACTIVE", "name" : "diaz", "countryCode" : "kr", "phone" : "01234567890", "accessToken" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0dGMiOiJhYyIsImR0YyI6Im1hIiwiZXhwIjoxNjcwODA3ODUzLCJyaWMiOjEsImlhdCI6MTY3MDgwNDI1M30.i-jEiLGExOQGotdy-VGEmDx45gV4LtVJ_waoH18sfog", "refreshToken" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0dGMiOiJyZSIsImR0YyI6Im1hIiwiZXhwIjoxNzAyMzQwMjUzLCJyaWMiOjEsImlhdCI6MTY3MDgwNDI1M30.2idXYbteVFfFDSnYecM3QpW5KBHERrEIx3kZX0L77hw" } }
ここでの重要なポイントは、レスポンス・ボディからAccess Tokenを取得し、この値を他のAPIコールでAuthorization Headerとして使用することである。
4. Sample Code in C#
static async Task<string> LoginTask() { sAccessToken = null; string jsonRequestBody = "{"; jsonRequestBody += "\"countryCode\" : \"" + sCountryCode + "\","; jsonRequestBody += "\"phone\" : \"" + sPhone + "\","; jsonRequestBody += "\"password\" : \"" + sPassword + "\","; jsonRequestBody += "\"accountType\" : \"" + sAccountType + "\","; jsonRequestBody += "\"authDeviceType\" : \"" + sAuthDeviceType + "\"}"; using (HttpClient client = new HttpClient()) { string apiUrl = "https://api.moon.supremainc.com/v1/accounts/login/phone"; // Set the JSON content StringContent content = new StringContent(jsonRequestBody, Encoding.UTF8, "application/json"); HttpResponseMessage response = await client.PostAsync(apiUrl, content); if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); sLoginResponse = responseBody; var loginResponse = LoginResponse.FromJson(responseBody); sAccessToken = loginResponse.Data.AccessToken; } else { string responseBody = await response.Content.ReadAsStringAsync(); var clueErrorResponse = ClueErrorResponse.FromJson(responseBody); string errorResponse = clueErrorResponse.Errors[0].Code + ":" + clueErrorResponse.Errors[0].Message; MessageBox.Show("失敗しました。\n" + errorResponse, "Error"); } } return sAccessToken; }
sAccessToken = レスポンスボディから取得したアクセストークン
ログ取得
1. API endpoint and Parameters
[GET] https://api.moon.supremainc.com/v1/events/places/:placeId
Request Header:
Key | Type | Required | Description |
---|---|---|---|
Authorization | JWT Token | yes | ログインAPIから取得したアクセストークン |
Path Variables:
Key | Type | Required | Description |
---|---|---|---|
placeId | Number | yes | あなたの店舗に割り当てられたplaceIDです。 Suprema Agentに資料請求してください。 |
Query Parameter:
Key | Type | Required | Description |
---|---|---|---|
startTime | Unix Time (Millisec) | no | この日付から始まるログを検索する。 指定がない場合、すべてのログが表示されます。 |
endTime | Unix Time (Millisec) | no | この日付までのログを検索する。 指定がない場合は、すべてのログが表示されます。 |
filterEvents | string | no | 指定されたイベントタイプのイベントのみを表示する。 指定しない場合は、すべてのログが表示されます。 |
page | Number | no | ログは複数ページで表示されます。 指定しない場合は1ページのみ表示されます。 |
size | Number | no | startTimeから取得するログの数 |
sort | string | no | ログをIDで昇順('asc')または降順('desc')にソートする。 Example: id%2Cdesc |
curl --location 'https://api.moon.supremainc.com/v1/events/places/178?startTime=1675124016000&endTime=1703981616000&filterEvents=DEV_FACE_AUTH_SUCCESS&page=0&size=256&sort=id%2Cdesc' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0dGMiOiJhYyIsImR0YyI6Im1hIiwiZXhwIjoxNjk0NzM1OTkxLCJyaWMiOjM1LCJpYXQiOjE2OTQ3MzIzOTF9.yH_Fc7j4CDHEMNVoDdstakVNqtYbkXTN5-JFM3tgaJY'
2. Request Body
None
3. Response Body
Field | Type | Nullable | Description |
---|---|---|---|
code | Number | false | API response code |
status | Boolean | false | API response status |
message | String | false | API response message |
total | Number | false | total number of retrieved logs. |
data.logId | Number | false | CLUe server side's log ID. |
data.eventAt | Unix Time | false | Date and time when the event occurred. |
data.placeId | Number | false | Place ID |
data.deviceId | Number | true | Device ID |
data.doorId | Number | true | Door ID |
data.doorName | String | true | Door Name |
data.authId | Number | true | Authentication ID |
data.userId | Number | true | User Key |
data.useName | String | true | User Name |
data.localLogId | Number | false | Device side's log ID |
data.eventType | Event Type | false | event type |
HTTP/1.1 200 OK Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers Content-Type: application/json Content-Length: 634 { { "code": 200, "status": true, "message": "OK", "total": 507, "data": [ { "logId": 12907987, "eventAt": 1694066002529, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4607, "eventType": "DEV_DOOR_RELAY_OFF" }, { "logId": 12907979, "eventAt": 1694065999512, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4606, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12907978, "eventAt": 1694065999471, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4605, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12907965, "eventAt": 1694065996127, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4604, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907955, "eventAt": 1694065992829, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4603, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907951, "eventAt": 1694065989790, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4602, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907946, "eventAt": 1694065986920, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4601, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907942, "eventAt": 1694065983825, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4600, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907937, "eventAt": 1694065980832, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4599, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907933, "eventAt": 1694065977903, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4598, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907924, "eventAt": 1694065974147, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4597, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907915, "eventAt": 1694065969479, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4596, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907880, "eventAt": 1694065948852, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4595, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907853, "eventAt": 1694065943870, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4594, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907837, "eventAt": 1694065940445, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4593, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907831, "eventAt": 1694065937586, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4592, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12907819, "eventAt": 1694065926868, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4591, "eventType": "DEV_FACE_AUTH_FAIL" }, { "logId": 12905071, "eventAt": 1694063933649, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4590, "eventType": "DEV_DOOR_RELAY_OFF" }, { "logId": 12905069, "eventAt": 1694063930647, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4589, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12905066, "eventAt": 1694063930569, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4588, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12905065, "eventAt": 1694063930492, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4587, "eventType": "DEV_DOOR_RELAY_OFF" }, { "logId": 12905064, "eventAt": 1694063927477, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4586, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12905062, "eventAt": 1694063927452, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4585, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12905060, "eventAt": 1694063924568, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4584, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12905058, "eventAt": 1694063924490, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4583, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12905055, "eventAt": 1694063921597, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4582, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12905052, "eventAt": 1694063921556, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4581, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12904676, "eventAt": 1694063600474, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4580, "eventType": "DEV_DOOR_RELAY_OFF" }, { "logId": 12904672, "eventAt": 1694063597477, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4579, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12904671, "eventAt": 1694063597440, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4578, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12904667, "eventAt": 1694063594788, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4577, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12904664, "eventAt": 1694063594753, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8744, "doorName": "testDoor", "userId": "12345678", "userName": "EBISU", "localLogId": 4576, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12904657, "eventAt": 1694063590253, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4575, "eventType": "DEV_DOOR_RELAY_OFF" }, { "logId": 12904651, "eventAt": 1694063587211, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4574, "eventType": "DEV_DOOR_RELAY_ON" }, { "logId": 12904650, "eventAt": 1694063587143, "placeId": 178, "deviceId": 902, "doorId": 181, "authId": 8173, "doorName": "testDoor", "userId": "34567", "userName": "Jack", "localLogId": 4573, "eventType": "DEV_FACE_AUTH_SUCCESS" }, { "logId": 12904640, "eventAt": 1694063580664, "placeId": 178, "deviceId": 902, "doorId": 181, "localLogId": 4572, "eventType": "DEV_FACE_AUTH_FAIL" } ] } }
4. Sample Code in C#
static async Task<string> GetLogEvents( string placeID, int numOfLogs ) { using (HttpClient client = new HttpClient()) { string apiUrl = sApiEndpoint + "/v1/events/places/" + placeID + "?size=" + numOfLogs + "&sort=id%2Cdesc"; string authHeader = "Bearer " + sAccessToken; CookieContainer cookieContainer = new CookieContainer(); HttpClientHandler handler = new HttpClientHandler { CookieContainer = cookieContainer }; // Set the JSON content client.DefaultRequestHeaders.Add("Authorization", authHeader); cookieContainer.Add(new Uri(sApiEndpoint), new Cookie("Authorization", authHeader)); HttpResponseMessage response = client.GetAsync(apiUrl).Result; if (response.IsSuccessStatusCode) { string responseBody = await response.Content.ReadAsStringAsync(); sLogEventResponse = responseBody; } else { string responseBody = await response.Content.ReadAsStringAsync(); var clueErrorResponse = ClueErrorResponse.FromJson(responseBody); string errorResponse = clueErrorResponse.Errors[0].Code + ":" + clueErrorResponse.Errors[0].Message; MessageBox.Show("c。\n" + errorResponse, "Error"); } } return sLogEventResponse; }
sLogEventResponse = contains the entire API response body in JSON format. You can then convert this JSON string to Array or List<>.
Sample Application
イベント説明
- DEV_FACE_AUTH_SUCCESS - ユーザの顔テンプレートはCLUeサーバに登録される。そのため、デバイスからの認証に成功する。
- VENDOR_AUTH_SUCCESS - これは、ユーザーID(上記の例64455)が登録され、サードパーティーシステムからのアクセスが許可されていることを意味します。
- DEV_DOOR_RELAY_ON - デバイスのリレーがONになる。ドアが解錠される。
- DEV_DOOR_RELAY_OFF - デバイスのリレーがオフになる。ドアがロックされる。
認証成功時のイベントのフロー例
認証失敗時のフロー例(CLUe側)
認証失敗時のフロー例( サードパーティ・システム側)