diff --git a/docs/emart24-app-scraping-replay-guide.md b/docs/emart24-app-scraping-replay-guide.md index 81aaeb54..9b47b9ca 100644 --- a/docs/emart24-app-scraping-replay-guide.md +++ b/docs/emart24-app-scraping-replay-guide.md @@ -13,7 +13,7 @@ - 상품 검색: `POST /stock/stock/search` - 상품별 재고 조회 준비: `POST /api/stock/v1/search/keyword` - 상품 기본 재고 메타: `GET /api/stock/v1/stock/goods/{pluCd}` -- 매장별 재고 수량: `GET /api/stock/v2/stock-search/store` +- 매장별 재고 수량: `GET /api/stock/v3/stock-search/store` - 매장 상세: `GET /api/stock/stock/store/{bizNo}` 베이스 URL: @@ -80,7 +80,7 @@ curl -sS 'https://everse.emart24.co.kr/api/stock/v1/stock/goods/8800244010504' \ ### D. 매장별 재고 수량 조회 ```bash -curl -sS 'https://everse.emart24.co.kr/api/stock/v2/stock-search/store?searchPluCode=8800244010504&bizNoArr=28339%2C05015%2C23233%2C29512%2C24437%2C29109%2C26137%2C29796%2C30200%2C28057%2C27928%2C29570%2C30162%2C28187%2C22579%2C00367%2C28967%2C00737' \ +curl -sS 'https://everse.emart24.co.kr/api/stock/v3/stock-search/store?searchPluCode=8800244010504&bizNoArr=28339%2C05015%2C23233%2C29512%2C24437%2C29109%2C26137%2C29796%2C30200%2C28057%2C27928%2C29570%2C30162%2C28187%2C22579%2C00367%2C28967%2C00737' \ -H 'x-requested-with: XMLHttpRequest' \ | jq '{ goods: .storeGoodsInfo | {pluCd,goodsNm,viewPrice}, @@ -133,7 +133,7 @@ jq -r 'select(.request.path|test("^/api/stock|^/stock/stock/search")) | [.reques - `emart24_check_inventory` - 소스: - - `GET /api/stock/v2/stock-search/store` (매장별 수량) + - `GET /api/stock/v3/stock-search/store` (매장별 수량) - `GET /api/stock/stock/store/{bizNo}` (매장 상세) - 조합 키: `BIZNO`(매장), `PLU_CD`(상품) @@ -150,3 +150,11 @@ jq -r 'select(.request.path|test("^/api/stock|^/stock/stock/search")) | [.reques 3. DNS/네트워크 실패 - 실행 환경 네트워크 정책(샌드박스/사내망) 확인 + +## 8. 2026-10-15 공식 공개 재고 계약 확인 + +공식 [재고확인 페이지](https://everse.emart24.co.kr/stock/stock/search)의 inline `fn_getStoreListForGoods`는 현재 `GET /api/stock/v3/stock-search/store`를 호출한다. 파라미터는 `searchPluCode`와 `bizNoArr`이며 HTTP 메서드·호스트·파라미터 이름은 기존과 같다. 연결된 [stockUtil.js](https://everse.emart24.co.kr/assets/js/stock/stockUtil.js)는 `storeGoodsQty` 배열의 `BIZNO`와 `BIZQTY`를 처리한다. 이 문서의 재고 조회 예제도 v3로 갱신했다. + +확인 당일 v3 원본 1건에서 HTTP 200, `storeGoodsInfo` 객체와 `storeGoodsQty` 배열을 확인했고 기존 엄격한 응답 스키마를 통과했다. 요청한 상품 코드·매장 코드가 일치하는 행의 숫자 수량 0도 확인했다. 이는 해당 조회의 실제 응답이며 전체 매장이나 상품이 품절이라는 뜻은 아니다. + +앞선 v2 조회는 HTTP 200이어도 `storeGoodsInfo`·`storeGoodsQty`·`storeInfo`가 문자열이고 내부 JSON은 숫자여서 정상 재고 객체·배열이 아니었다. 이 응답은 재고 미확인이며 빈 배열이나 0으로 바꾸면 안 된다. v3 전환은 공통 경로 상수만 변경하며 인증 헤더·파라미터·응답 스키마·실패 처리·캐시 정책은 유지한다. 접근 제한이나 알 수 없는 수량은 계속 명시적인 실패 또는 미확인으로 처리한다. diff --git a/src/services/emart24/api.ts b/src/services/emart24/api.ts index a72d57dd..1f854fbb 100644 --- a/src/services/emart24/api.ts +++ b/src/services/emart24/api.ts @@ -7,6 +7,6 @@ export const EMART24_API = { EVERSE_BASE_URL: 'https://everse.emart24.co.kr', STORE_PATH: '/api1/store', PRODUCT_SEARCH_PATH: '/stock/stock/search', - STOCK_SEARCH_STORE_PATH: '/api/stock/v2/stock-search/store', + STOCK_SEARCH_STORE_PATH: '/api/stock/v3/stock-search/store', STORE_DETAIL_PATH_PREFIX: '/api/stock/stock/store/', } as const; diff --git a/tests/relay/emart24.test.ts b/tests/relay/emart24.test.ts index 83a7ff22..0a4b2681 100644 --- a/tests/relay/emart24.test.ts +++ b/tests/relay/emart24.test.ts @@ -66,9 +66,9 @@ describe('이마트24 고정 HTTP 중계', () => { { searchPluCode: '8801115139836', bizNoArr: '00940' }, { storeGoodsInfo: { pluCd: '8801115139836' }, - storeGoodsQty: [{ BIZNO: '00940', BIZQTY: '0' }], + storeGoodsQty: [{ BIZNO: '00940', BIZQTY: 0 }], }, - 'https://everse.emart24.co.kr/api/stock/v2/stock-search/store', + 'https://everse.emart24.co.kr/api/stock/v3/stock-search/store', ], [ 'emart24-store-detail', @@ -85,6 +85,7 @@ describe('이마트24 고정 HTTP 중계', () => { const [url, init] = fetcher.mock.calls[0] as unknown as [URL, RequestInit]; expect(url.href.split('?')[0]).toBe(path); expect(init.method).toBe('GET'); + if (operation === 'emart24-stock') expect(Object.fromEntries(url.searchParams)).toEqual(body); expect(init.body).toBeUndefined(); }); it('임의 URL·경로·필드와 인증 없는 호출은 원본을 호출하지 않는다', async () => { diff --git a/tests/services/emart24/client.test.ts b/tests/services/emart24/client.test.ts index 21780c49..4bdd5f8f 100644 --- a/tests/services/emart24/client.test.ts +++ b/tests/services/emart24/client.test.ts @@ -289,6 +289,16 @@ describe('searchEmart24StockByStores', () => { expect(result.storeGoodsQty).toHaveLength(1); expect(result.storeGoodsQty?.[0].BIZNO).toBe('28339'); + const [input, init] = mockFetch.mock.calls[0] as [string, RequestInit]; + const endpoint = new URL(input); + expect(endpoint.origin).toBe('https://everse.emart24.co.kr'); + expect(endpoint.pathname).toBe('/api/stock/v3/stock-search/store'); + expect(Object.fromEntries(endpoint.searchParams)).toEqual({ + searchPluCode: '8800244010504', + bizNoArr: '28339', + }); + expect(init.method).toBe('GET'); + expect(init.body).toBeUndefined(); }); });