이슈 본연: API 레퍼런스의 미채움 마커 5종(실측 제외/TODO/필드 없음/대표 에러 없음)
1,194건을 코드에서 읽어 전수 채우고(0건), api:docgen 재생성이 사람이 채운 내용을
손실·열화시키던 멱등성 결함 4종(CRLF, 표 파이프 이스케이프, 에러 서술 보존, 중복
라우트명 키)을 근본 수정. --check 를 실측 제외와 드리프트가 구분되도록 재정의.
ParameterDescriber/ResourceFieldDescriber 에 leaf 폴백·SEO 스코프·공통 사전 확장.
파생 결함(문서 실측 중 발견): ResponseHelper 기본 메시지 키 6종이 존재하지 않는
messages.* 를 가리켜 응답 message 가 번역문 대신 키 문자열로 노출되던 문제를 common.*
으로 정정하고, 코어 7 + gdpr/marketing/pay_kginicis/verification/ecommerce 확장의
호출부와 누락 lang 키(게시판 10키 + 이커머스 category_images 4키 포함)를 ko/en/ja
전수 정정. 중복 그룹 키 2건은 기존 키로 호출부 통합.
보안: GET /api/identity/challenges/{id} 는 권한 가드 없는 공개 폴링 엔드포인트인데
Service::getStatus 가 attempts/max_attempts 를 응답에 담아 남은 시도 횟수를 추론할 수
있었다. 두 필드를 제거하고, 챌린지 화면(admin_basic/basic)의 서버 attempts 참조를
제거(남은 횟수 UI 는 query fallback + verify 실패 시 로컬 증가로 유지).
부수 정리(변경셋에 들어온 board 컨트롤러의 audit 사전 결함): FormRequest 4개 신설로
base Request 주입 제거, CommentController 의 Board 직접 호출을 BoardService 위임으로
전환, PHPDoc @return 보강. board 스위트에서 발견한 stale test 3건(seed SSoT 불일치,
admin 계정 user 역할 누락)도 같은 세션에서 정정.
버전 정렬(공개 release 기준): 코어 7.0.3→7.0.4, sirsoft-board 1.0.1→1.0.2,
verification_kginicis 1.0.0→1.0.1, admin_basic 1.0.1→1.0.4.
592 lines
26 KiB
Markdown
592 lines
26 KiB
Markdown
# Coupons API 레퍼런스
|
||
|
||
> **소유**: module `sirsoft-ecommerce` · **생성**: `php artisan api:docgen` (실측 기반). @generated 블록은 재생성 시 갱신되며, 사람이 작성한 설명은 보존됩니다.
|
||
|
||
---
|
||
|
||
## TL;DR (5초 요약)
|
||
|
||
```text
|
||
1. 이 문서는 실제 API 호출로 실측한 Coupons 엔드포인트 레퍼런스입니다
|
||
2. 각 엔드포인트: 메서드/URI/권한 + 요청 파라미터 표 + 요청 예시(curl) + 실측 응답 필드 표 + 응답 예시(envelope)
|
||
3. 응답 필드의 예시값·응답 예시 JSON 은 실제 호출 응답에서 관측된 값입니다
|
||
4. 갱신: 코드 변경 후 php artisan api:docgen 재실행
|
||
5. 설명(TODO) 칸은 사람이 채웁니다
|
||
```
|
||
|
||
---
|
||
|
||
|
||
### GET /api/modules/sirsoft-ecommerce/user/coupons
|
||
<!-- @generated:start:api.modules.sirsoft-ecommerce.user.coupons.index -->
|
||
- **라우트명**: `api.modules.sirsoft-ecommerce.user.coupons.index`
|
||
- **컨트롤러**: `Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@index`
|
||
- **인증/권한**: `auth:sanctum`
|
||
|
||
**요청 파라미터**
|
||
|
||
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| status | query | string | 아니오 | `available`, `used`, `expired` | 상태 필터 (해당 상태의 항목만 조회) |
|
||
| per_page | query | integer | 아니오 | min 1, max 50 | 페이지당 항목 수 |
|
||
|
||
> 이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (`sirsoft-ecommerce.coupon.user_list_validation_rules`).
|
||
|
||
**요청 예시**
|
||
|
||
```http
|
||
GET /api/modules/sirsoft-ecommerce/user/coupons?status=available&per_page=1 HTTP/1.1
|
||
Host: api.example.com
|
||
Accept: application/json
|
||
Authorization: Bearer {YOUR_TOKEN}
|
||
```
|
||
|
||
**응답 필드** (`data` 내부)
|
||
|
||
_단건 응답: `data` 객체의 필드._
|
||
|
||
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|
||
| --- | --- | --- | --- |
|
||
| coupons | object | `{"data":[{"id":2512,"coupon_id":107,"user_id":"a26219fc-9…` | 회원이 발급받은 쿠폰(발급 내역) 페이지네이션 객체 (`data[]` 발급 건 + `pagination` — CouponIssueCollection 직렬화, 쿠폰 정의가 아닌 회원별 발급 건) |
|
||
|
||
**응답 예시**
|
||
|
||
```http
|
||
HTTP/1.1 200
|
||
```
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "쿠폰 목록을 조회했습니다.",
|
||
"data": {
|
||
"coupons": {
|
||
"data": [
|
||
{
|
||
"id": 2512,
|
||
"coupon_id": 107,
|
||
"user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
|
||
"coupon_code": "DL-ORG8PPAH",
|
||
"status": "used",
|
||
"...": "(12개 키 생략, 총 17개)"
|
||
},
|
||
{
|
||
"id": 2513,
|
||
"coupon_id": 61,
|
||
"user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
|
||
"coupon_code": "DR-WC3RLEDB",
|
||
"status": "used",
|
||
"...": "(12개 키 생략, 총 17개)"
|
||
},
|
||
{
|
||
"id": 2514,
|
||
"coupon_id": 62,
|
||
"user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
|
||
"coupon_code": "DR-VHQFNYRR",
|
||
"status": "used",
|
||
"...": "(12개 키 생략, 총 17개)"
|
||
},
|
||
{
|
||
"id": 2515,
|
||
"coupon_id": 63,
|
||
"user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
|
||
"coupon_code": "DR-4QRXNXAI",
|
||
"status": "used",
|
||
"...": "(12개 키 생략, 총 17개)"
|
||
},
|
||
{
|
||
"id": 2516,
|
||
"coupon_id": 64,
|
||
"user_id": "a26219fc-94a0-4f63-9404-04c2a6ac99e4",
|
||
"coupon_code": "DR-IT4CCTSM",
|
||
"status": "used",
|
||
"...": "(12개 키 생략, 총 17개)"
|
||
},
|
||
"... (총 25건 중 5건 표시)"
|
||
],
|
||
"pagination": {
|
||
"current_page": 1,
|
||
"last_page": 2,
|
||
"per_page": 25,
|
||
"total": 41,
|
||
"from": 1,
|
||
"...": "(2개 키 생략, 총 7개)"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**에러 응답**
|
||
|
||
| 상태코드 | 의미 | 발생 조건 |
|
||
| --- | --- | --- |
|
||
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
|
||
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (`error.errors` 에 필드별 메시지) |
|
||
|
||
<!-- @generated:end -->
|
||
|
||
**설명** 로그인한 회원이 마이페이지 쿠폰함에서 자신이 발급받은 쿠폰(발급 내역)을 페이지네이션으로 조회합니다. `auth:sanctum` 인증이 필요하며, `status` 필터(available·used·expired)로 사용 가능/사용 완료/만료 쿠폰을 구분합니다. `UserCouponService::getUserCoupons()`가 조회하고 `CouponIssueCollection`으로 직렬화되므로, 여기의 항목은 쿠폰 정의(마스터)가 아니라 회원별 발급 건입니다.
|
||
|
||
|
||
### GET /api/modules/sirsoft-ecommerce/user/coupons/available
|
||
<!-- @generated:start:api.modules.sirsoft-ecommerce.user.coupons.available -->
|
||
- **라우트명**: `api.modules.sirsoft-ecommerce.user.coupons.available`
|
||
- **컨트롤러**: `Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@available`
|
||
- **인증/권한**: `auth:sanctum`
|
||
|
||
**요청 파라미터**
|
||
|
||
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| product_ids | query | array | 아니오 | — | product 식별자 배열 |
|
||
|
||
> 이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (`sirsoft-ecommerce.coupon.user_available_validation_rules`).
|
||
|
||
**요청 예시**
|
||
|
||
```http
|
||
GET /api/modules/sirsoft-ecommerce/user/coupons/available?product_ids=%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` 객체의 필드._
|
||
|
||
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|
||
| --- | --- | --- | --- |
|
||
| coupons | array | `[{"id":2534,"coupon_id":85,"user_id":1209,"coupon_code":"…` | 현재 장바구니 상품에 적용 가능한 보유 쿠폰(발급 건) 배열 (상품/카테고리 범위·최소 주문금액·유효기간을 만족해 주문에 곧바로 선택 가능한 후보만) |
|
||
|
||
**응답 예시**
|
||
|
||
```http
|
||
HTTP/1.1 200
|
||
```
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "사용 가능한 쿠폰 목록을 조회했습니다.",
|
||
"data": {
|
||
"coupons": [
|
||
{
|
||
"id": 2534,
|
||
"coupon_id": 85,
|
||
"user_id": 1209,
|
||
"coupon_code": "DR-PDZ7HT4G",
|
||
"status": "available",
|
||
"...": "(8개 키 생략, 총 13개)"
|
||
},
|
||
{
|
||
"id": 2542,
|
||
"coupon_id": 94,
|
||
"user_id": 1209,
|
||
"coupon_code": "DR-ROQPOOED",
|
||
"status": "available",
|
||
"...": "(8개 키 생략, 총 13개)"
|
||
},
|
||
{
|
||
"id": 2552,
|
||
"coupon_id": 106,
|
||
"user_id": 1209,
|
||
"coupon_code": "DR-XBLQUABC",
|
||
"status": "available",
|
||
"...": "(8개 키 생략, 총 13개)"
|
||
},
|
||
{
|
||
"id": 2529,
|
||
"coupon_id": 79,
|
||
"user_id": 1209,
|
||
"coupon_code": "DR-90IO2SWI",
|
||
"status": "available",
|
||
"...": "(8개 키 생략, 총 13개)"
|
||
},
|
||
{
|
||
"id": 2532,
|
||
"coupon_id": 83,
|
||
"user_id": 1209,
|
||
"coupon_code": "DR-FEKYVAFT",
|
||
"status": "available",
|
||
"...": "(8개 키 생략, 총 13개)"
|
||
},
|
||
"... (총 27건 중 5건 표시)"
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
**에러 응답**
|
||
|
||
| 상태코드 | 의미 | 발생 조건 |
|
||
| --- | --- | --- |
|
||
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
|
||
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (`error.errors` 에 필드별 메시지) |
|
||
|
||
<!-- @generated:end -->
|
||
|
||
**설명** 체크아웃 화면에서 회원이 현재 장바구니 상품에 실제로 적용할 수 있는 보유 쿠폰만 추려서 반환합니다. `auth:sanctum` 인증이 필요하고 `product_ids` 로 대상 상품을 전달하면, `UserCouponService::getAvailableCoupons()`가 보유 쿠폰 중 상품/카테고리 적용 범위·최소 주문금액·유효기간 등을 만족하는 것만 필터링해 내려줍니다. 쿠폰함 목록(index)과 달리 주문에 곧바로 선택 가능한 후보만 반환하는 점이 다릅니다.
|
||
|
||
|
||
### GET /api/modules/sirsoft-ecommerce/user/coupons/downloadable
|
||
<!-- @generated:start:api.modules.sirsoft-ecommerce.user.coupons.downloadable -->
|
||
- **라우트명**: `api.modules.sirsoft-ecommerce.user.coupons.downloadable`
|
||
- **컨트롤러**: `Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@downloadable`
|
||
- **인증/권한**: `auth:sanctum`
|
||
|
||
**요청 파라미터**
|
||
|
||
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| per_page | query | integer | 아니오 | min 1, max 50 | 페이지당 항목 수 |
|
||
|
||
> 이 엔드포인트는 확장이 파라미터를 추가할 수 있습니다 (`sirsoft-ecommerce.coupon.user_downloadable_validation_rules`).
|
||
|
||
**요청 예시**
|
||
|
||
```http
|
||
GET /api/modules/sirsoft-ecommerce/user/coupons/downloadable?per_page=1 HTTP/1.1
|
||
Host: api.example.com
|
||
Accept: application/json
|
||
Authorization: Bearer {YOUR_TOKEN}
|
||
```
|
||
|
||
**응답 필드** (`data` 내부)
|
||
|
||
_목록 응답: `data.data[]` 배열 항목의 필드._
|
||
|
||
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|
||
| --- | --- | --- | --- |
|
||
| id | integer | `107` | 기본 키 (내부 식별자) |
|
||
| name | object | `{"ko":"카테고리 배송비 3,000원 할인","en":"Category Shipping 3,000 …` | 대상의 이름/명칭 (다국어 필드는 로케일별 값 객체) |
|
||
| description | object | `{"ko":"특정 카테고리 배송비 할인","en":"Shipping discount on categor…` | 설명 (다국어 필드는 로케일별 값 객체) |
|
||
| target_type | string | `shipping_fee` | 할인 적용 대상 (product_amount=상품금액, order_amount=주문금액, shipping_fee=배송비) |
|
||
| discount_type | string | `fixed` | 혜택 유형 (fixed=정액 할인, rate=정률(%) 할인) |
|
||
| discount_value | string | `3000.00` | 혜택값 (정액이면 할인 금액, 정률이면 할인율 %) |
|
||
| discount_max_amount | string | `3000.00` | 정률 할인 시 최대 할인 금액 상한 (없으면 null) |
|
||
| min_order_amount | string | `20000.00` | 쿠폰 적용 최소 주문금액 (미만 주문에는 사용 불가) |
|
||
| issue_method | string | `download` | 발급 방법 (direct=직접발급, download=다운로드, auto=자동발급) |
|
||
| issue_condition | string | `manual` | 발급 조건 (manual=수동, signup=회원가입, first_purchase=첫구매, birthday=생일) |
|
||
| issue_status | string | `issuing` | 발급 상태 (issuing=발급중, stopped=발급중단) |
|
||
| total_quantity | integer | `300` | 총 발급 수량 상한 (null=무제한) |
|
||
| issued_count | integer | `1` | issued 개수 (집계) |
|
||
| per_user_limit | integer | `1` | 회원 1인당 발급 제한 수량 |
|
||
| valid_type | string | `period` | 유효기간 유형 (period=기간지정, days_from_issue=발급일로부터 N일) |
|
||
| valid_days | integer | `14` | 발급일로부터 유효한 일수 (valid_type=days_from_issue 인 경우) |
|
||
| valid_from | string | `2026-07-23T14:36:17.000000Z` | 유효기간 시작일 (쿠폰 사용 가능 시작 시각) |
|
||
| valid_to | string | `2026-09-21T14:36:17.000000Z` | 유효기간 종료일 (쿠폰 사용 가능 종료 시각) |
|
||
| issue_from | string | `2026-07-23T14:36:17.000000Z` | 발급기간 시작일 (다운로드 가능 시작 시각) |
|
||
| issue_to | string | `2026-08-29T14:36:17.000000Z` | 발급기간 종료일 (다운로드 가능 종료 시각) |
|
||
| is_combinable | boolean | `true` | combinable 여부 |
|
||
| target_scope | string | `categories` | 적용 범위 (all=전체 상품, products=특정 상품, categories=특정 카테고리) |
|
||
| created_by | null | `null` | 쿠폰 등록자(관리자) 식별자 (users 참조, 삭제 시 null) |
|
||
| created_at | string | `2026-07-30T14:36:17.000000Z` | 생성 일시 |
|
||
| updated_at | string | `2026-07-31T12:51:54.000000Z` | 최종 수정 일시 |
|
||
| deleted_at | null | `null` | 소프트 삭제 일시 (미삭제 시 null) |
|
||
| is_downloaded | boolean | `true` | downloaded 여부 |
|
||
| user_issued_count | integer | `1` | user issued 개수 (집계) |
|
||
| coupon_id | integer | `107` | coupon 식별자 (연관 리소스 참조) |
|
||
| localized_name | string | `카테고리 배송비 3,000원 할인` | `name` 의 현재 로케일 해석 값 (다국어 필드를 표시용 문자열로 해석) |
|
||
| target_type_short_label | string | `배송비` | `target_type_short` 값의 사람이 읽는 라벨 (현지화/Enum 파생) |
|
||
| valid_period_formatted | string | `2026-07-23 ~ 2026-09-21` | `valid_period` 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
|
||
| min_order_amount_formatted | string | `¥20,000` | `min_order_amount` 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
|
||
| remaining_quantity | integer | `299` | 잔여 발급 가능 수량 (total_quantity − issued_count, 무제한이면 null) |
|
||
| benefit_formatted | string | `¥3,000 할인` | `benefit` 값의 표시용 포맷 문자열 (통화/용량/일시 등 로케일·단위 포맷) |
|
||
| included_products | array | `[]` | 적용 대상 포함 상품 목록 (target_scope=products 시 이 상품에만 적용) |
|
||
| excluded_products | array | `[]` | 적용 제외 상품 목록 (해당 상품은 쿠폰 적용에서 제외) |
|
||
| included_categories | array | `[{"id":32,"name":{"ko":"바지","en":"Pants"},"description":{…` | 적용 대상 포함 카테고리 목록 (target_scope=categories 시 이 카테고리에만 적용) |
|
||
| excluded_categories | array | `[]` | 적용 제외 카테고리 목록 (해당 카테고리는 쿠폰 적용에서 제외) |
|
||
|
||
**응답 예시**
|
||
|
||
```http
|
||
HTTP/1.1 200
|
||
```
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "다운로드 가능한 쿠폰 목록을 불러왔습니다.",
|
||
"data": {
|
||
"current_page": 1,
|
||
"data": [
|
||
{
|
||
"id": 107,
|
||
"name": {
|
||
"ko": "카테고리 배송비 3,000원 할인",
|
||
"en": "Category Shipping 3,000 KRW Off"
|
||
},
|
||
"description": {
|
||
"ko": "특정 카테고리 배송비 할인",
|
||
"en": "Shipping discount on categories"
|
||
},
|
||
"target_type": "shipping_fee",
|
||
"discount_type": "fixed",
|
||
"discount_value": "3000.00",
|
||
"discount_max_amount": null,
|
||
"min_order_amount": "20000.00",
|
||
"issue_method": "download",
|
||
"issue_condition": "manual",
|
||
"issue_status": "issuing",
|
||
"total_quantity": 300,
|
||
"issued_count": 1,
|
||
"per_user_limit": 1,
|
||
"valid_type": "period",
|
||
"valid_days": null,
|
||
"valid_from": "2026-07-23T14:36:17.000000Z",
|
||
"valid_to": "2026-09-21T14:36:17.000000Z",
|
||
"issue_from": "2026-07-23T14:36:17.000000Z",
|
||
"issue_to": "2026-08-29T14:36:17.000000Z",
|
||
"is_combinable": true,
|
||
"target_scope": "categories",
|
||
"created_by": null,
|
||
"created_at": "2026-07-30T14:36:17.000000Z",
|
||
"updated_at": "2026-07-31T12:51:54.000000Z",
|
||
"deleted_at": null,
|
||
"is_downloaded": true,
|
||
"user_issued_count": 1,
|
||
"coupon_id": 107,
|
||
"localized_name": "카테고리 배송비 3,000원 할인",
|
||
"target_type_short_label": "배송비",
|
||
"valid_period_formatted": "2026-07-23 ~ 2026-09-21",
|
||
"min_order_amount_formatted": "¥20,000",
|
||
"remaining_quantity": 299,
|
||
"benefit_formatted": "¥3,000 할인",
|
||
"included_products": [],
|
||
"excluded_products": [],
|
||
"included_categories": [
|
||
{
|
||
"id": 32,
|
||
"name": {
|
||
"ko": "바지",
|
||
"en": "Pants"
|
||
},
|
||
"description": {
|
||
"ko": "다양한 스타일의 바지",
|
||
"en": "Various styles of pants"
|
||
},
|
||
"parent_id": 30,
|
||
"path": "29/30/32",
|
||
"depth": 2,
|
||
"sort_order": 1,
|
||
"is_active": true,
|
||
"slug": "men-pants",
|
||
"meta_title": null,
|
||
"meta_description": null,
|
||
"created_at": "2026-07-30T14:35:47.000000Z",
|
||
"updated_at": "2026-07-30T14:35:47.000000Z",
|
||
"pivot": {
|
||
"coupon_id": 107,
|
||
"category_id": 32
|
||
}
|
||
},
|
||
{
|
||
"id": 42,
|
||
"name": {
|
||
"ko": "노트북",
|
||
"en": "Laptops"
|
||
},
|
||
"description": {
|
||
"ko": "노트북 컴퓨터",
|
||
"en": "Laptop computers"
|
||
},
|
||
"parent_id": 38,
|
||
"path": "38/42",
|
||
"depth": 1,
|
||
"sort_order": 1,
|
||
"is_active": true,
|
||
"slug": "laptops",
|
||
"meta_title": null,
|
||
"meta_description": null,
|
||
"created_at": "2026-07-30T14:35:47.000000Z",
|
||
"updated_at": "2026-07-30T14:35:47.000000Z",
|
||
"pivot": {
|
||
"coupon_id": 107,
|
||
"category_id": 42
|
||
}
|
||
}
|
||
],
|
||
"excluded_categories": []
|
||
},
|
||
{
|
||
"id": 103,
|
||
"name": {
|
||
"ko": "배송비 50% 할인",
|
||
"en": "Shipping 50% Off"
|
||
},
|
||
"description": {
|
||
"ko": "배송비 반값 할인",
|
||
"en": "50% off shipping fee"
|
||
},
|
||
"target_type": "shipping_fee",
|
||
"discount_type": "rate",
|
||
"discount_value": "50.00",
|
||
"discount_max_amount": "3000.00",
|
||
"min_order_amount": "20000.00",
|
||
"issue_method": "download",
|
||
"issue_condition": "manual",
|
||
"issue_status": "issuing",
|
||
"total_quantity": 1000,
|
||
"issued_count": 62,
|
||
"per_user_limit": 1,
|
||
"valid_type": "days_from_issue",
|
||
"valid_days": 14,
|
||
"valid_from": null,
|
||
"valid_to": null,
|
||
"issue_from": "2026-07-25T14:36:17.000000Z",
|
||
"issue_to": "2026-09-28T14:36:17.000000Z",
|
||
"is_combinable": true,
|
||
"target_scope": "all",
|
||
"created_by": null,
|
||
"created_at": "2026-07-30T14:36:17.000000Z",
|
||
"updated_at": "2026-07-31T12:52:41.000000Z",
|
||
"deleted_at": null,
|
||
"is_downloaded": true,
|
||
"user_issued_count": 1,
|
||
"coupon_id": 103,
|
||
"localized_name": "배송비 50% 할인",
|
||
"target_type_short_label": "배송비",
|
||
"valid_period_formatted": "발급일로부터 14일",
|
||
"min_order_amount_formatted": "¥20,000",
|
||
"remaining_quantity": 938,
|
||
"benefit_formatted": "50.00% 할인 (최대 ¥3,000)",
|
||
"included_products": [],
|
||
"excluded_products": [],
|
||
"included_categories": [],
|
||
"excluded_categories": []
|
||
},
|
||
"... (총 11건 중 2건 표시)"
|
||
],
|
||
"first_page_url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
|
||
"from": 1,
|
||
"last_page": 1,
|
||
"last_page_url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
|
||
"links": [
|
||
{
|
||
"url": null,
|
||
"label": "pagination.previous",
|
||
"page": null,
|
||
"active": false
|
||
},
|
||
{
|
||
"url": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable?page=1",
|
||
"label": "1",
|
||
"page": 1,
|
||
"active": true
|
||
},
|
||
{
|
||
"url": null,
|
||
"label": "pagination.next",
|
||
"page": null,
|
||
"active": false
|
||
}
|
||
],
|
||
"next_page_url": null,
|
||
"path": "https://api.example.com/api/modules/sirsoft-ecommerce/user/coupons/downloadable",
|
||
"per_page": 25,
|
||
"prev_page_url": null,
|
||
"to": 11,
|
||
"total": 11
|
||
}
|
||
}
|
||
```
|
||
|
||
**에러 응답**
|
||
|
||
| 상태코드 | 의미 | 발생 조건 |
|
||
| --- | --- | --- |
|
||
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
|
||
| 422 | Unprocessable Entity | 요청 파라미터가 검증 규칙을 위반한 경우 (`error.errors` 에 필드별 메시지) |
|
||
|
||
<!-- @generated:end -->
|
||
|
||
**설명** 로그인한 회원이 지금 다운로드해 발급받을 수 있는 쿠폰(다운로드형) 목록을 페이지네이션으로 조회합니다. `auth:sanctum` 인증이 필요하며, `UserCouponService::getDownloadableCoupons()`가 발급기간·수량·회원당 한도를 만족하는 다운로드형 쿠폰을 반환하고 각 항목에 `is_downloaded`·`user_issued_count`로 이미 받았는지 여부를 표시합니다. 여기 항목은 아직 발급 전이므로 쿠폰 정의(마스터) 기준이며, 실제 발급은 download 엔드포인트로 수행합니다.
|
||
|
||
|
||
### POST /api/modules/sirsoft-ecommerce/user/coupons/{couponId}/download
|
||
<!-- @generated:start:api.modules.sirsoft-ecommerce.user.coupons.download -->
|
||
- **라우트명**: `api.modules.sirsoft-ecommerce.user.coupons.download`
|
||
- **컨트롤러**: `Modules\Sirsoft\Ecommerce\Http\Controllers\User\UserCouponController@download`
|
||
- **인증/권한**: `auth:sanctum`
|
||
|
||
**요청 파라미터**
|
||
|
||
| 이름 | 위치 | 타입 | 필수 | 허용값 | 용도 |
|
||
| --- | --- | --- | --- | --- | --- |
|
||
| couponId | path | string | 예 | — | 대상 coupon의 식별자 |
|
||
| coupon_id | body | integer | 예 | — | coupon 식별자 |
|
||
|
||
**요청 예시**
|
||
|
||
```http
|
||
POST /api/modules/sirsoft-ecommerce/user/coupons/{couponId}/download HTTP/1.1
|
||
Host: api.example.com
|
||
Accept: application/json
|
||
Authorization: Bearer {YOUR_TOKEN}
|
||
Content-Type: application/json
|
||
|
||
{
|
||
"coupon_id": 1
|
||
}
|
||
```
|
||
|
||
**응답 필드** (`data` 내부)
|
||
|
||
_단건 응답: `data` 객체의 필드 (생성된 쿠폰 발급 내역 `CouponIssue` 모델 직렬화 — 전용 Resource 를 거치지 않고 모델의 컬럼/캐스트가 그대로 노출됩니다)._
|
||
|
||
| 필드 | 타입 | 실측 예시값 | 용도/설명 |
|
||
| --- | --- | --- | --- |
|
||
| id | integer | `8611` | 발급 내역 ID (기본 키) |
|
||
| coupon_id | integer | `157` | 발급된 쿠폰 정의(마스터)의 식별자 |
|
||
| user_id | integer | `1` | 발급받은 회원 식별자 |
|
||
| coupon_code | string | `DL-8QK2ZX4M` | 발급 시 생성된 쿠폰 코드 (다운로드 발급은 `DL-` + 8자리 랜덤 대문자) |
|
||
| status | string | `available` | 발급 건 상태 (available=사용가능, used=사용완료, expired=만료, cancelled=취소) |
|
||
| issued_at | string | `2026-07-14T02:24:18.000000Z` | 발급일시 (발급 처리 시각) |
|
||
| expired_at | string \| null | `2026-08-07T02:24:18.000000Z` | 만료일시 (valid_type=period 이면 쿠폰의 `valid_to`, days_from_issue 이면 발급일 + `valid_days`, 둘 다 아니면 null) |
|
||
| used_at | null | `null` | 사용일시 (발급 직후에는 항상 null) |
|
||
| order_id | null | `null` | 사용된 주문 식별자 (발급 직후에는 항상 null) |
|
||
| discount_amount | string \| null | `null` | 실제 적용된 할인 금액 (사용 전에는 null, decimal(15,2)) |
|
||
| created_at | string | `2026-07-14T02:24:18.000000Z` | 생성 일시 |
|
||
| updated_at | string | `2026-07-14T02:24:18.000000Z` | 최종 수정 일시 |
|
||
|
||
**응답 예시**
|
||
|
||
```http
|
||
HTTP/1.1 201
|
||
```
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"message": "쿠폰이 다운로드되었습니다.",
|
||
"data": {
|
||
"coupon_id": 157,
|
||
"user_id": 1,
|
||
"coupon_code": "DL-8QK2ZX4M",
|
||
"status": "available",
|
||
"issued_at": "2026-07-14T02:24:18.000000Z",
|
||
"expired_at": "2026-08-07T02:24:18.000000Z",
|
||
"updated_at": "2026-07-14T02:24:18.000000Z",
|
||
"created_at": "2026-07-14T02:24:18.000000Z",
|
||
"id": 8611
|
||
}
|
||
}
|
||
```
|
||
|
||
**에러 응답**
|
||
|
||
| 상태코드 | 의미 | 발생 조건 |
|
||
| --- | --- | --- |
|
||
| 400 | 쿠폰 다운로드 제한 횟수를 초과했습니다. | 회원 1인당 발급 제한(`per_user_limit`) 을 이미 채운 경우 |
|
||
| 401 | Unauthenticated | 유효한 Bearer 토큰이 없거나 만료된 경우 |
|
||
| 404 | Not Found | path 파라미터에 해당하는 리소스가 없는 경우 |
|
||
| 422 | Unprocessable Entity | `coupon_id` 가 정수가 아니거나 존재하지 않는 쿠폰인 경우 (`error.errors` 에 필드별 메시지) |
|
||
|
||
<!-- @generated:end -->
|
||
|
||
**설명** 로그인한 회원이 다운로드형 쿠폰 1건을 실제로 발급받습니다. `auth:sanctum` 인증이 필요하고 대상 쿠폰은 `couponId`(경로)로 지정하며, `UserCouponService::downloadCoupon()`이 발급기간·수량·회원당 한도·중복 발급 여부를 검증한 뒤 발급 내역을 생성해 201로 반환합니다. 한도 초과·발급기간 종료 등 발급 불가 사유는 서비스 예외의 메시지와 코드가 그대로 오류 응답에 전달됩니다.
|
||
|
||
|