@sayren/store-sdk 0.11.0 → 0.12.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 +171 -1
- package/dist/index.mjs +75 -6
- package/package.json +1 -1
- package/src/client.ts +12 -0
- package/src/http.ts +16 -1
- package/src/schemas/api-log.ts +12 -1
- package/src/schemas/misc.ts +134 -1
package/dist/index.d.mts
CHANGED
|
@@ -8,9 +8,13 @@ export declare class ApiError extends Error {
|
|
|
8
8
|
readonly body?: unknown | undefined;
|
|
9
9
|
/** 엔벨로프 `$.error.details` — 에러 코드별 보조 데이터. 없으면 undefined */
|
|
10
10
|
readonly details?: Record<string, unknown> | undefined;
|
|
11
|
+
/** 엔벨로프 `$.error.docs` — 이 에러 코드를 설명하는 문서 URL. 매핑이 없으면 undefined */
|
|
12
|
+
readonly docs?: string | undefined;
|
|
11
13
|
constructor(status: number, code: string, message: string, traceId?: string | undefined, body?: unknown | undefined,
|
|
12
14
|
/** 엔벨로프 `$.error.details` — 에러 코드별 보조 데이터. 없으면 undefined */
|
|
13
|
-
details?: Record<string, unknown> | undefined
|
|
15
|
+
details?: Record<string, unknown> | undefined,
|
|
16
|
+
/** 엔벨로프 `$.error.docs` — 이 에러 코드를 설명하는 문서 URL. 매핑이 없으면 undefined */
|
|
17
|
+
docs?: string | undefined);
|
|
14
18
|
}
|
|
15
19
|
type TokenSource = string | null | undefined | (() => string | null | undefined);
|
|
16
20
|
type Query = Record<string, string | number | boolean | undefined>;
|
|
@@ -619,6 +623,7 @@ export declare const apiLogListQuerySchema: z.ZodObject<{
|
|
|
619
623
|
"5xx": "5xx";
|
|
620
624
|
}>>;
|
|
621
625
|
q: z.ZodOptional<z.ZodString>;
|
|
626
|
+
traceId: z.ZodOptional<z.ZodString>;
|
|
622
627
|
cursor: z.ZodOptional<z.ZodString>;
|
|
623
628
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
624
629
|
}, z.core.$strip>;
|
|
@@ -1956,6 +1961,34 @@ export declare const webhookDeliveryErrorCodeSchema: z.ZodEnum<{
|
|
|
1956
1961
|
WEBHOOK_SUSPENDED: "WEBHOOK_SUSPENDED";
|
|
1957
1962
|
}>;
|
|
1958
1963
|
export type WebhookDeliveryErrorCode = z.infer<typeof webhookDeliveryErrorCodeSchema>;
|
|
1964
|
+
/**
|
|
1965
|
+
* 실패 원인 분류의 **현재** 값. 응답 스키마(`webhookFailureReasonSchema`)는 문자열로 열려 있다 —
|
|
1966
|
+
* 서버가 값을 더해도 이전 SDK가 목록 파싱에 실패하지 않게 한다(택배 추적 `stage`와 같은 이유).
|
|
1967
|
+
* 모르는 값은 `errorCode`로 판단한다.
|
|
1968
|
+
*/
|
|
1969
|
+
export declare const WEBHOOK_FAILURE_REASONS: readonly ["DNS", "TLS", "TIMEOUT", "CONNECTION", "HTTP_4XX", "HTTP_5XX", "HTTP_OTHER", "SSRF_BLOCKED", "SUSPENDED"];
|
|
1970
|
+
/** 알려진 실패 원인. 응답에는 이 밖의 문자열이 올 수 있다 */
|
|
1971
|
+
export type WebhookFailureReason = (typeof WEBHOOK_FAILURE_REASONS)[number];
|
|
1972
|
+
export declare const webhookFailureReasonSchema: z.ZodString;
|
|
1973
|
+
/**
|
|
1974
|
+
* 대상 리소스 종류의 **현재** 값. 응답 스키마는 문자열로 열려 있다(새 이벤트가 새 리소스를 가리킬 수 있다).
|
|
1975
|
+
*/
|
|
1976
|
+
export declare const WEBHOOK_RESOURCE_TYPES: readonly ["ORDER", "CLAIM", "PRODUCT", "REVIEW", "INQUIRY"];
|
|
1977
|
+
/** 알려진 리소스 종류. 응답에는 이 밖의 문자열이 올 수 있다 */
|
|
1978
|
+
export type WebhookResourceType = (typeof WEBHOOK_RESOURCE_TYPES)[number];
|
|
1979
|
+
export declare const webhookResourceTypeSchema: z.ZodString;
|
|
1980
|
+
/** 이벤트가 가리키는 대상 리소스 — 전송 기록을 주문·상품과 잇는 키 */
|
|
1981
|
+
export declare const webhookDeliveryResourceSchema: z.ZodObject<{
|
|
1982
|
+
type: z.ZodString;
|
|
1983
|
+
id: z.ZodString;
|
|
1984
|
+
}, z.core.$strip>;
|
|
1985
|
+
export type WebhookDeliveryResource = z.infer<typeof webhookDeliveryResourceSchema>;
|
|
1986
|
+
/** 발송 요청 헤더 한 줄 (값 마스킹) */
|
|
1987
|
+
export declare const webhookRequestHeaderSchema: z.ZodObject<{
|
|
1988
|
+
name: z.ZodString;
|
|
1989
|
+
value: z.ZodNullable<z.ZodString>;
|
|
1990
|
+
}, z.core.$strip>;
|
|
1991
|
+
export type WebhookRequestHeader = z.infer<typeof webhookRequestHeaderSchema>;
|
|
1959
1992
|
/** 웹훅 전송 기록 한 건 (전송 기록 조회 항목) */
|
|
1960
1993
|
export declare const webhookDeliverySchema: z.ZodObject<{
|
|
1961
1994
|
deliveryId: z.ZodString;
|
|
@@ -1992,6 +2025,11 @@ export declare const webhookDeliverySchema: z.ZodObject<{
|
|
|
1992
2025
|
NON_2XX: "NON_2XX";
|
|
1993
2026
|
WEBHOOK_SUSPENDED: "WEBHOOK_SUSPENDED";
|
|
1994
2027
|
}>>;
|
|
2028
|
+
failureReason: z.ZodNullable<z.ZodString>;
|
|
2029
|
+
resource: z.ZodNullable<z.ZodObject<{
|
|
2030
|
+
type: z.ZodString;
|
|
2031
|
+
id: z.ZodString;
|
|
2032
|
+
}, z.core.$strip>>;
|
|
1995
2033
|
attemptCount: z.ZodNumber;
|
|
1996
2034
|
createdAt: z.ZodString;
|
|
1997
2035
|
attemptedAt: z.ZodNullable<z.ZodString>;
|
|
@@ -2000,6 +2038,64 @@ export declare const webhookDeliverySchema: z.ZodObject<{
|
|
|
2000
2038
|
redeliveredAs: z.ZodNullable<z.ZodString>;
|
|
2001
2039
|
}, z.core.$strip>;
|
|
2002
2040
|
export type WebhookDelivery = z.infer<typeof webhookDeliverySchema>;
|
|
2041
|
+
/** 발송 본문 최대 노출 길이(바이트). 넘으면 잘라 주고 `payloadTruncated`가 true다 */
|
|
2042
|
+
export declare const WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES: number;
|
|
2043
|
+
/** 웹훅 전송 기록 상세 — `GET /webhooks/{id}/deliveries/{deliveryId}`. 목록 항목 + 요청 본문·헤더 */
|
|
2044
|
+
export declare const webhookDeliveryDetailSchema: z.ZodObject<{
|
|
2045
|
+
deliveryId: z.ZodString;
|
|
2046
|
+
eventId: z.ZodString;
|
|
2047
|
+
eventType: z.ZodEnum<{
|
|
2048
|
+
"ORDER.PAID": "ORDER.PAID";
|
|
2049
|
+
"ORDER.CONFIRMED": "ORDER.CONFIRMED";
|
|
2050
|
+
"ORDER.DISPATCHED": "ORDER.DISPATCHED";
|
|
2051
|
+
"ORDER.DELIVERED": "ORDER.DELIVERED";
|
|
2052
|
+
"ORDER.PURCHASE_DECIDED": "ORDER.PURCHASE_DECIDED";
|
|
2053
|
+
"ORDER.ADDRESS_CHANGE_REQUESTED": "ORDER.ADDRESS_CHANGE_REQUESTED";
|
|
2054
|
+
"CLAIM.CANCEL_REQUESTED": "CLAIM.CANCEL_REQUESTED";
|
|
2055
|
+
"CLAIM.RETURN_REQUESTED": "CLAIM.RETURN_REQUESTED";
|
|
2056
|
+
"CLAIM.EXCHANGE_REQUESTED": "CLAIM.EXCHANGE_REQUESTED";
|
|
2057
|
+
"CLAIM.COMPLETED": "CLAIM.COMPLETED";
|
|
2058
|
+
"INQUIRY.CREATED": "INQUIRY.CREATED";
|
|
2059
|
+
"REVIEW.CREATED": "REVIEW.CREATED";
|
|
2060
|
+
"PRODUCT.OUT_OF_STOCK": "PRODUCT.OUT_OF_STOCK";
|
|
2061
|
+
}>;
|
|
2062
|
+
url: z.ZodString;
|
|
2063
|
+
status: z.ZodEnum<{
|
|
2064
|
+
PENDING: "PENDING";
|
|
2065
|
+
PENDING_RETRY: "PENDING_RETRY";
|
|
2066
|
+
SUCCESS: "SUCCESS";
|
|
2067
|
+
FAILED: "FAILED";
|
|
2068
|
+
}>;
|
|
2069
|
+
responseStatusCode: z.ZodNullable<z.ZodNumber>;
|
|
2070
|
+
responseTimeMs: z.ZodNullable<z.ZodNumber>;
|
|
2071
|
+
responseBodyExcerpt: z.ZodNullable<z.ZodString>;
|
|
2072
|
+
errorCode: z.ZodNullable<z.ZodEnum<{
|
|
2073
|
+
TIMEOUT: "TIMEOUT";
|
|
2074
|
+
CONNECTION_FAILED: "CONNECTION_FAILED";
|
|
2075
|
+
BLOCKED_ADDRESS: "BLOCKED_ADDRESS";
|
|
2076
|
+
NON_2XX: "NON_2XX";
|
|
2077
|
+
WEBHOOK_SUSPENDED: "WEBHOOK_SUSPENDED";
|
|
2078
|
+
}>>;
|
|
2079
|
+
failureReason: z.ZodNullable<z.ZodString>;
|
|
2080
|
+
resource: z.ZodNullable<z.ZodObject<{
|
|
2081
|
+
type: z.ZodString;
|
|
2082
|
+
id: z.ZodString;
|
|
2083
|
+
}, z.core.$strip>>;
|
|
2084
|
+
attemptCount: z.ZodNumber;
|
|
2085
|
+
createdAt: z.ZodString;
|
|
2086
|
+
attemptedAt: z.ZodNullable<z.ZodString>;
|
|
2087
|
+
nextAttemptAt: z.ZodNullable<z.ZodString>;
|
|
2088
|
+
redeliveryOf: z.ZodNullable<z.ZodString>;
|
|
2089
|
+
redeliveredAs: z.ZodNullable<z.ZodString>;
|
|
2090
|
+
payload: z.ZodString;
|
|
2091
|
+
payloadTruncated: z.ZodBoolean;
|
|
2092
|
+
payloadMasked: z.ZodBoolean;
|
|
2093
|
+
requestHeaders: z.ZodArray<z.ZodObject<{
|
|
2094
|
+
name: z.ZodString;
|
|
2095
|
+
value: z.ZodNullable<z.ZodString>;
|
|
2096
|
+
}, z.core.$strip>>;
|
|
2097
|
+
}, z.core.$strip>;
|
|
2098
|
+
export type WebhookDeliveryDetail = z.infer<typeof webhookDeliveryDetailSchema>;
|
|
2003
2099
|
/** 전송 기록 조회 쿼리 — `GET /webhooks/{id}/deliveries` */
|
|
2004
2100
|
export declare const webhookDeliveryListQuerySchema: z.ZodObject<{
|
|
2005
2101
|
status: z.ZodOptional<z.ZodEnum<{
|
|
@@ -2008,6 +2104,22 @@ export declare const webhookDeliveryListQuerySchema: z.ZodObject<{
|
|
|
2008
2104
|
SUCCESS: "SUCCESS";
|
|
2009
2105
|
FAILED: "FAILED";
|
|
2010
2106
|
}>>;
|
|
2107
|
+
eventType: z.ZodOptional<z.ZodEnum<{
|
|
2108
|
+
"ORDER.PAID": "ORDER.PAID";
|
|
2109
|
+
"ORDER.CONFIRMED": "ORDER.CONFIRMED";
|
|
2110
|
+
"ORDER.DISPATCHED": "ORDER.DISPATCHED";
|
|
2111
|
+
"ORDER.DELIVERED": "ORDER.DELIVERED";
|
|
2112
|
+
"ORDER.PURCHASE_DECIDED": "ORDER.PURCHASE_DECIDED";
|
|
2113
|
+
"ORDER.ADDRESS_CHANGE_REQUESTED": "ORDER.ADDRESS_CHANGE_REQUESTED";
|
|
2114
|
+
"CLAIM.CANCEL_REQUESTED": "CLAIM.CANCEL_REQUESTED";
|
|
2115
|
+
"CLAIM.RETURN_REQUESTED": "CLAIM.RETURN_REQUESTED";
|
|
2116
|
+
"CLAIM.EXCHANGE_REQUESTED": "CLAIM.EXCHANGE_REQUESTED";
|
|
2117
|
+
"CLAIM.COMPLETED": "CLAIM.COMPLETED";
|
|
2118
|
+
"INQUIRY.CREATED": "INQUIRY.CREATED";
|
|
2119
|
+
"REVIEW.CREATED": "REVIEW.CREATED";
|
|
2120
|
+
"PRODUCT.OUT_OF_STOCK": "PRODUCT.OUT_OF_STOCK";
|
|
2121
|
+
}>>;
|
|
2122
|
+
resourceId: z.ZodOptional<z.ZodString>;
|
|
2011
2123
|
limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
2012
2124
|
}, z.core.$strip>;
|
|
2013
2125
|
export type WebhookDeliveryListParams = z.infer<typeof webhookDeliveryListQuerySchema>;
|
|
@@ -2045,6 +2157,13 @@ export declare const webhookTestResultSchema: z.ZodObject<{
|
|
|
2045
2157
|
NON_2XX: "NON_2XX";
|
|
2046
2158
|
WEBHOOK_SUSPENDED: "WEBHOOK_SUSPENDED";
|
|
2047
2159
|
}>>;
|
|
2160
|
+
failureReason: z.ZodNullable<z.ZodString>;
|
|
2161
|
+
responseBodyExcerpt: z.ZodNullable<z.ZodString>;
|
|
2162
|
+
requestHeaders: z.ZodArray<z.ZodObject<{
|
|
2163
|
+
name: z.ZodString;
|
|
2164
|
+
value: z.ZodNullable<z.ZodString>;
|
|
2165
|
+
}, z.core.$strip>>;
|
|
2166
|
+
payload: z.ZodString;
|
|
2048
2167
|
}, z.core.$strip>;
|
|
2049
2168
|
export type WebhookTestResult = z.infer<typeof webhookTestResultSchema>;
|
|
2050
2169
|
export declare const webhookRequestSchema: z.ZodObject<{
|
|
@@ -6924,6 +7043,11 @@ export declare function createStoreClient(options: StoreClientOptions): {
|
|
|
6924
7043
|
responseTimeMs: number | null;
|
|
6925
7044
|
responseBodyExcerpt: string | null;
|
|
6926
7045
|
errorCode: "TIMEOUT" | "CONNECTION_FAILED" | "BLOCKED_ADDRESS" | "NON_2XX" | "WEBHOOK_SUSPENDED" | null;
|
|
7046
|
+
failureReason: string | null;
|
|
7047
|
+
resource: {
|
|
7048
|
+
type: string;
|
|
7049
|
+
id: string;
|
|
7050
|
+
} | null;
|
|
6927
7051
|
attemptCount: number;
|
|
6928
7052
|
createdAt: string;
|
|
6929
7053
|
attemptedAt: string | null;
|
|
@@ -6931,6 +7055,40 @@ export declare function createStoreClient(options: StoreClientOptions): {
|
|
|
6931
7055
|
redeliveryOf: string | null;
|
|
6932
7056
|
redeliveredAs: string | null;
|
|
6933
7057
|
}[]>;
|
|
7058
|
+
/**
|
|
7059
|
+
* 전송 기록 한 건의 상세. 목록 항목에 보낸 요청 본문(최대 16KB)과 요청 헤더가 더해진다.
|
|
7060
|
+
* 실패 원인 분류(`failureReason`)·응답 본문(`responseBodyExcerpt`)으로 원인을 찾고,
|
|
7061
|
+
* `resource.id`를 API 로그 조회의 `q`로 넘겨 같은 리소스의 API 요청과 맞춰 본다.
|
|
7062
|
+
*/
|
|
7063
|
+
getDelivery: (webhookId: string, deliveryId: string) => Promise<{
|
|
7064
|
+
deliveryId: string;
|
|
7065
|
+
eventId: string;
|
|
7066
|
+
eventType: "ORDER.PAID" | "ORDER.CONFIRMED" | "ORDER.DISPATCHED" | "ORDER.DELIVERED" | "ORDER.PURCHASE_DECIDED" | "ORDER.ADDRESS_CHANGE_REQUESTED" | "CLAIM.CANCEL_REQUESTED" | "CLAIM.RETURN_REQUESTED" | "CLAIM.EXCHANGE_REQUESTED" | "CLAIM.COMPLETED" | "INQUIRY.CREATED" | "REVIEW.CREATED" | "PRODUCT.OUT_OF_STOCK";
|
|
7067
|
+
url: string;
|
|
7068
|
+
status: "PENDING" | "PENDING_RETRY" | "SUCCESS" | "FAILED";
|
|
7069
|
+
responseStatusCode: number | null;
|
|
7070
|
+
responseTimeMs: number | null;
|
|
7071
|
+
responseBodyExcerpt: string | null;
|
|
7072
|
+
errorCode: "TIMEOUT" | "CONNECTION_FAILED" | "BLOCKED_ADDRESS" | "NON_2XX" | "WEBHOOK_SUSPENDED" | null;
|
|
7073
|
+
failureReason: string | null;
|
|
7074
|
+
resource: {
|
|
7075
|
+
type: string;
|
|
7076
|
+
id: string;
|
|
7077
|
+
} | null;
|
|
7078
|
+
attemptCount: number;
|
|
7079
|
+
createdAt: string;
|
|
7080
|
+
attemptedAt: string | null;
|
|
7081
|
+
nextAttemptAt: string | null;
|
|
7082
|
+
redeliveryOf: string | null;
|
|
7083
|
+
redeliveredAs: string | null;
|
|
7084
|
+
payload: string;
|
|
7085
|
+
payloadTruncated: boolean;
|
|
7086
|
+
payloadMasked: boolean;
|
|
7087
|
+
requestHeaders: {
|
|
7088
|
+
name: string;
|
|
7089
|
+
value: string | null;
|
|
7090
|
+
}[];
|
|
7091
|
+
}>;
|
|
6934
7092
|
/**
|
|
6935
7093
|
* FAILED 전송 기록 한 건을 같은 eventId로 다시 보낸다(202). 새로 적재된 기록을 돌려주며
|
|
6936
7094
|
* `redeliveryOf`가 원본 deliveryId다. 원본이 FAILED가 아니면 409 `DELIVERY_NOT_FAILED`,
|
|
@@ -6947,6 +7105,11 @@ export declare function createStoreClient(options: StoreClientOptions): {
|
|
|
6947
7105
|
responseTimeMs: number | null;
|
|
6948
7106
|
responseBodyExcerpt: string | null;
|
|
6949
7107
|
errorCode: "TIMEOUT" | "CONNECTION_FAILED" | "BLOCKED_ADDRESS" | "NON_2XX" | "WEBHOOK_SUSPENDED" | null;
|
|
7108
|
+
failureReason: string | null;
|
|
7109
|
+
resource: {
|
|
7110
|
+
type: string;
|
|
7111
|
+
id: string;
|
|
7112
|
+
} | null;
|
|
6950
7113
|
attemptCount: number;
|
|
6951
7114
|
createdAt: string;
|
|
6952
7115
|
attemptedAt: string | null;
|
|
@@ -6969,6 +7132,13 @@ export declare function createStoreClient(options: StoreClientOptions): {
|
|
|
6969
7132
|
responseStatusCode: number | null;
|
|
6970
7133
|
responseTimeMs: number | null;
|
|
6971
7134
|
errorCode: "TIMEOUT" | "CONNECTION_FAILED" | "BLOCKED_ADDRESS" | "NON_2XX" | "WEBHOOK_SUSPENDED" | null;
|
|
7135
|
+
failureReason: string | null;
|
|
7136
|
+
responseBodyExcerpt: string | null;
|
|
7137
|
+
requestHeaders: {
|
|
7138
|
+
name: string;
|
|
7139
|
+
value: string | null;
|
|
7140
|
+
}[];
|
|
7141
|
+
payload: string;
|
|
6972
7142
|
}>;
|
|
6973
7143
|
};
|
|
6974
7144
|
/** API 로그 (보관 7일, 콘솔 OWNER/ADMIN) */
|
package/dist/index.mjs
CHANGED
|
@@ -34,6 +34,11 @@ const errorDetailSchema = z.object({
|
|
|
34
34
|
message: z.string(),
|
|
35
35
|
traceId: z.string().optional(),
|
|
36
36
|
/**
|
|
37
|
+
* 이 에러 코드를 설명하는 문서 URL(선택). 서버가 코드별 매핑을 가진 코드에만 실린다 —
|
|
38
|
+
* 없으면 필드가 아예 없으므로 소비측은 있을 때만 쓴다
|
|
39
|
+
*/
|
|
40
|
+
docs: z.url().optional().catch(void 0),
|
|
41
|
+
/**
|
|
37
42
|
* 에러 코드별 보조 데이터(선택). 예: 관리 API `LIVE_GATE_NOT_MET`·`LIVE_PAYMENTS_DISABLED`의
|
|
38
43
|
* `{ conditions: LiveGateCondition[] }`. 형태는 에러 코드마다 다르므로 소비측이 코드별 스키마로 다시 파싱한다
|
|
39
44
|
*/
|
|
@@ -69,13 +74,15 @@ var ApiError = class extends Error {
|
|
|
69
74
|
traceId;
|
|
70
75
|
body;
|
|
71
76
|
details;
|
|
72
|
-
|
|
77
|
+
docs;
|
|
78
|
+
constructor(status, code, message, traceId, body, details, docs) {
|
|
73
79
|
super(message);
|
|
74
80
|
this.status = status;
|
|
75
81
|
this.code = code;
|
|
76
82
|
this.traceId = traceId;
|
|
77
83
|
this.body = body;
|
|
78
84
|
this.details = details;
|
|
85
|
+
this.docs = docs;
|
|
79
86
|
this.name = "ApiError";
|
|
80
87
|
}
|
|
81
88
|
};
|
|
@@ -88,7 +95,7 @@ var ApiError = class extends Error {
|
|
|
88
95
|
function toApiError(status, raw) {
|
|
89
96
|
const envelope = envelopeSchema.safeParse(raw);
|
|
90
97
|
const detail = envelope.success ? envelope.data.error : errorDetailSchema.safeParse(raw).data ?? null;
|
|
91
|
-
if (detail) return new ApiError(status, detail.code, detail.message, detail.traceId, raw, detail.details);
|
|
98
|
+
if (detail) return new ApiError(status, detail.code, detail.message, detail.traceId, raw, detail.details, detail.docs);
|
|
92
99
|
const oauth = envelope.success ? null : oauthErrorSchema.safeParse(raw).data;
|
|
93
100
|
if (oauth) return new ApiError(status, oauth.error, oauth.error_description ?? oauth.error, void 0, raw);
|
|
94
101
|
return new ApiError(status, "UNKNOWN", `HTTP ${status}`, void 0, raw);
|
|
@@ -467,7 +474,8 @@ const apiLogListQuerySchema = z.object({
|
|
|
467
474
|
principalType: z.union([z.string(), z.array(z.string())]).transform((value) => (Array.isArray(value) ? value : [value]).flatMap((part) => part.split(",")).map((part) => part.trim()).filter((part) => part.length > 0)).pipe(z.array(apiLogPrincipalTypeSchema).min(1)).optional().describe("호출 주체 유형 필터. 여러 개는 쉼표로 구분한다 (예: `PAT,CLIENT`). 파싱 결과는 배열로 정규화된다"),
|
|
468
475
|
principalId: z.string().optional().describe("호출 주체 ID 필터"),
|
|
469
476
|
status: apiLogStatusFilterSchema.optional(),
|
|
470
|
-
q: z.string().optional().describe("경로 부분 일치
|
|
477
|
+
q: z.string().optional().describe("경로 부분 일치 검색어. 리소스 id(예: `ord_…`)를 넣으면 그 리소스를 건드린 요청만 남으므로 웹훅 전송 기록의 `resource.id`와 짝지어 쓴다"),
|
|
478
|
+
traceId: z.string().optional().describe("추적 ID 필터(정확히 일치). 에러 응답 `error.traceId` 값을 그대로 넣어 그 요청 한 건을 찾는다"),
|
|
471
479
|
cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
|
|
472
480
|
limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)")
|
|
473
481
|
});
|
|
@@ -1180,6 +1188,44 @@ const webhookDeliveryErrorCodeSchema = z.enum([
|
|
|
1180
1188
|
"NON_2XX",
|
|
1181
1189
|
"WEBHOOK_SUSPENDED"
|
|
1182
1190
|
]).describe("전송 실패 사유. `TIMEOUT`=10초 안에 응답 없음, `CONNECTION_FAILED`=연결 실패(DNS·TLS 포함), `BLOCKED_ADDRESS`=사설·루프백 등 전송이 허용되지 않는 주소, `NON_2XX`=2xx가 아닌 응답(리다이렉트 포함), `WEBHOOK_SUSPENDED`=구독 정지로 대기 중인 전송이 종료됨");
|
|
1191
|
+
/**
|
|
1192
|
+
* 실패 원인 분류의 **현재** 값. 응답 스키마(`webhookFailureReasonSchema`)는 문자열로 열려 있다 —
|
|
1193
|
+
* 서버가 값을 더해도 이전 SDK가 목록 파싱에 실패하지 않게 한다(택배 추적 `stage`와 같은 이유).
|
|
1194
|
+
* 모르는 값은 `errorCode`로 판단한다.
|
|
1195
|
+
*/
|
|
1196
|
+
const WEBHOOK_FAILURE_REASONS = [
|
|
1197
|
+
"DNS",
|
|
1198
|
+
"TLS",
|
|
1199
|
+
"TIMEOUT",
|
|
1200
|
+
"CONNECTION",
|
|
1201
|
+
"HTTP_4XX",
|
|
1202
|
+
"HTTP_5XX",
|
|
1203
|
+
"HTTP_OTHER",
|
|
1204
|
+
"SSRF_BLOCKED",
|
|
1205
|
+
"SUSPENDED"
|
|
1206
|
+
];
|
|
1207
|
+
const webhookFailureReasonSchema = z.string().describe("실패 원인 분류(진단용). 현재 값은 `DNS`=호스트 이름을 주소로 바꾸지 못함, `TLS`=인증서·핸드셰이크 실패, `TIMEOUT`=10초 안에 응답 없음, `CONNECTION`=연결 거부·끊김, `HTTP_4XX`·`HTTP_5XX`=그 대역의 응답, `HTTP_OTHER`=2xx·4xx·5xx가 아닌 응답(리다이렉트 등), `SSRF_BLOCKED`=사설·루프백 등 전송이 허용되지 않는 주소, `SUSPENDED`=구독 정지로 대기 중인 전송이 종료됨. `errorCode`보다 잘게 나눈 값이며 둘은 함께 쓸 수 있다. 값이 추가될 수 있으므로 모르는 값은 `errorCode`로 판단한다");
|
|
1208
|
+
/**
|
|
1209
|
+
* 대상 리소스 종류의 **현재** 값. 응답 스키마는 문자열로 열려 있다(새 이벤트가 새 리소스를 가리킬 수 있다).
|
|
1210
|
+
*/
|
|
1211
|
+
const WEBHOOK_RESOURCE_TYPES = [
|
|
1212
|
+
"ORDER",
|
|
1213
|
+
"CLAIM",
|
|
1214
|
+
"PRODUCT",
|
|
1215
|
+
"REVIEW",
|
|
1216
|
+
"INQUIRY"
|
|
1217
|
+
];
|
|
1218
|
+
const webhookResourceTypeSchema = z.string().describe("이벤트가 가리키는 리소스 종류. 현재 값은 `ORDER`·`CLAIM`·`PRODUCT`·`REVIEW`·`INQUIRY`이고 값이 추가될 수 있다");
|
|
1219
|
+
/** 이벤트가 가리키는 대상 리소스 — 전송 기록을 주문·상품과 잇는 키 */
|
|
1220
|
+
const webhookDeliveryResourceSchema = z.object({
|
|
1221
|
+
type: webhookResourceTypeSchema,
|
|
1222
|
+
id: z.string().describe("리소스 ID. 전송 기록 조회의 `resourceId`, API 로그 조회의 `q`로 그대로 넣을 수 있다")
|
|
1223
|
+
});
|
|
1224
|
+
/** 발송 요청 헤더 한 줄 (값 마스킹) */
|
|
1225
|
+
const webhookRequestHeaderSchema = z.object({
|
|
1226
|
+
name: z.string().describe("헤더 이름"),
|
|
1227
|
+
value: z.string().nullable().describe("헤더 값. 서명(`Sayren-Signature`)처럼 비밀이 섞이는 헤더는 이름만 주고 값은 null이다")
|
|
1228
|
+
});
|
|
1183
1229
|
/** 웹훅 전송 기록 한 건 (전송 기록 조회 항목) */
|
|
1184
1230
|
const webhookDeliverySchema = z.object({
|
|
1185
1231
|
deliveryId: z.string().describe("전송 기록 ID. 수신 요청의 `Sayren-Delivery-Id` 헤더 값"),
|
|
@@ -1189,8 +1235,10 @@ const webhookDeliverySchema = z.object({
|
|
|
1189
1235
|
status: webhookDeliveryStatusSchema,
|
|
1190
1236
|
responseStatusCode: z.number().int().nullable().describe("마지막 시도의 HTTP 응답 코드. 미시도·연결 실패·타임아웃·차단이면 null"),
|
|
1191
1237
|
responseTimeMs: z.number().int().nullable().describe("마지막 시도의 응답 시간(ms). 미시도·연결 실패면 null"),
|
|
1192
|
-
responseBodyExcerpt: z.string().nullable().describe("마지막 시도의 응답 본문 앞부분(최대
|
|
1238
|
+
responseBodyExcerpt: z.string().nullable().describe("마지막 시도의 응답 본문 앞부분(최대 4,096자). 응답이 없으면 null. 가린 뒤에 자른다. 키 이름에 `authorization`·`token`·`secret`·`password`·`key`·`signature`·`credential`·`cookie`가 **들어 있으면**(부분 일치, 대소문자 무시. 예: `apiKey`·`access_token`·`keyword`) 그 값을 `***`로 가린다. 값이 객체·배열이면 통째로 가린다. 평문 `Authorization: …` 같은 헤더 줄, `Bearer <토큰>`, 쿼리 형식 `access_token=…`, 끝에서 잘려 닫히지 않은 값도 가린다"),
|
|
1193
1239
|
errorCode: webhookDeliveryErrorCodeSchema.nullable().describe("마지막 시도의 실패 사유. 성공했거나 미시도면 null"),
|
|
1240
|
+
failureReason: webhookFailureReasonSchema.nullable().describe("마지막 시도의 실패 원인 분류. 성공했거나 미시도면 null. `errorCode`를 더 잘게 나눈 진단 값이다"),
|
|
1241
|
+
resource: webhookDeliveryResourceSchema.nullable().describe("이벤트가 가리키는 대상 리소스. 리소스를 특정할 수 없는 이벤트면 null. 이 값으로 전송 기록(`resourceId`)과 API 로그(`q`)를 오갈 수 있다"),
|
|
1194
1242
|
attemptCount: z.number().int().min(0).describe("지금까지의 시도 횟수. 최초 시도 1회 + 재시도 최대 4회"),
|
|
1195
1243
|
createdAt: z.string().describe("전송 기록이 적재된 일시 (ISO 8601)"),
|
|
1196
1244
|
attemptedAt: z.string().nullable().describe("마지막 시도 일시 (ISO 8601). 미시도면 null"),
|
|
@@ -1198,9 +1246,20 @@ const webhookDeliverySchema = z.object({
|
|
|
1198
1246
|
redeliveryOf: z.string().nullable().describe("수동 재전송으로 생긴 기록이면 원본 전송 기록 ID. 아니면 null"),
|
|
1199
1247
|
redeliveredAs: z.string().nullable().describe("이 기록을 원본으로 수동 재전송해 생긴 기록의 전송 기록 ID. 아직 재전송하지 않았으면 null. 재전송은 원본당 1회다")
|
|
1200
1248
|
});
|
|
1249
|
+
/** 발송 본문 최대 노출 길이(바이트). 넘으면 잘라 주고 `payloadTruncated`가 true다 */
|
|
1250
|
+
const WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES = 16384;
|
|
1251
|
+
/** 웹훅 전송 기록 상세 — `GET /webhooks/{id}/deliveries/{deliveryId}`. 목록 항목 + 요청 본문·헤더 */
|
|
1252
|
+
const webhookDeliveryDetailSchema = webhookDeliverySchema.extend({
|
|
1253
|
+
payload: z.string().describe(`수신 서버로 보낸 요청 본문 그대로(JSON 문자열). 서명은 이 문자열을 대상으로 계산한다. 최대 ${WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES / 1024}KB까지 주고 넘으면 잘라 준다`),
|
|
1254
|
+
payloadTruncated: z.boolean().describe("본문이 길어서 잘렸으면 true. true면 `payload`는 유효한 JSON이 아니다"),
|
|
1255
|
+
payloadMasked: z.boolean().describe("민감 키 마스킹(`responseBodyExcerpt`와 같은 키 이름 규칙)이 본문을 바꿨으면 true. true면 `payload`는 보낸 본문과 달라 서명을 맞춰 볼 수 없다. 이벤트 본문에는 보통 민감 키가 없어 false다"),
|
|
1256
|
+
requestHeaders: z.array(webhookRequestHeaderSchema).describe("발송 요청에 실은 헤더. 값은 전송 시점 그대로이나 서명 헤더는 이름만 주고 값은 null이다. `Content-Length`는 실제로 보낸 본문(마스킹·자르기 전)의 바이트 수다. 매 시도가 같은 헤더 집합을 쓰고 서명·타임스탬프만 달라진다")
|
|
1257
|
+
});
|
|
1201
1258
|
/** 전송 기록 조회 쿼리 — `GET /webhooks/{id}/deliveries` */
|
|
1202
1259
|
const webhookDeliveryListQuerySchema = z.object({
|
|
1203
1260
|
status: webhookDeliveryStatusSchema.optional().describe("전송 상태 필터. 생략하면 전체"),
|
|
1261
|
+
eventType: eventTypeSchema.optional().describe("이벤트 타입 필터. 생략하면 전체"),
|
|
1262
|
+
resourceId: z.string().optional().describe("대상 리소스 ID 필터(정확히 일치). 주문·클레임·상품·리뷰·문의 id를 넣으면 그 리소스의 이벤트만 남는다. 같은 id로 API 로그를 `q`로 검색하면 그 리소스를 건드린 API 요청을 볼 수 있다"),
|
|
1204
1263
|
limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50). 최신 적재순으로 반환하며 보관 기간은 30일이다")
|
|
1205
1264
|
});
|
|
1206
1265
|
/** 실패 건 일괄 재전송 응답 — `POST /webhooks/{id}/deliveries/redeliver-failed` */
|
|
@@ -1210,7 +1269,11 @@ const webhookTestRequestSchema = z.object({ eventType: eventTypeSchema.describe(
|
|
|
1210
1269
|
const webhookTestResultSchema = z.object({
|
|
1211
1270
|
responseStatusCode: z.number().int().nullable().describe("수신 서버의 HTTP 응답 코드. 연결 실패·타임아웃·차단이면 null"),
|
|
1212
1271
|
responseTimeMs: z.number().int().nullable().describe("응답 시간(ms). 연결 실패면 null"),
|
|
1213
|
-
errorCode: webhookDeliveryErrorCodeSchema.nullable().describe("실패 사유. 2xx 응답이면 null")
|
|
1272
|
+
errorCode: webhookDeliveryErrorCodeSchema.nullable().describe("실패 사유. 2xx 응답이면 null"),
|
|
1273
|
+
failureReason: webhookFailureReasonSchema.nullable().describe("실패 원인 분류. 2xx 응답이면 null"),
|
|
1274
|
+
responseBodyExcerpt: z.string().nullable().describe("응답 본문 앞부분(최대 4,096자). 규칙은 전송 기록의 `responseBodyExcerpt`와 같다. 응답이 없으면 null"),
|
|
1275
|
+
requestHeaders: z.array(webhookRequestHeaderSchema).describe("보낸 요청 헤더. 서명 헤더는 이름만 주고 값은 null이다"),
|
|
1276
|
+
payload: z.string().describe("보낸 요청 본문 그대로(JSON 문자열). 샘플 이벤트다")
|
|
1214
1277
|
});
|
|
1215
1278
|
const webhookRequestSchema = z.object({
|
|
1216
1279
|
url: z.url().startsWith("https://", "웹훅 URL은 HTTPS만 허용됩니다"),
|
|
@@ -3392,6 +3455,12 @@ get: (params) => storeHttp.request("GET", "/sales-report", salesReportSchema, {
|
|
|
3392
3455
|
/** 전송 기록 (최신 적재순, 기본 50건·최대 100건, 보관 30일) */
|
|
3393
3456
|
listDeliveries: (webhookId, params) => storeHttp.request("GET", path`/webhooks/${webhookId}/deliveries`, z.array(webhookDeliverySchema), { query: params }),
|
|
3394
3457
|
/**
|
|
3458
|
+
* 전송 기록 한 건의 상세. 목록 항목에 보낸 요청 본문(최대 16KB)과 요청 헤더가 더해진다.
|
|
3459
|
+
* 실패 원인 분류(`failureReason`)·응답 본문(`responseBodyExcerpt`)으로 원인을 찾고,
|
|
3460
|
+
* `resource.id`를 API 로그 조회의 `q`로 넘겨 같은 리소스의 API 요청과 맞춰 본다.
|
|
3461
|
+
*/
|
|
3462
|
+
getDelivery: (webhookId, deliveryId) => storeHttp.request("GET", path`/webhooks/${webhookId}/deliveries/${deliveryId}`, webhookDeliveryDetailSchema),
|
|
3463
|
+
/**
|
|
3395
3464
|
* FAILED 전송 기록 한 건을 같은 eventId로 다시 보낸다(202). 새로 적재된 기록을 돌려주며
|
|
3396
3465
|
* `redeliveryOf`가 원본 deliveryId다. 원본이 FAILED가 아니면 409 `DELIVERY_NOT_FAILED`,
|
|
3397
3466
|
* 원본이 이미 재전송됐으면 409 `DELIVERY_ALREADY_REDELIVERED`(원본당 1회, 원본의 `redeliveredAs` 참고),
|
|
@@ -3831,4 +3900,4 @@ function createStoreSession(options) {
|
|
|
3831
3900
|
};
|
|
3832
3901
|
}
|
|
3833
3902
|
//#endregion
|
|
3834
|
-
export { ApiError, CASH_RECEIPT_STATUS_VALUES, 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, REFUND_POLICY_DEFAULTS, REMOTE_AREA_ZIP_RANGES, RESERVED_STORE_CODES, SHIPPING_POLICY_DEFAULTS, 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, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, consentActionSchema, consentKindSchema, consentSourceSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, 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, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedRefundBase, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, quoteDelivery, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, resolveRefundPolicy, resolveShippingPolicy, reviewListQuerySchema, reviewReportResultSchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, scopeAccessSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingPolicyPatchSchema, shippingPolicySchema, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeTokenResponseSchema, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, 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 };
|
|
3903
|
+
export { ApiError, CASH_RECEIPT_STATUS_VALUES, 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, REFUND_POLICY_DEFAULTS, REMOTE_AREA_ZIP_RANGES, RESERVED_STORE_CODES, SHIPPING_POLICY_DEFAULTS, 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_FAILURE_REASONS, WEBHOOK_HEADERS, WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES, WEBHOOK_RESOURCE_TYPES, 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, cashReceiptSchema, categoryAttributeSchema, categoryCreateRequestSchema, categoryDeleteQuerySchema, categoryDeleteStrategySchema, categoryListQuerySchema, categoryPatchRequestSchema, categoryProductSortSchema, categorySchema, categorySearchResultSchema, categoryTreeNodeSchema, categoryWithPathSchema, changeTypeSchema, claimDetailSchema, claimHoldResultSchema, claimListQuerySchema, claimReasonSchema, claimReturnAddressSchema, claimSchema, claimStatusSchema, claimTypeSchema, claimWebhookEventDataSchema, claimWebhookEventSchema, clientCredentialsTokenResponseSchema, consentActionSchema, consentKindSchema, consentSourceSchema, createPkcePair, createStoreClient, createStoreSession, customerAddressSchema, customerConsentListQuerySchema, customerConsentSchema, customerConsentStateSchema, customerConsentsSchema, customerDetailSchema, customerInquiryCategorySchema, customerInquiryListQuerySchema, customerListQuerySchema, customerOrderSchema, customerSortSchema, customerStatsSchema, customerSummarySchema, customerWithdrawalBlockedDetailsSchema, deliveryBundleKeyOf, deliveryFeeWaiverSchema, 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, policyDocumentUrlSchema, policyVersionSchema, portOneChannelSchema, portOneCredentialsInputSchema, productCreateRequestSchema, productImageRejection, productImageUrlSchema, productListQuerySchema, productOutOfStockWebhookEventDataSchema, productOutOfStockWebhookEventSchema, productPatchRequestSchema, productRefundPolicyOverride, productSchema, productSortSchema, productStatusSchema, productSummarySchema, productVariantRequestSchema, productVariantSchema, proratedRefundBase, purchaseDecisionExtendResultSchema, purchaseDecisionRequestResultSchema, quoteDelivery, refreshUserToken, refundPolicyPatchSchema, refundPolicySchema, rejectClaimRequestSchema, remoteAreaLabelOf, remoteAreaOf, remoteAreaSchema, remoteSurchargeOf, resolveRefundPolicy, resolveShippingPolicy, reviewListQuerySchema, reviewReportResultSchema, reviewSchema, reviewSortSchema, reviewWebhookEventDataSchema, reviewWebhookEventSchema, salesReportGroupBySchema, salesReportQuerySchema, salesReportRowSchema, salesReportSchema, salesTotalsSchema, saveLoginProviderRequestSchema, scopeAccessSchema, sellerAddressListQuerySchema, sellerAddressRequestSchema, sellerAddressSchema, sellerCustomerInquirySchema, settlementDetailQuerySchema, settlementDetailSchema, settlementListQuerySchema, settlementStatusSchema, settlementSummarySchema, settlementWithDetailsSchema, shippingAddressSchema, shippingPolicyPatchSchema, shippingPolicySchema, storeCodeSchema, storeMemberRoleUpdatedSchema, storeMemberSchema, storeRoleSchema, storeSchema, storeScopeResourceSchema, storeTokenResponseSchema, tossPaymentsCredentialsInputSchema, trackingStageResponseSchema, trackingUpdateResultSchema, updateLoginProviderRequestSchema, updateLoginSettingsRequestSchema, updatePaymentProviderRequestSchema, updatePaymentSettingsRequestSchema, updateStoreRequestSchema, uploadExtensionOf, uploadPurposeSchema, uploadRejection, uploadRequestSchema, uploadTicketSchema, upsertPortOneProviderRequestSchema, upsertTossPaymentsProviderRequestSchema, userTokenResponseSchema, variantStockRequestSchema, variantStockSchema, verifyPaymentProviderRequestSchema, webhookCreatedSchema, webhookDeliveryDetailSchema, webhookDeliveryErrorCodeSchema, webhookDeliveryListQuerySchema, webhookDeliveryResourceSchema, webhookDeliverySchema, webhookDeliveryStatusSchema, webhookEventSchema, webhookFailureReasonSchema, webhookRedeliverFailedResultSchema, webhookRequestHeaderSchema, webhookRequestSchema, webhookResourceTypeSchema, webhookSchema, webhookSecretRotatedSchema, webhookStatusSchema, webhookTestRequestSchema, webhookTestResultSchema, withdrawCustomerRequestSchema };
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -101,6 +101,7 @@ import {
|
|
|
101
101
|
type WebhookRequest,
|
|
102
102
|
type WebhookTestRequest,
|
|
103
103
|
webhookCreatedSchema,
|
|
104
|
+
webhookDeliveryDetailSchema,
|
|
104
105
|
webhookDeliverySchema,
|
|
105
106
|
webhookRedeliverFailedResultSchema,
|
|
106
107
|
webhookRequestSchema,
|
|
@@ -984,6 +985,17 @@ export function createStoreClient(options: StoreClientOptions) {
|
|
|
984
985
|
z.array(webhookDeliverySchema),
|
|
985
986
|
{ query: params as Query },
|
|
986
987
|
),
|
|
988
|
+
/**
|
|
989
|
+
* 전송 기록 한 건의 상세. 목록 항목에 보낸 요청 본문(최대 16KB)과 요청 헤더가 더해진다.
|
|
990
|
+
* 실패 원인 분류(`failureReason`)·응답 본문(`responseBodyExcerpt`)으로 원인을 찾고,
|
|
991
|
+
* `resource.id`를 API 로그 조회의 `q`로 넘겨 같은 리소스의 API 요청과 맞춰 본다.
|
|
992
|
+
*/
|
|
993
|
+
getDelivery: (webhookId: string, deliveryId: string) =>
|
|
994
|
+
storeHttp.request(
|
|
995
|
+
"GET",
|
|
996
|
+
path`/webhooks/${webhookId}/deliveries/${deliveryId}`,
|
|
997
|
+
webhookDeliveryDetailSchema,
|
|
998
|
+
),
|
|
987
999
|
/**
|
|
988
1000
|
* FAILED 전송 기록 한 건을 같은 eventId로 다시 보낸다(202). 새로 적재된 기록을 돌려주며
|
|
989
1001
|
* `redeliveryOf`가 원본 deliveryId다. 원본이 FAILED가 아니면 409 `DELIVERY_NOT_FAILED`,
|
package/src/http.ts
CHANGED
|
@@ -5,6 +5,11 @@ export const errorDetailSchema = z.object({
|
|
|
5
5
|
code: z.string(),
|
|
6
6
|
message: z.string(),
|
|
7
7
|
traceId: z.string().optional(),
|
|
8
|
+
/**
|
|
9
|
+
* 이 에러 코드를 설명하는 문서 URL(선택). 서버가 코드별 매핑을 가진 코드에만 실린다 —
|
|
10
|
+
* 없으면 필드가 아예 없으므로 소비측은 있을 때만 쓴다
|
|
11
|
+
*/
|
|
12
|
+
docs: z.url().optional().catch(undefined),
|
|
8
13
|
/**
|
|
9
14
|
* 에러 코드별 보조 데이터(선택). 예: 관리 API `LIVE_GATE_NOT_MET`·`LIVE_PAYMENTS_DISABLED`의
|
|
10
15
|
* `{ conditions: LiveGateCondition[] }`. 형태는 에러 코드마다 다르므로 소비측이 코드별 스키마로 다시 파싱한다
|
|
@@ -50,6 +55,8 @@ export class ApiError extends Error {
|
|
|
50
55
|
public readonly body?: unknown,
|
|
51
56
|
/** 엔벨로프 `$.error.details` — 에러 코드별 보조 데이터. 없으면 undefined */
|
|
52
57
|
public readonly details?: Record<string, unknown>,
|
|
58
|
+
/** 엔벨로프 `$.error.docs` — 이 에러 코드를 설명하는 문서 URL. 매핑이 없으면 undefined */
|
|
59
|
+
public readonly docs?: string,
|
|
53
60
|
) {
|
|
54
61
|
super(message);
|
|
55
62
|
this.name = "ApiError";
|
|
@@ -68,7 +75,15 @@ export function toApiError(status: number, raw: unknown): ApiError {
|
|
|
68
75
|
? envelope.data.error
|
|
69
76
|
: (errorDetailSchema.safeParse(raw).data ?? null);
|
|
70
77
|
if (detail) {
|
|
71
|
-
return new ApiError(
|
|
78
|
+
return new ApiError(
|
|
79
|
+
status,
|
|
80
|
+
detail.code,
|
|
81
|
+
detail.message,
|
|
82
|
+
detail.traceId,
|
|
83
|
+
raw,
|
|
84
|
+
detail.details,
|
|
85
|
+
detail.docs,
|
|
86
|
+
);
|
|
72
87
|
}
|
|
73
88
|
const oauth = envelope.success ? null : oauthErrorSchema.safeParse(raw).data;
|
|
74
89
|
if (oauth) {
|
package/src/schemas/api-log.ts
CHANGED
|
@@ -68,7 +68,18 @@ export const apiLogListQuerySchema = z.object({
|
|
|
68
68
|
),
|
|
69
69
|
principalId: z.string().optional().describe("호출 주체 ID 필터"),
|
|
70
70
|
status: apiLogStatusFilterSchema.optional(),
|
|
71
|
-
q: z
|
|
71
|
+
q: z
|
|
72
|
+
.string()
|
|
73
|
+
.optional()
|
|
74
|
+
.describe(
|
|
75
|
+
"경로 부분 일치 검색어. 리소스 id(예: `ord_…`)를 넣으면 그 리소스를 건드린 요청만 남으므로 웹훅 전송 기록의 `resource.id`와 짝지어 쓴다",
|
|
76
|
+
),
|
|
77
|
+
traceId: z
|
|
78
|
+
.string()
|
|
79
|
+
.optional()
|
|
80
|
+
.describe(
|
|
81
|
+
"추적 ID 필터(정확히 일치). 에러 응답 `error.traceId` 값을 그대로 넣어 그 요청 한 건을 찾는다",
|
|
82
|
+
),
|
|
72
83
|
cursor: z.string().optional().describe("이전 응답의 `nextCursor`. 생략하면 가장 최신부터"),
|
|
73
84
|
limit: z.coerce.number().int().min(1).max(100).optional().describe("최대 건수 (1~100, 기본 50)"),
|
|
74
85
|
});
|
package/src/schemas/misc.ts
CHANGED
|
@@ -208,6 +208,71 @@ export const webhookDeliveryErrorCodeSchema = z
|
|
|
208
208
|
);
|
|
209
209
|
export type WebhookDeliveryErrorCode = z.infer<typeof webhookDeliveryErrorCodeSchema>;
|
|
210
210
|
|
|
211
|
+
/**
|
|
212
|
+
* 실패 원인 분류의 **현재** 값. 응답 스키마(`webhookFailureReasonSchema`)는 문자열로 열려 있다 —
|
|
213
|
+
* 서버가 값을 더해도 이전 SDK가 목록 파싱에 실패하지 않게 한다(택배 추적 `stage`와 같은 이유).
|
|
214
|
+
* 모르는 값은 `errorCode`로 판단한다.
|
|
215
|
+
*/
|
|
216
|
+
export const WEBHOOK_FAILURE_REASONS = [
|
|
217
|
+
"DNS",
|
|
218
|
+
"TLS",
|
|
219
|
+
"TIMEOUT",
|
|
220
|
+
"CONNECTION",
|
|
221
|
+
"HTTP_4XX",
|
|
222
|
+
"HTTP_5XX",
|
|
223
|
+
"HTTP_OTHER",
|
|
224
|
+
"SSRF_BLOCKED",
|
|
225
|
+
"SUSPENDED",
|
|
226
|
+
] as const;
|
|
227
|
+
/** 알려진 실패 원인. 응답에는 이 밖의 문자열이 올 수 있다 */
|
|
228
|
+
export type WebhookFailureReason = (typeof WEBHOOK_FAILURE_REASONS)[number];
|
|
229
|
+
|
|
230
|
+
export const webhookFailureReasonSchema = z
|
|
231
|
+
.string()
|
|
232
|
+
.describe(
|
|
233
|
+
"실패 원인 분류(진단용). 현재 값은 `DNS`=호스트 이름을 주소로 바꾸지 못함, `TLS`=인증서·핸드셰이크 실패, " +
|
|
234
|
+
"`TIMEOUT`=10초 안에 응답 없음, `CONNECTION`=연결 거부·끊김, `HTTP_4XX`·`HTTP_5XX`=그 대역의 응답, " +
|
|
235
|
+
"`HTTP_OTHER`=2xx·4xx·5xx가 아닌 응답(리다이렉트 등), `SSRF_BLOCKED`=사설·루프백 등 전송이 허용되지 않는 주소, " +
|
|
236
|
+
"`SUSPENDED`=구독 정지로 대기 중인 전송이 종료됨. `errorCode`보다 잘게 나눈 값이며 둘은 함께 쓸 수 있다. " +
|
|
237
|
+
"값이 추가될 수 있으므로 모르는 값은 `errorCode`로 판단한다",
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 대상 리소스 종류의 **현재** 값. 응답 스키마는 문자열로 열려 있다(새 이벤트가 새 리소스를 가리킬 수 있다).
|
|
242
|
+
*/
|
|
243
|
+
export const WEBHOOK_RESOURCE_TYPES = ["ORDER", "CLAIM", "PRODUCT", "REVIEW", "INQUIRY"] as const;
|
|
244
|
+
/** 알려진 리소스 종류. 응답에는 이 밖의 문자열이 올 수 있다 */
|
|
245
|
+
export type WebhookResourceType = (typeof WEBHOOK_RESOURCE_TYPES)[number];
|
|
246
|
+
|
|
247
|
+
export const webhookResourceTypeSchema = z
|
|
248
|
+
.string()
|
|
249
|
+
.describe(
|
|
250
|
+
"이벤트가 가리키는 리소스 종류. 현재 값은 `ORDER`·`CLAIM`·`PRODUCT`·`REVIEW`·`INQUIRY`이고 값이 추가될 수 있다",
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
/** 이벤트가 가리키는 대상 리소스 — 전송 기록을 주문·상품과 잇는 키 */
|
|
254
|
+
export const webhookDeliveryResourceSchema = z.object({
|
|
255
|
+
type: webhookResourceTypeSchema,
|
|
256
|
+
id: z
|
|
257
|
+
.string()
|
|
258
|
+
.describe(
|
|
259
|
+
"리소스 ID. 전송 기록 조회의 `resourceId`, API 로그 조회의 `q`로 그대로 넣을 수 있다",
|
|
260
|
+
),
|
|
261
|
+
});
|
|
262
|
+
export type WebhookDeliveryResource = z.infer<typeof webhookDeliveryResourceSchema>;
|
|
263
|
+
|
|
264
|
+
/** 발송 요청 헤더 한 줄 (값 마스킹) */
|
|
265
|
+
export const webhookRequestHeaderSchema = z.object({
|
|
266
|
+
name: z.string().describe("헤더 이름"),
|
|
267
|
+
value: z
|
|
268
|
+
.string()
|
|
269
|
+
.nullable()
|
|
270
|
+
.describe(
|
|
271
|
+
"헤더 값. 서명(`Sayren-Signature`)처럼 비밀이 섞이는 헤더는 이름만 주고 값은 null이다",
|
|
272
|
+
),
|
|
273
|
+
});
|
|
274
|
+
export type WebhookRequestHeader = z.infer<typeof webhookRequestHeaderSchema>;
|
|
275
|
+
|
|
211
276
|
/** 웹훅 전송 기록 한 건 (전송 기록 조회 항목) */
|
|
212
277
|
export const webhookDeliverySchema = z.object({
|
|
213
278
|
deliveryId: z.string().describe("전송 기록 ID. 수신 요청의 `Sayren-Delivery-Id` 헤더 값"),
|
|
@@ -232,10 +297,27 @@ export const webhookDeliverySchema = z.object({
|
|
|
232
297
|
responseBodyExcerpt: z
|
|
233
298
|
.string()
|
|
234
299
|
.nullable()
|
|
235
|
-
.describe(
|
|
300
|
+
.describe(
|
|
301
|
+
"마지막 시도의 응답 본문 앞부분(최대 4,096자). 응답이 없으면 null. 가린 뒤에 자른다. " +
|
|
302
|
+
"키 이름에 `authorization`·`token`·`secret`·`password`·`key`·`signature`·`credential`·`cookie`가 " +
|
|
303
|
+
"**들어 있으면**(부분 일치, 대소문자 무시. 예: `apiKey`·`access_token`·`keyword`) 그 값을 `***`로 가린다. " +
|
|
304
|
+
"값이 객체·배열이면 통째로 가린다. 평문 `Authorization: …` 같은 헤더 줄, `Bearer <토큰>`, " +
|
|
305
|
+
"쿼리 형식 `access_token=…`, 끝에서 잘려 닫히지 않은 값도 가린다",
|
|
306
|
+
),
|
|
236
307
|
errorCode: webhookDeliveryErrorCodeSchema
|
|
237
308
|
.nullable()
|
|
238
309
|
.describe("마지막 시도의 실패 사유. 성공했거나 미시도면 null"),
|
|
310
|
+
failureReason: webhookFailureReasonSchema
|
|
311
|
+
.nullable()
|
|
312
|
+
.describe(
|
|
313
|
+
"마지막 시도의 실패 원인 분류. 성공했거나 미시도면 null. `errorCode`를 더 잘게 나눈 진단 값이다",
|
|
314
|
+
),
|
|
315
|
+
resource: webhookDeliveryResourceSchema
|
|
316
|
+
.nullable()
|
|
317
|
+
.describe(
|
|
318
|
+
"이벤트가 가리키는 대상 리소스. 리소스를 특정할 수 없는 이벤트면 null. " +
|
|
319
|
+
"이 값으로 전송 기록(`resourceId`)과 API 로그(`q`)를 오갈 수 있다",
|
|
320
|
+
),
|
|
239
321
|
attemptCount: z
|
|
240
322
|
.number()
|
|
241
323
|
.int()
|
|
@@ -260,9 +342,47 @@ export const webhookDeliverySchema = z.object({
|
|
|
260
342
|
});
|
|
261
343
|
export type WebhookDelivery = z.infer<typeof webhookDeliverySchema>;
|
|
262
344
|
|
|
345
|
+
/** 발송 본문 최대 노출 길이(바이트). 넘으면 잘라 주고 `payloadTruncated`가 true다 */
|
|
346
|
+
export const WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES = 16 * 1024;
|
|
347
|
+
|
|
348
|
+
/** 웹훅 전송 기록 상세 — `GET /webhooks/{id}/deliveries/{deliveryId}`. 목록 항목 + 요청 본문·헤더 */
|
|
349
|
+
export const webhookDeliveryDetailSchema = webhookDeliverySchema.extend({
|
|
350
|
+
payload: z
|
|
351
|
+
.string()
|
|
352
|
+
.describe(
|
|
353
|
+
"수신 서버로 보낸 요청 본문 그대로(JSON 문자열). 서명은 이 문자열을 대상으로 계산한다. " +
|
|
354
|
+
`최대 ${WEBHOOK_PAYLOAD_EXCERPT_MAX_BYTES / 1024}KB까지 주고 넘으면 잘라 준다`,
|
|
355
|
+
),
|
|
356
|
+
payloadTruncated: z
|
|
357
|
+
.boolean()
|
|
358
|
+
.describe("본문이 길어서 잘렸으면 true. true면 `payload`는 유효한 JSON이 아니다"),
|
|
359
|
+
payloadMasked: z
|
|
360
|
+
.boolean()
|
|
361
|
+
.describe(
|
|
362
|
+
"민감 키 마스킹(`responseBodyExcerpt`와 같은 키 이름 규칙)이 본문을 바꿨으면 true. " +
|
|
363
|
+
"true면 `payload`는 보낸 본문과 달라 서명을 맞춰 볼 수 없다. 이벤트 본문에는 보통 민감 키가 없어 false다",
|
|
364
|
+
),
|
|
365
|
+
requestHeaders: z
|
|
366
|
+
.array(webhookRequestHeaderSchema)
|
|
367
|
+
.describe(
|
|
368
|
+
"발송 요청에 실은 헤더. 값은 전송 시점 그대로이나 서명 헤더는 이름만 주고 값은 null이다. " +
|
|
369
|
+
"`Content-Length`는 실제로 보낸 본문(마스킹·자르기 전)의 바이트 수다. " +
|
|
370
|
+
"매 시도가 같은 헤더 집합을 쓰고 서명·타임스탬프만 달라진다",
|
|
371
|
+
),
|
|
372
|
+
});
|
|
373
|
+
export type WebhookDeliveryDetail = z.infer<typeof webhookDeliveryDetailSchema>;
|
|
374
|
+
|
|
263
375
|
/** 전송 기록 조회 쿼리 — `GET /webhooks/{id}/deliveries` */
|
|
264
376
|
export const webhookDeliveryListQuerySchema = z.object({
|
|
265
377
|
status: webhookDeliveryStatusSchema.optional().describe("전송 상태 필터. 생략하면 전체"),
|
|
378
|
+
eventType: eventTypeSchema.optional().describe("이벤트 타입 필터. 생략하면 전체"),
|
|
379
|
+
resourceId: z
|
|
380
|
+
.string()
|
|
381
|
+
.optional()
|
|
382
|
+
.describe(
|
|
383
|
+
"대상 리소스 ID 필터(정확히 일치). 주문·클레임·상품·리뷰·문의 id를 넣으면 그 리소스의 이벤트만 남는다. " +
|
|
384
|
+
"같은 id로 API 로그를 `q`로 검색하면 그 리소스를 건드린 API 요청을 볼 수 있다",
|
|
385
|
+
),
|
|
266
386
|
limit: z.coerce
|
|
267
387
|
.number()
|
|
268
388
|
.int()
|
|
@@ -299,6 +419,19 @@ export const webhookTestResultSchema = z.object({
|
|
|
299
419
|
.describe("수신 서버의 HTTP 응답 코드. 연결 실패·타임아웃·차단이면 null"),
|
|
300
420
|
responseTimeMs: z.number().int().nullable().describe("응답 시간(ms). 연결 실패면 null"),
|
|
301
421
|
errorCode: webhookDeliveryErrorCodeSchema.nullable().describe("실패 사유. 2xx 응답이면 null"),
|
|
422
|
+
failureReason: webhookFailureReasonSchema
|
|
423
|
+
.nullable()
|
|
424
|
+
.describe("실패 원인 분류. 2xx 응답이면 null"),
|
|
425
|
+
responseBodyExcerpt: z
|
|
426
|
+
.string()
|
|
427
|
+
.nullable()
|
|
428
|
+
.describe(
|
|
429
|
+
"응답 본문 앞부분(최대 4,096자). 규칙은 전송 기록의 `responseBodyExcerpt`와 같다. 응답이 없으면 null",
|
|
430
|
+
),
|
|
431
|
+
requestHeaders: z
|
|
432
|
+
.array(webhookRequestHeaderSchema)
|
|
433
|
+
.describe("보낸 요청 헤더. 서명 헤더는 이름만 주고 값은 null이다"),
|
|
434
|
+
payload: z.string().describe("보낸 요청 본문 그대로(JSON 문자열). 샘플 이벤트다"),
|
|
302
435
|
});
|
|
303
436
|
export type WebhookTestResult = z.infer<typeof webhookTestResultSchema>;
|
|
304
437
|
|