@sayren/store-sdk 0.7.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +185 -42
- package/dist/index.mjs +412 -239
- package/package.json +1 -1
- package/src/client.ts +69 -2
- package/src/schemas/common.ts +3 -0
- package/src/schemas/order.ts +10 -0
- package/src/schemas/payment.ts +84 -32
- package/src/schemas/product.ts +63 -8
- package/src/schemas/store.ts +27 -0
- package/src/schemas/upload.ts +86 -0
package/dist/index.mjs
CHANGED
|
@@ -693,6 +693,7 @@ const changeTypeSchema = z.enum([
|
|
|
693
693
|
"CLAIM.CANCEL_REQUESTED",
|
|
694
694
|
"CLAIM.RETURN_REQUESTED",
|
|
695
695
|
"CLAIM.EXCHANGE_REQUESTED",
|
|
696
|
+
"CLAIM.COMPLETED",
|
|
696
697
|
"ORDER.ADDRESS_CHANGE_REQUESTED"
|
|
697
698
|
]);
|
|
698
699
|
//#endregion
|
|
@@ -1182,205 +1183,6 @@ const reviewReportResultSchema = z.object({
|
|
|
1182
1183
|
status: z.literal("PENDING_REVIEW")
|
|
1183
1184
|
});
|
|
1184
1185
|
//#endregion
|
|
1185
|
-
//#region src/schemas/order.ts
|
|
1186
|
-
const orderSummarySchema = z.object({
|
|
1187
|
-
orderId: z.string(),
|
|
1188
|
-
ordererName: z.string(),
|
|
1189
|
-
itemCount: z.number().int(),
|
|
1190
|
-
totalAmount: z.number().int(),
|
|
1191
|
-
representativeStatus: orderItemStatusSchema,
|
|
1192
|
-
orderedAt: z.string(),
|
|
1193
|
-
testPayment: z.boolean().describe("테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요")
|
|
1194
|
-
});
|
|
1195
|
-
const shippingAddressSchema = z.object({
|
|
1196
|
-
receiverName: z.string(),
|
|
1197
|
-
phone: z.string(),
|
|
1198
|
-
zipCode: z.string(),
|
|
1199
|
-
address1: z.string(),
|
|
1200
|
-
address2: z.string().nullish(),
|
|
1201
|
-
deliveryMemo: z.string().nullish(),
|
|
1202
|
-
entranceCode: z.string().nullish()
|
|
1203
|
-
});
|
|
1204
|
-
const orderItemSchema = z.object({
|
|
1205
|
-
orderItemId: z.string(),
|
|
1206
|
-
orderId: z.string(),
|
|
1207
|
-
status: orderItemStatusSchema,
|
|
1208
|
-
claimStatus: z.enum([
|
|
1209
|
-
"CANCEL_REQUESTED",
|
|
1210
|
-
"RETURN_REQUESTED",
|
|
1211
|
-
"EXCHANGE_REQUESTED"
|
|
1212
|
-
]).nullable(),
|
|
1213
|
-
productId: z.string(),
|
|
1214
|
-
productName: z.string(),
|
|
1215
|
-
optionId: z.string().nullable(),
|
|
1216
|
-
optionName: z.string().nullable(),
|
|
1217
|
-
sellerCode: z.string().nullable(),
|
|
1218
|
-
quantity: z.number().int(),
|
|
1219
|
-
unitPrice: z.number().int(),
|
|
1220
|
-
discountAmount: z.number().int(),
|
|
1221
|
-
totalPrice: z.number().int(),
|
|
1222
|
-
hold: z.object({
|
|
1223
|
-
reason: z.string(),
|
|
1224
|
-
expectedDispatchDate: z.string()
|
|
1225
|
-
}).nullable(),
|
|
1226
|
-
autoDecisionDate: z.string().nullable(),
|
|
1227
|
-
sellerMemo: z.string().nullable(),
|
|
1228
|
-
orderedAt: z.string(),
|
|
1229
|
-
lastChangedAt: z.string(),
|
|
1230
|
-
lastChangedType: changeTypeSchema,
|
|
1231
|
-
testPayment: z.boolean().describe("소속 주문이 테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요")
|
|
1232
|
-
});
|
|
1233
|
-
const orderSchema = z.object({
|
|
1234
|
-
orderId: z.string(),
|
|
1235
|
-
orderedAt: z.string(),
|
|
1236
|
-
orderer: z.object({
|
|
1237
|
-
name: z.string(),
|
|
1238
|
-
phone: z.string(),
|
|
1239
|
-
email: z.email().optional()
|
|
1240
|
-
}),
|
|
1241
|
-
shippingAddress: shippingAddressSchema,
|
|
1242
|
-
payment: z.object({
|
|
1243
|
-
method: z.enum([
|
|
1244
|
-
"CARD",
|
|
1245
|
-
"BANK_TRANSFER",
|
|
1246
|
-
"VIRTUAL_ACCOUNT",
|
|
1247
|
-
"MOBILE",
|
|
1248
|
-
"POINT",
|
|
1249
|
-
"MIXED"
|
|
1250
|
-
]).describe("method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다"),
|
|
1251
|
-
approvedMethod: z.string().nullable().optional().default(null).describe("실제 결제수단. method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다. 현재 값은 `pgPaymentMethodSchema`(`PgPaymentMethod`: CARD·BANK_TRANSFER·VIRTUAL_ACCOUNT·MOBILE·EASY_PAY)이고 매출 리포트·스토어프론트·환불 원장과 같은 값이다. 값이 추가될 수 있어 문자열로 받는다. PG가 알려 주지 않았으면 요청 수단, 시도 기록이 없는 오래된 주문은 null. 서버는 항상 싣는다"),
|
|
1252
|
-
productAmount: z.number().int(),
|
|
1253
|
-
deliveryFee: z.number().int(),
|
|
1254
|
-
discountAmount: z.number().int(),
|
|
1255
|
-
totalAmount: z.number().int(),
|
|
1256
|
-
paidAt: z.string().nullable()
|
|
1257
|
-
}),
|
|
1258
|
-
testPayment: z.boolean().describe("테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요"),
|
|
1259
|
-
items: z.array(orderItemSchema)
|
|
1260
|
-
});
|
|
1261
|
-
/** 주문 목록 응답 — `GET /v1/orders` */
|
|
1262
|
-
const orderSummaryPageSchema = pageSchema(orderSummarySchema);
|
|
1263
|
-
/** 주문상품 변경 목록 응답 — `GET /v1/order-items` */
|
|
1264
|
-
const orderItemPageSchema = pageSchema(orderItemSchema);
|
|
1265
|
-
const testPaymentQuery = z.enum(["true", "false"]).optional().describe("테스트 결제(샌드박스 결제) 필터. `true`면 테스트 결제만, `false`면 실결제만, 생략하면 전부예요");
|
|
1266
|
-
const pageQuery = { page: z.string().optional().describe("페이지 번호 (1부터, 기본 1)") };
|
|
1267
|
-
/**
|
|
1268
|
-
* `GET /v1/orders` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열). 검증 규칙은 서버가 적용한다:
|
|
1269
|
-
* `orderedFrom` 누락 400 `MISSING_PARAMETER`, 날짜 형식 오류 400 `INVALID_PARAMETER`, 31일 초과 400 `RANGE_TOO_WIDE`,
|
|
1270
|
-
* `testPayment`가 `true`·`false`가 아니면 400 `INVALID_PARAMETER`
|
|
1271
|
-
*/
|
|
1272
|
-
const orderListQuerySchema = z.object({
|
|
1273
|
-
orderedFrom: z.string().describe("조회 시작 시각 (ISO 8601 날짜 또는 일시, 포함). 필수"),
|
|
1274
|
-
orderedTo: z.string().optional().describe("조회 끝 시각 (ISO 8601, 포함). 생략하면 orderedFrom부터 31일. 기간은 최대 31일"),
|
|
1275
|
-
status: orderItemStatusSchema.optional().describe("주문상품 상태 필터 — 이 상태의 주문상품이 하나라도 있는 주문"),
|
|
1276
|
-
keyword: z.string().optional().describe("주문번호(일치)·주문자명·수령인명(포함) 검색"),
|
|
1277
|
-
testPayment: testPaymentQuery,
|
|
1278
|
-
...pageQuery,
|
|
1279
|
-
size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)")
|
|
1280
|
-
});
|
|
1281
|
-
/**
|
|
1282
|
-
* `GET /v1/order-items` 쿼리 — OpenAPI 문서용 형태. `lastChangedFrom` 누락 400 `MISSING_PARAMETER`, 형식 오류 400
|
|
1283
|
-
* `INVALID_PARAMETER`, 24시간 초과 400 `RANGE_TOO_WIDE`, `testPayment` 값 오류 400 `INVALID_PARAMETER`
|
|
1284
|
-
*/
|
|
1285
|
-
const orderItemListQuerySchema = z.object({
|
|
1286
|
-
lastChangedFrom: z.string().describe("마지막 변경 시각 조회 시작 (ISO 8601, 포함). 필수"),
|
|
1287
|
-
lastChangedTo: z.string().optional().describe("마지막 변경 시각 조회 끝 (ISO 8601, 포함). 생략하면 시작부터 24시간. 기간은 최대 24시간"),
|
|
1288
|
-
lastChangedType: changeTypeSchema.optional().describe("마지막 변경 유형 필터"),
|
|
1289
|
-
testPayment: testPaymentQuery,
|
|
1290
|
-
...pageQuery,
|
|
1291
|
-
size: z.string().optional().describe("페이지 크기 (기본 100, 최대 300)")
|
|
1292
|
-
});
|
|
1293
|
-
const deliveryMethodSchema = z.enum([
|
|
1294
|
-
"COURIER",
|
|
1295
|
-
"DIRECT",
|
|
1296
|
-
"QUICK",
|
|
1297
|
-
"NOTHING"
|
|
1298
|
-
]);
|
|
1299
|
-
const dispatchRequestSchema = z.object({
|
|
1300
|
-
deliveryMethod: deliveryMethodSchema,
|
|
1301
|
-
carrierCode: z.string().optional(),
|
|
1302
|
-
trackingNumber: z.string().optional(),
|
|
1303
|
-
dispatchedAt: z.string().optional()
|
|
1304
|
-
}).refine((value) => value.deliveryMethod === "DIRECT" || value.deliveryMethod === "NOTHING" ? true : !!value.carrierCode && !!value.trackingNumber, { message: "COURIER/QUICK 발송은 carrierCode와 trackingNumber가 필수입니다" });
|
|
1305
|
-
const deliveryInfoSchema = z.object({
|
|
1306
|
-
orderItemId: z.string(),
|
|
1307
|
-
deliveryMethod: deliveryMethodSchema,
|
|
1308
|
-
carrierCode: z.string().nullable(),
|
|
1309
|
-
carrierName: z.string().nullable(),
|
|
1310
|
-
trackingNumber: z.string().nullable(),
|
|
1311
|
-
trackingUrl: z.url().nullable(),
|
|
1312
|
-
status: z.enum([
|
|
1313
|
-
"DISPATCHED",
|
|
1314
|
-
"DELIVERING",
|
|
1315
|
-
"DELIVERED"
|
|
1316
|
-
]),
|
|
1317
|
-
dispatchedAt: z.string(),
|
|
1318
|
-
deliveredAt: z.string().nullable()
|
|
1319
|
-
});
|
|
1320
|
-
/** `GET /v1/order-items/{orderItemId}/delivery` 응답 — 배송 정보 + 배송 추적 이벤트 */
|
|
1321
|
-
const deliveryStatusSchema = deliveryInfoSchema.extend({ trackingEvents: z.array(z.object({
|
|
1322
|
-
status: z.string(),
|
|
1323
|
-
location: z.string(),
|
|
1324
|
-
occurredAt: z.string()
|
|
1325
|
-
})).optional() });
|
|
1326
|
-
/** `PUT /v1/order-items/{orderItemId}/dispatch/tracking` 응답 — 바뀐 송장 */
|
|
1327
|
-
const trackingUpdateResultSchema = z.object({
|
|
1328
|
-
orderItemId: z.string(),
|
|
1329
|
-
carrierCode: z.string(),
|
|
1330
|
-
trackingNumber: z.string()
|
|
1331
|
-
});
|
|
1332
|
-
const carrierSchema = z.object({
|
|
1333
|
-
carrierCode: z.string(),
|
|
1334
|
-
name: z.string(),
|
|
1335
|
-
trackingUrlTemplate: z.string()
|
|
1336
|
-
});
|
|
1337
|
-
const holdOrderItemRequestSchema = z.object({
|
|
1338
|
-
reason: z.enum([
|
|
1339
|
-
"OUT_OF_STOCK",
|
|
1340
|
-
"CUSTOMER_REQUEST",
|
|
1341
|
-
"CUSTOMS",
|
|
1342
|
-
"ETC"
|
|
1343
|
-
]),
|
|
1344
|
-
detail: z.string().max(500).optional(),
|
|
1345
|
-
expectedDispatchDate: z.string()
|
|
1346
|
-
});
|
|
1347
|
-
const cancelBySellerRequestSchema = z.object({
|
|
1348
|
-
reason: z.enum([
|
|
1349
|
-
"OUT_OF_STOCK",
|
|
1350
|
-
"PRICE_ERROR",
|
|
1351
|
-
"DELIVERY_IMPOSSIBLE",
|
|
1352
|
-
"ETC"
|
|
1353
|
-
]),
|
|
1354
|
-
detail: z.string().max(500).optional()
|
|
1355
|
-
});
|
|
1356
|
-
/** `POST /v1/order-items/{orderItemId}/cancel` 응답 — 셀러 직권취소 환불 결과 */
|
|
1357
|
-
const cancelBySellerResultSchema = z.object({
|
|
1358
|
-
orderItemId: z.string(),
|
|
1359
|
-
refundAmount: z.number().int(),
|
|
1360
|
-
refundedAt: z.string()
|
|
1361
|
-
});
|
|
1362
|
-
/** `PUT /v1/order-items/{orderItemId}/memo` 응답 — 빈 문자열로 저장하면 메모가 지워져 `null`이다 */
|
|
1363
|
-
const orderItemMemoResultSchema = z.object({
|
|
1364
|
-
orderItemId: z.string(),
|
|
1365
|
-
sellerMemo: z.string().nullable()
|
|
1366
|
-
});
|
|
1367
|
-
/** `POST /v1/order-items/{orderItemId}/purchase-decision/request` 응답 */
|
|
1368
|
-
const purchaseDecisionRequestResultSchema = z.object({
|
|
1369
|
-
orderItemId: z.string(),
|
|
1370
|
-
requestedAt: z.string()
|
|
1371
|
-
});
|
|
1372
|
-
/** `POST /v1/order-items/{orderItemId}/purchase-decision/extend` 응답 — 연장은 최대 2회 */
|
|
1373
|
-
const purchaseDecisionExtendResultSchema = z.object({
|
|
1374
|
-
orderItemId: z.string(),
|
|
1375
|
-
autoDecisionDate: z.string(),
|
|
1376
|
-
extendCount: z.number().int().max(2)
|
|
1377
|
-
});
|
|
1378
|
-
/**
|
|
1379
|
-
* `GET /v1/orders/{orderId}/address-change-requests` 응답 — 배송지 변경 요청 플로우는 아직 제공하지 않아
|
|
1380
|
-
* 현재는 항상 빈 배열이다
|
|
1381
|
-
*/
|
|
1382
|
-
const addressChangeRequestListSchema = z.array(z.record(z.string(), z.unknown())).describe("배송지 변경 요청 목록 (현재 항상 빈 배열)");
|
|
1383
|
-
//#endregion
|
|
1384
1186
|
//#region src/schemas/payment.ts
|
|
1385
1187
|
/**
|
|
1386
1188
|
* 스토어 결제(PG) 설정과 매출 리포트 계약.
|
|
@@ -1397,13 +1199,22 @@ const pgPaymentMethodSchema = z.enum([
|
|
|
1397
1199
|
"MOBILE",
|
|
1398
1200
|
"EASY_PAY"
|
|
1399
1201
|
]).describe("결제수단 (스토어프론트 결제 요청의 `paymentMethod`와 같은 값)");
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
"
|
|
1406
|
-
|
|
1202
|
+
/**
|
|
1203
|
+
* 간편결제사 — 결제 옵션(스토어프론트 `paymentOptions`)과 PG 설정의 `easyPayProviders`에 쓴다.
|
|
1204
|
+
* `@sayren/storefront-sdk`의 `easyPayProviderSchema`와 같은 값이다(api 계약 테스트가 고정한다)
|
|
1205
|
+
*/
|
|
1206
|
+
const easyPayProviderSchema = z.enum([
|
|
1207
|
+
"NAVERPAY",
|
|
1208
|
+
"KAKAOPAY",
|
|
1209
|
+
"TOSSPAY",
|
|
1210
|
+
"PAYCO"
|
|
1211
|
+
]);
|
|
1212
|
+
/**
|
|
1213
|
+
* 응답에 실리는 간편결제사 — 서버가 간편결제사를 추가해도 파싱이 깨지지 않게 문자열로 받는다
|
|
1214
|
+
* (`pgProvider`·결제수단과 같은 방식). 요청(`easyPayProviders`)은 값을 골라 보내는 자리라 enum 그대로다.
|
|
1215
|
+
* 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 화면은 모르는 값을 원문 그대로 보여 준다.
|
|
1216
|
+
*/
|
|
1217
|
+
const easyPayProviderResponseSchema = z.string();
|
|
1407
1218
|
const pgEnvironmentSchema = z.enum(["TEST", "LIVE"]).describe("PG 결제 환경. `TEST`=PG 샌드박스(테스트 키, 실제로 돈이 오가지 않음), `LIVE`=실결제(운영 키)");
|
|
1408
1219
|
const pgVerificationResultSchema = z.enum(["SUCCESS", "FAILED"]).describe("연결 테스트 결과");
|
|
1409
1220
|
/** 비밀 값 입력 — 저장 후 다시 조회할 수 없다 */
|
|
@@ -1462,13 +1273,14 @@ const upsertPortOneProviderRequestSchema = z.object({
|
|
|
1462
1273
|
});
|
|
1463
1274
|
const updatePaymentProviderRequestSchema = z.object({
|
|
1464
1275
|
enabled: z.boolean().optional().describe("사용 여부. 켜려면 활성 환경(샌드박스면 TEST, 아니면 LIVE) 자격 증명이 모두 저장돼 있어야 한다(`PAYMENT_PROVIDER_INCOMPLETE`)"),
|
|
1465
|
-
sandboxMode: z.boolean().optional().describe("샌드박스 스위치. `true`면 새 결제에 TEST 세트를 쓴다(항상 허용). `false`(라이브 전환)는 라이브 개방 조건을 모두 충족해야 한다(`LIVE_GATE_NOT_MET`)")
|
|
1466
|
-
|
|
1276
|
+
sandboxMode: z.boolean().optional().describe("샌드박스 스위치. `true`면 새 결제에 TEST 세트를 쓴다(항상 허용). `false`(라이브 전환)는 라이브 개방 조건을 모두 충족해야 한다(`LIVE_GATE_NOT_MET`)"),
|
|
1277
|
+
easyPayProviders: z.array(easyPayProviderSchema).max(easyPayProviderSchema.options.length).optional().describe("이 PG로 받는 간편결제사 — 통째로 바꾼다. PG 계약(포트원은 채널)에 추가한 간편결제만 켠다. 켠 간편결제사마다 스토어프론트 결제 옵션이 하나씩 생긴다(포트원은 간편결제를 받는 채널이 있어야 한다)")
|
|
1278
|
+
}).refine((body) => body.enabled !== void 0 || body.sandboxMode !== void 0 || body.easyPayProviders !== void 0, { message: "enabled·sandboxMode·easyPayProviders 중 하나는 보내야 해요" });
|
|
1467
1279
|
const verifyPaymentProviderRequestSchema = z.object({ environment: pgEnvironmentSchema.optional().describe("연결 테스트할 자격 증명 세트. 생략하면 활성 환경(샌드박스면 TEST, 아니면 LIVE)") });
|
|
1468
1280
|
const updatePaymentSettingsRequestSchema = z.object({
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
});
|
|
1281
|
+
priority: z.array(pgProviderSchema).min(1).max(50).optional().describe("PG 우선순위(앞이 1순위) — 스토어프론트 결제 옵션 목록의 PG 순서다. 연결된 PG 수만큼 **모두 한 번씩** 나열한다(길이 상한 50은 안전장치다). 빠지거나 중복되거나 연결되지 않은 PG가 있으면 `INVALID_PRIORITY`"),
|
|
1282
|
+
checkoutOrigins: z.array(z.string().max(200)).max(20).optional().describe("결제 도메인 — 통째로 바꾼다. 결제를 마친 구매자가 돌아올 스토어프론트 origin(`https://shop.example.com`, https·경로 없음). 결제 시작의 `returnUrl`은 이 목록 안이어야 한다. 비어 있으면 실결제를 시작할 수 없다(테스트 결제는 localhost 허용). 같은 도메인을 PG 가맹 정보에도 등록한다. 형식이 틀리면 `INVALID_CHECKOUT_ORIGIN`")
|
|
1283
|
+
}).refine((body) => body.priority !== void 0 || body.checkoutOrigins !== void 0, { message: "priority 또는 checkoutOrigins 중 하나는 보내야 해요" });
|
|
1472
1284
|
const maskedSecretSchema = z.object({
|
|
1473
1285
|
field: z.string().describe("비밀 필드 이름 (`secretKey`·`apiSecret`·`webhookSecret`)"),
|
|
1474
1286
|
configured: z.boolean().describe("값이 저장돼 있는가"),
|
|
@@ -1529,6 +1341,7 @@ const paymentProviderSchema = z.object({
|
|
|
1529
1341
|
LIVE: paymentCredentialSetSchema.nullable()
|
|
1530
1342
|
}).describe("환경별 자격 증명 세트. 등록되지 않은 세트는 null"),
|
|
1531
1343
|
liveGate: liveGateSchema.describe("라이브 개방 조건. 조건을 모두 충족해야 샌드박스를 끌 수 있다"),
|
|
1344
|
+
easyPayProviders: z.array(easyPayProviderResponseSchema).describe("이 PG로 받는 간편결제사. 연결되지 않았으면 빈 목록. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
|
|
1532
1345
|
retiredCredentialCount: z.number().int().describe("보관된(가맹점 교체·연결 해제로 새 결제에 더 쓰이지 않는) 자격 증명 수. 그 가맹점으로 받은 결제의 환불·대사에 계속 쓰인다"),
|
|
1533
1346
|
routingExclusion: z.string().nullable().optional().default(null).describe("지금 새 결제의 후보가 아닌 사유. 후보면 null. 판정 원천은 서버 라우팅이다(콘솔이 다시 계산하지 않는다). 후보가 아닌 PG에는 항상 사유 코드를 붙인다(연결 안 된 PG 포함) — 모든 PG는 `candidates`에 있거나 이 값이 null이 아니다. 현재 값: `NOT_CONNECTED`(연결 안 됨) · `DISABLED`(사용 중지) · `CREDENTIAL_MISSING`(활성 환경 자격 증명 없음) · `SANDBOX_IN_LIVE_STORE`(다른 PG가 라이브라 이 샌드박스 PG는 실구매자 결제에 쓰지 않음) · `PLATFORM_BLOCKED`(플랫폼이 실결제를 막음) · `MODE_MISMATCH`(라이브를 연 서버 모드와 현재 모드가 다름). 값이 추가될 수 있어 문자열로 받는다 — 모르는 값은 후보 아님으로 다룬다. 서버는 항상 싣는다. 이 필드가 없는 이전 서버 응답은 기본값(null)으로 읽는다")
|
|
1534
1347
|
});
|
|
@@ -1545,8 +1358,7 @@ const PAYMENT_ROUTING_EXCLUSION_CODES = [
|
|
|
1545
1358
|
"MODE_MISMATCH"
|
|
1546
1359
|
];
|
|
1547
1360
|
const paymentSettingsSchema = z.object({
|
|
1548
|
-
|
|
1549
|
-
effectiveRoutingMode: effectivePaymentRoutingModeSchema,
|
|
1361
|
+
checkoutOrigins: z.array(z.string()).describe("결제 도메인 — 결제를 마친 구매자가 돌아올 스토어프론트 origin 목록"),
|
|
1550
1362
|
providers: z.array(paymentProviderSchema).describe("지원하는 모든 PG. 연결된 것은 우선순위순, 연결되지 않은 것은 뒤에 온다"),
|
|
1551
1363
|
environment: pgEnvironmentSchema.nullable().optional().default(null).describe("지금 결제를 시작하면 쓰는 결제 환경. 사용 가능한 PG 중 하나라도 라이브면 `LIVE`(샌드박스 PG는 제외), 아니면 `TEST`. 사용 가능한 PG가 없으면 null. 서버는 항상 싣는다. 이 필드가 없는 이전 서버 응답은 기본값(null)으로 읽는다"),
|
|
1552
1364
|
candidates: z.array(z.string()).optional().default(() => []).describe("지금 결제를 시작하면 쓰는 PG, 우선순위순(`tosspayments`·`portone`). 비어 있으면 구매자가 결제할 수 없다. 빠진 PG의 사유는 `providers[].routingExclusion` — 후보가 아닌 PG에는 항상 사유 코드를 붙인다. 서버는 항상 싣는다. 이 필드가 없는 이전 서버 응답은 기본값(빈 배열)으로 읽는다")
|
|
@@ -1623,6 +1435,7 @@ const paymentRecordSchema = z.object({
|
|
|
1623
1435
|
refundedAmount: z.number().int().describe("환불 완료 금액 합계. 실패한 환불은 빼고 센다"),
|
|
1624
1436
|
provider: pgProviderSchema.nullable().describe("승인한 PG. 승인 전에 끝났으면 마지막 시도의 PG"),
|
|
1625
1437
|
method: pgPaymentMethodSchema.nullable().describe("실제 결제수단. 모르면 요청 수단"),
|
|
1438
|
+
easyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("간편결제사. `method`가 `EASY_PAY`일 때만 값이 있고, PG가 알려 주지 않았으면 요청한 간편결제사다. 그 밖의 결제수단과 간편결제 이전 결제는 null. 서버는 항상 싣는다. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
|
|
1626
1439
|
environment: pgEnvironmentSchema.nullable().describe("결제 환경"),
|
|
1627
1440
|
testPayment: z.boolean().describe("샌드박스 결제인가"),
|
|
1628
1441
|
pgTransactionId: z.string().nullable().describe("PG 거래 id (토스 paymentKey, 포트원 txId)"),
|
|
@@ -1640,7 +1453,9 @@ const paymentAttemptRecordSchema = z.object({
|
|
|
1640
1453
|
provider: pgProviderSchema,
|
|
1641
1454
|
status: paymentAttemptStatusSchema,
|
|
1642
1455
|
method: pgPaymentMethodSchema.describe("주문서에서 고른 결제수단"),
|
|
1456
|
+
easyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("주문서에서 고른 간편결제사. 간편결제가 아니면 null. 서버는 항상 싣는다(값이 추가될 수 있어 문자열)"),
|
|
1643
1457
|
approvedMethod: pgPaymentMethodSchema.nullable().describe("PG가 보고한 실제 결제수단"),
|
|
1458
|
+
approvedEasyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("PG가 보고한 실제 간편결제사. 모르거나 간편결제가 아니면 null. 서버는 항상 싣는다(값이 추가될 수 있어 문자열)"),
|
|
1644
1459
|
amount: z.number().int(),
|
|
1645
1460
|
environment: pgEnvironmentSchema,
|
|
1646
1461
|
pgTransactionId: z.string().nullable(),
|
|
@@ -1678,6 +1493,292 @@ const paymentListQuerySchema = z.object({
|
|
|
1678
1493
|
size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)")
|
|
1679
1494
|
});
|
|
1680
1495
|
//#endregion
|
|
1496
|
+
//#region src/schemas/order.ts
|
|
1497
|
+
const orderSummarySchema = z.object({
|
|
1498
|
+
orderId: z.string(),
|
|
1499
|
+
ordererName: z.string(),
|
|
1500
|
+
itemCount: z.number().int(),
|
|
1501
|
+
totalAmount: z.number().int(),
|
|
1502
|
+
representativeStatus: orderItemStatusSchema,
|
|
1503
|
+
orderedAt: z.string(),
|
|
1504
|
+
testPayment: z.boolean().describe("테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요")
|
|
1505
|
+
});
|
|
1506
|
+
const shippingAddressSchema = z.object({
|
|
1507
|
+
receiverName: z.string(),
|
|
1508
|
+
phone: z.string(),
|
|
1509
|
+
zipCode: z.string(),
|
|
1510
|
+
address1: z.string(),
|
|
1511
|
+
address2: z.string().nullish(),
|
|
1512
|
+
deliveryMemo: z.string().nullish(),
|
|
1513
|
+
entranceCode: z.string().nullish()
|
|
1514
|
+
});
|
|
1515
|
+
const orderItemSchema = z.object({
|
|
1516
|
+
orderItemId: z.string(),
|
|
1517
|
+
orderId: z.string(),
|
|
1518
|
+
status: orderItemStatusSchema,
|
|
1519
|
+
claimStatus: z.enum([
|
|
1520
|
+
"CANCEL_REQUESTED",
|
|
1521
|
+
"RETURN_REQUESTED",
|
|
1522
|
+
"EXCHANGE_REQUESTED"
|
|
1523
|
+
]).nullable(),
|
|
1524
|
+
productId: z.string(),
|
|
1525
|
+
productName: z.string(),
|
|
1526
|
+
optionId: z.string().nullable(),
|
|
1527
|
+
optionName: z.string().nullable(),
|
|
1528
|
+
sellerCode: z.string().nullable(),
|
|
1529
|
+
quantity: z.number().int(),
|
|
1530
|
+
unitPrice: z.number().int(),
|
|
1531
|
+
discountAmount: z.number().int(),
|
|
1532
|
+
totalPrice: z.number().int(),
|
|
1533
|
+
hold: z.object({
|
|
1534
|
+
reason: z.string(),
|
|
1535
|
+
expectedDispatchDate: z.string()
|
|
1536
|
+
}).nullable(),
|
|
1537
|
+
autoDecisionDate: z.string().nullable(),
|
|
1538
|
+
sellerMemo: z.string().nullable(),
|
|
1539
|
+
orderedAt: z.string(),
|
|
1540
|
+
lastChangedAt: z.string(),
|
|
1541
|
+
lastChangedType: changeTypeSchema,
|
|
1542
|
+
testPayment: z.boolean().describe("소속 주문이 테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요")
|
|
1543
|
+
});
|
|
1544
|
+
const orderSchema = z.object({
|
|
1545
|
+
orderId: z.string(),
|
|
1546
|
+
orderedAt: z.string(),
|
|
1547
|
+
orderer: z.object({
|
|
1548
|
+
name: z.string(),
|
|
1549
|
+
phone: z.string(),
|
|
1550
|
+
email: z.email().optional()
|
|
1551
|
+
}),
|
|
1552
|
+
shippingAddress: shippingAddressSchema,
|
|
1553
|
+
payment: z.object({
|
|
1554
|
+
method: z.enum([
|
|
1555
|
+
"CARD",
|
|
1556
|
+
"BANK_TRANSFER",
|
|
1557
|
+
"VIRTUAL_ACCOUNT",
|
|
1558
|
+
"MOBILE",
|
|
1559
|
+
"POINT",
|
|
1560
|
+
"MIXED"
|
|
1561
|
+
]).describe("method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다"),
|
|
1562
|
+
approvedMethod: z.string().nullable().optional().default(null).describe("실제 결제수단. method는 호환용이며 간편결제를 CARD로 표시한다. 실제 수단은 approvedMethod를 본다. 현재 값은 `pgPaymentMethodSchema`(`PgPaymentMethod`: CARD·BANK_TRANSFER·VIRTUAL_ACCOUNT·MOBILE·EASY_PAY)이고 매출 리포트·스토어프론트·환불 원장과 같은 값이다. 값이 추가될 수 있어 문자열로 받는다. PG가 알려 주지 않았으면 요청 수단, 시도 기록이 없는 오래된 주문은 null. 서버는 항상 싣는다"),
|
|
1563
|
+
easyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("승인된 간편결제사. `approvedMethod`가 `EASY_PAY`일 때만 값이 있고, PG가 알려 주지 않았으면 요청한 간편결제사다. 그 밖의 결제수단과 간편결제 이전 주문은 null. 서버는 항상 싣는다. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
|
|
1564
|
+
productAmount: z.number().int(),
|
|
1565
|
+
deliveryFee: z.number().int(),
|
|
1566
|
+
discountAmount: z.number().int(),
|
|
1567
|
+
totalAmount: z.number().int(),
|
|
1568
|
+
paidAt: z.string().nullable()
|
|
1569
|
+
}),
|
|
1570
|
+
testPayment: z.boolean().describe("테스트 결제(샌드박스 결제) 주문인가. true면 실제로 돈이 오가지 않았어요. 상품을 발송하지 않도록 주의하세요"),
|
|
1571
|
+
items: z.array(orderItemSchema)
|
|
1572
|
+
});
|
|
1573
|
+
/** 주문 목록 응답 — `GET /v1/orders` */
|
|
1574
|
+
const orderSummaryPageSchema = pageSchema(orderSummarySchema);
|
|
1575
|
+
/** 주문상품 변경 목록 응답 — `GET /v1/order-items` */
|
|
1576
|
+
const orderItemPageSchema = pageSchema(orderItemSchema);
|
|
1577
|
+
const testPaymentQuery = z.enum(["true", "false"]).optional().describe("테스트 결제(샌드박스 결제) 필터. `true`면 테스트 결제만, `false`면 실결제만, 생략하면 전부예요");
|
|
1578
|
+
const pageQuery = { page: z.string().optional().describe("페이지 번호 (1부터, 기본 1)") };
|
|
1579
|
+
/**
|
|
1580
|
+
* `GET /v1/orders` 쿼리 — OpenAPI 문서용 형태(값은 쿼리 문자열). 검증 규칙은 서버가 적용한다:
|
|
1581
|
+
* `orderedFrom` 누락 400 `MISSING_PARAMETER`, 날짜 형식 오류 400 `INVALID_PARAMETER`, 31일 초과 400 `RANGE_TOO_WIDE`,
|
|
1582
|
+
* `testPayment`가 `true`·`false`가 아니면 400 `INVALID_PARAMETER`
|
|
1583
|
+
*/
|
|
1584
|
+
const orderListQuerySchema = z.object({
|
|
1585
|
+
orderedFrom: z.string().describe("조회 시작 시각 (ISO 8601 날짜 또는 일시, 포함). 필수"),
|
|
1586
|
+
orderedTo: z.string().optional().describe("조회 끝 시각 (ISO 8601, 포함). 생략하면 orderedFrom부터 31일. 기간은 최대 31일"),
|
|
1587
|
+
status: orderItemStatusSchema.optional().describe("주문상품 상태 필터 — 이 상태의 주문상품이 하나라도 있는 주문"),
|
|
1588
|
+
keyword: z.string().optional().describe("주문번호(일치)·주문자명·수령인명(포함) 검색"),
|
|
1589
|
+
testPayment: testPaymentQuery,
|
|
1590
|
+
...pageQuery,
|
|
1591
|
+
size: z.string().optional().describe("페이지 크기 (기본 20, 최대 100)")
|
|
1592
|
+
});
|
|
1593
|
+
/**
|
|
1594
|
+
* `GET /v1/order-items` 쿼리 — OpenAPI 문서용 형태. `lastChangedFrom` 누락 400 `MISSING_PARAMETER`, 형식 오류 400
|
|
1595
|
+
* `INVALID_PARAMETER`, 24시간 초과 400 `RANGE_TOO_WIDE`, `testPayment` 값 오류 400 `INVALID_PARAMETER`
|
|
1596
|
+
*/
|
|
1597
|
+
const orderItemListQuerySchema = z.object({
|
|
1598
|
+
lastChangedFrom: z.string().describe("마지막 변경 시각 조회 시작 (ISO 8601, 포함). 필수"),
|
|
1599
|
+
lastChangedTo: z.string().optional().describe("마지막 변경 시각 조회 끝 (ISO 8601, 포함). 생략하면 시작부터 24시간. 기간은 최대 24시간"),
|
|
1600
|
+
lastChangedType: changeTypeSchema.optional().describe("마지막 변경 유형 필터"),
|
|
1601
|
+
testPayment: testPaymentQuery,
|
|
1602
|
+
...pageQuery,
|
|
1603
|
+
size: z.string().optional().describe("페이지 크기 (기본 100, 최대 300)")
|
|
1604
|
+
});
|
|
1605
|
+
const deliveryMethodSchema = z.enum([
|
|
1606
|
+
"COURIER",
|
|
1607
|
+
"DIRECT",
|
|
1608
|
+
"QUICK",
|
|
1609
|
+
"NOTHING"
|
|
1610
|
+
]);
|
|
1611
|
+
const dispatchRequestSchema = z.object({
|
|
1612
|
+
deliveryMethod: deliveryMethodSchema,
|
|
1613
|
+
carrierCode: z.string().optional(),
|
|
1614
|
+
trackingNumber: z.string().optional(),
|
|
1615
|
+
dispatchedAt: z.string().optional()
|
|
1616
|
+
}).refine((value) => value.deliveryMethod === "DIRECT" || value.deliveryMethod === "NOTHING" ? true : !!value.carrierCode && !!value.trackingNumber, { message: "COURIER/QUICK 발송은 carrierCode와 trackingNumber가 필수입니다" });
|
|
1617
|
+
const deliveryInfoSchema = z.object({
|
|
1618
|
+
orderItemId: z.string(),
|
|
1619
|
+
deliveryMethod: deliveryMethodSchema,
|
|
1620
|
+
carrierCode: z.string().nullable(),
|
|
1621
|
+
carrierName: z.string().nullable(),
|
|
1622
|
+
trackingNumber: z.string().nullable(),
|
|
1623
|
+
trackingUrl: z.url().nullable(),
|
|
1624
|
+
status: z.enum([
|
|
1625
|
+
"DISPATCHED",
|
|
1626
|
+
"DELIVERING",
|
|
1627
|
+
"DELIVERED"
|
|
1628
|
+
]),
|
|
1629
|
+
dispatchedAt: z.string(),
|
|
1630
|
+
deliveredAt: z.string().nullable()
|
|
1631
|
+
});
|
|
1632
|
+
/** `GET /v1/order-items/{orderItemId}/delivery` 응답 — 배송 정보 + 배송 추적 이벤트 */
|
|
1633
|
+
const deliveryStatusSchema = deliveryInfoSchema.extend({ trackingEvents: z.array(z.object({
|
|
1634
|
+
status: z.string(),
|
|
1635
|
+
location: z.string(),
|
|
1636
|
+
occurredAt: z.string()
|
|
1637
|
+
})).optional() });
|
|
1638
|
+
/** `PUT /v1/order-items/{orderItemId}/dispatch/tracking` 응답 — 바뀐 송장 */
|
|
1639
|
+
const trackingUpdateResultSchema = z.object({
|
|
1640
|
+
orderItemId: z.string(),
|
|
1641
|
+
carrierCode: z.string(),
|
|
1642
|
+
trackingNumber: z.string()
|
|
1643
|
+
});
|
|
1644
|
+
const carrierSchema = z.object({
|
|
1645
|
+
carrierCode: z.string(),
|
|
1646
|
+
name: z.string(),
|
|
1647
|
+
trackingUrlTemplate: z.string()
|
|
1648
|
+
});
|
|
1649
|
+
const holdOrderItemRequestSchema = z.object({
|
|
1650
|
+
reason: z.enum([
|
|
1651
|
+
"OUT_OF_STOCK",
|
|
1652
|
+
"CUSTOMER_REQUEST",
|
|
1653
|
+
"CUSTOMS",
|
|
1654
|
+
"ETC"
|
|
1655
|
+
]),
|
|
1656
|
+
detail: z.string().max(500).optional(),
|
|
1657
|
+
expectedDispatchDate: z.string()
|
|
1658
|
+
});
|
|
1659
|
+
const cancelBySellerRequestSchema = z.object({
|
|
1660
|
+
reason: z.enum([
|
|
1661
|
+
"OUT_OF_STOCK",
|
|
1662
|
+
"PRICE_ERROR",
|
|
1663
|
+
"DELIVERY_IMPOSSIBLE",
|
|
1664
|
+
"ETC"
|
|
1665
|
+
]),
|
|
1666
|
+
detail: z.string().max(500).optional()
|
|
1667
|
+
});
|
|
1668
|
+
/** `POST /v1/order-items/{orderItemId}/cancel` 응답 — 셀러 직권취소 환불 결과 */
|
|
1669
|
+
const cancelBySellerResultSchema = z.object({
|
|
1670
|
+
orderItemId: z.string(),
|
|
1671
|
+
refundAmount: z.number().int(),
|
|
1672
|
+
refundedAt: z.string()
|
|
1673
|
+
});
|
|
1674
|
+
/** `PUT /v1/order-items/{orderItemId}/memo` 응답 — 빈 문자열로 저장하면 메모가 지워져 `null`이다 */
|
|
1675
|
+
const orderItemMemoResultSchema = z.object({
|
|
1676
|
+
orderItemId: z.string(),
|
|
1677
|
+
sellerMemo: z.string().nullable()
|
|
1678
|
+
});
|
|
1679
|
+
/** `POST /v1/order-items/{orderItemId}/purchase-decision/request` 응답 */
|
|
1680
|
+
const purchaseDecisionRequestResultSchema = z.object({
|
|
1681
|
+
orderItemId: z.string(),
|
|
1682
|
+
requestedAt: z.string()
|
|
1683
|
+
});
|
|
1684
|
+
/** `POST /v1/order-items/{orderItemId}/purchase-decision/extend` 응답 — 연장은 최대 2회 */
|
|
1685
|
+
const purchaseDecisionExtendResultSchema = z.object({
|
|
1686
|
+
orderItemId: z.string(),
|
|
1687
|
+
autoDecisionDate: z.string(),
|
|
1688
|
+
extendCount: z.number().int().max(2)
|
|
1689
|
+
});
|
|
1690
|
+
/**
|
|
1691
|
+
* `GET /v1/orders/{orderId}/address-change-requests` 응답 — 배송지 변경 요청 플로우는 아직 제공하지 않아
|
|
1692
|
+
* 현재는 항상 빈 배열이다
|
|
1693
|
+
*/
|
|
1694
|
+
const addressChangeRequestListSchema = z.array(z.record(z.string(), z.unknown())).describe("배송지 변경 요청 목록 (현재 항상 빈 배열)");
|
|
1695
|
+
//#endregion
|
|
1696
|
+
//#region src/schemas/upload.ts
|
|
1697
|
+
/**
|
|
1698
|
+
* 업로드 용도. 허용 확장자와 크기 상한이 용도별로 다르다.
|
|
1699
|
+
*
|
|
1700
|
+
* - `product-image`: 상품 목록·상세의 상품 이미지. 목록 썸네일로 쓰이므로 정지 이미지만 받는다.
|
|
1701
|
+
* - `description`: 상세설명 본문에 삽입하는 미디어. 동영상과 svg도 받는다.
|
|
1702
|
+
*/
|
|
1703
|
+
const uploadPurposeSchema = z.enum(["product-image", "description"]);
|
|
1704
|
+
const MB = 1048576;
|
|
1705
|
+
/**
|
|
1706
|
+
* 용도별 업로드 제한 — 서버(`POST /v1/uploads`)와 클라이언트가 공유하는 단일 원천이다.
|
|
1707
|
+
*
|
|
1708
|
+
* 크기는 **요청이 스스로 신고한 값**으로만 검사한다. 바이트는 api를 거치지 않고 CDN으로
|
|
1709
|
+
* 직접 PUT되므로 이 검사는 셀러가 올리기 전에 알게 하는 장치이고, 실제 상한은 CDN이 강제한다.
|
|
1710
|
+
*/
|
|
1711
|
+
const UPLOAD_PURPOSE_LIMITS = {
|
|
1712
|
+
"product-image": {
|
|
1713
|
+
extensions: [
|
|
1714
|
+
"jpg",
|
|
1715
|
+
"jpeg",
|
|
1716
|
+
"png",
|
|
1717
|
+
"webp",
|
|
1718
|
+
"avif",
|
|
1719
|
+
"gif"
|
|
1720
|
+
],
|
|
1721
|
+
maxBytes: 10 * MB
|
|
1722
|
+
},
|
|
1723
|
+
description: {
|
|
1724
|
+
extensions: [
|
|
1725
|
+
"jpg",
|
|
1726
|
+
"jpeg",
|
|
1727
|
+
"png",
|
|
1728
|
+
"gif",
|
|
1729
|
+
"webp",
|
|
1730
|
+
"avif",
|
|
1731
|
+
"svg",
|
|
1732
|
+
"mp4",
|
|
1733
|
+
"webm",
|
|
1734
|
+
"mov"
|
|
1735
|
+
],
|
|
1736
|
+
maxBytes: 50 * MB
|
|
1737
|
+
}
|
|
1738
|
+
};
|
|
1739
|
+
/** 파일명의 소문자 확장자. 확장자가 없으면 `""` */
|
|
1740
|
+
function uploadExtensionOf(filename) {
|
|
1741
|
+
const dot = filename.lastIndexOf(".");
|
|
1742
|
+
if (dot < 0 || dot === filename.length - 1) return "";
|
|
1743
|
+
return filename.slice(dot + 1).toLowerCase();
|
|
1744
|
+
}
|
|
1745
|
+
/**
|
|
1746
|
+
* 용도 제한 위반 여부. 통과하면 `null`.
|
|
1747
|
+
* 서버가 던지는 오류와 콘솔이 먼저 띄우는 안내가 갈리지 않도록 한 함수로 판정한다.
|
|
1748
|
+
*/
|
|
1749
|
+
function uploadRejection(purpose, filename, size) {
|
|
1750
|
+
const limit = UPLOAD_PURPOSE_LIMITS[purpose];
|
|
1751
|
+
if (!limit.extensions.includes(uploadExtensionOf(filename))) return {
|
|
1752
|
+
status: 400,
|
|
1753
|
+
code: "UNSUPPORTED_FILE_TYPE",
|
|
1754
|
+
message: `지원하지 않는 파일 형식입니다. ${limit.extensions.join(", ")}만 올릴 수 있습니다`
|
|
1755
|
+
};
|
|
1756
|
+
if (size !== void 0 && size > limit.maxBytes) return {
|
|
1757
|
+
status: 413,
|
|
1758
|
+
code: "FILE_TOO_LARGE",
|
|
1759
|
+
message: `파일이 너무 큽니다. ${Math.floor(limit.maxBytes / MB)}MB까지 올릴 수 있습니다`
|
|
1760
|
+
};
|
|
1761
|
+
return null;
|
|
1762
|
+
}
|
|
1763
|
+
/**
|
|
1764
|
+
* 미디어 업로드 자리 발급 — `POST /v1/uploads`.
|
|
1765
|
+
*
|
|
1766
|
+
* 파일 바이트는 api를 거치지 않는다. 응답의 `uploadUrl`로 클라이언트가 직접 PUT하고,
|
|
1767
|
+
* 끝나면 `url`이 공개 주소가 된다. 서버가 객체 키를 정하므로 요청은 파일명만 보낸다
|
|
1768
|
+
* (확장자만 쓰이고 이름 자체는 저장되지 않는다).
|
|
1769
|
+
*/
|
|
1770
|
+
const uploadRequestSchema = z.object({
|
|
1771
|
+
filename: z.string().min(1).max(255),
|
|
1772
|
+
purpose: uploadPurposeSchema.default("description").describe("업로드 용도. 허용 확장자와 크기 상한이 용도별로 다르다"),
|
|
1773
|
+
size: z.number().int().positive().optional().describe("파일 바이트 크기. 주면 용도별 상한을 발급 전에 검사한다")
|
|
1774
|
+
});
|
|
1775
|
+
const uploadTicketSchema = z.object({
|
|
1776
|
+
/** 업로드 완료 후 공개될 주소 */
|
|
1777
|
+
url: z.url(),
|
|
1778
|
+
/** 파일 바이트를 PUT할 presigned URL. 1시간 유효 */
|
|
1779
|
+
uploadUrl: z.url()
|
|
1780
|
+
});
|
|
1781
|
+
//#endregion
|
|
1681
1782
|
//#region src/schemas/product.ts
|
|
1682
1783
|
const productStatusSchema = z.enum([
|
|
1683
1784
|
"SALE",
|
|
@@ -1761,6 +1862,54 @@ const productSchema = productSummarySchema.extend({
|
|
|
1761
1862
|
returnAddressId: z.string().nullable().optional(),
|
|
1762
1863
|
createdAt: z.string().optional()
|
|
1763
1864
|
});
|
|
1865
|
+
/** 상품 하나에 등록할 수 있는 이미지 최대 장수 — 첫 장이 대표(썸네일)다 */
|
|
1866
|
+
const MAX_PRODUCT_IMAGES = 10;
|
|
1867
|
+
/**
|
|
1868
|
+
* 상품 이미지 주소의 와이어 형식 — URL이고 2048자 이하다.
|
|
1869
|
+
*
|
|
1870
|
+
* https·확장자 규칙은 여기서 강제하지 않고 `productImageRejection`이 판정한다. 서버가
|
|
1871
|
+
* **새로 추가된 주소에만** 그 규칙을 적용해야 하기 때문이다(규칙이 생기기 전에 저장된
|
|
1872
|
+
* 주소 하나로 상품 수정 전체가 막히면 셀러가 빠져나갈 길이 없다).
|
|
1873
|
+
*
|
|
1874
|
+
* 응답 스키마(`productSchema.images`)도 넓게 둔다. 과거에 저장된 주소를 파싱 오류로
|
|
1875
|
+
* 만들면 상품 조회 자체가 막힌다.
|
|
1876
|
+
*/
|
|
1877
|
+
const productImageUrlSchema = z.url().max(2048).describe("상품 이미지 주소. https만 허용하고, 확장자가 있으면 이미지 형식이어야 한다");
|
|
1878
|
+
/**
|
|
1879
|
+
* 상품에 **새로 붙이는** 이미지 주소의 규칙. 통과하면 `null`.
|
|
1880
|
+
*
|
|
1881
|
+
* - https만 받는다. http는 https 스토어프론트에서 혼합 콘텐츠로 차단되고 `data:`·`javascript:`는
|
|
1882
|
+
* 상세 화면에 박히는 주입 경로가 된다.
|
|
1883
|
+
* - 호스트는 제한하지 않는다 — 셀러가 이미 쓰는 이미지 호스트를 그대로 붙일 수 있어야 한다.
|
|
1884
|
+
* - 경로에 확장자가 있으면 상품 이미지 형식이어야 한다(svg·동영상 거부). **확장자가 없으면 통과시킨다**
|
|
1885
|
+
* — 외부 이미지 CDN은 확장자 없는 키를 쓰는 경우가 흔하고, 주소만으로는 실제 형식을 알 수 없다.
|
|
1886
|
+
*/
|
|
1887
|
+
function productImageRejection(url) {
|
|
1888
|
+
if (url.length > 2048) return {
|
|
1889
|
+
code: "INVALID_IMAGE_URL",
|
|
1890
|
+
message: "이미지 주소가 너무 깁니다"
|
|
1891
|
+
};
|
|
1892
|
+
let parsed;
|
|
1893
|
+
try {
|
|
1894
|
+
parsed = new URL(url);
|
|
1895
|
+
} catch {
|
|
1896
|
+
return {
|
|
1897
|
+
code: "INVALID_IMAGE_URL",
|
|
1898
|
+
message: "이미지 주소 형식이 아닙니다"
|
|
1899
|
+
};
|
|
1900
|
+
}
|
|
1901
|
+
if (parsed.protocol !== "https:") return {
|
|
1902
|
+
code: "INVALID_IMAGE_URL",
|
|
1903
|
+
message: "이미지 주소는 https로 시작해야 합니다"
|
|
1904
|
+
};
|
|
1905
|
+
const extension = uploadExtensionOf(parsed.pathname);
|
|
1906
|
+
const allowed = UPLOAD_PURPOSE_LIMITS["product-image"].extensions;
|
|
1907
|
+
if (extension && !allowed.includes(extension)) return {
|
|
1908
|
+
code: "UNSUPPORTED_FILE_TYPE",
|
|
1909
|
+
message: `상품 이미지는 ${allowed.join(", ")}만 쓸 수 있습니다`
|
|
1910
|
+
};
|
|
1911
|
+
return null;
|
|
1912
|
+
}
|
|
1764
1913
|
/** 옵션 축(그룹) 최대 개수 — 스키마 상한의 단일 원천 */
|
|
1765
1914
|
const MAX_OPTION_GROUPS = 3;
|
|
1766
1915
|
/** 축 하나가 가질 수 있는 값의 최대 개수 */
|
|
@@ -1842,7 +1991,7 @@ const productCreateRequestSchema = z.object({
|
|
|
1842
1991
|
* 표시는 `description`(HTML)이 맡는다 — 소비자는 이 필드를 몰라도 된다.
|
|
1843
1992
|
*/
|
|
1844
1993
|
descriptionJson: z.string().nullable().optional(),
|
|
1845
|
-
images: z.array(
|
|
1994
|
+
images: z.array(productImageUrlSchema).min(1).max(10).optional().describe("상품 이미지 주소 목록. 첫 장이 대표 이미지(썸네일)다"),
|
|
1846
1995
|
attributes: z.array(z.object({
|
|
1847
1996
|
attributeId: z.string(),
|
|
1848
1997
|
value: z.string()
|
|
@@ -1877,12 +2026,6 @@ const productListQuerySchema = z.object({
|
|
|
1877
2026
|
sort: productSortSchema.optional().describe("정렬 (기본 createdAt.desc)"),
|
|
1878
2027
|
...pageQueryShape()
|
|
1879
2028
|
});
|
|
1880
|
-
/** `POST /v1/product-images` 응답 — 업로드된 이미지의 CDN 주소 */
|
|
1881
|
-
const productImageUploadResultSchema = z.object({ images: z.array(z.object({
|
|
1882
|
-
url: z.url(),
|
|
1883
|
-
width: z.number().int(),
|
|
1884
|
-
height: z.number().int()
|
|
1885
|
-
})) });
|
|
1886
2029
|
const discountSchema = z.object({
|
|
1887
2030
|
productId: z.string(),
|
|
1888
2031
|
discountType: z.enum(["RATE", "AMOUNT"]),
|
|
@@ -1971,6 +2114,10 @@ function isWebOrigin(value) {
|
|
|
1971
2114
|
const analyticsOriginSchema = z.string().trim().max(255).refine(isWebOrigin, "https://shop.example.com 형식(경로 없이)으로 입력해 주세요").describe("스토어프론트 오리진. 예: `https://shop.example.com`");
|
|
1972
2115
|
/** 허용 오리진 상한 */
|
|
1973
2116
|
const MAX_ANALYTICS_ALLOWED_ORIGINS = 20;
|
|
2117
|
+
/** 자동 배송완료·자동 구매확정 대기일 상한 */
|
|
2118
|
+
const MAX_AUTO_TRANSITION_DAYS = 30;
|
|
2119
|
+
const autoDeliverDaysDescription = "발송 후 자동 배송완료까지의 일수(0~30, 기본 7). 발송(`DISPATCHED`)·배송중(`DELIVERING`) 주문상품을 이 기간이 지나면 배송완료(`DELIVERED`)로 바꾼다. `0`이면 자동 배송완료를 하지 않는다";
|
|
2120
|
+
const autoConfirmDaysDescription = "배송완료 후 자동 구매확정까지의 일수(0~30, 기본 7). 배송완료 시점에 구매확정 예정일(`autoDecisionDate`)을 이 값으로 잡고, 그 날짜가 지나면 구매확정(`PURCHASE_DECIDED`)으로 바꾼다. 진행 중인 클레임이 있으면 건너뛴다. `0`이면 자동 구매확정을 하지 않는다";
|
|
1974
2121
|
/** `PATCH /v1/store` 본문 — 바꿀 필드만 보낸다 */
|
|
1975
2122
|
const updateStoreRequestSchema = z.object({
|
|
1976
2123
|
name: z.string().min(2).max(50).optional(),
|
|
@@ -1979,7 +2126,9 @@ const updateStoreRequestSchema = z.object({
|
|
|
1979
2126
|
businessHours: z.string().max(100).optional(),
|
|
1980
2127
|
analyticsAllowedOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("@deprecated `storefrontOrigins`를 쓴다(같은 목록). 방문 분석 수집을 받을 스토어프론트 오리진(최대 20개). 비우면 모든 오리진에서 받는다. 넣으면 목록에 없는 오리진의 수집 요청은 403 `ORIGIN_NOT_ALLOWED`이고, 페이지 URL이 목록 밖인 이벤트는 버린다"),
|
|
1981
2128
|
storefrontOrigins: z.array(analyticsOriginSchema).max(20).optional().describe("스토어프론트 도메인(최대 20개) — 소셜 로그인 뒤 돌아갈 주소와 방문 분석 수집을 함께 제한한다. `analyticsAllowedOrigins`와 같은 목록이다(둘 다 주면 이 값이 이긴다)"),
|
|
1982
|
-
guestCheckoutEnabled: z.boolean().optional().describe("비회원 주문 허용. false(회원만)면 로그인하지 않은 구매자의 주문서 생성·결제 요청이 403 `GUEST_CHECKOUT_DISABLED`다. 장바구니 담기와 이미 받은 비회원 주문의 조회·취소는 막지 않는다")
|
|
2129
|
+
guestCheckoutEnabled: z.boolean().optional().describe("비회원 주문 허용. false(회원만)면 로그인하지 않은 구매자의 주문서 생성·결제 요청이 403 `GUEST_CHECKOUT_DISABLED`다. 장바구니 담기와 이미 받은 비회원 주문의 조회·취소는 막지 않는다"),
|
|
2130
|
+
autoDeliverDays: z.number().int().min(0).max(30).optional().describe(autoDeliverDaysDescription),
|
|
2131
|
+
autoConfirmDays: z.number().int().min(0).max(30).optional().describe(autoConfirmDaysDescription)
|
|
1983
2132
|
}).refine((value) => Object.values(value).some((v) => v !== void 0), { message: "최소 1개 필드가 필요합니다" });
|
|
1984
2133
|
const storeSchema = z.object({
|
|
1985
2134
|
storeId: z.string(),
|
|
@@ -1997,6 +2146,8 @@ const storeSchema = z.object({
|
|
|
1997
2146
|
analyticsAllowedOrigins: z.array(z.string()).describe("방문 분석 수집을 받는 스토어프론트 오리진. 비어 있으면 모든 오리진에서 받는다"),
|
|
1998
2147
|
storefrontOrigins: z.array(z.string()).describe("스토어프론트 도메인 — 소셜 로그인 리디렉트와 방문 분석 수집이 함께 쓴다(`analyticsAllowedOrigins`와 같은 값)"),
|
|
1999
2148
|
guestCheckoutEnabled: z.boolean().describe("비회원 주문 허용. false면 회원만 주문할 수 있다"),
|
|
2149
|
+
autoDeliverDays: z.number().int().describe(autoDeliverDaysDescription),
|
|
2150
|
+
autoConfirmDays: z.number().int().describe(autoConfirmDaysDescription),
|
|
2000
2151
|
memberCount: z.number().int(),
|
|
2001
2152
|
createdAt: z.string()
|
|
2002
2153
|
});
|
|
@@ -2054,22 +2205,6 @@ const sellerAddressRequestSchema = z.object({
|
|
|
2054
2205
|
address2: z.string().optional()
|
|
2055
2206
|
});
|
|
2056
2207
|
//#endregion
|
|
2057
|
-
//#region src/schemas/upload.ts
|
|
2058
|
-
/**
|
|
2059
|
-
* 미디어 업로드 자리 발급 — `POST /v1/uploads`.
|
|
2060
|
-
*
|
|
2061
|
-
* 파일 바이트는 api를 거치지 않는다. 응답의 `uploadUrl`로 클라이언트가 직접 PUT하고,
|
|
2062
|
-
* 끝나면 `url`이 공개 주소가 된다. 서버가 객체 키를 정하므로 요청은 파일명만 보낸다
|
|
2063
|
-
* (확장자만 쓰이고 이름 자체는 저장되지 않는다).
|
|
2064
|
-
*/
|
|
2065
|
-
const uploadRequestSchema = z.object({ filename: z.string().min(1).max(255) });
|
|
2066
|
-
const uploadTicketSchema = z.object({
|
|
2067
|
-
/** 업로드 완료 후 공개될 주소 */
|
|
2068
|
-
url: z.url(),
|
|
2069
|
-
/** 파일 바이트를 PUT할 presigned URL. 1시간 유효 */
|
|
2070
|
-
uploadUrl: z.url()
|
|
2071
|
-
});
|
|
2072
|
-
//#endregion
|
|
2073
2208
|
//#region src/client.ts
|
|
2074
2209
|
function formBody(fields) {
|
|
2075
2210
|
return new URLSearchParams(fields).toString();
|
|
@@ -2197,7 +2332,35 @@ function createStoreClient(options) {
|
|
|
2197
2332
|
* 미디어 업로드 — 자리를 받아(`POST /uploads`) 파일 바이트는 호출자가
|
|
2198
2333
|
* `uploadUrl`로 직접 PUT한다. 업로드가 끝나면 `url`이 공개 주소가 된다.
|
|
2199
2334
|
*/
|
|
2200
|
-
uploads: {
|
|
2335
|
+
uploads: {
|
|
2336
|
+
create: (body) => storeHttp.request("POST", "/uploads", uploadTicketSchema, { body: uploadRequestSchema.parse(body) }),
|
|
2337
|
+
/**
|
|
2338
|
+
* 자리 발급 + 바이트 PUT을 한 번에 — 끝나면 `url`이 공개 주소다.
|
|
2339
|
+
*
|
|
2340
|
+
* 용도 제한(확장자·크기)은 서버가 판정하지만, 같은 규칙으로 여기서 먼저 걸러
|
|
2341
|
+
* 큰 파일을 CDN까지 보내고 나서 거절되는 왕복을 없앤다.
|
|
2342
|
+
*/
|
|
2343
|
+
upload: async (file, options) => {
|
|
2344
|
+
const filename = options?.filename ?? (typeof File !== "undefined" && file instanceof File ? file.name : "");
|
|
2345
|
+
if (!filename) throw new ApiError(400, "UPLOAD_FILENAME_REQUIRED", "파일명이 필요합니다");
|
|
2346
|
+
if (file.size === 0) throw new ApiError(400, "EMPTY_FILE", `파일이 비어 있습니다: ${filename}`);
|
|
2347
|
+
const purpose = options?.purpose ?? "description";
|
|
2348
|
+
const rejection = uploadRejection(purpose, filename, file.size);
|
|
2349
|
+
if (rejection) throw new ApiError(rejection.status, rejection.code, rejection.message);
|
|
2350
|
+
const ticket = await storeHttp.request("POST", "/uploads", uploadTicketSchema, { body: uploadRequestSchema.parse({
|
|
2351
|
+
filename,
|
|
2352
|
+
purpose,
|
|
2353
|
+
size: file.size
|
|
2354
|
+
}) });
|
|
2355
|
+
const put = await fetchFn(ticket.uploadUrl, {
|
|
2356
|
+
method: "PUT",
|
|
2357
|
+
headers: { "content-type": file.type || "application/octet-stream" },
|
|
2358
|
+
body: file
|
|
2359
|
+
});
|
|
2360
|
+
if (!put.ok) throw new ApiError(put.status, "UPLOAD_PUT_FAILED", `업로드에 실패했습니다: ${filename}`);
|
|
2361
|
+
return ticket;
|
|
2362
|
+
}
|
|
2363
|
+
},
|
|
2201
2364
|
products: {
|
|
2202
2365
|
list: (params) => storeHttp.request("GET", "/products", pageSchema(productSummarySchema), { query: params }),
|
|
2203
2366
|
get: (productId) => storeHttp.request("GET", path`/products/${productId}`, productSchema),
|
|
@@ -2278,6 +2441,16 @@ function createStoreClient(options) {
|
|
|
2278
2441
|
carrierCode,
|
|
2279
2442
|
trackingNumber
|
|
2280
2443
|
} }),
|
|
2444
|
+
/**
|
|
2445
|
+
* 배송완료 처리 — `DISPATCHED`·`DELIVERING`만 넘어간다. 응답의 `autoDecisionDate`가 자동 구매확정 예정일이다
|
|
2446
|
+
* (스토어 설정 `autoConfirmDays`가 0이면 null).
|
|
2447
|
+
*/
|
|
2448
|
+
markDelivered: (orderItemId, idempotencyKey) => storeHttp.request("POST", path`/order-items/${orderItemId}/delivered`, orderItemSchema, { headers: idempotency(idempotencyKey) }),
|
|
2449
|
+
/** 배송완료 일괄 처리 — 항목별 부분 성공이다 */
|
|
2450
|
+
markDeliveredBulk: (orderItemIds, idempotencyKey) => storeHttp.request("POST", "/order-items/delivered", bulkResultSchema, {
|
|
2451
|
+
body: { orderItemIds },
|
|
2452
|
+
headers: idempotency(idempotencyKey)
|
|
2453
|
+
}),
|
|
2281
2454
|
getDelivery: (orderItemId) => storeHttp.request("GET", path`/order-items/${orderItemId}/delivery`, deliveryStatusSchema)
|
|
2282
2455
|
},
|
|
2283
2456
|
carriers: { list: () => storeHttp.request("GET", "/carriers", z.array(carrierSchema)) },
|
|
@@ -2912,4 +3085,4 @@ function createStoreSession(options) {
|
|
|
2912
3085
|
};
|
|
2913
3086
|
}
|
|
2914
3087
|
//#endregion
|
|
2915
|
-
export { ApiError, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_OPTION_GROUPS, MAX_VALUES_PER_GROUP, MAX_VARIANTS, PAYMENT_ROUTING_EXCLUSION_CODES, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, RESERVED_STORE_CODES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_HEADERS, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addressChangeRequestListSchema, addressTypeSchema, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiClientListQuerySchema, apiClientSchema, apiClientSecretRotatedSchema, apiClientStatusSchema, apiClientTypeSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, apiTokenCreateRequestSchema, apiTokenCreatedSchema, apiTokenSchema, approveClaimResultSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, discountRequestSchema, discountSchema, dispatchRequestSchema,
|
|
3088
|
+
export { ApiError, MAX_ANALYTICS_ALLOWED_ORIGINS, MAX_AUTO_TRANSITION_DAYS, MAX_OPTION_GROUPS, MAX_PRODUCT_IMAGES, MAX_VALUES_PER_GROUP, MAX_VARIANTS, PAYMENT_ROUTING_EXCLUSION_CODES, PORTONE_CHANNEL_NAME_MAX_LENGTH, PORTONE_MAX_CHANNELS, PORTONE_MIN_CHANNELS, RESERVED_STORE_CODES, STORE_CODE_PATTERN, STORE_ROLE_SCOPES, STORE_SCOPE_RESOURCES, STORE_SESSION_KEYS, TOSS_WIDGET_CLIENT_KEY_PATTERN, TOSS_WIDGET_KEY_MESSAGE, TOSS_WIDGET_SECRET_KEY_PATTERN, UPLOAD_PURPOSE_LIMITS, VARIANT_STOCK_EXCLUSIVE_MESSAGE, WEBHOOK_DEFAULT_TOLERANCE_SEC, WEBHOOK_DELIVERY_ID_HEADER, WEBHOOK_EVENT_ID_HEADER, WEBHOOK_EVENT_TYPE_HEADER, WEBHOOK_HEADERS, WEBHOOK_SIGNATURE_HEADER, WEBHOOK_USER_AGENT, addressChangeRequestListSchema, addressTypeSchema, analyticsChannelSchema, analyticsCheckoutOutcomeSchema, analyticsCheckoutSchema, analyticsDeviceRowSchema, analyticsDevicesSchema, analyticsFunnelStepSchema, analyticsOriginSchema, analyticsOverviewSchema, analyticsPagesQuerySchema, analyticsPagesSchema, analyticsProductRowSchema, analyticsProductSortSchema, analyticsProductsQuerySchema, analyticsProductsSchema, analyticsRangeQuerySchema, analyticsRealtimeSchema, analyticsSearchQuerySchema, analyticsSearchSchema, analyticsSourceGroupBySchema, analyticsSourceRowSchema, analyticsSourcesQuerySchema, analyticsSourcesSchema, analyticsTotalsSchema, apiClientListQuerySchema, apiClientSchema, apiClientSecretRotatedSchema, apiClientStatusSchema, apiClientTypeSchema, apiLogErrorSchema, apiLogListQuerySchema, apiLogPageSchema, apiLogPrincipalSchema, apiLogPrincipalTypeSchema, apiLogSchema, apiLogStatusFilterSchema, apiLogSummarySchema, apiTokenCreateRequestSchema, apiTokenCreatedSchema, apiTokenSchema, approveClaimResultSchema, buildAuthorizeUrl, buildQuery, bulkResultSchema, cancelBySellerRequestSchema, cancelBySellerResultSchema, carrierSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryInfoSchema, deliveryMethodSchema, deliveryStatusSchema, deliveryTypeSchema, discountRequestSchema, discountSchema, dispatchRequestSchema, easyPayProviderResponseSchema, easyPayProviderSchema, eventTypeSchema, exchangeAuthorizationCode, exchangeStoreTokenViaOAuth, holdOrderItemRequestSchema, inquiryListQuerySchema, inquirySchema, inquiryWebhookEventDataSchema, inquiryWebhookEventSchema, invitationListQuerySchema, invitationSchema, isReservedStoreCode, isStoreScope, isWebOrigin, liveGateConditionCodeSchema, liveGateConditionSchema, liveGateErrorDetailsSchema, liveGateSchema, loginProviderSchema, loginProviderStatusSchema, loginProviderTestSchema, loginSettingsSchema, maskedSecretSchema, myAccountSchema, myStoreSchema, oauthClientRegistrationRequestSchema, oauthClientRegistrationResponseSchema, oauthTokenResponseSchema, optionGroupRequestSchema, optionGroupSchema, optionModelRequestSchema, optionModelSchema, optionValueRequestSchema, optionValueSchema, orderItemListQuerySchema, orderItemMemoResultSchema, orderItemPageSchema, orderItemSchema, orderItemStatusSchema, orderListQuerySchema, orderSchema, orderSummaryPageSchema, orderSummarySchema, orderWebhookEventDataSchema, orderWebhookEventSchema, pageInfoSchema, pageQueryShape, pageSchema, paymentAttemptRecordSchema, paymentAttemptStatusSchema, paymentCredentialSetSchema, paymentListQuerySchema, paymentProviderSchema, paymentProviderVerificationSchema, paymentRecordDetailSchema, paymentRecordPageSchema, paymentRecordSchema, paymentRecordStatusSchema, paymentRefundRecordSchema, paymentSettingsSchema, pgEnvironmentSchema, pgPaymentMethodSchema, pgProviderSchema, pgVerificationResultSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, refreshUserToken, rejectClaimRequestSchema, reviewListQuerySchema, reviewReportResultSchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, scopeAccessSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeTokenResponseSchema, tossPaymentsCredentialsInputSchema, trackingUpdateResultSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updateStoreRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, userTokenResponseSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookRedeliverFailedResultSchema, webhookRequestSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema };
|