개요
HTTP 동사
본 REST API에서 사용하는 HTTP 동사(verbs)는 가능한한 표준 HTTP와 REST 규약을 따릅니다.
| 동사 | 용례 |
|---|---|
|
리소스를 가져올 때 사용 |
|
새 리소스를 만들 때 사용 |
|
기존 리소스를 수정할 때 사용 |
|
기존 리소스의 일부를 수정할 때 사용 |
|
기존 리소스를 삭제할 떄 사용 |
HTTP 상태 코드
본 REST API에서 사용하는 HTTP 상태 코드는 가능한한 표준 HTTP와 REST 규약을 따릅니다.
| 상태 코드 | 용례 |
|---|---|
|
요청을 성공적으로 처리함 |
|
새 리소스를 성공적으로 생성함. 응답의 |
|
기존 리소스를 성공적으로 수정함. |
|
잘못된 요청을 보낸 경우. 응답 본문에 더 오류에 대한 정보가 담겨있다. |
|
요청한 리소스가 없음. |
오류
에러 응답이 발생했을 때 (상태 코드 >= 400), 본문에 해당 문제를 기술한 JSON 객체가 담겨있다.
Auth Error
Error0001
Response body
{
"timestamp" : "2021-02-06T10:20:21.7024383",
"status" : 202,
"error" : "0001",
"message" : "ID: TestUser1 이미 사용중인 아이디입니다."
}
Error0002
Response body
{
"timestamp" : "2021-02-06T10:20:20.1984677",
"status" : 403,
"error" : "0002",
"message" : "ID: TestUser1 회원가입이 되어있지 않거나 잠긴 계정입니다."
}
Error0005
Response body
{
"timestamp" : "2021-02-06T10:20:18.5203357",
"status" : 403,
"error" : "0005",
"message" : "잘못된 인증입니다."
}
System Error
Error2001
Response body
Snippet response-body not found for operation::2001
하이퍼미디어
본 REST API는 하이퍼미디어와 사용하며 응답에 담겨있는 리소스는 다른 리소스에 대한 링크를 가지고 있다. 응답은 Hypertext Application from resource to resource. Language (HAL) 형식을 따른다. 링크는 `_links`라는 키로 제공한다. 본 API의 사용자(클라이언트)는 URI를 직접 생성하지 않아야 하며, 리소스에서 제공하는 링크를 사용해야 한다.
인증
JWT인증은 표준을 따른다.
Authorization 헤더에 Bearer + 공백 + JWT 토큰값 을 보내주어야 한다.
인증하기
Post 요청을 사용해서 인증할수있다.
HTTP request
POST /auth/signin HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 79
Host: templet.restapi.com
{
"id" : "TestUser1",
"password" : "password",
"role" : "ROLE_USER"
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 253
{
"accessToken" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0VXNlcjEiLCJyb2xlcyI6WyJST0xFX1VTRVIiXSwiaWF0IjoxNjEyNTc0NDIwfQ.4wehBPFLcxgz_4sT9d0VuBKDyEG8dSxO0EtX6k4T2NY",
"id" : "TestUser1",
"name" : "테스트 유저 1",
"storeName" : null
}
회원가입하기(회원)
Post 요청을 사용해서 회원가입을 할 수있다.
HTTP request
POST /auth/signup HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 275
Host: templet.restapi.com
{
"id" : "TestUser1",
"password" : "Password",
"name" : "테스트 유저 1",
"phoneNumber" : "전화번호~",
"address" : "집주소",
"role" : "ROLE_USER",
"storePhoneNumber" : null,
"storeName" : null,
"latitude" : null,
"longitude" : null
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 253
{
"accessToken" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0VXNlcjEiLCJyb2xlcyI6WyJST0xFX1VTRVIiXSwiaWF0IjoxNjEyNTc0NDIxfQ.HEkQD9qA4FG79rr85b3ABRBmmWZdTKG2-nMV39LDOgs",
"id" : "TestUser1",
"name" : "테스트 유저 1",
"storeName" : null
}
회원가입하기(매장)
Post 요청을 사용해서 회원가입을 할 수있다.
HTTP request
POST /auth/signup HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 310
Host: templet.restapi.com
{
"id" : "TestUser1",
"password" : "Password",
"name" : "테스트 유저 1",
"phoneNumber" : "전화번호~",
"address" : "집주소",
"role" : "ROLE_STORE",
"storePhoneNumber" : "매장번호",
"storeName" : "매장이름",
"latitude" : "위도값",
"longitude" : "경도값"
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 264
{
"accessToken" : "eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0VXNlcjEiLCJyb2xlcyI6WyJST0xFX1NUT1JFIl0sImlhdCI6MTYxMjU3NDQyMX0.kcAHIe29Ua2Dg5eZXprsGTzCafqpx2oFeNB-5CJ3ZtI",
"id" : "TestUser1",
"name" : "테스트 유저 1",
"storeName" : "매장이름"
}
아이디 중복 검사하기
Get 요청을 사용해서 아이디 중복확인을 할 수있다.
HTTP request
GET /auth/checkid/TestUser1 HTTP/1.1
Host: templet.restapi.com
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
매장단말기
출입 기록하기
HTTP request
POST /visits HTTP/1.1
Content-Type: application/json;charset=UTF-8
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0U3RvcmUxIiwicm9sZXMiOlsiUk9MRV9TVE9SRSJdLCJpYXQiOjE2MTI1NzQ0MDl9.u_x6qnA74tjIBX41DupHWqEerhOimAmb445wEiRcqFM
Content-Length: 110
Host: templet.restapi.com
{
"storeId" : "TestStore1",
"visitorId" : "TestUser2",
"entryTime" : "2021-02-06T10:20:09.2387547"
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 2
50
퇴장 기록하기
HTTP request
PUT /visits/51 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0U3RvcmUxIiwicm9sZXMiOlsiUk9MRV9TVE9SRSJdLCJpYXQiOjE2MTI1NzQ0MDl9.u_x6qnA74tjIBX41DupHWqEerhOimAmb445wEiRcqFM
Content-Length: 50
Host: templet.restapi.com
{
"exitTime" : "2021-02-06T10:20:09.5827574"
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
출입 기록 조회하기
HTTP request
GET /visits/Teststore1 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0U3RvcmUxIiwicm9sZXMiOlsiUk9MRV9TVE9SRSJdLCJpYXQiOjE2MTI1NzQ0MTN9.lEvlbhoEQmLJ-9yhbDtYKJTZzjjDGar1Ogk-_uyJOGs
Host: templet.restapi.com
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 871
{
"visitLogs" : [ {
"id" : 56,
"visitor" : {
"id" : 58,
"name" : "테스트 유저 3",
"phoneNumber" : "010-1234-5678",
"address" : "주소"
},
"store" : {
"id" : 35,
"storeName" : "매장명1",
"storePhoneNumber" : "010-1234-5678",
"address" : "주소"
},
"entryTime" : "2021-02-06T08:20:13.9419654",
"exitTime" : "2021-02-06T10:20:13.946963"
}, {
"id" : 58,
"visitor" : {
"id" : 59,
"name" : "테스트 유저 4",
"phoneNumber" : "010-1234-5678",
"address" : "주소"
},
"store" : {
"id" : 35,
"storeName" : "매장명1",
"storePhoneNumber" : "010-1234-5678",
"address" : "주소"
},
"entryTime" : "2021-02-06T08:20:13.9529677",
"exitTime" : "2021-02-06T10:20:13.9579639"
} ]
}
출입 기록 조회(관리자)
HTTP request
GET /visits?storeName=%EB%A7%A4%EC%9E%A5%EB%AA%851&visitorName=%ED%85%8C%EC%8A%A4%ED%8A%B8+%EC%9C%A0%EC%A0%80+3&time=2021-02-06T09%3A20%3A11.867772300 HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0VXNlcjUiLCJyb2xlcyI6WyJST0xFX0FETUlOIl0sImlhdCI6MTYxMjU3NDQxMX0.2qJknZhWTs8Zd0rCkkL2hFsE_J7W1D01D6zFfb9dEe8
Host: templet.restapi.com
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Content-Type: application/json;charset=UTF-8
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Content-Length: 448
{
"visitLogs" : [ {
"id" : 52,
"visitor" : {
"id" : 55,
"name" : "테스트 유저 3",
"phoneNumber" : "010-1234-5678",
"address" : "주소"
},
"store" : {
"id" : 33,
"storeName" : "매장명1",
"storePhoneNumber" : "010-1234-5678",
"address" : "주소"
},
"entryTime" : "2021-02-06T08:20:11.8437713",
"exitTime" : "2021-02-06T10:20:11.8497722"
} ]
}
토큰 등록
HTTP request
POST /push HTTP/1.1
Content-Type: application/json;charset=UTF-8
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiJUZXN0VXNlcjEiLCJyb2xlcyI6WyJST0xFX1VTRVIiXSwiaWF0IjoxNjEyNTc0NDA1fQ.MyQaCrufKYXkSNZ9n8p5A2D3G-UksGL-pUeZGTlovFw
Content-Length: 58
Host: templet.restapi.com
{
"userId" : "TestUser1",
"token" : "Token Value"
}
Example response
HTTP/1.1 200 OK
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY