import {z} from 'zod' export type GetApiApiV3ShoppingFepClaimsArgs = {type?: ('CANCEL' | 'EXCHANGE' | 'RETURN') | undefined, status?: ('REQUESTED' | 'REVOKED_REQUEST') | undefined, fromRequestDate?: string | undefined, toRequestDate?: string | undefined, fromRequestRevokedDate?: string | undefined, toRequestRevokedDate?: string | undefined, orderIds?: Array | undefined, nextToken?: string | undefined, size?: number | undefined, partnerName?: string | undefined}; export type GetApiApiV3ShoppingFepClaimsOptions = {baseUrl?: string | undefined, fetch?: typeof fetch | undefined}; export const getClaimFepResponseOrder = z.object({id: z.number().int(), orderProductId: z.number().int(), ordererName: z.string(), ordererPhoneNumber: z.string(), receiverName: z.string(), receiverPhoneNumber: z.string(), deliveryCompany: z.enum(["CJ대한통운", "우체국택배", "한덱스", "합동택배", "한의사랑택배", "굿투럭", "우리택배", "홈픽택배", "용마로지스", "컬리넥스트마일", "큐런택배", "지니고", "한샘서비스원", "LG전자", "썬더히어로", "핑퐁", "GTS로지스", "UFO로지스", "에이치케이홀딩스", "더바오", "탱고앤고", "ARGO", "한진택배", "로젠택배", "대신택배", "CU편의점택배", "천일택배", "애니트랙", "우리한방택배", "IK물류", "원더스퀵", "풀앳홈", "두발히어로", "오늘의픽업", "NDEXKOREA", "부릉", "팀프레시", "발렉스", "로지스팟", "딜리래빗", "HTNS", "라스트마일", "투데이", "자이언트", "롯데택배", "일양로지스", "경동택배", "GS25편의점택배", "건영택배", "SLX택배", "농협택배", "성훈물류", "로지스밸리택배", "삼성전자물류", "위니아딤채", "큐익스프레스", "로지스밸리", "도도플렉스", "1004홈", "롯데칠성", "엔티엘피스", "홈픽", "지오피", "케이제이티", "오늘회러쉬", "현대글로비스", "위니온로지스", "딜리박스", "이스트라", "hy", "CR로지텍", "나은물류", "지케이글로벌", "유피로지스(제주)", "반얀로지스틱스", "삼다수 가정배송", "프리즘코리아", "올인닷컴", "물류대장(택배)", "풀무원샘물", "SLO", "바로스", "레터스", "벤더피아", "세븐일레븐(착한택배)", "물류대장(설치)", "BoxN", "리터니즈", "직접전달"]).optional(), shippingTrackingNumber: z.string().optional(), address: z.string(), price: z.number().int(), createdDt: z.string()}); export const getClaimFepResponseProduct = z.object({id: z.number().int(), name: z.string(), optionName: z.string(), quantity: z.number().int()}); export const getClaimFepResponse = z.object({id: z.number().int(), requestedDt: z.string().optional(), type: z.enum(["CANCEL", "EXCHANGE", "RETURN"]), status: z.enum(["REQUESTED", "REVOKED_REQUEST", "REJECTED_REQUEST", "COLLECTING", "COLLECTED", "REJECTED", "DELIVERING", "COMPLETED", "CANCELLED_ORDER"]), requestReason: z.string(), requestDetailReason: z.string().optional(), requestImages: z.array(z.string()), requestDeliveryPenaltyCharger: z.enum(["USER", "MERCHANT"]), refundOneWayDeliveryFee: z.number().int(), roundTripDeliveryFee: z.number().int(), returnAddress: z.string().optional(), order: getClaimFepResponseOrder, product: getClaimFepResponseProduct, claimDeliveryPaymentAmount: z.number().int().optional()}); export const getClaimListFepResponse = z.object({items: z.array(getClaimFepResponse), nextToken: z.string(), hasNext: z.boolean()}); export const getApiApiV3ShoppingFepClaimsResponse = z.object({resultType: z.enum(["SUCCESS", "FAIL"]).optional(), error: z.object({errorCode: z.enum(["INVALID_REQUEST", "REQUEST_FAILED", "UNKNOWN", "COMMON_ERROR"]).optional(), reason: z.string().optional()}).optional(), success: getClaimListFepResponse.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * 클레임(취소, 반품, 교환) 목록 조회 * * GET /api/v3/shopping-fep/claims */ export const getApiApiV3ShoppingFepClaims = async (args: GetApiApiV3ShoppingFepClaimsArgs, options?: GetApiApiV3ShoppingFepClaimsOptions) => { const {baseUrl = "https://oauth2.cert.toss.im", fetch: fetchFn = fetch} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.type != null) query.append("type", String(args.type)) if (args.status != null) query.append("status", String(args.status)) if (args.fromRequestDate != null) query.append("fromRequestDate", String(args.fromRequestDate)) if (args.toRequestDate != null) query.append("toRequestDate", String(args.toRequestDate)) if (args.fromRequestRevokedDate != null) query.append("fromRequestRevokedDate", String(args.fromRequestRevokedDate)) if (args.toRequestRevokedDate != null) query.append("toRequestRevokedDate", String(args.toRequestRevokedDate)) for (const item of args.orderIds ?? []) query.append("orderIds", String(item)) if (args.nextToken != null) query.append("nextToken", String(args.nextToken)) if (args.size != null) query.append("size", String(args.size)) if (args.partnerName != null) query.append("partnerName", String(args.partnerName)) const url = `${baseUrl.replace(/\/+$/, '')}/api/v3/shopping-fep/claims${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getApiApiV3ShoppingFepClaimsResponse, await res.json()) };