관리자 상품목록을 한 페이지 여는 것만으로 그 페이지 모든 상품의 옵션이 응답에 실렸다. 같은 패턴을 저장소 전역에서 찾아 14개 목록 엔드포인트를 함께 정리했다. 근본 원인은 둘이다. Resource 가 whenLoaded 로 방어하는데 Repository 가 목록 쿼리에서 관계를 무조건 로드해 가드가 항상 참이 되는 가짜 가드, 그리고 toListArray 경량 표현을 정의해 두고도 컬렉션이 toArray 를 부르는 목록/상세 미분리다. 둘 다 응답만 보면 정상이라 오류도 경고도 없이 페이로드만 불어난다. 목록은 화면이 실제로 그리는 것만 싣는다. 개수·합계는 PHP 컬렉션 연산이 아니라 DB 집계로, 대표 1건이 필요한 곳은 관계 자체를 oldestOfMany 로 좁힌다. eager load 의 limit(1) 은 부모별이 아니라 배치 쿼리 전체에 걸려 첫 행만 값을 갖게 되므로 쓸 수 없다. 뺀 값에는 대체 경로를 먼저 만들었다. 상품 옵션은 행을 펼칠 때 배치로 불러오고(상품 수와 무관하게 쿼리 상수), 종전 동작이 필요한 호출자를 위해 ?with_options=1 등 opt-in 을 남겼다. 배송정책 국가설정과 리뷰 첨부 이미지는 소비처를 실측한 결과 화면이 실제로 그리고 있어 제거하지 않았다 — 그 소비 사실을 회귀 테스트로 고정했다. 재발 방지로 정적 검사 룰 4종과 규정 문서 항목을 함께 넣었다.
119 KiB
Orders API 레퍼런스
소유: module
sirsoft-ecommerce· 생성:php artisan api:docgen(실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.
TL;DR (5초 요약)
1. 이 문서는 실제 API 호출로 실측한 Orders 엔드포인트 레퍼런스입니다
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(curl) + 실측 응답 필드 표 + 응답 예시(envelope)
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
5. 설명(TODO) 칸은 사람이 채웁니다
GET /api/modules/sirsoft-ecommerce/admin/orders
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.index - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@index - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| search_field | query | string | 아니오 | all, order_number, orderer_name, recipient_name, orderer_phone, recipient_phone, product_name, sku |
검색 대상 필드명 (검색어를 적용할 컬럼) |
| search_keyword | query | string | 아니오 | max 200 | 검색 키워드 (부분 일치) |
| date_type | query | string | 아니오 | — | 기간 필터 기준 일자 종류 (ordered_at 주문일 / paid_at 결제일 / confirmed_at 구매확정일 / delivered_at 배송완료일 / cancelled_at 취소일) |
| start_date | query | date | 아니오 | — | 조회 기간 시작일 (이 날짜 이후 데이터) |
| end_date | query | date | 아니오 | — | 조회 기간 종료일 (이 날짜 이전 데이터) |
| order_status | query | array | 아니오 | — | 주문상태 다중 선택 필터 (OrderStatusEnum 값 배열, 해당 상태의 주문만 조회) |
| option_status | query | array | 아니오 | — | 주문옵션 상태 다중 선택 필터 (OrderStatusEnum 값 배열, 해당 옵션 상태를 가진 주문만 조회) |
| shipping_type | query | array | 아니오 | — | 배송유형 다중 선택 필터 (ShippingType 코드 배열) |
| payment_method | query | array | 아니오 | — | 결제수단 다중 선택 필터. 코어 8종과 PG 플러그인이 등록한 확장 결제수단 ID(예: nhnkcp_naverpay)를 모두 허용 |
| category_id | query | integer | 아니오 | — | category 식별자 |
| min_amount | query | integer | 아니오 | min 0 | 주문금액 범위 필터 하한 (이 금액 이상 주문만 조회) |
| max_amount | query | integer | 아니오 | min 0 | 주문금액 범위 필터 상한 (이 금액 이하 주문만 조회) |
| country_codes | query | array | 아니오 | — | 배송국가 코드 다중 선택 필터 (ISO 3166-1 alpha-2 2자리 코드 배열) |
| order_device | query | array | 아니오 | — | 주문 디바이스 다중 선택 필터 (DeviceTypeEnum 값 배열 — pc/mobile/app 등) |
| min_shipping_amount | query | integer | 아니오 | min 0 | 배송비 범위 필터 하한 (이 배송비 이상 주문만 조회) |
| max_shipping_amount | query | integer | 아니오 | min 0 | 배송비 범위 필터 상한 (이 배송비 이하 주문만 조회) |
| shipping_policy_id | query | integer | 아니오 | — | shipping policy 식별자 |
| user_id | query | integer | 아니오 | — | user 식별자 |
| orderer_uuid | query | uuid | 아니오 | — | 특정 회원의 주문만 조회하는 주문자 UUID 필터 (회원 검색 연동용) |
| member_type | query | string | 아니오 | member, guest |
회원 구분 필터 (member 회원 주문 / guest 비회원 주문) |
| sort_by | query | string | 아니오 | ordered_at, paid_at, total_amount, shipped_at |
정렬 기준 필드명 (그 외 값은 422). shipped_at 은 배송 테이블 기준 — desc 는 주문별 가장 늦은 발송일, asc 는 가장 이른 발송일로 정렬하며 발송 이력이 없는 주문도 목록에 남는다 |
| sort_order | query | string | 아니오 | asc, desc |
정렬 방향 (asc 오름차순 / desc 내림차순) |
| per_page | query | integer | 아니오 | min 10, max 100 | 페이지당 항목 수 |
| page | query | integer | 아니오 | min 1 | 조회할 페이지 번호 (1부터 시작) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
sirsoft-ecommerce.order.list_validation_rules,sirsoft-ecommerce.order.list_validation_messages).
요청 예시
GET /api/modules/sirsoft-ecommerce/admin/orders?search_field=all&search_keyword=%EC%98%88%EC%8B%9C%EA%B0%92&date_type=%EC%98%88%EC%8B%9C%EA%B0%92&start_date=2026-01-01&end_date=2026-01-01&order_status=%EC%98%88%EC%8B%9C%EA%B0%92&option_status=%EC%98%88%EC%8B%9C%EA%B0%92&shipping_type=%EC%98%88%EC%8B%9C%EA%B0%92&payment_method=%EC%98%88%EC%8B%9C%EA%B0%92&category_id=1&min_amount=1&max_amount=1&country_codes=KR&order_device=%EC%98%88%EC%8B%9C%EA%B0%92&min_shipping_amount=1&max_shipping_amount=1&shipping_policy_id=1&user_id=1&orderer_uuid=9f8b2c1a-4d3e-4a2b-8c1d-0e1f2a3b4c5d&member_type=member&sort_by=ordered_at&sort_order=asc&per_page=1&page=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| number | integer | 100 |
목록에서의 순번 (페이지네이션 반영 행 번호 — HasRowNumber 파생) |
| id | integer | 1408 |
기본 키 (내부 식별자) |
| order_number | string | 20260730-1436301187 |
주문번호 (사용자 노출용 고유 식별 코드) |
| order_status | string | pending_payment |
주문상태 (OrderStatusEnum 값 — 결제대기/결제완료/배송중 등) |
| order_status_label | string | 결제대기 |
order_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| order_status_variant | string | warning |
order_status 값의 표시 변형 키 (UI 배지 색상/스타일) |
| base_currency | string | JPY |
금액 표기 기준 통화 (모든 *_formatted 필드의 통화, 주문 시점 base_currency 고정) |
| payment_currency | string | JPY |
결제 통화 (유저가 선택·결제한 통화, base_currency 와 다르면 병기 표시) |
| is_cross_currency | boolean | false |
cross currency 여부 |
| is_partially_cancelled | boolean | false |
partially cancelled 여부 |
| total_amount | integer | 125000 |
최종 주문금액 (상품합계 − 할인 + 배송비) |
| total_amount_formatted | string | ¥125,000 |
total_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_shipping_amount | integer | 0 |
총 배송비 |
| total_shipping_amount_formatted | string | ¥0 |
total_shipping_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_paid_amount | integer | 0 |
총 실제 결제금액 (PG 결제된 금액) |
| total_paid_amount_formatted | string | ¥0 |
total_paid_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_unpaid_amount | integer | 125000 |
미결제 잔액 (최종 주문금액 − 실제 결제금액) |
| total_unpaid_amount_formatted | string | ¥125,000 |
total_unpaid_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_cancelled_amount | integer | 0 |
총 취소금액 |
| total_refunded_amount | integer | 0 |
총 환불금액 |
| total_points_used_amount | integer | 0 |
총 포인트(마일리지) 사용액 |
| total_points_used_amount_formatted | string | ¥0 |
total_points_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_earned_points_amount | integer | 1250 |
총 적립 예정 포인트 |
| total_earned_points_amount_formatted | string | ¥1,250 |
total_earned_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| ordered_at | string | 2026-07-30T10:36:30+00:00 |
ordered 일시 |
| ordered_at_formatted | string | 2026-07-30 19:36:30 |
ordered_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| order_device | string | pc |
주문 디바이스 (DeviceTypeEnum 값 — pc/mobile/app) |
| order_device_label | string | PC |
order_device 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| is_first_order | boolean | false |
first order 여부 |
| user | object | {"uuid":"a26219fc-94a0-4f63-9404-04c2a6ac99e4","name":"최고… |
회원 주문의 주문자 요약 (uuid·name, 비회원 주문이면 미포함) |
| first_option | object | {"product_name":"겨울 패딩 점퍼 #16","product_option_name":"카키\… |
대표 표시용 첫 번째 주문 옵션 요약 (상품명·옵션명·수량·썸네일·추가옵션 요약) |
| options_count | integer | 1 |
options 개수 (집계) |
| address | object | {"orderer_name":"연정훈","recipient_name":"소정훈","recipient_c… |
배송지 요약 (주문자명·수령인명·배송국가 코드/현지화명) |
| payment | object | {"payment_method":"dbank","payment_method_label":"무통장입금"} |
결제 요약 (결제수단 값·현지화 라벨) |
| shipping | object | {"shipping_type":null,"shipping_type_label":null,"shippin… |
배송 요약 (배송유형·배송방법 라벨·택배사명·송장번호, 첫 번째 배송 기준) |
| is_owner | boolean | false |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_read":true,"can_update":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "주문 정보를 조회했습니다.",
"data": {
"data": [
{
"number": 100,
"id": 1408,
"order_number": "20260730-1436301187",
"order_status": "pending_payment",
"order_status_label": "결제대기",
"order_status_variant": "warning",
"base_currency": "JPY",
"payment_currency": "JPY",
"is_cross_currency": false,
"is_partially_cancelled": false,
"total_amount": 125000,
"total_amount_formatted": "¥125,000",
"total_shipping_amount": 0,
"total_shipping_amount_formatted": "¥0",
"total_paid_amount": 0,
"total_paid_amount_formatted": "¥0",
"total_unpaid_amount": 125000,
"total_unpaid_amount_formatted": "¥125,000",
"total_cancelled_amount": 0,
"total_refunded_amount": 0,
"total_points_used_amount": 0,
"total_points_used_amount_formatted": "¥0",
"total_earned_points_amount": 1250,
"total_earned_points_amount_formatted": "¥1,250",
"ordered_at": "2026-07-30T10:36:30+00:00",
"ordered_at_formatted": "2026-07-30 19:36:30",
"order_device": "pc",
"order_device_label": "PC",
"is_first_order": false,
"user": null,
"first_option": {
"product_name": "겨울 패딩 점퍼 #16",
"product_option_name": "카키/XL",
"product_code": "5E1WSBY0CHFX7UJU",
"quantity": 1,
"thumbnail_url": "/api/modules/sirsoft-ecommerce/product-image/81d10a0b743c",
"additional_options_summary": null
},
"options_count": 1,
"address": {
"orderer_name": "연정훈",
"recipient_name": "소정훈",
"recipient_country_code": "KR",
"recipient_country_name": {
"ko": "한국",
"en": "South Korea"
}
},
"payment": null,
"shipping": {
"shipping_type": null,
"shipping_type_label": null,
"shipping_method_label": null,
"carrier_name": null,
"tracking_number": null
},
"is_owner": false,
"abilities": {
"can_read": true,
"can_update": true
}
},
{
"number": 99,
"id": 1405,
"order_number": "20260730-1436298546",
"order_status": "pending_payment",
"order_status_label": "결제대기",
"order_status_variant": "warning",
"base_currency": "JPY",
"payment_currency": "JPY",
"is_cross_currency": false,
"is_partially_cancelled": true,
"total_amount": 66000,
"total_amount_formatted": "¥66,000",
"total_shipping_amount": 0,
"total_shipping_amount_formatted": "¥0",
"total_paid_amount": 66000,
"total_paid_amount_formatted": "¥66,000",
"total_unpaid_amount": 0,
"total_unpaid_amount_formatted": "¥0",
"total_cancelled_amount": 0,
"total_refunded_amount": 0,
"total_points_used_amount": 0,
"total_points_used_amount_formatted": "¥0",
"total_earned_points_amount": 698,
"total_earned_points_amount_formatted": "¥698",
"ordered_at": "2026-07-30T08:36:29+00:00",
"ordered_at_formatted": "2026-07-30 17:36:29",
"order_device": "pc",
"order_device_label": "PC",
"is_first_order": false,
"user": null,
"first_option": {
"product_name": "기본 양말 5족 #2",
"product_option_name": "그레이/M",
"product_code": "S0SO3A6SJFYLAKSF",
"quantity": 3,
"thumbnail_url": "/api/modules/sirsoft-ecommerce/product-image/8fc3ae669be2",
"additional_options_summary": null
},
"options_count": 3,
"address": {
"orderer_name": "양호민",
"recipient_name": "전종수",
"recipient_country_code": "KR",
"recipient_country_name": {
"ko": "한국",
"en": "South Korea"
}
},
"payment": null,
"shipping": {
"shipping_type": null,
"shipping_type_label": null,
"shipping_method_label": null,
"carrier_name": null,
"tracking_number": null
},
"is_owner": false,
"abilities": {
"can_read": true,
"can_update": true
}
},
"... (총 25건 중 2건 표시)"
],
"abilities": {
"can_update": true
},
"statistics": {
"total": 100,
"status_counts": {
"confirmed": 10,
"delivered": 20,
"cancelled": 5,
"shipping": 13,
"payment_complete": 20,
"preparing": 15,
"shipping_ready": 5,
"shipping_hold": 5,
"pending_payment": 7
},
"today_count": 0,
"today_revenue": 0,
"monthly_revenue": 0
},
"pagination": {
"current_page": 1,
"last_page": 4,
"per_page": 25,
"total": 100,
"from": 1,
"to": 25,
"has_more_pages": true
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.read)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 관리자가 주문을 다양한 필터·검색·정렬 조건으로 페이지네이션 조회합니다. auth:sanctum + sirsoft-ecommerce.orders.read 권한이 필요하며, Admin\OrderController@index가 OrderService::getList()로 목록을, getStatistics()로 상태별 통계를 함께 가져와 OrderCollection에 담아 반환합니다. 검색 필드(주문번호/주문자명/상품명/SKU 등)·기간·주문상태·결제수단·금액대·회원/비회원 구분 등 폭넓은 필터를 지원합니다. 관리자 주문 목록 화면의 기본 데이터 소스입니다.
PATCH /api/modules/sirsoft-ecommerce/admin/orders/bulk
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.bulk - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@bulkUpdate - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| ids | body | array | 예 | min 1 | 대상 리소스 식별자 배열 (대량 작업 대상) |
| order_status | body | string | 아니오 | — | 일괄 전환할 주문상태 (OrderStatusEnum 값, pending_order 제외 · 전이 규칙 검증) |
| carrier_id | body | integer | 아니오 | — | carrier 식별자 |
| tracking_number | body | string | 아니오 | max 50 | 송장(운송장)번호 (배송 관련 상태로 전환 시 carrier_id 와 함께 필수) |
요청 예시
PATCH /api/modules/sirsoft-ecommerce/admin/orders/bulk HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"ids": [
"예시값"
],
"order_status": "예시값",
"carrier_id": 1,
"tracking_number": "예시값"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 관리자가 여러 주문(ids)의 주문상태나 배송 정보(택배사·송장번호)를 일괄 변경합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@bulkUpdate가 OrderService::bulkUpdate()로 처리합니다. 주문 목록에서 여러 건을 선택해 "배송 처리"·"상태 일괄 변경" 등을 수행할 때 사용합니다.
DELETE /api/modules/sirsoft-ecommerce/admin/orders/{order}
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.destroy - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@destroy - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.delete
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
요청 예시
DELETE /api/modules/sirsoft-ecommerce/admin/orders/1316 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.delete)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)을 소프트 삭제합니다. auth:sanctum + sirsoft-ecommerce.orders.delete 권한이 필요하며, Admin\OrderController@destroy가 OrderService::delete()를 호출합니다. 물리 삭제가 아닌 소프트 삭제(deleted_at 표시)이므로 데이터는 보존되며, 주문 목록/상세에서 제외됩니다.
GET /api/modules/sirsoft-ecommerce/admin/orders/{order}
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.show - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@show - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
요청 예시
GET /api/modules/sirsoft-ecommerce/admin/orders/1316 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1316 |
기본 키 (내부 식별자) |
| order_number | string | 20260730-1436224914 |
주문번호 |
| base_currency | string | JPY |
금액 표기 기준 통화 (모든 *_formatted 필드의 통화, 주문 시점 base_currency 고정) |
| payment_currency | string | JPY |
결제 통화 (유저가 선택·결제한 통화, base_currency 와 다르면 병기 표시) |
| is_cross_currency | boolean | false |
cross currency 여부 |
| order_status | string | payment_complete |
주문상태 (OrderStatusEnum) |
| order_status_label | string | 결제완료 |
order_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| order_status_variant | string | info |
order_status 값의 표시 변형 키 (UI 배지 색상/스타일) |
| is_partially_cancelled | boolean | false |
partially cancelled 여부 |
| order_device | string | pc |
주문 디바이스 (pc/mobile/app) |
| order_device_label | string | PC |
order_device 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| is_first_order | boolean | true |
first order 여부 |
| subtotal_amount | integer | 179000 |
상품 합계 (할인 전, 상품가×수량 합계) |
| subtotal_amount_formatted | string | ¥179,000 |
subtotal_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_discount_amount | integer | 3000 |
총 할인금액 (모든 할인 합계) |
| total_discount_amount_formatted | string | ¥3,000 |
total_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_shipping_amount | integer | 0 |
총 배송비 |
| total_shipping_amount_formatted | string | ¥0 |
total_shipping_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_amount | integer | 176000 |
최종 주문금액 (subtotal - discount + shipping) |
| total_amount_formatted | string | ¥176,000 |
total_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_paid_amount | integer | 176000 |
총 실제 결제금액 (PG 결제액) |
| total_paid_amount_formatted | string | ¥176,000 |
total_paid_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_due_amount | integer | 0 |
총 결제예정금액 (무통장 등) |
| total_due_amount_formatted | string | ¥0 |
total_due_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| depositor_name | null | null |
무통장 입금자명 (입금확인 모달 기본값, payment 관계 로드 시에만 노출) |
| total_cancelled_amount | integer | 0 |
총 취소금액 |
| total_cancelled_amount_formatted | string | ¥0 |
total_cancelled_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_amount | integer | 0 |
총 환불금액 |
| total_refunded_amount_formatted | string | ¥0 |
total_refunded_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_points_amount | integer | 0 |
총 환불 포인트 |
| total_refunded_points_amount_formatted | string | ¥0 |
total_refunded_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_product_coupon_discount_amount | integer | 3000 |
상품 쿠폰 할인 합계 |
| total_product_coupon_discount_amount_formatted | string | ¥3,000 |
total_product_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_order_coupon_discount_amount | integer | 0 |
주문 쿠폰 할인 합계 |
| total_order_coupon_discount_amount_formatted | string | ¥0 |
total_order_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_coupon_discount_amount | integer | 3000 |
총 쿠폰 할인금액 |
| total_coupon_discount_amount_formatted | string | ¥3,000 |
total_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_code_discount_amount | integer | 0 |
총 할인코드 할인금액 |
| total_code_discount_amount_formatted | string | ¥0 |
total_code_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_points_used_amount | integer | 0 |
총 포인트 사용액 |
| total_points_used_amount_formatted | string | ¥0 |
total_points_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_deposit_used_amount | integer | 0 |
총 예치금 사용액 |
| total_deposit_used_amount_formatted | string | ¥0 |
total_deposit_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_earned_points_amount | integer | 1760 |
총 적립 예정 포인트 |
| total_earned_points_amount_formatted | string | ¥1,760 |
total_earned_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| mc_subtotal_amount | object | {"KRW":{"amount":179000,"formatted":"179,000원"},"USD":{"a… |
상품합계 다중 통화 |
| mc_total_discount_amount | object | {"KRW":{"amount":3000,"formatted":"3,000원"},"USD":{"amoun… |
총 할인 다중 통화 |
| mc_total_shipping_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
총 배송비 다중 통화 |
| mc_total_amount | object | {"KRW":{"amount":176000,"formatted":"176,000원"},"USD":{"a… |
최종금액 다중 통화 (payment_amount) |
| mc_total_product_coupon_discount_amount | object | {"KRW":{"amount":3000,"formatted":"3,000원"},"USD":{"amoun… |
상품 쿠폰 할인 다중 통화 |
| mc_total_order_coupon_discount_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
주문 쿠폰 할인 다중 통화 |
| mc_total_coupon_discount_amount | object | {"KRW":{"amount":3000,"formatted":"3,000원"},"USD":{"amoun… |
쿠폰 할인 합계 다중 통화 |
| mc_total_code_discount_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
할인코드 할인 다중 통화 |
| mc_total_points_used_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
포인트 사용 다중 통화 |
| mc_total_deposit_used_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
예치금 사용 다중 통화 |
| item_count | integer | 2 |
item 개수 (집계) |
| total_quantity | integer | 5 |
주문 옵션 수량 합계 (options 로드 시) |
| total_list_price | integer | 207000 |
정가 합계 (옵션 스냅샷 정가 × 수량 합계) |
| total_list_price_formatted | string | ¥207,000 |
total_list_price 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| ordered_at | string | 2026-07-27T14:36:22+00:00 |
ordered 일시 |
| ordered_at_formatted | string | 2026-07-27 23:36:22 |
ordered_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| paid_at | string | 2026-07-30T14:36:22+00:00 |
paid 일시 |
| paid_at_formatted | string | 2026-07-30 23:36:22 |
paid_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| confirmed_at | null | null |
confirmed 일시 |
| confirmed_at_formatted | null | null |
confirmed_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| cancelled_at | null | null |
cancelled 일시 |
| cancelled_at_formatted | null | null |
cancelled_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| delivered_at | null | null |
delivered 일시 |
| total_tax_amount | integer | 16000 |
총 과세금액 |
| total_tax_amount_formatted | string | ¥16,000 |
total_tax_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_vat_amount | integer | 1455 |
총 부가세금액 |
| total_vat_amount_formatted | string | ¥1,455 |
total_vat_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_taxable_supply_amount | integer | 14545 |
과세 공급가액 (총 과세금액 − 부가세, 영수증 과세금액 표시 SSoT) |
| total_taxable_supply_amount_formatted | string | ¥14,545 |
total_taxable_supply_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_tax_free_amount | integer | 0 |
총 면세금액 |
| total_tax_free_amount_formatted | string | ¥0 |
total_tax_free_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| user | object | {"uuid":"a26219fc-94a0-4f63-9404-04c2a6ac99e4","name":"최고… |
회원 주문의 주문자 정보 (uuid·name·email, user 관계 로드 시 · 비회원이면 미포함) |
| user_id | string | a26219fc-94a0-4f63-9404-04c2a6ac99e4 |
user 식별자 (연관 리소스 참조) |
| user_login_id | null | null |
회원 로그인 아이디 (login_id, 비회원 주문이면 null) |
| orderer_name | string | 박대수 |
주문자 이름 (배송지에서 플래튼) |
| orderer_phone | string | 010-4416-4675 |
주문자 휴대전화 (배송지에서 플래튼) |
| orderer_tel | null | null |
주문자 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| orderer_email | string | shin.yewon@cheon.biz |
주문자 이메일 (배송지에서 플래튼, 비회원 알림 수신 통로) |
| recipient_name | string | 권강희 |
수령인 이름 (배송지에서 플래튼) |
| recipient_phone | string | 010-6286-6243 |
수령인 휴대전화 (배송지에서 플래튼) |
| recipient_tel | null | null |
수령인 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| recipient_zipcode | string | 25530 |
수령인 우편번호 (배송지에서 플래튼) |
| recipient_address | string | 경상남도 광주시 선릉로 768 |
수령인 기본 주소 (배송지에서 플래튼) |
| recipient_detail_address | null | null |
수령인 상세 주소 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo | string | parcel_box |
배송 메모 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo_label | string | 택배함에 넣어주세요 |
delivery_memo 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| options | array | [{"id":1263,"option_status":"payment_complete","option_st… |
주문 옵션(품목) 목록 (OrderOptionResource — 상품·옵션·수량·옵션상태·금액) |
| shipping_address | object | {"id":319,"address_type":"shipping","orderer_name":"박대수",… |
배송지 상세 (OrderAddressResource — 주문자/수령인/국내·해외 주소) |
| billing_address | null | null |
청구지 상세 (OrderAddressResource, 미분리 시 null) |
| payment | object | {"id":334,"payment_status":"paid","payment_status_label":… |
대표 결제 정보 (OrderPaymentResource — 결제수단·결제상태·금액) |
| payments | array | [{"id":334,"payment_status":"paid","payment_status_label"… |
결제 이력 목록 (OrderPaymentResource 배열 — 다회 결제/부분결제 포함) |
| shippings | array | [] |
배송 이력 목록 (OrderShippingResource 배열 — 배송유형·택배사·송장번호) |
| cancels | array | [] |
취소 이력 목록 (OrderCancelResource 배열 — 취소 사유·상세·취소일시, 최근순) |
| promotions_applied_snapshot | object | {"coupon_issue_ids":[7330],"item_coupons":[],"discount_co… |
적용된 프로모션 스냅샷 (재계산용) |
| shipping_policy_applied_snapshot | object | {"items": [], "address": {}} |
적용된 배송정책 스냅샷 (재계산용). items 는 옵션별 적용 정책 목록(각 항목: product_option_id, policy), address 는 주문 시점 배송지 메타(country_code, zipcode). 항목이 없어도 items 는 빈 배열이다 |
| shipping_policy_applied_snapshot (비회원 응답) | object | {"items": [{"product_option_id": 481, "policy": {"policy_name": "국내 무료배송", "standalone_shipping_amount": 0, "standalone_shipping_amount_formatted": "무료배송"}}]} |
비로그인(비회원 조회 토큰) 응답은 표시용 필드만 내보낸다 — policy_name · standalone_shipping_amount(_formatted). 정책 id·계산 근거와 배송지 메타(address)는 제외된다. 비회원 주문 상세 화면이 회원과 같은 partial 로 상품별 정책명·개별 배송비를 그리므로 필드 자체를 빼면 그 줄만 오류 없이 사라진다 |
| admin_memo | null | null |
관리자 메모 (내부 관리용) |
| customer_memo | null | null |
고객 메모 (주문 시 고객이 남긴 메모) |
| created_at | string | 2026-07-30T14:36:22+00:00 |
생성 일시 |
| updated_at | string | 2026-07-30T14:36:22+00:00 |
최종 수정 일시 |
| is_owner | boolean | true |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_read":true,"can_update":true,"can_cancel":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "주문 정보를 조회했습니다.",
"data": {
"id": 1316,
"order_number": "20260730-1436224914",
"base_currency": "JPY",
"payment_currency": "JPY",
"is_cross_currency": false,
"...": "(101개 키 생략, 총 106개)"
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.read)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)의 전체 상세를 조회합니다. auth:sanctum + sirsoft-ecommerce.orders.read 권한이 필요하며, Admin\OrderController@show가 OrderService::getDetail()로 옵션·배송·결제·취소 이력·금액 내역(과세/면세/다중통화 포함)까지 풀로드해 OrderResource로 반환합니다. 관리자 주문 상세 화면의 데이터 소스이며, 주문이 없으면 404를 반환합니다.
PATCH /api/modules/sirsoft-ecommerce/admin/orders/{order}
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.update - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@update - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| order_status | body | string | 아니오 | — | 변경할 주문상태 (OrderStatusEnum 값, 현재 상태에서 전이 가능한 값만 허용) |
| admin_memo | body | string | 아니오 | max 2000 | 관리자 메모 (내부 관리용, 고객 비노출) |
| recipient_name | body | string | 예 | max 50 | 수령인 이름 |
| recipient_phone | body | string | 아니오 | max 20 | 수령인 연락처 |
| recipient_tel | body | string | 아니오 | max 20 | 수령인 일반전화 (recipient_phone 없을 때 필수) |
| recipient_zipcode | body | string | 아니오 | max 10 | 수령인 우편번호 (국내 주소, 해외 주소 없을 때 필수) |
| recipient_address | body | string | 아니오 | max 255 | 수령인 기본 주소 (국내 주소, 해외 주소 없을 때 필수) |
| recipient_detail_address | body | string | 아니오 | max 255 | 수령인 상세 주소 (recipient_address 입력 시 필수) |
| address_line_1 | body | string | 아니오 | max 255 | 주소 1행 (기본 주소) |
| address_line_2 | body | string | 아니오 | max 255 | 주소 2행 (상세 주소) |
| intl_city | body | string | 아니오 | max 100 | 도시 (국제 주소) |
| intl_state | body | string | 아니오 | max 100 | 주/도 (국제 주소) |
| intl_postal_code | body | string | 아니오 | max 20 | 우편번호 (국제 주소) |
| delivery_memo | body | string | 아니오 | max 500 | 배송 메모 (배송 시 요청사항) |
| recipient_country_code | body | string | 아니오 | — | 수령인 배송국가 코드 (ISO 3166-1 alpha-2 2자리) |
요청 예시
PATCH /api/modules/sirsoft-ecommerce/admin/orders/1316 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"order_status": "예시값",
"admin_memo": "예시값",
"recipient_name": "예시 이름",
"recipient_phone": "010-1234-5678",
"recipient_tel": "예시값",
"recipient_zipcode": "06234",
"recipient_address": "서울특별시 강남구 테헤란로 1",
"recipient_detail_address": "서울특별시 강남구 테헤란로 1",
"address_line_1": "서울특별시 강남구 테헤란로 1",
"address_line_2": "서울특별시 강남구 테헤란로 1",
"intl_city": "예시값",
"intl_state": "예시값",
"intl_postal_code": "06234",
"delivery_memo": "예시값",
"recipient_country_code": "KR"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)의 주문상태·관리자 메모·수취인 배송지(국내/해외 주소 포함)를 수정합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@update가 OrderService::update()로 처리한 뒤 수정된 주문을 OrderResource로 반환합니다. 관리자 주문 상세에서 배송지 정정·메모 기록·상태 변경 등에 사용합니다.
POST /api/modules/sirsoft-ecommerce/admin/orders/{order}/cancel
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.cancel - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@cancelOrder - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| type | body | string | 예 | — | 취소 유형 (full 전체취소 / partial 부분취소 — partial 이면 items 필수) |
| reason | body | string | 예 | — | 취소 사유 코드 (ClaimReason 의 refund·활성 코드) |
| reason_detail | body | string | 아니오 | max 500 | 취소 사유 상세 (관리자 입력 자유 텍스트) |
| items | body | array | 아니오 | min 1 | 처리 대상 항목 배열 |
| cancel_pg | body | boolean | 아니오 | — | PG 결제 취소 동반 여부 (미지정 시 기본 true — 실제 PG 취소 수행) |
| refund_priority | body | string | 아니오 | pg_first, points_first |
환불 배분 우선순위 (pg_first PG 우선 / points_first 포인트 우선, 기본 pg_first) |
요청 예시
POST /api/modules/sirsoft-ecommerce/admin/orders/1316/cancel HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"type": "예시값",
"reason": "예시값",
"reason_detail": "예시값",
"items": [
"예시값"
],
"cancel_pg": true,
"refund_priority": "pg_first"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)을 전체취소 또는 부분취소합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@cancelOrder가 items 유무에 따라 OrderCancellationService의 cancelOrder()(전체) 또는 cancelOrderOptions()(부분)를 호출합니다. 취소자(cancelledBy)로 관리자 ID가 기록되고, cancel_pg로 PG 결제 취소 동반 여부를, refund_priority로 PG/포인트 환불 우선순위를 지정합니다. 취소 후 갱신된 주문을 OrderResource로 반환하며, 취소 불가 상태 등 실패 시 422를 반환합니다.
PATCH /api/modules/sirsoft-ecommerce/admin/orders/{order}/confirm-deposit
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.confirm-deposit - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@confirmDeposit - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| amount | body | number | 예 | min 0 | 확인된 입금액 (결제예정금액과 정확히 일치해야 함, 불일치 시 422) |
| depositor_name | body | string | 아니오 | max 100 | depositor 이름 (식별자) |
| mark_order_complete | body | boolean | 아니오 | — | 입금확인과 동시에 주문완료 처리 여부 (미지정 시 기본 false — 결제완료 전이만) |
요청 예시
PATCH /api/modules/sirsoft-ecommerce/admin/orders/1316/confirm-deposit HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"amount": 1,
"depositor_name": "예시 이름",
"mark_order_complete": true
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 무통장(dbank) 미결제 주문(order)의 입금을 확인해 결제완료로 전이합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@confirmDeposit가 OrderProcessingService::confirmManualDeposit()으로 입금자명·입금액을 기록하고 결제완료 처리합니다. 입금액(amount)이 결제예정금액과 정확히 일치하지 않으면 422(deposit_amount_mismatch)를 반환하며, mark_order_complete로 결제완료와 동시에 주문완료 처리 여부를 지정할 수 있습니다.
POST /api/modules/sirsoft-ecommerce/admin/orders/{order}/estimate-refund
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.estimate-refund - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@estimateRefund - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| items | body | array | 예 | min 1 | 처리 대상 항목 배열 |
| refund_priority | body | string | 아니오 | pg_first, points_first |
환불 배분 우선순위 (pg_first PG 우선 / points_first 포인트 우선, 기본 pg_first) |
요청 예시
POST /api/modules/sirsoft-ecommerce/admin/orders/1316/estimate-refund HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"items": [
"예시값"
],
"refund_priority": "pg_first"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)의 선택 옵션(items) 취소 시 예상 환불 금액을 실제 취소 없이 미리 계산합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@estimateRefund가 OrderCancellationService::previewRefund()로 환불 예상값을 반환합니다. refund_priority에 따라 PG 우선/포인트 우선 환불 배분 결과가 달라집니다. 취소 화면에서 "환불 예정 금액"을 관리자에게 미리 보여주는 용도입니다.
GET /api/modules/sirsoft-ecommerce/admin/orders/{order}/logs
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.logs - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@logs - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.read
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| per_page | query | integer | 아니오 | min 1, max 100 | 페이지당 항목 수 |
| sort_order | query | string | 아니오 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
요청 예시
GET /api/modules/sirsoft-ecommerce/admin/orders/1316/logs?per_page=1&sort_order=%EC%98%88%EC%8B%9C%EA%B0%92 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 27789 |
기본 키 (내부 식별자) |
| log_type | string | admin |
|
| log_type_label | string | 관리자 |
log_type 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| loggable_type | string | Modules\Sirsoft\Ecommerce\Models\Orde… |
|
| loggable_type_display | string | OrderOption |
|
| loggable_id | integer | 1264 |
loggable 식별자 (연관 리소스 참조) |
| action | string | order_option.partial_cancel |
|
| action_label | string | 부분 취소 |
action 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| localized_description | string | 주문 옵션 부분 취소 (옵션 ID: 1264) |
description 의 현재 로케일 해석 값 (다국어 필드를 표시용 문자열로 해석) |
| description_key | string | sirsoft-ecommerce::activity_log.descr… |
|
| properties | object | {"order_id":1316,"product_name":{"ko":"신제품 출시 예정 #21","en… |
|
| changes | null | null |
|
| bulk_changes | null | null |
|
| has_changes | boolean | false |
changes 여부 |
| actor_name | string | 시스템 |
행위를 수행한 주체(사용자/시스템)의 이름 |
| user | object | {"name":"시스템"} |
대상 사용자 정보 객체 (uuid/name/email 등 — user 관계 파생) |
| ip_address | string | 10.10.10.1 |
요청/행위가 발생한 IP 주소 |
| created_at | string | 2026-07-29 19:56:44 |
생성 일시 |
| is_owner | boolean | false |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_read":true,"can_delete":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "주문 처리 이력을 조회했습니다.",
"data": {
"data": [
{
"id": 27789,
"log_type": "admin",
"log_type_label": "관리자",
"loggable_type": "Modules\\Sirsoft\\Ecommerce\\Models\\OrderOption",
"loggable_type_display": "OrderOption",
"loggable_id": 1264,
"action": "order_option.partial_cancel",
"action_label": "부분 취소",
"localized_description": "주문 옵션 부분 취소 (옵션 ID: 1264)",
"description_key": "sirsoft-ecommerce::activity_log.description.order_option_partial_cancel",
"properties": {
"order_id": 1316,
"product_name": {
"ko": "신제품 출시 예정 #21",
"en": "Coming Soon Product #21"
},
"quantity": 3
},
"changes": null,
"bulk_changes": null,
"has_changes": false,
"actor_name": "시스템",
"user": {
"name": "시스템"
},
"ip_address": "10.10.10.1",
"created_at": "2026-07-29 19:56:44",
"is_owner": false,
"abilities": {
"can_read": true,
"can_delete": true
}
},
{
"id": 27766,
"log_type": "admin",
"log_type_label": "관리자",
"loggable_type": "Modules\\Sirsoft\\Ecommerce\\Models\\OrderOption",
"loggable_type_display": "OrderOption",
"loggable_id": 1263,
"action": "order_option.confirm",
"action_label": "구매 확정",
"localized_description": "구매확인 (옵션 ID: 1263)",
"description_key": "sirsoft-ecommerce::activity_log.description.order_option_confirm",
"properties": {
"order_id": 1316
},
"changes": null,
"bulk_changes": null,
"has_changes": false,
"actor_name": "시스템",
"user": {
"name": "시스템"
},
"ip_address": "10.0.0.5",
"created_at": "2026-07-29 09:06:44",
"is_owner": false,
"abilities": {
"can_read": true,
"can_delete": true
}
},
"... (총 25건 중 2건 표시)"
],
"links": {
"first": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=1",
"last": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=6",
"prev": null,
"next": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 6,
"links": [
{
"url": null,
"label": "pagination.previous",
"page": null,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=1",
"label": "1",
"page": 1,
"active": true
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=2",
"label": "2",
"page": 2,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=3",
"label": "3",
"page": 3,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=4",
"label": "4",
"page": 4,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=5",
"label": "5",
"page": 5,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=6",
"label": "6",
"page": 6,
"active": false
},
{
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs?page=2",
"label": "pagination.next",
"page": 2,
"active": false
}
],
"path": "https://api.example.com/api/modules/sirsoft-ecommerce/admin/orders/1316/logs",
"per_page": 25,
"to": 25,
"total": 126
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.read)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)의 활동 로그(주문·주문옵션·배송지 변경 이력 합산)를 페이지네이션 조회합니다. auth:sanctum + sirsoft-ecommerce.orders.read 권한이 필요하며, Admin\OrderController@logs가 OrderService::getActivityLogs()로 조회해 ActivityLogResource로 반환합니다. sort_order로 시간 정렬 방향을 지정할 수 있습니다. 관리자 주문 상세의 "처리 이력" 탭에서 누가 언제 무엇을 변경했는지 추적하는 용도입니다.
PATCH /api/modules/sirsoft-ecommerce/admin/orders/{order}/options/bulk-status
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.options.bulk-status - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@bulkChangeOptionStatus - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| items | body | array | 예 | min 1 | 처리 대상 항목 배열 |
| status | body | string | 예 | — | 일괄 전환할 옵션 상태 (OrderStatusEnum 값, 옵션별 전이 규칙 검증) |
| carrier_id | body | integer | 아니오 | — | carrier 식별자 |
| tracking_number | body | string | 아니오 | max 50 | 송장(운송장)번호 (배송 관련 상태로 전환 시 carrier_id 와 함께 필수) |
요청 예시
PATCH /api/modules/sirsoft-ecommerce/admin/orders/1316/options/bulk-status HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"items": [
"예시값"
],
"status": "예시값",
"carrier_id": 1,
"tracking_number": "예시값"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)의 여러 주문 옵션 상태를 수량 분할까지 지원해 일괄 변경합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@bulkChangeOptionStatus가 status를 OrderStatusEnum으로 변환한 뒤 OrderOptionService::bulkChangeStatusWithQuantity()로 처리합니다. 배송중으로 전환 시 carrier_id·tracking_number(택배사·송장번호)를 함께 넘길 수 있습니다. 한 옵션의 일부 수량만 상태 전환(부분 배송 등)하는 시나리오를 지원합니다. items[].option_id는 경로의 {order}에 속한 옵션이어야 합니다. 다른 주문의 옵션 ID를 포함하면 422(items.N.option_id)로 거절되며, 요청 전체가 반영되지 않습니다. 검증을 거치지 않는 내부·훅 호출 경로에서 같은 불일치가 감지되면 400으로 응답합니다.
POST /api/modules/sirsoft-ecommerce/admin/orders/{order}/reset-guest-lookup-password
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.reset-guest-lookup-password - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@resetGuestLookupPassword - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| guest_lookup_password | body | string | 예 | min 8, max 255 | 재설정할 비회원 주문 조회 비밀번호 (8자 이상, 해시로 저장 · 회원가입 정책과 동일) |
| guest_lookup_password_confirmation | body | string | 예 | — | 조회 비밀번호 확인 (guest_lookup_password 와 일치해야 함) |
요청 예시
POST /api/modules/sirsoft-ecommerce/admin/orders/1316/reset-guest-lookup-password HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"guest_lookup_password": "Password123!",
"guest_lookup_password_confirmation": "Password123!"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 비회원 주문(order)의 조회 비밀번호를 재설정합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, 비회원 주문(user_id IS NULL)만 허용하고 회원 주문에는 422를 반환합니다. Admin\OrderController@resetGuestLookupPassword가 OrderService::resetGuestLookupPassword()로 새 비밀번호를 해시로 저장하며, 평문은 응답/로그에 노출하지 않습니다. 비회원이 조회 비밀번호를 분실했을 때 관리자가 대신 재설정해 주는 용도입니다.
POST /api/modules/sirsoft-ecommerce/admin/orders/{order}/send-email
- 라우트명:
api.modules.sirsoft-ecommerce.admin.orders.send-email - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Admin\OrderController@sendEmail - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.orders.update
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| order | path | string | 예 | — | 정렬 방향 (asc 오름차순 / desc 내림차순) |
| body | 예 | max 255 | 이메일 주소 | ||
| message | body | string | 예 | max 5000 | 관리자가 작성한 안내 메일 본문 |
요청 예시
POST /api/modules/sirsoft-ecommerce/admin/orders/1316/send-email HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"email": "user@example.com",
"message": "예시값"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.orders.update)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 관리자가 특정 주문(order)에 대해 주문 관련 안내 이메일을 지정 주소(email)로 발송합니다. auth:sanctum + sirsoft-ecommerce.orders.update 권한이 필요하며, Admin\OrderController@sendEmail이 OrderService::sendEmail()로 관리자가 작성한 메시지(message)를 전송합니다. 주문 관련 개별 안내가 필요할 때 관리자가 상세 화면에서 수동으로 메일을 보내는 용도입니다.
POST /api/modules/sirsoft-ecommerce/orders/{orderNumber}/cancel-payment
- 라우트명:
api.modules.sirsoft-ecommerce.orders.cancel-payment - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Public\OrderController@cancelPayment - 인증/권한:
optional.sanctum(선택적 인증: 회원/비회원 모두 접근)
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| orderNumber | path | string | 예 | — | 대상 order number의 식별자 |
| cancel_code | body | string | 아니오 | max 100 | PG사 취소 코드 (예: USER_CANCEL, order_payments 취소 이력에 기록) |
| cancel_message | body | string | 아니오 | max 500 | PG사 취소 메시지 (order_payments 취소 이력에 기록) |
요청 예시
POST /api/modules/sirsoft-ecommerce/orders/{orderNumber}/cancel-payment HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN} (optional.sanctum: 비회원은 헤더 생략 가능)
Content-Type: application/json
{
"cancel_code": "예시값",
"cancel_message": "예시값"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원/비회원이 PG 결제창을 닫았을 때 결제 취소 이력만 기록합니다. optional.sanctum으로 회원/비회원 모두 접근하며, Public\OrderController@cancelPayment가 OrderProcessingService::recordPaymentCancellation()으로 주문 상태는 변경하지 않고 order_payments에 취소창 닫힘 이력(cancel_code·cancel_message)만 남깁니다. 결제 SDK가 사용자 취소 콜백을 받았을 때 프론트가 호출해 결제 시도 이력을 추적하는 용도입니다.
GET /api/modules/sirsoft-ecommerce/user/orders
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.index - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@index - 인증/권한:
auth:sanctum
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| page | query | integer | 아니오 | min 1 | 조회할 페이지 번호 (1부터 시작) |
| per_page | query | integer | 아니오 | min 1, max 50 | 페이지당 항목 수 |
| status | query | string | 아니오 | — | 상태 필터 (해당 상태의 항목만 조회) |
| with_items | query | boolean | 아니오 | 기본 false |
주문 아이템 전량을 포함할지. 기본값에서는 대표 아이템 1건과 전체 개수(item_count)만 내려갑니다. 주문마다 상품을 전부 나열하는 화면만 켜세요 |
목록은 경량 표현입니다.
기본 응답의 items[] 에는 대표 아이템 1건만 담기고, 전체 개수는 item_count 로 제공됩니다. 아이템이 없는 주문은 빈 배열입니다. 주문마다 상품을 전부 나열해야 하는 화면은 with_items=1 로 전량을 요청하세요 — 그렇지 않은 호출자까지 주문 수 × 아이템 수를 받지 않게 하려는 기본값입니다.
부분취소 뱃지(is_partially_cancelled)는 아이템 전량 없이도 정확합니다. 서버가 집계로 판정하므로 두 경로의 값이 같습니다.
요청 예시
GET /api/modules/sirsoft-ecommerce/user/orders?page=1&per_page=1&status=%EC%98%88%EC%8B%9C%EA%B0%92&with_items=1 HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
목록 응답: data.data[] 배열 항목의 필드 + data.pagination.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 1345 |
기본 키 (내부 식별자) |
| order_number | string | 20260730-1436245243 |
주문번호 (사용자 노출용 고유 식별 코드) |
| status | string | preparing |
주문상태 값 (OrderStatusEnum value — 마이페이지용 status 별칭) |
| status_label | string | 상품준비중 |
상태의 사람이 읽는 라벨 (상태 Enum label() 산물) |
| status_variant | string | info |
상태 표시 색상/스타일 변형 키 (상태 Enum variant() 산물 — UI 배지용) |
| is_partially_cancelled | boolean | false |
partially cancelled 여부 |
| recipient_country_code | string | KR |
배송국가 코드 (ISO 3166-1 alpha-2, shippingAddress 로드 시) |
| recipient_country_name | object | {"ko":"한국","en":"South Korea"} |
배송국가 현지화명 (로케일별 국가명 맵) |
| ordered_at | string | 2026-07-29T14:36:24+00:00 |
ordered 일시 |
| ordered_at_formatted | string | 2026-07-29 23:36:24 |
ordered_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_amount | integer | 30000 |
최종 주문금액 (상품합계 − 할인 + 배송비) |
| total_amount_formatted | string | ¥30,000 |
total_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| mc_total_amount | object | {"KRW":{"amount":30000,"formatted":"30,000원"},"USD":{"amo… |
최종 주문금액 다중 통화 (주문 시점 스냅샷, 통화별 amount·formatted) |
| total_shipping_amount | integer | 0 |
총 배송비 |
| total_shipping_amount_formatted | string | ¥0 |
total_shipping_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| mc_total_shipping_amount | object | {"KRW":{"amount":0,"formatted":"0원"},"USD":{"amount":0,"f… |
총 배송비 다중 통화 (주문 시점 스냅샷, 통화별 amount·formatted) |
| total_points_used_amount | integer | 0 |
총 포인트(마일리지) 사용액 |
| total_points_used_amount_formatted | string | ¥0 |
total_points_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_earned_points_amount | integer | 300 |
총 적립 예정 포인트 |
| total_earned_points_amount_formatted | string | ¥300 |
total_earned_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| items | array | [{"product_name":"USB 충전 케이블 #7","product_option_name":"2… |
주문 품목 목록 (상품명·옵션명·썸네일·수량·단가/소계·추가옵션 요약) |
| item_count | integer | 1 |
item 개수 (집계) |
| abilities | object | {"can_view":true,"can_cancel":false} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
HTTP/1.1 200
{
"success": true,
"message": "주문 정보를 조회했습니다.",
"data": {
"data": [
{
"id": 1345,
"order_number": "20260730-1436245243",
"status": "preparing",
"status_label": "상품준비중",
"status_variant": "info",
"...": "(18개 키 생략, 총 23개)"
},
{
"id": 1344,
"order_number": "20260730-1436244391",
"status": "preparing",
"status_label": "상품준비중",
"status_variant": "info",
"...": "(18개 키 생략, 총 23개)"
},
"... (총 25건 중 2건 표시)"
],
"statistics": {
"pending_payment": 0,
"payment_complete": 20,
"preparing": 10,
"shipping": 0,
"delivered": 0,
"...": "(1개 키 생략, 총 6개)"
},
"abilities": {
"can_create": true
},
"pagination": {
"current_page": 1,
"last_page": 2,
"per_page": 25,
"total": 30
}
}
}
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
설명 회원이 마이페이지 주문내역에서 본인 주문 목록을 상태별 통계와 함께 페이지네이션 조회합니다. auth:sanctum 인증이 필요하며, User\OrderController@index가 user_id를 본인으로 고정한 뒤 OrderService::getList()와 getUserStatistics()를 호출해 UserOrderCollection으로 반환합니다. status로 특정 주문상태만 필터링할 수 있습니다. 관리자 목록과 달리 항상 본인 주문으로만 한정됩니다.
POST /api/modules/sirsoft-ecommerce/user/orders
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.store - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Public\OrderController@store - 인증/권한:
optional.sanctum(선택적 인증: 회원/비회원 모두 접근) +permission:sirsoft-ecommerce.user-orders.create
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| payment_method | body | string | 예 | — | 결제수단. 코어 8종(card/vbank/dbank/bank/phone/point/deposit/free) 과 PG 플러그인이 등록한 확장 결제수단 ID(예: nhnkcp_naverpay, kginicis_lpay)를 모두 허용한다. 확장 결제수단도 1급 시민으로 그대로 저장된다. 카탈로그에 없는 값은 422 |
| expected_total_amount | body | number | 예 | min 0 | 프론트가 계산한 예상 결제금액 (서버 재계산값과 대조해 금액 위변조 검증) |
| shipping_memo | body | string | 아니오 | max 500 | 배송 요청사항 메모 |
| depositor_name | body | string | 아니오 | max 50 | depositor 이름 (식별자) |
| save_shipping_address | body | boolean | 아니오 | — | 회원 주소록에 이번 배송지 저장 여부 (회원 주문 한정) |
| guest_lookup_password | body | string | 예 | min 8, max 255 | 비회원 주문 조회 비밀번호 (비회원만 필수, 8자 이상 · 해시로 저장) |
| guest_lookup_password_confirmation | body | string | 예 | — | 조회 비밀번호 확인 (guest_lookup_password 와 일치해야 함) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
sirsoft-ecommerce.order.create_validation_rules).
요청 예시
POST /api/modules/sirsoft-ecommerce/user/orders HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN} (optional.sanctum: 비회원은 헤더 생략 가능)
Content-Type: application/json
{
"payment_method": "예시값",
"expected_total_amount": 1,
"shipping_memo": "예시값",
"depositor_name": "예시 이름",
"save_shipping_address": true,
"guest_lookup_password": "Password123!",
"guest_lookup_password_confirmation": "Password123!"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.user-orders.create)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지). payment_method 가 결제수단 카탈로그에 없는 값이면 여기서 차단된다 |
설명 주문서 작성을 마치고 실제 주문을 생성(결제하기)하는 회원/비회원 공용 엔드포인트입니다. PG 플러그인의 fetch 인터셉터가 이 한 경로만 매칭하므로 회원/비회원이 동일 URL로 진입하고, Public\OrderController@store가 Auth::id()로 분기합니다(회원은 OrderResource, 비회원은 민감 필드를 가린 GuestOrderResource). optional.sanctum + sirsoft-ecommerce.user-orders.create 권한이 필요하며, expected_total_amount로 금액 위변조를 검증하고 비회원은 guest_lookup_password로 이후 조회 비밀번호를 설정합니다. 회원이 save_shipping_address를 켜면 배송지가 자동 저장(PG 결제는 결제완료 시점) 됩니다.
주문 확정 시점에는 재고·구매대상제한·배송국가·쿠폰 유효성과 함께 마일리지 사용 정책도 현재 설정 기준으로 재검증합니다. 임시 주문을 만든 뒤 관리자가 한도를 강화했거나 임시 주문이 조작된 경우 422(errors.code = mileage_usage_not_allowed)로 차단되며 주문은 생성되지 않습니다. 반대로 정상 생성된 주문에는 그 시점의 사용 정책이 mileage_policy_snapshot 으로 고정되어, 이후 설정이 바뀌어도 해당 주문의 판정 근거를 재현할 수 있습니다(통화·프로모션·배송정책 스냅샷과 동일 취지).
GET /api/modules/sirsoft-ecommerce/user/orders/{id}
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.show-by-id - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@show - 인증/권한:
auth:sanctum
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
요청 예시
GET /api/modules/sirsoft-ecommerce/user/orders/{id} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 4 |
기본 키 (내부 식별자) |
| order_number | string | APIDOC-20260708-000001 |
주문번호 |
| base_currency | string | KRW |
금액 표기 기준 통화 (모든 *_formatted 필드의 통화, 주문 시점 base_currency 고정) |
| payment_currency | string | KRW |
결제 통화 (유저가 선택·결제한 통화, base_currency 와 다르면 병기 표시) |
| is_cross_currency | boolean | false |
cross currency 여부 |
| order_status | string | pending_payment |
주문상태 (OrderStatusEnum) |
| order_status_label | string | 결제대기 |
order_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| order_status_variant | string | warning |
order_status 값의 표시 변형 키 (UI 배지 색상/스타일) |
| is_partially_cancelled | boolean | false |
partially cancelled 여부 |
| order_device | string | pc |
주문 디바이스 (pc/mobile/app) |
| order_device_label | string | PC |
order_device 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| is_first_order | boolean | false |
first order 여부 |
| subtotal_amount | integer | 324327 |
상품 합계 (할인 전, 상품가×수량 합계) |
| subtotal_amount_formatted | string | 324,327원 |
subtotal_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_discount_amount | integer | 0 |
총 할인금액 (모든 할인 합계) |
| total_discount_amount_formatted | string | 0원 |
total_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_shipping_amount | integer | 3000 |
총 배송비 |
| total_shipping_amount_formatted | string | 3,000원 |
total_shipping_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_amount | integer | 327327 |
최종 주문금액 (subtotal - discount + shipping) |
| total_amount_formatted | string | 327,327원 |
total_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_paid_amount | integer | 0 |
총 실제 결제금액 (PG 결제액) |
| total_paid_amount_formatted | string | 0원 |
total_paid_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_due_amount | integer | 327327 |
총 결제예정금액 (무통장 등) |
| total_due_amount_formatted | string | 327,327원 |
total_due_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| depositor_name | null | null |
무통장 입금자명 (입금확인 모달 기본값, payment 관계 로드 시에만 노출) |
| total_cancelled_amount | integer | 0 |
총 취소금액 |
| total_cancelled_amount_formatted | string | 0원 |
total_cancelled_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_amount | integer | 0 |
총 환불금액 |
| total_refunded_amount_formatted | string | 0원 |
total_refunded_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_points_amount | integer | 0 |
총 환불 포인트 |
| total_refunded_points_amount_formatted | string | 0원 |
total_refunded_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_product_coupon_discount_amount | integer | 0 |
상품 쿠폰 할인 합계 |
| total_product_coupon_discount_amount_formatted | string | 0원 |
total_product_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_order_coupon_discount_amount | integer | 0 |
주문 쿠폰 할인 합계 |
| total_order_coupon_discount_amount_formatted | string | 0원 |
total_order_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_coupon_discount_amount | integer | 0 |
총 쿠폰 할인금액 |
| total_coupon_discount_amount_formatted | string | 0원 |
total_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_code_discount_amount | integer | 0 |
총 할인코드 할인금액 |
| total_code_discount_amount_formatted | string | 0원 |
total_code_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_points_used_amount | integer | 0 |
총 포인트 사용액 |
| total_points_used_amount_formatted | string | 0원 |
total_points_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_deposit_used_amount | integer | 0 |
총 예치금 사용액 |
| total_deposit_used_amount_formatted | string | 0원 |
total_deposit_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_earned_points_amount | integer | 3273 |
총 적립 예정 포인트 |
| total_earned_points_amount_formatted | string | 3,273원 |
total_earned_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| mc_subtotal_amount | array | [] |
상품합계 다중 통화 |
| mc_total_discount_amount | array | [] |
총 할인 다중 통화 |
| mc_total_shipping_amount | array | [] |
총 배송비 다중 통화 |
| mc_total_amount | array | [] |
최종금액 다중 통화 (payment_amount) |
| mc_total_product_coupon_discount_amount | array | [] |
상품 쿠폰 할인 다중 통화 |
| mc_total_order_coupon_discount_amount | array | [] |
주문 쿠폰 할인 다중 통화 |
| mc_total_coupon_discount_amount | array | [] |
쿠폰 할인 합계 다중 통화 |
| mc_total_code_discount_amount | array | [] |
할인코드 할인 다중 통화 |
| mc_total_points_used_amount | array | [] |
포인트 사용 다중 통화 |
| mc_total_deposit_used_amount | array | [] |
예치금 사용 다중 통화 |
| item_count | integer | 4 |
item 개수 (집계) |
| total_quantity | integer | 0 |
주문 옵션 수량 합계 (options 로드 시) |
| total_list_price | integer | 0 |
정가 합계 (옵션 스냅샷 정가 × 수량 합계) |
| total_list_price_formatted | string | 0원 |
total_list_price 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| ordered_at | string | 2026-07-08T01:44:49+00:00 |
ordered 일시 |
| ordered_at_formatted | string | 2026-07-08 10:44:49 |
ordered_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| paid_at | null | null |
paid 일시 |
| paid_at_formatted | null | null |
paid_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| confirmed_at | null | null |
confirmed 일시 |
| confirmed_at_formatted | null | null |
confirmed_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| cancelled_at | null | null |
cancelled 일시 |
| cancelled_at_formatted | null | null |
cancelled_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| delivered_at | null | null |
delivered 일시 |
| total_tax_amount | integer | 29757 |
총 과세금액 |
| total_tax_amount_formatted | string | 29,757원 |
total_tax_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_vat_amount | integer | 0 |
총 부가세금액 |
| total_vat_amount_formatted | string | 0원 |
total_vat_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_taxable_supply_amount | integer | 29757 |
과세 공급가액 (총 과세금액 − 부가세, 영수증 과세금액 표시 SSoT) |
| total_taxable_supply_amount_formatted | string | 29,757원 |
total_taxable_supply_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_tax_free_amount | integer | 0 |
총 면세금액 |
| total_tax_free_amount_formatted | string | 0원 |
total_tax_free_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| user | object | {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… |
대상 사용자 정보 객체 (uuid/name/email 등 — user 관계 파생) |
| user_id | string | a234c2b1-cde8-437f-b28b-23323be2b98d |
user 식별자 (연관 리소스 참조) |
| user_login_id | null | null |
회원 로그인 아이디 (login_id, 비회원 주문이면 null) |
| orderer_name | null | null |
주문자 이름 (배송지에서 플래튼) |
| orderer_phone | null | null |
주문자 휴대전화 (배송지에서 플래튼) |
| orderer_tel | null | null |
주문자 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| orderer_email | null | null |
주문자 이메일 (배송지에서 플래튼, 비회원 알림 수신 통로) |
| recipient_name | null | null |
수령인 이름 (배송지에서 플래튼) |
| recipient_phone | null | null |
수령인 휴대전화 (배송지에서 플래튼) |
| recipient_tel | null | null |
수령인 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| recipient_zipcode | null | null |
수령인 우편번호 (배송지에서 플래튼) |
| recipient_address | null | null |
수령인 기본 주소 (배송지에서 플래튼) |
| recipient_detail_address | null | null |
수령인 상세 주소 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo | null | null |
배송 메모 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo_label | null | null |
delivery_memo 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| options | array | [] |
주문 옵션(품목) 목록 (OrderOptionResource — 상품·옵션·수량·옵션상태·금액) |
| shipping_address | null | null |
배송지 상세 (OrderAddressResource — 주문자/수령인/국내·해외 주소) |
| billing_address | null | null |
청구지 상세 (OrderAddressResource, 미분리 시 null) |
| payment | null | null |
대표 결제 정보 (OrderPaymentResource — 결제수단·결제상태·금액) |
| payments | array | [] |
결제 이력 목록 (OrderPaymentResource 배열 — 다회 결제/부분결제 포함) |
| shippings | array | [] |
배송 이력 목록 (OrderShippingResource 배열 — 배송유형·택배사·송장번호) |
| cancels | array | [] |
취소 이력 목록 (OrderCancelResource 배열 — 취소 사유·상세·취소일시, 최근순) |
| promotions_applied_snapshot | null | null |
적용된 프로모션 스냅샷 (재계산용) |
| shipping_policy_applied_snapshot | object | {"items": [], "address": {}} |
적용된 배송정책 스냅샷 (재계산용). items 는 옵션별 적용 정책 목록(각 항목: product_option_id, policy), address 는 주문 시점 배송지 메타(country_code, zipcode). 항목이 없어도 items 는 빈 배열이다 |
| admin_memo | null | null |
관리자 메모 (내부 관리용) |
| customer_memo | null | null |
고객 메모 (주문 시 고객이 남긴 메모) |
| created_at | string | 2026-07-08T01:44:49+00:00 |
생성 일시 |
| updated_at | string | 2026-07-08T01:44:49+00:00 |
최종 수정 일시 |
| is_owner | boolean | true |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_read":true,"can_update":true,"can_cancel":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 마이페이지 주문 상세에서 주문 ID(id)로 본인 주문의 전체 상세를 조회합니다. auth:sanctum 인증이 필요하며, User\OrderController@show가 OrderService::getDetail()로 로드한 뒤 소유자 검증(user_id === Auth::id())을 거쳐 OrderResource로 반환합니다. 본인 주문이 아니거나 존재하지 않으면 정보 노출 방지를 위해 404를 반환합니다. 주문번호로 조회하는 showByOrderNumber와 달리 내부 주문 ID를 사용합니다.
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/cancel
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.cancel - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@cancel - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.user-orders.cancel
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
| reason | body | string | 예 | — | 취소 사유 코드 (ClaimReason 의 refund·활성·사용자 선택 가능 코드) |
| reason_detail | body | string | 아니오 | max 500 | 취소 사유 상세 (회원 입력 자유 텍스트) |
| items | body | array | 아니오 | min 1 | 처리 대상 항목 배열 |
| refund_priority | body | string | 아니오 | pg_first, points_first |
환불 배분 우선순위 (pg_first PG 우선 / points_first 포인트 우선, 기본 pg_first) |
요청 예시
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/cancel HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"reason": "예시값",
"reason_detail": "예시값",
"items": [
"예시값"
],
"refund_priority": "pg_first"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.user-orders.cancel)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 마이페이지에서 본인 주문(id)을 취소합니다. auth:sanctum + sirsoft-ecommerce.user-orders.cancel 권한이 필요하며, User\OrderController@cancel이 items 유무에 따라 OrderCancellationService의 cancelOrderOptions()(부분) 또는 cancelOrder()(전체)를 호출합니다. 취소자(cancelledBy)로 회원 본인 ID가 기록되고, refund_priority로 PG/포인트 환불 우선순위를 지정합니다. 취소 가능 상태의 주문만 취소되며, 취소 후 갱신된 주문을 OrderResource로 반환합니다.
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/estimate-refund
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.estimate-refund - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@estimateRefund - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.user-orders.cancel
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
| items | body | array | 예 | min 1 | 처리 대상 항목 배열 |
| refund_priority | body | string | 아니오 | pg_first, points_first |
환불 배분 우선순위 (pg_first PG 우선 / points_first 포인트 우선, 기본 pg_first) |
요청 예시
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/estimate-refund HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"items": [
"예시값"
],
"refund_priority": "pg_first"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.user-orders.cancel)이 없는 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 마이페이지에서 본인 주문(id)의 선택 옵션(items) 취소 시 예상 환불 금액을 실제 취소 없이 미리 계산합니다. auth:sanctum + sirsoft-ecommerce.user-orders.cancel 권한이 필요하며, User\OrderController@estimateRefund가 OrderCancellationService::previewRefund()로 환불 예상값을 반환합니다. refund_priority에 따라 PG 우선/포인트 우선 환불 배분 결과가 달라집니다. 취소 확정 전 "환불 예정 금액"을 회원에게 안내하는 용도입니다.
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/options/{optionId}/confirm
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.confirm-option - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@confirmOption - 인증/권한:
auth:sanctum+permission:sirsoft-ecommerce.user-orders.confirm
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
| optionId | path | string | 예 | — | 대상 option의 식별자 |
요청 예시
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/options/{optionId}/confirm HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 403 | Forbidden | 요구 권한(sirsoft-ecommerce.user-orders.confirm)이 없는 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 마이페이지에서 본인 주문(id)의 개별 옵션(optionId)을 구매확정합니다. auth:sanctum + sirsoft-ecommerce.user-orders.confirm 권한이 필요하며, User\OrderController@confirmOption이 OrderService::confirmOption()을 호출합니다. 구매확정 시 적립 포인트 확정 등 후속 처리가 이어지며, 확정 불가 상태(배송 미완료 등)면 422를 반환합니다. 배송 완료된 상품을 회원이 직접 "구매확정" 할 때 사용합니다.
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/reorder
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.reorder - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@reorder - 인증/권한:
auth:sanctum
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
요청 예시
POST /api/modules/sirsoft-ecommerce/user/orders/{id}/reorder HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 과거 주문(id)의 옵션들을 현재 장바구니에 다시 담는 재주문 기능입니다. auth:sanctum 인증이 필요하며, User\OrderController@reorder가 CartService::reorderFromOrder()로 처리해 담긴 수량(added_count), 담지 못한 항목(skipped[]), 현재 장바구니 총 개수(cart_count)를 반환합니다. 취소된 주문도 재주문 대상이 되며, 품절·단종·상품별 구매수량 한도 초과 등으로 추가 불가한 항목은 건너뛰어 skipped 배열로 안내합니다. 한 항목이 담기지 못해도 나머지 항목은 그대로 담기며, 응답은 200 입니다(항목 하나 때문에 재주문 전체를 실패시키지 않습니다). 마이페이지 주문내역의 "재주문" 버튼에 사용합니다.
PUT /api/modules/sirsoft-ecommerce/user/orders/{id}/shipping-address
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.update-shipping-address - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\User\OrderController@updateShippingAddress - 인증/권한:
auth:sanctum
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| id | path | string | 예 | — | 대상 리소스의 식별자 |
| address_id | body | integer | 아니오 | — | address 식별자 |
| recipient_name | body | string | 아니오 | max 50 | 수령인 이름 |
| recipient_phone | body | string | 아니오 | max 20 | 수령인 연락처 |
| country_code | body | string | 아니오 | — | 국가 코드 (ISO 3166-1 alpha-2) |
| zipcode | body | string | 아니오 | max 10 | 우편번호 |
| address | body | string | 아니오 | max 255 | 기본 주소 |
| address_detail | body | string | 아니오 | max 255 | 상세 주소 |
| address_line_1 | body | string | 아니오 | max 255 | 주소 1행 (기본 주소) |
| address_line_2 | body | string | 아니오 | max 255 | 주소 2행 (상세 주소) |
| intl_city | body | string | 아니오 | max 100 | 도시 (국제 주소) |
| intl_state | body | string | 아니오 | max 100 | 주/도 (국제 주소) |
| intl_postal_code | body | string | 아니오 | max 20 | 우편번호 (국제 주소) |
| delivery_memo | body | string | 아니오 | max 255 | 배송 메모 (배송 시 요청사항) |
이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (
sirsoft-ecommerce.order.shipping_address_validation_rules).
요청 예시
PUT /api/modules/sirsoft-ecommerce/user/orders/{id}/shipping-address HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN}
Content-Type: application/json
{
"address_id": 1,
"recipient_name": "예시 이름",
"recipient_phone": "010-1234-5678",
"country_code": "KR",
"zipcode": "06234",
"address": "서울특별시 강남구 테헤란로 1",
"address_detail": "서울특별시 강남구 테헤란로 1",
"address_line_1": "서울특별시 강남구 테헤란로 1",
"address_line_2": "서울특별시 강남구 테헤란로 1",
"intl_city": "예시값",
"intl_state": "예시값",
"intl_postal_code": "06234",
"delivery_memo": "예시값"
}
응답 필드 (data 내부)
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (error.errors 에 필드별 메시지) |
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 회원이 배송 전 상태의 본인 주문(id) 배송지를 변경합니다. auth:sanctum 인증이 필요하며, User\OrderController@updateShippingAddress가 소유자 검증 후 OrderService::updateShippingAddress()로 처리합니다. 저장된 회원 주소(address_id)를 선택하거나 수취인·연락처·주소 필드를 직접 입력할 수 있고, 국내(zipcode/address)와 해외(address_line_1·intl_city 등) 주소를 모두 지원합니다. 이미 배송이 시작된 주문 등 변경 불가 상태면 422를 반환합니다.
GET /api/modules/sirsoft-ecommerce/user/orders/{orderNumber}
- 라우트명:
api.modules.sirsoft-ecommerce.user.orders.show - 컨트롤러:
Modules\Sirsoft\Ecommerce\Http\Controllers\Public\OrderController@showByOrderNumber - 인증/권한:
optional.sanctum(선택적 인증: 회원/비회원 모두 접근)
요청 파라미터
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|---|---|---|---|---|---|
| orderNumber | path | string | 예 | — | 대상 order number의 식별자 |
요청 예시
GET /api/modules/sirsoft-ecommerce/user/orders/{orderNumber} HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer {YOUR_TOKEN} (optional.sanctum: 비회원은 헤더 생략 가능)
응답 필드 (data 내부)
단건 응답: data 객체의 필드.
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|---|---|---|---|
| id | integer | 4 |
기본 키 (내부 식별자) |
| order_number | string | APIDOC-20260708-000001 |
주문번호 |
| base_currency | string | KRW |
금액 표기 기준 통화 (모든 *_formatted 필드의 통화, 주문 시점 base_currency 고정) |
| payment_currency | string | KRW |
결제 통화 (유저가 선택·결제한 통화, base_currency 와 다르면 병기 표시) |
| is_cross_currency | boolean | false |
cross currency 여부 |
| order_status | string | pending_payment |
주문상태 (OrderStatusEnum) |
| order_status_label | string | 결제대기 |
order_status 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| order_status_variant | string | warning |
order_status 값의 표시 변형 키 (UI 배지 색상/스타일) |
| is_partially_cancelled | boolean | false |
partially cancelled 여부 |
| order_device | string | pc |
주문 디바이스 (pc/mobile/app) |
| order_device_label | string | PC |
order_device 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| is_first_order | boolean | false |
first order 여부 |
| subtotal_amount | integer | 324327 |
상품 합계 (할인 전, 상품가×수량 합계) |
| subtotal_amount_formatted | string | 324,327원 |
subtotal_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_discount_amount | integer | 0 |
총 할인금액 (모든 할인 합계) |
| total_discount_amount_formatted | string | 0원 |
total_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_shipping_amount | integer | 3000 |
총 배송비 |
| total_shipping_amount_formatted | string | 3,000원 |
total_shipping_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_amount | integer | 327327 |
최종 주문금액 (subtotal - discount + shipping) |
| total_amount_formatted | string | 327,327원 |
total_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_paid_amount | integer | 0 |
총 실제 결제금액 (PG 결제액) |
| total_paid_amount_formatted | string | 0원 |
total_paid_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_due_amount | integer | 327327 |
총 결제예정금액 (무통장 등) |
| total_due_amount_formatted | string | 327,327원 |
total_due_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| depositor_name | null | null |
무통장 입금자명 (입금확인 모달 기본값, payment 관계 로드 시에만 노출) |
| total_cancelled_amount | integer | 0 |
총 취소금액 |
| total_cancelled_amount_formatted | string | 0원 |
total_cancelled_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_amount | integer | 0 |
총 환불금액 |
| total_refunded_amount_formatted | string | 0원 |
total_refunded_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_refunded_points_amount | integer | 0 |
총 환불 포인트 |
| total_refunded_points_amount_formatted | string | 0원 |
total_refunded_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_product_coupon_discount_amount | integer | 0 |
상품 쿠폰 할인 합계 |
| total_product_coupon_discount_amount_formatted | string | 0원 |
total_product_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_order_coupon_discount_amount | integer | 0 |
주문 쿠폰 할인 합계 |
| total_order_coupon_discount_amount_formatted | string | 0원 |
total_order_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_coupon_discount_amount | integer | 0 |
총 쿠폰 할인금액 |
| total_coupon_discount_amount_formatted | string | 0원 |
total_coupon_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_code_discount_amount | integer | 0 |
총 할인코드 할인금액 |
| total_code_discount_amount_formatted | string | 0원 |
total_code_discount_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_points_used_amount | integer | 0 |
총 포인트 사용액 |
| total_points_used_amount_formatted | string | 0원 |
total_points_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_deposit_used_amount | integer | 0 |
총 예치금 사용액 |
| total_deposit_used_amount_formatted | string | 0원 |
total_deposit_used_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_earned_points_amount | integer | 3273 |
총 적립 예정 포인트 |
| total_earned_points_amount_formatted | string | 3,273원 |
total_earned_points_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| mc_subtotal_amount | array | [] |
상품합계 다중 통화 |
| mc_total_discount_amount | array | [] |
총 할인 다중 통화 |
| mc_total_shipping_amount | array | [] |
총 배송비 다중 통화 |
| mc_total_amount | array | [] |
최종금액 다중 통화 (payment_amount) |
| mc_total_product_coupon_discount_amount | array | [] |
상품 쿠폰 할인 다중 통화 |
| mc_total_order_coupon_discount_amount | array | [] |
주문 쿠폰 할인 다중 통화 |
| mc_total_coupon_discount_amount | array | [] |
쿠폰 할인 합계 다중 통화 |
| mc_total_code_discount_amount | array | [] |
할인코드 할인 다중 통화 |
| mc_total_points_used_amount | array | [] |
포인트 사용 다중 통화 |
| mc_total_deposit_used_amount | array | [] |
예치금 사용 다중 통화 |
| item_count | integer | 4 |
item 개수 (집계) |
| total_quantity | integer | 0 |
주문 옵션 수량 합계 (options 로드 시) |
| total_list_price | integer | 0 |
정가 합계 (옵션 스냅샷 정가 × 수량 합계) |
| total_list_price_formatted | string | 0원 |
total_list_price 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| ordered_at | string | 2026-07-08T01:44:49+00:00 |
ordered 일시 |
| ordered_at_formatted | string | 2026-07-08 10:44:49 |
ordered_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| paid_at | null | null |
paid 일시 |
| paid_at_formatted | null | null |
paid_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| confirmed_at | null | null |
confirmed 일시 |
| confirmed_at_formatted | null | null |
confirmed_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| cancelled_at | null | null |
cancelled 일시 |
| cancelled_at_formatted | null | null |
cancelled_at 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| delivered_at | null | null |
delivered 일시 |
| total_tax_amount | integer | 29757 |
총 과세금액 |
| total_tax_amount_formatted | string | 29,757원 |
total_tax_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_vat_amount | integer | 0 |
총 부가세금액 |
| total_vat_amount_formatted | string | 0원 |
total_vat_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_taxable_supply_amount | integer | 29757 |
과세 공급가액 (총 과세금액 − 부가세, 영수증 과세금액 표시 SSoT) |
| total_taxable_supply_amount_formatted | string | 29,757원 |
total_taxable_supply_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| total_tax_free_amount | integer | 0 |
총 면세금액 |
| total_tax_free_amount_formatted | string | 0원 |
total_tax_free_amount 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
| user | object | {"uuid":"a234c2b1-cde8-437f-b28b-23323be2b98d","name":"AP… |
대상 사용자 정보 객체 (uuid/name/email 등 — user 관계 파생) |
| user_id | string | a234c2b1-cde8-437f-b28b-23323be2b98d |
user 식별자 (연관 리소스 참조) |
| user_login_id | null | null |
회원 로그인 아이디 (login_id, 비회원 주문이면 null) |
| orderer_name | null | null |
주문자 이름 (배송지에서 플래튼) |
| orderer_phone | null | null |
주문자 휴대전화 (배송지에서 플래튼) |
| orderer_tel | null | null |
주문자 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| orderer_email | null | null |
주문자 이메일 (배송지에서 플래튼, 비회원 알림 수신 통로) |
| recipient_name | null | null |
수령인 이름 (배송지에서 플래튼) |
| recipient_phone | null | null |
수령인 휴대전화 (배송지에서 플래튼) |
| recipient_tel | null | null |
수령인 일반전화 (배송지에서 플래튼, 미입력 시 null) |
| recipient_zipcode | null | null |
수령인 우편번호 (배송지에서 플래튼) |
| recipient_address | null | null |
수령인 기본 주소 (배송지에서 플래튼) |
| recipient_detail_address | null | null |
수령인 상세 주소 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo | null | null |
배송 메모 (배송지에서 플래튼, 미입력 시 null) |
| delivery_memo_label | null | null |
delivery_memo 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
| options | array | [] |
주문 옵션(품목) 목록 (OrderOptionResource — 상품·옵션·수량·옵션상태·금액) |
| shipping_address | null | null |
배송지 상세 (OrderAddressResource — 주문자/수령인/국내·해외 주소) |
| billing_address | null | null |
청구지 상세 (OrderAddressResource, 미분리 시 null) |
| payment | null | null |
대표 결제 정보 (OrderPaymentResource — 결제수단·결제상태·금액) |
| payments | array | [] |
결제 이력 목록 (OrderPaymentResource 배열 — 다회 결제/부분결제 포함) |
| shippings | array | [] |
배송 이력 목록 (OrderShippingResource 배열 — 배송유형·택배사·송장번호) |
| cancels | array | [] |
취소 이력 목록 (OrderCancelResource 배열 — 취소 사유·상세·취소일시, 최근순) |
| promotions_applied_snapshot | null | null |
적용된 프로모션 스냅샷 (재계산용) |
| shipping_policy_applied_snapshot | object | {"items": [], "address": {}} |
적용된 배송정책 스냅샷 (재계산용). items 는 옵션별 적용 정책 목록(각 항목: product_option_id, policy), address 는 주문 시점 배송지 메타(country_code, zipcode). 항목이 없어도 items 는 빈 배열이다 |
| admin_memo | null | null |
관리자 메모 (내부 관리용) |
| customer_memo | null | null |
고객 메모 (주문 시 고객이 남긴 메모) |
| created_at | string | 2026-07-08T01:44:49+00:00 |
생성 일시 |
| updated_at | string | 2026-07-08T01:44:49+00:00 |
최종 수정 일시 |
| is_owner | boolean | true |
현재 인증 사용자가 이 리소스의 소유자인지 여부 (BaseApiResource 표준 메타) |
| abilities | object | {"can_read":true,"can_update":true,"can_cancel":true} |
현재 사용자가 이 리소스에 수행 가능한 작업 불리언 맵 (can_update, can_delete 등 — 권한 맵 기반) |
응답 예시
에러 응답
| 상태코드 | 의미 | 발생 조건 |
|---|---|---|
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
설명 주문번호(orderNumber)로 주문 상세를 조회하는 회원/비회원 공용 엔드포인트입니다. optional.sanctum으로 로그인 여부에 따라 분기하는데, 로그인 상태면 본인 회원 주문만 OrderResource로 반환하고 아니면 404(마이페이지 주문 목록으로 안내), 비로그인이면 X-Guest-Order-Token으로 비회원 주문을 매칭해 GuestOrderResource로 반환하고 실패 시 404(비회원 조회 폼으로 안내)합니다. 회원이 비회원 토큰을 들고 와도 회원 분기가 우선하며, 실패 사유는 모두 동일한 404로 처리해 정보 노출을 차단합니다. 결제 완료 후 주문번호 기반 주문 완료/상세 페이지에서 사용합니다.