@sayren/storefront-sdk 0.19.0 → 0.20.1

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.
@@ -1,4 +1,4 @@
1
- import { Tt as ApiError, t as createStorefrontClient } from "../client-Dgpp9T8r.mjs";
1
+ import { kt as ApiError, t as createStorefrontClient } from "../client-jOhA2sZX.mjs";
2
2
  //#region src/auth/index.ts
3
3
  /** 소셜 로그인 실패 — 구매자가 취소했거나(`access_denied`) state가 맞지 않는다 */
4
4
  var IdpCallbackError = class extends Error {
@@ -178,12 +178,14 @@ const pricingAmountsSchema = z.object({
178
178
  deliveryFee: z.number().int(),
179
179
  couponDiscountAmount: z.number().int(),
180
180
  deliveryDiscountAmount: z.number().int(),
181
+ pointAmount: z.number().int().optional().default(0).describe("사용 적립금(#93). 요청에 `pointAmount`가 없으면 0. 서버는 항상 싣는다"),
181
182
  totalAmount: z.number().int().describe("결제 금액")
182
183
  });
183
184
  /** `POST /checkout/{checkoutId}/pricing` 요청 */
184
185
  const checkoutPricingRequestSchema = z.object({
185
186
  zipCode: z.string().regex(/^[0-9]{5}$/, "우편번호 5자리를 입력해 주십시오").optional().describe("배송지 우편번호. 주면 제주·도서산간 추가 배송비까지 반영한다"),
186
- coupons: couponApplicationListSchema
187
+ coupons: couponApplicationListSchema,
188
+ pointAmount: z.number().int().min(0).optional().describe("쓸 적립금(#93, 회원만). 결제 시작과 같은 규칙으로 실제 사용액을 계산한다(예약하지 않는다)")
187
189
  });
188
190
  /** 결제 금액의 하한 — 쿠폰 적용 뒤 결제 금액이 이보다 작으면 결제를 시작할 수 없다 */
189
191
  const MIN_PAYMENT_AMOUNT = 100;
@@ -193,8 +195,15 @@ const checkoutPricingSchema = z.object({
193
195
  items: z.array(z.object({
194
196
  optionId: z.string().nullable(),
195
197
  lineId: z.string().optional().describe("주문서 줄의 `lineId`(이슈 #59). 서버는 항상 싣는다"),
196
- couponDiscountAmount: z.number().int().describe("이 항목에 들어간 쿠폰 할인")
198
+ couponDiscountAmount: z.number().int().describe("이 항목에 들어간 쿠폰 할인"),
199
+ pointAllocation: z.number().int().optional().default(0).describe("이 항목에 배분한 적립금(#93). 서버는 항상 싣는다")
197
200
  })).describe("주문서 항목별 쿠폰 할인 — 주문서 `items`와 같은 순서"),
201
+ points: z.object({
202
+ balance: z.number().int().describe("내 적립금 잔액"),
203
+ maxUsable: z.number().int().describe("이 금액(쿠폰·배송지 반영)에서 쓸 수 있는 최대 적립금"),
204
+ adjustReason: z.string().nullable().describe("요청보다 적게 쓴 이유. `MIN_PAYMENT`: 결제 금액 100원을 남기려고 줄였다"),
205
+ rejectReason: z.string().nullable().describe("요청했지만 쓰지 못한 이유 — `MIN_BALANCE`·`MIN_AMOUNT`·`NOT_PAYABLE`. 값이 추가될 수 있다")
206
+ }).nullable().optional().default(null).describe("적립금(#93). 비회원이거나 적립금 사용이 꺼져 있으면 null"),
198
207
  payable: z.boolean().describe("이 금액으로 결제를 시작할 수 있는가 — 적용하지 못한 쿠폰이 있거나 결제 금액이 100원 미만이면 false")
199
208
  });
200
209
  /** `GET /checkout/{checkoutId}/coupons` 항목 — 이 주문서에 쓸 수 있는 내 쿠폰 */
@@ -287,8 +296,17 @@ const checkoutSessionSchema = z.object({
287
296
  deliveryFee: z.number().int(),
288
297
  totalAmount: z.number().int(),
289
298
  couponDiscountAmount: z.number().int().optional().default(0).describe("쿠폰 할인(상품·주문 쿠폰). 주문서는 쿠폰 전이라 0이고, 결제 시작 응답은 적용한 쿠폰의 할인이다"),
290
- deliveryDiscountAmount: z.number().int().optional().default(0).describe("배송비 쿠폰 할인. 쿠폰이 없으면 0")
299
+ deliveryDiscountAmount: z.number().int().optional().default(0).describe("배송비 쿠폰 할인. 쿠폰이 없으면 0"),
300
+ pointAmount: z.number().int().optional().default(0).describe("사용 적립금(#93). 주문서는 적립금 전이라 0이고, 결제 시작 응답은 쓴 적립금이다. `totalAmount`는 적립금을 뺀 금액이다")
291
301
  }),
302
+ points: z.object({
303
+ enabled: z.boolean().describe("이 주문서에서 적립금을 쓸 수 있는가. 비회원·사용 꺼짐이면 false"),
304
+ balance: z.number().int().describe("내 적립금 잔액"),
305
+ maxUsable: z.number().int().describe("이 주문서(쿠폰 전, 배송지 반영 전)에서 쓸 수 있는 최대 금액. 쿠폰·배송지를 바꾸면 금액 미리보기로 다시 받는다"),
306
+ unit: z.number().int().describe("사용 단위(원)"),
307
+ minAmount: z.number().int().describe("한 번에 쓰는 최소 금액(원)"),
308
+ minBalance: z.number().int().describe("쓸 수 있는 최소 보유액(원)")
309
+ }).nullable().optional().default(null).describe("적립금 사용 안내(#93). 비회원이거나 상점이 적립금 사용을 끄면 null"),
292
310
  delivery: checkoutDeliverySchema.describe("배송비 내역. 배송지를 입력하면 금액이 바뀔 수 있다 — 최종 금액은 결제 시작 응답의 `amounts`다"),
293
311
  requiresShipping: z.boolean().describe("택배 배송이 필요한 상품이 있는가. false면 배송지를 받지 않는다 — 결제 시작에 `shippingAddress`를 보내지 않아도 된다"),
294
312
  withdrawal: z.object({
@@ -317,6 +335,13 @@ const paymentMethodSchema = z.enum([
317
335
  "MOBILE",
318
336
  "EASY_PAY"
319
337
  ]);
338
+ /**
339
+ * 응답에 실리는 결제수단 — 아는 값(`PaymentMethod`)이거나 이 SDK가 모르는 새 값(문자열)이다. 서버가 결제수단을 더해도
340
+ * 응답 파싱이 깨지지 않게 넓게 받는다(`responsePlanCodeSchema`·`easyPayProviderResponseSchema`와 같은 방식, #93 P0).
341
+ * 적립금 전액 결제 주문은 `POINT`가 온다. 화면은 아는 값으로 분기하고 모르는 값은 그대로 표시하거나 「기타」로 다룬다.
342
+ * 요청(결제 옵션)은 값을 골라 보내는 자리라 `paymentMethodSchema`(enum) 그대로다.
343
+ */
344
+ const responsePaymentMethodSchema = z.union([paymentMethodSchema, z.string()]).describe("결제수단. `CARD` 카드 · `BANK_TRANSFER` 계좌이체 · `VIRTUAL_ACCOUNT` 가상계좌 · `MOBILE` 휴대폰 · `EASY_PAY` 간편결제 · `POINT` 적립금 전액 결제. 값이 추가될 수 있어 문자열로 받는다");
320
345
  /** 결제를 처리하는 PG. 셀러가 직접 계약하고 상점 플랫폼 설정 › 결제에서 연결한다 */
321
346
  const pgProviderSchema = z.enum(["tosspayments", "portone"]);
322
347
  /** 간편결제사. 토스페이먼츠·포트원 모두 같은 코드를 쓴다 */
@@ -479,7 +504,8 @@ const startPaymentRequestSchema = z.object({
479
504
  shippingAddress: shippingAddressInputSchema.optional().describe("배송지. 주문서의 `requiresShipping`이 true면 필수이고 없으면 400 `SHIPPING_ADDRESS_REQUIRED`다. 배송이 필요 없는 주문(배송 없는 상품만)은 보내지 않아도 된다. 보내면 형식을 검사한 뒤 버린다"),
480
505
  guest: guestInfoSchema.optional(),
481
506
  cashReceipt: cashReceiptField,
482
- coupons: couponApplicationListSchema.optional().describe("적용할 쿠폰(이슈 #47). 결제 시작이 쿠폰을 예약하고 할인한 금액으로 결제 금액을 정한다 — 응답의 `amounts`가 확정 금액이다. 적용하지 못하는 쿠폰이 하나라도 있으면 400 `COUPON_NOT_APPLICABLE`(`details`에 사유)이다. 결제가 실패하거나 만료되면 예약이 풀린다. 쿠폰을 바꾸려면 새로 결제를 시작한다(재시도는 같은 쿠폰을 쓴다)")
507
+ coupons: couponApplicationListSchema.optional().describe("적용할 쿠폰(이슈 #47). 결제 시작이 쿠폰을 예약하고 할인한 금액으로 결제 금액을 정한다 — 응답의 `amounts`가 확정 금액이다. 적용하지 못하는 쿠폰이 하나라도 있으면 400 `COUPON_NOT_APPLICABLE`(`details`에 사유)이다. 결제가 실패하거나 만료되면 예약이 풀린다. 쿠폰을 바꾸려면 새로 결제를 시작한다(재시도는 같은 쿠폰을 쓴다)"),
508
+ pointAmount: z.number().int().min(0).optional().describe("쓸 적립금(#93, 회원만). 결제 시작이 예약하고 쿠폰 뒤 금액에서 뺀다 — 응답 `amounts.pointAmount`가 실제 사용액이다(단위로 내리고 결제 금액 100원을 남긴다). 적립금 사용이 꺼져 있으면 409 `POINTS_UNAVAILABLE`, 쓸 수 없으면 400 `POINT_NOT_APPLICABLE`(`details.reason`), 그 사이 잔액이 줄었으면 409 `POINT_BALANCE_CHANGED`다. 결제가 실패하거나 만료되면 예약이 풀린다")
483
509
  });
484
510
  /**
485
511
  * 같은 결제에서 다른 결제 옵션으로 다시 시도. `returnUrl`을 생략하면 결제 시작 때의 복귀 주소를 쓴다.
@@ -491,11 +517,18 @@ const retryPaymentRequestSchema = z.object({
491
517
  returnUrl: startPaymentRequestSchema.shape.returnUrl.optional(),
492
518
  cashReceipt: cashReceiptField
493
519
  });
520
+ /**
521
+ * 결제 시작 상태 — `pending`이면 `payUrl`로 결제창을 연다. `completed`면 결제창 없이 결제가 끝나 주문이 만들어졌고
522
+ * `orderId`가 있다(적립금으로 결제 금액 전체를 낸 주문, #93). 값이 추가될 수 있어 응답은 문자열로 받는다.
523
+ */
524
+ const PAYMENT_START_STATUS_VALUES = ["pending", "completed"];
494
525
  const paymentStartSchema = z.object({
495
526
  paymentId: z.string().describe("결제 id. 상태 조회·재시도의 키다"),
496
- attemptId: z.string().describe("결제 시도 id. PG 주문번호(토스 orderId, 포트원 paymentId)다"),
497
- option: paymentOptionSchema.describe("이 시도의 결제 옵션"),
498
- payUrl: z.string().describe("결제 서비스 주소. 팝업으로 열려면 쿼리 `mode=popup`을 붙이고, 그대로 이동하면 리다이렉트 결제다"),
527
+ status: z.string().optional().default("pending").describe("결제 시작 상태. `pending`이면 `payUrl`로 결제창을 연다. `completed`면 결제창 없이 결제가 끝났고(적립금 전액 결제) `orderId`가 주문 번호다. 그 밖의 값은 결제 상태 조회(`GET /payments/{paymentId}`)로 확정한다. 이 필드가 없던 서버 응답은 `pending`으로 읽는다"),
528
+ orderId: z.string().nullable().optional().default(null).describe("만들어진 주문 번호. `status`가 `completed`일 때만 값이 있고 그 밖에는 null"),
529
+ attemptId: z.string().nullable().describe("결제 시도 id. PG 주문번호(토스 orderId, 포트원 paymentId)다. 결제창 없이 끝난 결제(`completed`)는 null"),
530
+ option: paymentOptionSchema.nullable().describe("이 시도의 결제 옵션. 결제창 없이 끝난 결제(`completed`)는 null"),
531
+ payUrl: z.string().nullable().describe("결제 서비스 주소. 팝업으로 열려면 쿼리 `mode=popup`을 붙이고, 그대로 이동하면 리다이렉트 결제다. 결제창 없이 끝난 결제(`completed`)는 null이다"),
499
532
  expiresAt: z.string().describe("결제 요청 만료 시각"),
500
533
  testPayment: z.boolean().describe("테스트 결제(샌드박스) 여부. true면 실제로 돈이 나가지 않는다 — 결제 화면에 테스트 결제 안내를 표시한다"),
501
534
  amounts: checkoutSessionSchema.shape.amounts.describe("**확정 결제 금액** — 보낸 배송지로 배송비를 다시 계산한 값이다. 주문서 조회 시점의 `amounts`와 다를 수 있다(제주·도서산간 추가 배송비)"),
@@ -553,4 +586,4 @@ const paymentMessageSchema = z.object({
553
586
  orderId: z.string().optional()
554
587
  });
555
588
  //#endregion
556
- export { lineFulfillmentSchema as $, startPaymentRequestSchema as A, myCouponListQuerySchema as B, paymentStartSchema as C, residentNumberLike as D, remoteAreaSchema as E, checkoutPricingSchema as F, customInputEntrySchema as G, pricingAmountsSchema as H, couponApplicationListSchema as I, customInputViewSchema as J, customInputLength as K, couponApplicationSchema as L, MIN_PAYMENT_AMOUNT as M, applicableCouponSchema as N, retryPaymentRequestSchema as O, checkoutPricingRequestSchema as P, optionSelectionViewSchema as Q, couponBenefitViewSchema as R, paymentOptionSchema as S, pgProviderSchema as T, addonGroupViewSchema as U, myCouponSchema as V, addonSelectionSchema as W, lineSelectionResponseShape as X, lineSelectionRequestShape as Y, normalizeCustomInputValue as Z, paymentFailureCategorySchema as _, cashReceiptAvailable as a, paymentOptionKey as b, cashReceiptTypeSchema as c, createCheckoutRequestSchema as d, myOrderItemFulfillmentSnapshotSchema as et, deliveryQuoteRequestSchema as f, guestInfoSchema as g, easyPayProviderSchema as h, availablePaymentOptionSchema as i, MAX_COUPONS_PER_CHECKOUT as j, shippingAddressInputSchema as k, checkoutDeliverySchema as l, easyPayProviderResponseSchema as m, PAYMENT_RESULT_VALUES as n, productFulfillmentViewSchema as nt, cashReceiptIdentityTypeOf as o, deliveryQuoteSchema as p, customInputValueViewSchema as q, PAYMENT_STATUS_VALUES as r, cashReceiptRequestSchema as s, CASH_RECEIPT_METHODS as t, productCardFulfillmentSchema as tt, checkoutSessionSchema as u, paymentMessageSchema as v, paymentStatusSchema as w, paymentOptionListSchema as x, paymentMethodSchema as y, couponResultSchema as z };
589
+ export { normalizeCustomInputValue as $, retryPaymentRequestSchema as A, couponBenefitViewSchema as B, paymentOptionSchema as C, remoteAreaSchema as D, pgProviderSchema as E, applicableCouponSchema as F, addonGroupViewSchema as G, myCouponListQuerySchema as H, checkoutPricingRequestSchema as I, customInputLength as J, addonSelectionSchema as K, checkoutPricingSchema as L, startPaymentRequestSchema as M, MAX_COUPONS_PER_CHECKOUT as N, residentNumberLike as O, MIN_PAYMENT_AMOUNT as P, lineSelectionResponseShape as Q, couponApplicationListSchema as R, paymentOptionListSchema as S, paymentStatusSchema as T, myCouponSchema as U, couponResultSchema as V, pricingAmountsSchema as W, customInputViewSchema as X, customInputValueViewSchema as Y, lineSelectionRequestShape as Z, guestInfoSchema as _, availablePaymentOptionSchema as a, paymentMethodSchema as b, cashReceiptRequestSchema as c, checkoutSessionSchema as d, optionSelectionViewSchema as et, createCheckoutRequestSchema as f, easyPayProviderSchema as g, easyPayProviderResponseSchema as h, PAYMENT_STATUS_VALUES as i, productFulfillmentViewSchema as it, shippingAddressInputSchema as j, responsePaymentMethodSchema as k, cashReceiptTypeSchema as l, deliveryQuoteSchema as m, PAYMENT_RESULT_VALUES as n, myOrderItemFulfillmentSnapshotSchema as nt, cashReceiptAvailable as o, deliveryQuoteRequestSchema as p, customInputEntrySchema as q, PAYMENT_START_STATUS_VALUES as r, productCardFulfillmentSchema as rt, cashReceiptIdentityTypeOf as s, CASH_RECEIPT_METHODS as t, lineFulfillmentSchema as tt, checkoutDeliverySchema as u, paymentFailureCategorySchema as v, paymentStartSchema as w, paymentOptionKey as x, paymentMessageSchema as y, couponApplicationSchema as z };
@@ -1,5 +1,5 @@
1
1
  import { a as ANALYTICS_VISITOR_HEADER, r as ANALYTICS_SESSION_HEADER } from "./analytics-CgD70OqH.mjs";
2
- import { $ as lineFulfillmentSchema, A as startPaymentRequestSchema, C as paymentStartSchema, F as checkoutPricingSchema, J as customInputViewSchema, N as applicableCouponSchema, O as retryPaymentRequestSchema, P as checkoutPricingRequestSchema, U as addonGroupViewSchema, V as myCouponSchema, X as lineSelectionResponseShape, Y as lineSelectionRequestShape, d as createCheckoutRequestSchema, et as myOrderItemFulfillmentSnapshotSchema, f as deliveryQuoteRequestSchema, m as easyPayProviderResponseSchema, nt as productFulfillmentViewSchema, p as deliveryQuoteSchema, tt as productCardFulfillmentSchema, u as checkoutSessionSchema, w as paymentStatusSchema, y as paymentMethodSchema } from "./checkout-CCsO8PY2.mjs";
2
+ import { A as retryPaymentRequestSchema, F as applicableCouponSchema, G as addonGroupViewSchema, I as checkoutPricingRequestSchema, L as checkoutPricingSchema, M as startPaymentRequestSchema, Q as lineSelectionResponseShape, T as paymentStatusSchema, U as myCouponSchema, X as customInputViewSchema, Z as lineSelectionRequestShape, d as checkoutSessionSchema, f as createCheckoutRequestSchema, h as easyPayProviderResponseSchema, it as productFulfillmentViewSchema, k as responsePaymentMethodSchema, m as deliveryQuoteSchema, nt as myOrderItemFulfillmentSnapshotSchema, p as deliveryQuoteRequestSchema, rt as productCardFulfillmentSchema, tt as lineFulfillmentSchema, w as paymentStartSchema } from "./checkout-DSAf758s.mjs";
3
3
  import { z } from "zod";
4
4
  //#region src/http.ts
5
5
  /** 표준 엔벨로프의 $.error 상세 */
@@ -449,7 +449,8 @@ const createClaimResultSchema = z.object({
449
449
  quantity: z.number().int().describe("접수된 수량. 요청에서 생략하면 남은 수량 전체다"),
450
450
  deliveryFeeRefundAmount: z.number().int().describe("환불 예정 배송비. 배송 묶음이 모두 취소되거나 판매자 귀책일 때만 0보다 크다"),
451
451
  couponChargeAmount: z.number().int().optional().default(0).describe("쿠폰 조건 미달 차감 예상액. 이 취소·반품으로 남은 주문상품이 쿠폰 조건(최소 주문 금액 등)을 잃으면 남은 주문상품이 받던 쿠폰 할인을 환불액에서 뺀다. 예상 환불액에 이미 반영돼 있다. 서버는 항상 싣는다"),
452
- couponChargeRefundAmount: z.number().int().optional().default(0).describe("되돌릴 쿠폰 차감 예상액 — 앞선 취소·반품에서 뺀 쿠폰 조건 미달 차감 중 이번에 돌려받을 몫이다. 예상 환불액에 이미 반영돼 있다. 서버는 항상 싣는다")
452
+ couponChargeRefundAmount: z.number().int().optional().default(0).describe("되돌릴 쿠폰 차감 예상액 — 앞선 취소·반품에서 뺀 쿠폰 조건 미달 차감 중 이번에 돌려받을 몫이다. 예상 환불액에 이미 반영돼 있다. 서버는 항상 싣는다"),
453
+ pointRefundAmount: z.number().int().optional().default(0).describe("돌려받을 적립금 예상액 (원, #93) — 결제에 쓴 적립금 중 이번 취소·반품 수량의 몫이다. 예상 환불액(현금)과 별개다. 차감은 현금에서 먼저 빼고 모자란 몫만 여기서 뺀다. 적립금을 쓰지 않은 주문은 0이다. 서버는 항상 싣는다")
453
454
  });
454
455
  /**
455
456
  * 반품지 (이슈 #30) — 반품·교환 수거가 안내하는 주소다. 상점 주소록의 기본 반품지이거나,
@@ -476,6 +477,7 @@ const myClaimSchema = z.object({
476
477
  reason: z.string(),
477
478
  expectedRefundAmount: z.number().int().nullable().describe("예상 환불액 — 수량 비율 상품 실결제 금액 − 반품 배송비 − 조건부 무료배송 미달 차감 − 쿠폰 조건 미달 차감 + 되돌릴 쿠폰 차감. **배송비 환불은 포함되지 않고 `expectedDeliveryFeeRefundAmount`로 따로 온다.** 교환은 null이다"),
478
479
  expectedDeliveryFeeRefundAmount: z.number().int().nullable().describe("예상 배송비 환불액. 배송 묶음이 모두 취소되거나 판매자 귀책일 때만 0보다 크다. 이 필드가 생기기 전에 접수된 클레임은 null이다"),
480
+ expectedPointRefundAmount: z.number().int().optional().default(0).describe("예상 반환 적립금 (원, #93) — 결제에 쓴 적립금 중 이 수량의 몫이다. 예상 환불액(현금)과 별개이고, 차감은 현금에서 먼저 뺀다. 교환·적립금을 쓰지 않은 주문은 0이다. 서버는 항상 싣는다"),
479
481
  rejectReason: z.string().nullable(),
480
482
  returnAddress: claimReturnAddressSchema.nullable().describe("반품·교환 물건을 보낼 반품지(이슈 #30). 직접 보내는 수거 안내에 쓴다. 취소 클레임은 null"),
481
483
  requestedAt: z.string(),
@@ -666,6 +668,7 @@ const myOrderItemSchema = z.object({
666
668
  activeQuantity: z.number().int().describe("남은 수량 (`quantity` − `canceledQuantity`). 취소·반품·교환 요청 수량의 상한이다"),
667
669
  totalPrice: z.number().int().describe("주문상품 금액 (즉시할인 반영, 쿠폰 전)"),
668
670
  couponDiscountAmount: z.number().int().optional().default(0).describe("이 주문상품에 배분된 쿠폰 할인. 실결제 금액은 `totalPrice − couponDiscountAmount`다. 쿠폰이 없으면 0. 서버는 항상 싣는다"),
671
+ pointAllocation: z.number().int().optional().default(0).describe("이 주문상품에 쓴 적립금 (원, #93). 현금 실결제는 `totalPrice − couponDiscountAmount − pointAllocation`이다. 적립금을 쓰지 않았으면 0. 서버는 항상 싣는다"),
669
672
  status: orderItemStatusSchema,
670
673
  fulfillmentSnapshot: myOrderItemFulfillmentSnapshotSchema.describe("주문 시점 이행 스냅샷(이슈 #57). `type`이 주문 시점 상품 유형이다. 배송 없는 상품(`MANUAL`)이면 `DELIVERED`는 제공 완료다"),
671
674
  fulfillment: z.object({
@@ -697,10 +700,11 @@ const myOrderSchema = z.object({
697
700
  requiresShipping: z.boolean().describe("택배 배송이 필요한 주문상품이 있는가. false면 `shippingAddress`는 주문자 이름·연락처만 있고 주소는 빈 문자열이다"),
698
701
  shippingAddress: orderShippingAddressSchema,
699
702
  payment: z.object({
700
- method: paymentMethodSchema.describe("실제 결제수단(PG가 보고한 수단, 모르면 주문서에서 고른 수단). 결제창에서 바뀔 수 있다(카드 결제창의 간편결제 탭 등)"),
703
+ method: responsePaymentMethodSchema.describe("실제 결제수단(PG가 보고한 수단, 모르면 주문서에서 고른 수단). 결제창에서 바뀔 수 있다(카드 결제창의 간편결제 탭 등). 적립금 전액 결제 주문은 `POINT`다. 값이 추가될 수 있어 문자열로 받는다"),
701
704
  easyPayProvider: easyPayProviderResponseSchema.nullable().optional().default(null).describe("간편결제사. `method`가 `EASY_PAY`일 때만 값이 있고, PG가 알려 주지 않았으면 주문서에서 고른 간편결제사다. 그 밖의 결제수단과 간편결제 이전 주문은 null. 서버는 항상 싣는다. 현재 값은 `NAVERPAY`·`KAKAOPAY`·`TOSSPAY`·`PAYCO`이고 값이 추가될 수 있어 문자열로 받는다"),
702
705
  couponDiscountAmount: z.number().int().optional().default(0).describe("상품·주문 쿠폰 할인 합계. 쿠폰이 없으면 0. 서버는 항상 싣는다"),
703
706
  deliveryDiscountAmount: z.number().int().optional().default(0).describe("배송비 쿠폰 할인. 쿠폰이 없으면 0. 서버는 항상 싣는다"),
707
+ pointAmount: z.number().int().optional().default(0).describe("사용 적립금 (원, #93). `totalAmount`는 적립금을 뺀 결제 금액이다. 적립금을 쓰지 않았으면 0. 서버는 항상 싣는다"),
704
708
  discounts: z.array(z.object({
705
709
  couponId: z.string(),
706
710
  name: z.string().describe("주문 시점 쿠폰 이름"),
@@ -743,6 +747,43 @@ const purchaseDecisionResultSchema = z.object({
743
747
  decidedAt: z.string()
744
748
  });
745
749
  //#endregion
750
+ //#region src/schemas/points.ts
751
+ /**
752
+ * 적립금 (이슈 #93) — 상점 적립 정책 안내와 구매자 잔액·내역. 금액은 원 단위 정수다.
753
+ * 적립금 사용(주문서·결제)은 다음 단계에서 가산한다.
754
+ */
755
+ /** `GET /point-policy` — 상점 적립 정책(인증 없음, 상점 단위). 리뷰 작성·주문 화면의 혜택 안내에 쓴다 */
756
+ const storefrontPointPolicySchema = z.object({
757
+ reviewReward: z.object({
758
+ enabled: z.boolean().describe("리뷰 적립 사용 여부. false면 리뷰 혜택 안내를 그리지 않는다"),
759
+ textPoint: z.number().int().describe("리뷰를 작성하면 주는 적립금(원)"),
760
+ photoPoint: z.number().int().describe("사진 리뷰에 더 주는 적립금(원). 사진 리뷰는 `textPoint + photoPoint`다")
761
+ }).describe("리뷰 적립"),
762
+ purchaseEarn: z.object({
763
+ enabled: z.boolean().describe("구매 적립 사용 여부"),
764
+ rateBp: z.number().int().describe("상점 기본 구매 적립률(만분율, 100 = 1%). 상품마다 다를 수 있다")
765
+ }).describe("구매 적립 — 구매확정 때 실결제 금액(배송비 제외) × 적립률을 준다"),
766
+ expiryDays: z.number().int().nullable().describe("적립금 유효 기간(일). 정하지 않았으면 null"),
767
+ review: z.object({
768
+ writableDays: z.number().int().describe("구매확정 뒤 리뷰를 쓸 수 있는 기간(일)"),
769
+ editableDays: z.number().int().describe("리뷰를 쓴 뒤 고칠 수 있는 기간(일)")
770
+ }).describe("리뷰 작성·수정 기한")
771
+ });
772
+ /** `GET /me/points` — 내 적립금 */
773
+ const memberPointsSchema = z.object({
774
+ balance: z.number().int().describe("잔액"),
775
+ expiringSoon: z.number().int().describe("30일 안에 소멸할 금액")
776
+ });
777
+ /** 내 적립금 내역 한 줄 — 셀러 메모는 싣지 않는다 */
778
+ const memberPointEntrySchema = z.object({
779
+ entryId: z.string(),
780
+ type: z.string().describe("유형. `EARN_REVIEW` 리뷰 적립 · `REVOKE_REVIEW` 리뷰 삭제 회수 · `EARN_PURCHASE` 구매 적립 · `EXPIRE` 소멸 · `ADJUST` 상점 지급·차감 · `OPENING` 기존 적립금 · `USE_RESERVE` 결제 사용 · `USE_RELEASE` 결제가 실패·만료되어 되돌림 · `REFUND_RESTORE` 취소·반품 환불로 반환. 값이 추가될 수 있어 문자열로 받는다"),
781
+ amount: z.number().int().describe("변동액. 적립 +, 회수·차감·소멸 −"),
782
+ balanceAfter: z.number().int().describe("이 변동 직후 잔액"),
783
+ createdAt: z.string()
784
+ });
785
+ const memberPointEntryPageSchema = pageSchema(memberPointEntrySchema);
786
+ //#endregion
746
787
  //#region src/schemas/review.ts
747
788
  const publicReviewSchema = z.object({
748
789
  reviewId: z.string(),
@@ -968,6 +1009,8 @@ function createStorefrontClient(options) {
968
1009
  get: () => http.request("GET", "/store", storefrontStoreSchema) },
969
1010
  catalog: {
970
1011
  listCategories: () => http.request("GET", "/categories", z.array(categoryNodeSchema)),
1012
+ /** `GET /point-policy` — 상점 적립 정책(리뷰·구매 적립, 유효 기간, 리뷰 작성·수정 기한, #93). 리뷰 혜택 안내에 쓴다 */
1013
+ getPointPolicy: () => http.request("GET", "/point-policy", storefrontPointPolicySchema),
971
1014
  searchProducts: (params) => http.request("GET", "/products", productPageSchema, { query: params }),
972
1015
  getProduct: (productId) => http.request("GET", path`/products/${productId}`, productDetailSchema),
973
1016
  /** 상품 리뷰 목록 — `variantId`로 옵션(조합)별 리뷰만 받는다(상품 상세 `variants[].variantId`) */
@@ -1060,6 +1103,10 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
1060
1103
  },
1061
1104
  member: {
1062
1105
  me: () => http.request("GET", "/me", memberSchema),
1106
+ /** `GET /me/points` — 내 적립금 잔액과 30일 안 소멸 예정액(#93) */
1107
+ getPoints: () => http.request("GET", "/me/points", memberPointsSchema),
1108
+ /** `GET /me/points/history` — 내 적립금 내역(최신순) */
1109
+ listPointHistory: (params) => http.request("GET", "/me/points/history", memberPointEntryPageSchema, { query: params }),
1063
1110
  updateMe: (body) => http.requestVoid("PATCH", "/me", { body: updateProfileRequestSchema.parse(body) }),
1064
1111
  /** 약관·개인정보·마케팅 동의의 현재 상태와 재동의 필요 여부 */
1065
1112
  consents: () => http.request("GET", "/me/consents", memberConsentsSchema),
@@ -1099,4 +1146,4 @@ get: () => http.request("GET", "/store", storefrontStoreSchema) },
1099
1146
  };
1100
1147
  }
1101
1148
  //#endregion
1102
- export { productPageSchema as $, publicInquirySchema as A, claimReasonSchema as B, memberAddressSchema as C, withdrawRequestSchema as Ct, createInquiryRequestSchema as D, toApiError as Dt, wishlistAddResultSchema as E, buildQuery as Et, consentKindSchema as F, myClaimSchema as G, claimTypeSchema as H, consentSourceSchema as I, collectionProductQuerySchema as J, categoryNodeSchema as K, consentStateSchema as L, customerInquiryCategorySchema as M, customerInquirySchema as N, createInquiryResultSchema as O, unwrapData as Ot, consentActionSchema as P, productFacetsSchema as Q, consentUpdateRequestSchema as R, memberAddressRequestSchema as S, tokenPairSchema as St, updateProfileRequestSchema as T, ApiError as Tt, createClaimRequestSchema as U, claimReturnAddressSchema as V, createClaimResultSchema as W, productCardSchema as X, collectionProductSortSchema as Y, productDetailSchema as Z, myOrderItemSchema as _, linkIdentityRequestSchema as _t, myReviewSchema as a, orderItemStatusSchema as at, purchaseDecisionResultSchema as b, signupRequestSchema as bt, publicReviewSchema as c, addCartItemRequestSchema as ct, reviewSummarySchema as d, updateCartItemRequestSchema as dt, productSortSchema as et, updateReviewRequestSchema as f, anonymousSessionSchema as ft, deliveryTrackingSchema as g, idpTokenRequestSchema as gt, writableReviewSchema as h, idpAuthorizeResponseSchema as ht, createReviewResultSchema as i, claimStatusSchema as it, createCustomerInquiryRequestSchema as j, productInquiryCategorySchema as k, reviewImageUploadRequestSchema as l, cartItemSchema as lt, uploadTicketSchema as m, idpAuthorizeRequestSchema as mt, storefrontStoreSchema as n, storefrontCollectionListQuerySchema as nt, productReviewQuerySchema as o, pageInfoSchema as ot, updateReviewResultSchema as p, idpAgreementsSchema as pt, collectionProductPageSchema as q, createReviewRequestSchema as r, storefrontCollectionSchema as rt, productReviewSortSchema as s, pageSchema as st, createStorefrontClient as t, storefrontCollectionDetailSchema as tt, reviewPageSchema as u, cartSchema as ut, myOrderSchema as v, loginRequestSchema as vt, memberSchema as w, withdrawalBlockedDetailsSchema as wt, trackingStageResponseSchema as x, socialProviderSchema as xt, orderShippingAddressSchema as y, memberIdentitiesSchema as yt, memberConsentsSchema as z };
1149
+ export { collectionProductSortSchema as $, wishlistAddResultSchema as A, buildQuery as At, consentSourceSchema as B, orderShippingAddressSchema as C, memberIdentitiesSchema as Ct, memberAddressSchema as D, withdrawRequestSchema as Dt, memberAddressRequestSchema as E, tokenPairSchema as Et, createCustomerInquiryRequestSchema as F, claimReturnAddressSchema as G, consentUpdateRequestSchema as H, customerInquiryCategorySchema as I, createClaimResultSchema as J, claimTypeSchema as K, customerInquirySchema as L, createInquiryResultSchema as M, unwrapData as Mt, productInquiryCategorySchema as N, memberSchema as O, withdrawalBlockedDetailsSchema as Ot, publicInquirySchema as P, collectionProductQuerySchema as Q, consentActionSchema as R, myOrderSchema as S, loginRequestSchema as St, trackingStageResponseSchema as T, socialProviderSchema as Tt, memberConsentsSchema as U, consentStateSchema as V, claimReasonSchema as W, categoryNodeSchema as X, myClaimSchema as Y, collectionProductPageSchema as Z, memberPointEntrySchema as _, idpAgreementsSchema as _t, myReviewSchema as a, storefrontCollectionDetailSchema as at, deliveryTrackingSchema as b, idpTokenRequestSchema as bt, publicReviewSchema as c, claimStatusSchema as ct, reviewSummarySchema as d, pageSchema as dt, productCardSchema as et, updateReviewRequestSchema as f, addCartItemRequestSchema as ft, memberPointEntryPageSchema as g, anonymousSessionSchema as gt, writableReviewSchema as h, updateCartItemRequestSchema as ht, createReviewResultSchema as i, productSortSchema as it, createInquiryRequestSchema as j, toApiError as jt, updateProfileRequestSchema as k, ApiError as kt, reviewImageUploadRequestSchema as l, orderItemStatusSchema as lt, uploadTicketSchema as m, cartSchema as mt, storefrontStoreSchema as n, productFacetsSchema as nt, productReviewQuerySchema as o, storefrontCollectionListQuerySchema as ot, updateReviewResultSchema as p, cartItemSchema as pt, createClaimRequestSchema as q, createReviewRequestSchema as r, productPageSchema as rt, productReviewSortSchema as s, storefrontCollectionSchema as st, createStorefrontClient as t, productDetailSchema as tt, reviewPageSchema as u, pageInfoSchema as ut, memberPointsSchema as v, idpAuthorizeRequestSchema as vt, purchaseDecisionResultSchema as w, signupRequestSchema as wt, myOrderItemSchema as x, linkIdentityRequestSchema as xt, storefrontPointPolicySchema as y, idpAuthorizeResponseSchema as yt, consentKindSchema as z };