@sazito/checkout 0.4.19 → 0.4.20
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/README.md +19 -37
- package/dist/chunks/{labels-Cysz2BgA.js → labels-CwHBYso8.js} +9 -5
- package/dist/chunks/labels-CwHBYso8.js.map +1 -0
- package/dist/chunks/{labels-Cy05dLJx.cjs → labels-FNi3eq4p.cjs} +9 -5
- package/dist/chunks/labels-FNi3eq4p.cjs.map +1 -0
- package/dist/chunks/{use-checkout-wHkKNkbK.cjs → use-checkout-DsTtOAMs.cjs} +9 -4
- package/dist/chunks/use-checkout-DsTtOAMs.cjs.map +1 -0
- package/dist/chunks/{use-checkout-uWEi8iqK.js → use-checkout-OyHfWeAh.js} +10 -5
- package/dist/chunks/use-checkout-OyHfWeAh.js.map +1 -0
- package/dist/core/index.cjs +3 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +18 -4
- package/dist/core/index.d.ts +18 -4
- package/dist/core/index.js +2 -2
- package/dist/next/index.cjs +12 -6
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +10 -3
- package/dist/next/index.d.ts +10 -3
- package/dist/next/index.js +14 -8
- package/dist/next/index.js.map +1 -1
- package/dist/next/payment-return.cjs +50 -0
- package/dist/next/payment-return.cjs.map +1 -1
- package/dist/next/payment-return.d.cts +16 -2
- package/dist/next/payment-return.d.ts +16 -2
- package/dist/next/payment-return.js +49 -1
- package/dist/next/payment-return.js.map +1 -1
- package/dist/next/server.cjs +10 -0
- package/dist/next/server.cjs.map +1 -0
- package/dist/next/server.d.cts +33 -0
- package/dist/next/server.d.ts +33 -0
- package/dist/next/server.js +4 -0
- package/dist/next/server.js.map +1 -0
- package/dist/react/index.cjs +2 -2
- package/dist/react/index.d.cts +3 -2
- package/dist/react/index.d.ts +3 -2
- package/dist/react/index.js +2 -2
- package/dist/server/index.cjs +182 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +33 -0
- package/dist/server/index.d.ts +33 -0
- package/dist/server/index.js +180 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +30 -2
- package/dist/chunks/labels-Cy05dLJx.cjs.map +0 -1
- package/dist/chunks/labels-Cysz2BgA.js.map +0 -1
- package/dist/chunks/use-checkout-uWEi8iqK.js.map +0 -1
- package/dist/chunks/use-checkout-wHkKNkbK.cjs.map +0 -1
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const SAZITO_PAYMENT_STATUS_QUERY = {
|
|
4
|
+
resolution: 'sazito_payment_return',
|
|
5
|
+
paymentId: 'sazito_payment_id',
|
|
6
|
+
paymentIdentifier: 'sazito_payment_identifier'
|
|
7
|
+
};
|
|
8
|
+
/** Remove server-return credentials from the visible URL after they are read. */
|
|
9
|
+
function stripPaymentStatusReturn(url) {
|
|
10
|
+
let parsedUrl;
|
|
11
|
+
try {
|
|
12
|
+
parsedUrl = typeof url === 'string'
|
|
13
|
+
? new URL(url, 'https://checkout.sazito.invalid')
|
|
14
|
+
: new URL(url.toString());
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);
|
|
23
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
|
|
24
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier);
|
|
25
|
+
return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;
|
|
26
|
+
}
|
|
3
27
|
const SAZITO_PAYMENT_RESULT_MARKERS = [
|
|
4
28
|
'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',
|
|
5
29
|
'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',
|
|
@@ -57,6 +81,9 @@ function parsePaymentReturnUrl(url, options = {}) {
|
|
|
57
81
|
catch {
|
|
58
82
|
return undefined;
|
|
59
83
|
}
|
|
84
|
+
const statusReturn = parsePaymentStatusReturn(parsedUrl);
|
|
85
|
+
if (statusReturn)
|
|
86
|
+
return statusReturn;
|
|
60
87
|
const segments = parsedUrl.pathname
|
|
61
88
|
.split('/')
|
|
62
89
|
.filter(Boolean)
|
|
@@ -73,6 +100,27 @@ function parsePaymentReturnUrl(url, options = {}) {
|
|
|
73
100
|
}
|
|
74
101
|
return parsePaymentReturn(segments.slice(-5), searchParams, options);
|
|
75
102
|
}
|
|
103
|
+
function parsePaymentStatusReturn(url) {
|
|
104
|
+
if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
|
|
108
|
+
const identifier = url.searchParams
|
|
109
|
+
.get(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier)
|
|
110
|
+
?.trim();
|
|
111
|
+
const paymentId = Number(rawPaymentId);
|
|
112
|
+
if (!Number.isSafeInteger(paymentId) || paymentId <= 0 || !identifier) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
payment: { id: paymentId, identifier },
|
|
117
|
+
params: {
|
|
118
|
+
id: String(paymentId),
|
|
119
|
+
paymentIdentifier: identifier
|
|
120
|
+
},
|
|
121
|
+
resolution: 'status'
|
|
122
|
+
};
|
|
123
|
+
}
|
|
76
124
|
function decodePathSegment(segment) {
|
|
77
125
|
try {
|
|
78
126
|
return decodeURIComponent(segment);
|
|
@@ -93,6 +141,8 @@ function normalizeSearchParams(searchParams) {
|
|
|
93
141
|
}
|
|
94
142
|
|
|
95
143
|
exports.SAZITO_PAYMENT_RESULT_MARKERS = SAZITO_PAYMENT_RESULT_MARKERS;
|
|
144
|
+
exports.SAZITO_PAYMENT_STATUS_QUERY = SAZITO_PAYMENT_STATUS_QUERY;
|
|
96
145
|
exports.parsePaymentReturn = parsePaymentReturn;
|
|
97
146
|
exports.parsePaymentReturnUrl = parsePaymentReturnUrl;
|
|
147
|
+
exports.stripPaymentStatusReturn = stripPaymentStatusReturn;
|
|
98
148
|
//# sourceMappingURL=payment-return.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-return.cjs","sources":["../../src/core/payment-return.ts"],"sourcesContent":["import type {\n CheckoutPaymentReturn,\n PaymentReturnParserOptions,\n PaymentReturnSearchParams\n} from './types';\n\nexport const SAZITO_PAYMENT_RESULT_MARKERS = [\n 'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',\n 'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',\n 'bazarpaymentresult', 'zifypaymentresult', 'zibalpaymentresult',\n 'snapppaypaymentresult', 'torobpaypaymentresult', 'ghestapaypaymentresult',\n 'azkipaymentresult', 'digipaypaymentresult', 'greenpaypaymentresult',\n 'novapaypaymentresult', 'zarinpluspaymentresult', 'tomanpaymentresult',\n 'tarapaymentresult', 'ozonpaymentresult', 'millipaypaymentresult',\n 'ayriapaymentresult', 'sadadpaymentresult', 'freepaymentresult',\n 'paymentinplaceresult', 'cardtocardpaymentresult', 'zarinpalpaymentresult',\n 'directpayresult', 'paypingpaymentresult', 'podpaymentresult',\n 'sabinpaymentresult', 'firoozepaymentresult', 'technopaypaymentresult',\n 'buywithdigikalaresult'\n] as const;\n\n/**\n * Parse Sazito's nested payment callback path into checkout-ready data.\n * Returns undefined for ordinary checkout URLs and malformed callbacks.\n */\nexport function parsePaymentReturn(\n segments: readonly string[] | undefined,\n searchParams: PaymentReturnSearchParams = {},\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n const [resultRoute, paymentSegment, rawPaymentId, identifierSegment, rawIdentifier] =\n segments ?? [];\n const paymentId = Number(rawPaymentId);\n const identifier = rawIdentifier?.trim();\n const allowedMarkers = new Set(\n (options.gatewayResultMarkers ?? SAZITO_PAYMENT_RESULT_MARKERS)\n .map((marker) => marker.toLowerCase())\n );\n\n if (\n segments?.length !== 5 ||\n !resultRoute ||\n !allowedMarkers.has(resultRoute.toLowerCase()) ||\n paymentSegment?.toLowerCase() !== 'payment' ||\n identifierSegment?.toLowerCase() !== 'identifier' ||\n !Number.isSafeInteger(paymentId) ||\n paymentId <= 0 ||\n !identifier\n ) {\n return undefined;\n }\n\n const params = normalizeSearchParams(searchParams);\n params.id = String(paymentId);\n params.paymentIdentifier = identifier;\n\n return {\n payment: { id: paymentId, identifier },\n params\n };\n}\n\n/**\n * Parse a complete checkout URL containing Sazito's nested payment callback.\n * The callback may be mounted below any checkout base path; only its final\n * five path segments are significant.\n */\nexport function parsePaymentReturnUrl(\n url: string | URL,\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n let parsedUrl: URL;\n\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : url;\n } catch {\n return undefined;\n }\n\n const segments = parsedUrl.pathname\n .split('/')\n .filter(Boolean)\n .map(decodePathSegment);\n\n if (segments.length < 5) {\n return undefined;\n }\n\n const searchParams: Record<string, string> = {};\n for (const [key, value] of parsedUrl.searchParams) {\n // Match Next.js search-param normalization: preserve the first value.\n if (searchParams[key] === undefined) {\n searchParams[key] = value;\n }\n }\n\n return parsePaymentReturn(segments.slice(-5), searchParams, options);\n}\n\nfunction decodePathSegment(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction normalizeSearchParams(\n searchParams: PaymentReturnSearchParams\n): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(searchParams)) {\n const firstValue = Array.isArray(value) ? value[0] : value;\n if (firstValue !== undefined) {\n normalized[key] = firstValue;\n }\n }\n\n return normalized;\n}\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"payment-return.cjs","sources":["../../src/core/payment-return.ts"],"sourcesContent":["import type {\n CheckoutPaymentReturn,\n PaymentReturnParserOptions,\n PaymentReturnSearchParams\n} from './types';\n\nexport const SAZITO_PAYMENT_STATUS_QUERY = {\n resolution: 'sazito_payment_return',\n paymentId: 'sazito_payment_id',\n paymentIdentifier: 'sazito_payment_identifier'\n} as const;\n\n/** Remove server-return credentials from the visible URL after they are read. */\nexport function stripPaymentStatusReturn(url: string | URL): string | undefined {\n let parsedUrl: URL;\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : new URL(url.toString());\n } catch {\n return undefined;\n }\n\n if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {\n return undefined;\n }\n\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentId);\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier);\n return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n}\n\nexport const SAZITO_PAYMENT_RESULT_MARKERS = [\n 'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',\n 'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',\n 'bazarpaymentresult', 'zifypaymentresult', 'zibalpaymentresult',\n 'snapppaypaymentresult', 'torobpaypaymentresult', 'ghestapaypaymentresult',\n 'azkipaymentresult', 'digipaypaymentresult', 'greenpaypaymentresult',\n 'novapaypaymentresult', 'zarinpluspaymentresult', 'tomanpaymentresult',\n 'tarapaymentresult', 'ozonpaymentresult', 'millipaypaymentresult',\n 'ayriapaymentresult', 'sadadpaymentresult', 'freepaymentresult',\n 'paymentinplaceresult', 'cardtocardpaymentresult', 'zarinpalpaymentresult',\n 'directpayresult', 'paypingpaymentresult', 'podpaymentresult',\n 'sabinpaymentresult', 'firoozepaymentresult', 'technopaypaymentresult',\n 'buywithdigikalaresult'\n] as const;\n\n/**\n * Parse Sazito's nested payment callback path into checkout-ready data.\n * Returns undefined for ordinary checkout URLs and malformed callbacks.\n */\nexport function parsePaymentReturn(\n segments: readonly string[] | undefined,\n searchParams: PaymentReturnSearchParams = {},\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n const [resultRoute, paymentSegment, rawPaymentId, identifierSegment, rawIdentifier] =\n segments ?? [];\n const paymentId = Number(rawPaymentId);\n const identifier = rawIdentifier?.trim();\n const allowedMarkers = new Set(\n (options.gatewayResultMarkers ?? SAZITO_PAYMENT_RESULT_MARKERS)\n .map((marker) => marker.toLowerCase())\n );\n\n if (\n segments?.length !== 5 ||\n !resultRoute ||\n !allowedMarkers.has(resultRoute.toLowerCase()) ||\n paymentSegment?.toLowerCase() !== 'payment' ||\n identifierSegment?.toLowerCase() !== 'identifier' ||\n !Number.isSafeInteger(paymentId) ||\n paymentId <= 0 ||\n !identifier\n ) {\n return undefined;\n }\n\n const params = normalizeSearchParams(searchParams);\n params.id = String(paymentId);\n params.paymentIdentifier = identifier;\n\n return {\n payment: { id: paymentId, identifier },\n params\n };\n}\n\n/**\n * Parse a complete checkout URL containing Sazito's nested payment callback.\n * The callback may be mounted below any checkout base path; only its final\n * five path segments are significant.\n */\nexport function parsePaymentReturnUrl(\n url: string | URL,\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n let parsedUrl: URL;\n\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : url;\n } catch {\n return undefined;\n }\n\n const statusReturn = parsePaymentStatusReturn(parsedUrl);\n if (statusReturn) return statusReturn;\n\n const segments = parsedUrl.pathname\n .split('/')\n .filter(Boolean)\n .map(decodePathSegment);\n\n if (segments.length < 5) {\n return undefined;\n }\n\n const searchParams: Record<string, string> = {};\n for (const [key, value] of parsedUrl.searchParams) {\n // Match Next.js search-param normalization: preserve the first value.\n if (searchParams[key] === undefined) {\n searchParams[key] = value;\n }\n }\n\n return parsePaymentReturn(segments.slice(-5), searchParams, options);\n}\n\nfunction parsePaymentStatusReturn(url: URL): CheckoutPaymentReturn | undefined {\n if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {\n return undefined;\n }\n\n const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);\n const identifier = url.searchParams\n .get(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier)\n ?.trim();\n const paymentId = Number(rawPaymentId);\n\n if (!Number.isSafeInteger(paymentId) || paymentId <= 0 || !identifier) {\n return undefined;\n }\n\n return {\n payment: { id: paymentId, identifier },\n params: {\n id: String(paymentId),\n paymentIdentifier: identifier\n },\n resolution: 'status'\n };\n}\n\nfunction decodePathSegment(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction normalizeSearchParams(\n searchParams: PaymentReturnSearchParams\n): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(searchParams)) {\n const firstValue = Array.isArray(value) ? value[0] : value;\n if (firstValue !== undefined) {\n normalized[key] = firstValue;\n }\n }\n\n return normalized;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,14 @@ interface CheckoutPaymentReturn {
|
|
|
12
12
|
identifier: string;
|
|
13
13
|
};
|
|
14
14
|
params: Record<string, string>;
|
|
15
|
+
/**
|
|
16
|
+
* `callback` forwards gateway fields for verification. `status` is emitted
|
|
17
|
+
* by the SDK server handler after it has already verified the gateway POST,
|
|
18
|
+
* so the browser performs only an authoritative status read.
|
|
19
|
+
*/
|
|
20
|
+
resolution?: PaymentReturnResolution;
|
|
15
21
|
}
|
|
22
|
+
type PaymentReturnResolution = 'callback' | 'status';
|
|
16
23
|
/** Search-param shape exposed by current Next.js App Router pages. */
|
|
17
24
|
type PaymentReturnSearchParams = Record<string, string | string[] | undefined>;
|
|
18
25
|
interface PaymentReturnParserOptions {
|
|
@@ -20,6 +27,13 @@ interface PaymentReturnParserOptions {
|
|
|
20
27
|
gatewayResultMarkers?: readonly string[];
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
declare const SAZITO_PAYMENT_STATUS_QUERY: {
|
|
31
|
+
readonly resolution: "sazito_payment_return";
|
|
32
|
+
readonly paymentId: "sazito_payment_id";
|
|
33
|
+
readonly paymentIdentifier: "sazito_payment_identifier";
|
|
34
|
+
};
|
|
35
|
+
/** Remove server-return credentials from the visible URL after they are read. */
|
|
36
|
+
declare function stripPaymentStatusReturn(url: string | URL): string | undefined;
|
|
23
37
|
declare const SAZITO_PAYMENT_RESULT_MARKERS: readonly ["mellatpaymentresult", "pecpaymentresult", "uppaymentresult", "seppaymentresult", "vandarpaymentresult", "yourgatepaymentresult", "bazarpaymentresult", "zifypaymentresult", "zibalpaymentresult", "snapppaypaymentresult", "torobpaypaymentresult", "ghestapaypaymentresult", "azkipaymentresult", "digipaypaymentresult", "greenpaypaymentresult", "novapaypaymentresult", "zarinpluspaymentresult", "tomanpaymentresult", "tarapaymentresult", "ozonpaymentresult", "millipaypaymentresult", "ayriapaymentresult", "sadadpaymentresult", "freepaymentresult", "paymentinplaceresult", "cardtocardpaymentresult", "zarinpalpaymentresult", "directpayresult", "paypingpaymentresult", "podpaymentresult", "sabinpaymentresult", "firoozepaymentresult", "technopaypaymentresult", "buywithdigikalaresult"];
|
|
24
38
|
/**
|
|
25
39
|
* Parse Sazito's nested payment callback path into checkout-ready data.
|
|
@@ -33,5 +47,5 @@ declare function parsePaymentReturn(segments: readonly string[] | undefined, sea
|
|
|
33
47
|
*/
|
|
34
48
|
declare function parsePaymentReturnUrl(url: string | URL, options?: PaymentReturnParserOptions): CheckoutPaymentReturn | undefined;
|
|
35
49
|
|
|
36
|
-
export { SAZITO_PAYMENT_RESULT_MARKERS, parsePaymentReturn, parsePaymentReturnUrl };
|
|
37
|
-
export type { CheckoutPaymentReturn, PaymentReturnParserOptions, PaymentReturnSearchParams };
|
|
50
|
+
export { SAZITO_PAYMENT_RESULT_MARKERS, SAZITO_PAYMENT_STATUS_QUERY, parsePaymentReturn, parsePaymentReturnUrl, stripPaymentStatusReturn };
|
|
51
|
+
export type { CheckoutPaymentReturn, PaymentReturnParserOptions, PaymentReturnResolution, PaymentReturnSearchParams };
|
|
@@ -12,7 +12,14 @@ interface CheckoutPaymentReturn {
|
|
|
12
12
|
identifier: string;
|
|
13
13
|
};
|
|
14
14
|
params: Record<string, string>;
|
|
15
|
+
/**
|
|
16
|
+
* `callback` forwards gateway fields for verification. `status` is emitted
|
|
17
|
+
* by the SDK server handler after it has already verified the gateway POST,
|
|
18
|
+
* so the browser performs only an authoritative status read.
|
|
19
|
+
*/
|
|
20
|
+
resolution?: PaymentReturnResolution;
|
|
15
21
|
}
|
|
22
|
+
type PaymentReturnResolution = 'callback' | 'status';
|
|
16
23
|
/** Search-param shape exposed by current Next.js App Router pages. */
|
|
17
24
|
type PaymentReturnSearchParams = Record<string, string | string[] | undefined>;
|
|
18
25
|
interface PaymentReturnParserOptions {
|
|
@@ -20,6 +27,13 @@ interface PaymentReturnParserOptions {
|
|
|
20
27
|
gatewayResultMarkers?: readonly string[];
|
|
21
28
|
}
|
|
22
29
|
|
|
30
|
+
declare const SAZITO_PAYMENT_STATUS_QUERY: {
|
|
31
|
+
readonly resolution: "sazito_payment_return";
|
|
32
|
+
readonly paymentId: "sazito_payment_id";
|
|
33
|
+
readonly paymentIdentifier: "sazito_payment_identifier";
|
|
34
|
+
};
|
|
35
|
+
/** Remove server-return credentials from the visible URL after they are read. */
|
|
36
|
+
declare function stripPaymentStatusReturn(url: string | URL): string | undefined;
|
|
23
37
|
declare const SAZITO_PAYMENT_RESULT_MARKERS: readonly ["mellatpaymentresult", "pecpaymentresult", "uppaymentresult", "seppaymentresult", "vandarpaymentresult", "yourgatepaymentresult", "bazarpaymentresult", "zifypaymentresult", "zibalpaymentresult", "snapppaypaymentresult", "torobpaypaymentresult", "ghestapaypaymentresult", "azkipaymentresult", "digipaypaymentresult", "greenpaypaymentresult", "novapaypaymentresult", "zarinpluspaymentresult", "tomanpaymentresult", "tarapaymentresult", "ozonpaymentresult", "millipaypaymentresult", "ayriapaymentresult", "sadadpaymentresult", "freepaymentresult", "paymentinplaceresult", "cardtocardpaymentresult", "zarinpalpaymentresult", "directpayresult", "paypingpaymentresult", "podpaymentresult", "sabinpaymentresult", "firoozepaymentresult", "technopaypaymentresult", "buywithdigikalaresult"];
|
|
24
38
|
/**
|
|
25
39
|
* Parse Sazito's nested payment callback path into checkout-ready data.
|
|
@@ -33,5 +47,5 @@ declare function parsePaymentReturn(segments: readonly string[] | undefined, sea
|
|
|
33
47
|
*/
|
|
34
48
|
declare function parsePaymentReturnUrl(url: string | URL, options?: PaymentReturnParserOptions): CheckoutPaymentReturn | undefined;
|
|
35
49
|
|
|
36
|
-
export { SAZITO_PAYMENT_RESULT_MARKERS, parsePaymentReturn, parsePaymentReturnUrl };
|
|
37
|
-
export type { CheckoutPaymentReturn, PaymentReturnParserOptions, PaymentReturnSearchParams };
|
|
50
|
+
export { SAZITO_PAYMENT_RESULT_MARKERS, SAZITO_PAYMENT_STATUS_QUERY, parsePaymentReturn, parsePaymentReturnUrl, stripPaymentStatusReturn };
|
|
51
|
+
export type { CheckoutPaymentReturn, PaymentReturnParserOptions, PaymentReturnResolution, PaymentReturnSearchParams };
|
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
const SAZITO_PAYMENT_STATUS_QUERY = {
|
|
2
|
+
resolution: 'sazito_payment_return',
|
|
3
|
+
paymentId: 'sazito_payment_id',
|
|
4
|
+
paymentIdentifier: 'sazito_payment_identifier'
|
|
5
|
+
};
|
|
6
|
+
/** Remove server-return credentials from the visible URL after they are read. */
|
|
7
|
+
function stripPaymentStatusReturn(url) {
|
|
8
|
+
let parsedUrl;
|
|
9
|
+
try {
|
|
10
|
+
parsedUrl = typeof url === 'string'
|
|
11
|
+
? new URL(url, 'https://checkout.sazito.invalid')
|
|
12
|
+
: new URL(url.toString());
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);
|
|
21
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
|
|
22
|
+
parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier);
|
|
23
|
+
return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;
|
|
24
|
+
}
|
|
1
25
|
const SAZITO_PAYMENT_RESULT_MARKERS = [
|
|
2
26
|
'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',
|
|
3
27
|
'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',
|
|
@@ -55,6 +79,9 @@ function parsePaymentReturnUrl(url, options = {}) {
|
|
|
55
79
|
catch {
|
|
56
80
|
return undefined;
|
|
57
81
|
}
|
|
82
|
+
const statusReturn = parsePaymentStatusReturn(parsedUrl);
|
|
83
|
+
if (statusReturn)
|
|
84
|
+
return statusReturn;
|
|
58
85
|
const segments = parsedUrl.pathname
|
|
59
86
|
.split('/')
|
|
60
87
|
.filter(Boolean)
|
|
@@ -71,6 +98,27 @@ function parsePaymentReturnUrl(url, options = {}) {
|
|
|
71
98
|
}
|
|
72
99
|
return parsePaymentReturn(segments.slice(-5), searchParams, options);
|
|
73
100
|
}
|
|
101
|
+
function parsePaymentStatusReturn(url) {
|
|
102
|
+
if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
|
|
106
|
+
const identifier = url.searchParams
|
|
107
|
+
.get(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier)
|
|
108
|
+
?.trim();
|
|
109
|
+
const paymentId = Number(rawPaymentId);
|
|
110
|
+
if (!Number.isSafeInteger(paymentId) || paymentId <= 0 || !identifier) {
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
payment: { id: paymentId, identifier },
|
|
115
|
+
params: {
|
|
116
|
+
id: String(paymentId),
|
|
117
|
+
paymentIdentifier: identifier
|
|
118
|
+
},
|
|
119
|
+
resolution: 'status'
|
|
120
|
+
};
|
|
121
|
+
}
|
|
74
122
|
function decodePathSegment(segment) {
|
|
75
123
|
try {
|
|
76
124
|
return decodeURIComponent(segment);
|
|
@@ -90,5 +138,5 @@ function normalizeSearchParams(searchParams) {
|
|
|
90
138
|
return normalized;
|
|
91
139
|
}
|
|
92
140
|
|
|
93
|
-
export { SAZITO_PAYMENT_RESULT_MARKERS, parsePaymentReturn, parsePaymentReturnUrl };
|
|
141
|
+
export { SAZITO_PAYMENT_RESULT_MARKERS, SAZITO_PAYMENT_STATUS_QUERY, parsePaymentReturn, parsePaymentReturnUrl, stripPaymentStatusReturn };
|
|
94
142
|
//# sourceMappingURL=payment-return.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payment-return.js","sources":["../../src/core/payment-return.ts"],"sourcesContent":["import type {\n CheckoutPaymentReturn,\n PaymentReturnParserOptions,\n PaymentReturnSearchParams\n} from './types';\n\nexport const SAZITO_PAYMENT_RESULT_MARKERS = [\n 'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',\n 'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',\n 'bazarpaymentresult', 'zifypaymentresult', 'zibalpaymentresult',\n 'snapppaypaymentresult', 'torobpaypaymentresult', 'ghestapaypaymentresult',\n 'azkipaymentresult', 'digipaypaymentresult', 'greenpaypaymentresult',\n 'novapaypaymentresult', 'zarinpluspaymentresult', 'tomanpaymentresult',\n 'tarapaymentresult', 'ozonpaymentresult', 'millipaypaymentresult',\n 'ayriapaymentresult', 'sadadpaymentresult', 'freepaymentresult',\n 'paymentinplaceresult', 'cardtocardpaymentresult', 'zarinpalpaymentresult',\n 'directpayresult', 'paypingpaymentresult', 'podpaymentresult',\n 'sabinpaymentresult', 'firoozepaymentresult', 'technopaypaymentresult',\n 'buywithdigikalaresult'\n] as const;\n\n/**\n * Parse Sazito's nested payment callback path into checkout-ready data.\n * Returns undefined for ordinary checkout URLs and malformed callbacks.\n */\nexport function parsePaymentReturn(\n segments: readonly string[] | undefined,\n searchParams: PaymentReturnSearchParams = {},\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n const [resultRoute, paymentSegment, rawPaymentId, identifierSegment, rawIdentifier] =\n segments ?? [];\n const paymentId = Number(rawPaymentId);\n const identifier = rawIdentifier?.trim();\n const allowedMarkers = new Set(\n (options.gatewayResultMarkers ?? SAZITO_PAYMENT_RESULT_MARKERS)\n .map((marker) => marker.toLowerCase())\n );\n\n if (\n segments?.length !== 5 ||\n !resultRoute ||\n !allowedMarkers.has(resultRoute.toLowerCase()) ||\n paymentSegment?.toLowerCase() !== 'payment' ||\n identifierSegment?.toLowerCase() !== 'identifier' ||\n !Number.isSafeInteger(paymentId) ||\n paymentId <= 0 ||\n !identifier\n ) {\n return undefined;\n }\n\n const params = normalizeSearchParams(searchParams);\n params.id = String(paymentId);\n params.paymentIdentifier = identifier;\n\n return {\n payment: { id: paymentId, identifier },\n params\n };\n}\n\n/**\n * Parse a complete checkout URL containing Sazito's nested payment callback.\n * The callback may be mounted below any checkout base path; only its final\n * five path segments are significant.\n */\nexport function parsePaymentReturnUrl(\n url: string | URL,\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n let parsedUrl: URL;\n\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : url;\n } catch {\n return undefined;\n }\n\n const segments = parsedUrl.pathname\n .split('/')\n .filter(Boolean)\n .map(decodePathSegment);\n\n if (segments.length < 5) {\n return undefined;\n }\n\n const searchParams: Record<string, string> = {};\n for (const [key, value] of parsedUrl.searchParams) {\n // Match Next.js search-param normalization: preserve the first value.\n if (searchParams[key] === undefined) {\n searchParams[key] = value;\n }\n }\n\n return parsePaymentReturn(segments.slice(-5), searchParams, options);\n}\n\nfunction decodePathSegment(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction normalizeSearchParams(\n searchParams: PaymentReturnSearchParams\n): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(searchParams)) {\n const firstValue = Array.isArray(value) ? value[0] : value;\n if (firstValue !== undefined) {\n normalized[key] = firstValue;\n }\n }\n\n return normalized;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"payment-return.js","sources":["../../src/core/payment-return.ts"],"sourcesContent":["import type {\n CheckoutPaymentReturn,\n PaymentReturnParserOptions,\n PaymentReturnSearchParams\n} from './types';\n\nexport const SAZITO_PAYMENT_STATUS_QUERY = {\n resolution: 'sazito_payment_return',\n paymentId: 'sazito_payment_id',\n paymentIdentifier: 'sazito_payment_identifier'\n} as const;\n\n/** Remove server-return credentials from the visible URL after they are read. */\nexport function stripPaymentStatusReturn(url: string | URL): string | undefined {\n let parsedUrl: URL;\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : new URL(url.toString());\n } catch {\n return undefined;\n }\n\n if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {\n return undefined;\n }\n\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentId);\n parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier);\n return `${parsedUrl.pathname}${parsedUrl.search}${parsedUrl.hash}`;\n}\n\nexport const SAZITO_PAYMENT_RESULT_MARKERS = [\n 'mellatpaymentresult', 'pecpaymentresult', 'uppaymentresult',\n 'seppaymentresult', 'vandarpaymentresult', 'yourgatepaymentresult',\n 'bazarpaymentresult', 'zifypaymentresult', 'zibalpaymentresult',\n 'snapppaypaymentresult', 'torobpaypaymentresult', 'ghestapaypaymentresult',\n 'azkipaymentresult', 'digipaypaymentresult', 'greenpaypaymentresult',\n 'novapaypaymentresult', 'zarinpluspaymentresult', 'tomanpaymentresult',\n 'tarapaymentresult', 'ozonpaymentresult', 'millipaypaymentresult',\n 'ayriapaymentresult', 'sadadpaymentresult', 'freepaymentresult',\n 'paymentinplaceresult', 'cardtocardpaymentresult', 'zarinpalpaymentresult',\n 'directpayresult', 'paypingpaymentresult', 'podpaymentresult',\n 'sabinpaymentresult', 'firoozepaymentresult', 'technopaypaymentresult',\n 'buywithdigikalaresult'\n] as const;\n\n/**\n * Parse Sazito's nested payment callback path into checkout-ready data.\n * Returns undefined for ordinary checkout URLs and malformed callbacks.\n */\nexport function parsePaymentReturn(\n segments: readonly string[] | undefined,\n searchParams: PaymentReturnSearchParams = {},\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n const [resultRoute, paymentSegment, rawPaymentId, identifierSegment, rawIdentifier] =\n segments ?? [];\n const paymentId = Number(rawPaymentId);\n const identifier = rawIdentifier?.trim();\n const allowedMarkers = new Set(\n (options.gatewayResultMarkers ?? SAZITO_PAYMENT_RESULT_MARKERS)\n .map((marker) => marker.toLowerCase())\n );\n\n if (\n segments?.length !== 5 ||\n !resultRoute ||\n !allowedMarkers.has(resultRoute.toLowerCase()) ||\n paymentSegment?.toLowerCase() !== 'payment' ||\n identifierSegment?.toLowerCase() !== 'identifier' ||\n !Number.isSafeInteger(paymentId) ||\n paymentId <= 0 ||\n !identifier\n ) {\n return undefined;\n }\n\n const params = normalizeSearchParams(searchParams);\n params.id = String(paymentId);\n params.paymentIdentifier = identifier;\n\n return {\n payment: { id: paymentId, identifier },\n params\n };\n}\n\n/**\n * Parse a complete checkout URL containing Sazito's nested payment callback.\n * The callback may be mounted below any checkout base path; only its final\n * five path segments are significant.\n */\nexport function parsePaymentReturnUrl(\n url: string | URL,\n options: PaymentReturnParserOptions = {}\n): CheckoutPaymentReturn | undefined {\n let parsedUrl: URL;\n\n try {\n parsedUrl = typeof url === 'string'\n ? new URL(url, 'https://checkout.sazito.invalid')\n : url;\n } catch {\n return undefined;\n }\n\n const statusReturn = parsePaymentStatusReturn(parsedUrl);\n if (statusReturn) return statusReturn;\n\n const segments = parsedUrl.pathname\n .split('/')\n .filter(Boolean)\n .map(decodePathSegment);\n\n if (segments.length < 5) {\n return undefined;\n }\n\n const searchParams: Record<string, string> = {};\n for (const [key, value] of parsedUrl.searchParams) {\n // Match Next.js search-param normalization: preserve the first value.\n if (searchParams[key] === undefined) {\n searchParams[key] = value;\n }\n }\n\n return parsePaymentReturn(segments.slice(-5), searchParams, options);\n}\n\nfunction parsePaymentStatusReturn(url: URL): CheckoutPaymentReturn | undefined {\n if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {\n return undefined;\n }\n\n const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);\n const identifier = url.searchParams\n .get(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier)\n ?.trim();\n const paymentId = Number(rawPaymentId);\n\n if (!Number.isSafeInteger(paymentId) || paymentId <= 0 || !identifier) {\n return undefined;\n }\n\n return {\n payment: { id: paymentId, identifier },\n params: {\n id: String(paymentId),\n paymentIdentifier: identifier\n },\n resolution: 'status'\n };\n}\n\nfunction decodePathSegment(segment: string): string {\n try {\n return decodeURIComponent(segment);\n } catch {\n return segment;\n }\n}\n\nfunction normalizeSearchParams(\n searchParams: PaymentReturnSearchParams\n): Record<string, string> {\n const normalized: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(searchParams)) {\n const firstValue = Array.isArray(value) ? value[0] : value;\n if (firstValue !== undefined) {\n normalized[key] = firstValue;\n }\n }\n\n return normalized;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SazitoConfig } from '@sazito/client-sdk';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @sazito/checkout/server — server-only payment callback handlers.
|
|
5
|
+
*
|
|
6
|
+
* The implementation uses only the standard Web Request/Response APIs so the
|
|
7
|
+
* same handlers work in Next.js Route Handlers and other compatible runtimes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;
|
|
11
|
+
interface SazitoCheckoutServerConfig extends SazitoConfig {
|
|
12
|
+
/** Page that renders `SazitoCheckoutPage` after server verification. */
|
|
13
|
+
checkoutPath?: string;
|
|
14
|
+
/** Maximum accepted gateway callback body size. Defaults to 64 KiB. */
|
|
15
|
+
maxCallbackBodyBytes?: number;
|
|
16
|
+
/** Replace the built-in gateway-result marker allowlist. */
|
|
17
|
+
gatewayResultMarkers?: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
interface SazitoCheckoutServer {
|
|
20
|
+
handlers: {
|
|
21
|
+
GET: SazitoPaymentRouteHandler;
|
|
22
|
+
POST: SazitoPaymentRouteHandler;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create GET and POST route handlers for payment callbacks.
|
|
27
|
+
* A fresh SDK client is created for each request so server-side guest
|
|
28
|
+
* credentials can never leak between concurrent callbacks.
|
|
29
|
+
*/
|
|
30
|
+
declare function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer;
|
|
31
|
+
|
|
32
|
+
export { SazitoCheckout };
|
|
33
|
+
export type { SazitoCheckoutServer, SazitoCheckoutServerConfig, SazitoPaymentRouteHandler };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SazitoConfig } from '@sazito/client-sdk';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @sazito/checkout/server — server-only payment callback handlers.
|
|
5
|
+
*
|
|
6
|
+
* The implementation uses only the standard Web Request/Response APIs so the
|
|
7
|
+
* same handlers work in Next.js Route Handlers and other compatible runtimes.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;
|
|
11
|
+
interface SazitoCheckoutServerConfig extends SazitoConfig {
|
|
12
|
+
/** Page that renders `SazitoCheckoutPage` after server verification. */
|
|
13
|
+
checkoutPath?: string;
|
|
14
|
+
/** Maximum accepted gateway callback body size. Defaults to 64 KiB. */
|
|
15
|
+
maxCallbackBodyBytes?: number;
|
|
16
|
+
/** Replace the built-in gateway-result marker allowlist. */
|
|
17
|
+
gatewayResultMarkers?: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
interface SazitoCheckoutServer {
|
|
20
|
+
handlers: {
|
|
21
|
+
GET: SazitoPaymentRouteHandler;
|
|
22
|
+
POST: SazitoPaymentRouteHandler;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Create GET and POST route handlers for payment callbacks.
|
|
27
|
+
* A fresh SDK client is created for each request so server-side guest
|
|
28
|
+
* credentials can never leak between concurrent callbacks.
|
|
29
|
+
*/
|
|
30
|
+
declare function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer;
|
|
31
|
+
|
|
32
|
+
export { SazitoCheckout };
|
|
33
|
+
export type { SazitoCheckoutServer, SazitoCheckoutServerConfig, SazitoPaymentRouteHandler };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
package/dist/react/index.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var useCheckout = require('../chunks/use-checkout-
|
|
4
|
+
var useCheckout = require('../chunks/use-checkout-DsTtOAMs.cjs');
|
|
5
5
|
require('react/jsx-runtime');
|
|
6
6
|
require('react');
|
|
7
7
|
require('../next/payment-return.cjs');
|
|
8
|
-
require('../chunks/labels-
|
|
8
|
+
require('../chunks/labels-FNi3eq4p.cjs');
|
|
9
9
|
require('@sazito/client-sdk');
|
|
10
10
|
|
|
11
11
|
|
package/dist/react/index.d.cts
CHANGED
|
@@ -99,6 +99,7 @@ interface CheckoutCredentials {
|
|
|
99
99
|
identifier: string;
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
+
type PaymentReturnResolution = 'callback' | 'status';
|
|
102
103
|
interface CheckoutConfig {
|
|
103
104
|
locale?: CheckoutLocale;
|
|
104
105
|
direction?: CheckoutDirection;
|
|
@@ -240,8 +241,8 @@ interface CheckoutActions {
|
|
|
240
241
|
placeOrder(): Promise<void>;
|
|
241
242
|
/** Rehydrate a failed gateway return and reopen a usable payment step. */
|
|
242
243
|
retryPayment(): Promise<void>;
|
|
243
|
-
/** Resolve a
|
|
244
|
-
resolvePaymentReturn(params: Record<string, string
|
|
244
|
+
/** Resolve a gateway callback or a server-verified payment status return. */
|
|
245
|
+
resolvePaymentReturn(params: Record<string, string>, resolution?: PaymentReturnResolution): Promise<void>;
|
|
245
246
|
reset(): void;
|
|
246
247
|
}
|
|
247
248
|
|
package/dist/react/index.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ interface CheckoutCredentials {
|
|
|
99
99
|
identifier: string;
|
|
100
100
|
};
|
|
101
101
|
}
|
|
102
|
+
type PaymentReturnResolution = 'callback' | 'status';
|
|
102
103
|
interface CheckoutConfig {
|
|
103
104
|
locale?: CheckoutLocale;
|
|
104
105
|
direction?: CheckoutDirection;
|
|
@@ -240,8 +241,8 @@ interface CheckoutActions {
|
|
|
240
241
|
placeOrder(): Promise<void>;
|
|
241
242
|
/** Rehydrate a failed gateway return and reopen a usable payment step. */
|
|
242
243
|
retryPayment(): Promise<void>;
|
|
243
|
-
/** Resolve a
|
|
244
|
-
resolvePaymentReturn(params: Record<string, string
|
|
244
|
+
/** Resolve a gateway callback or a server-verified payment status return. */
|
|
245
|
+
resolvePaymentReturn(params: Record<string, string>, resolution?: PaymentReturnResolution): Promise<void>;
|
|
245
246
|
reset(): void;
|
|
246
247
|
}
|
|
247
248
|
|
package/dist/react/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { C as CheckoutProvider, S as SazitoProvider, u as useCheckout, a as useCheckoutEngine, b as useSazitoClient } from '../chunks/use-checkout-
|
|
2
|
+
export { C as CheckoutProvider, S as SazitoProvider, u as useCheckout, a as useCheckoutEngine, b as useSazitoClient } from '../chunks/use-checkout-OyHfWeAh.js';
|
|
3
3
|
import 'react/jsx-runtime';
|
|
4
4
|
import 'react';
|
|
5
5
|
import '../next/payment-return.js';
|
|
6
|
-
import '../chunks/labels-
|
|
6
|
+
import '../chunks/labels-CwHBYso8.js';
|
|
7
7
|
import '@sazito/client-sdk';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clientSdk = require('@sazito/client-sdk');
|
|
4
|
+
var next_paymentReturn = require('../next/payment-return.cjs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @sazito/checkout/server — server-only payment callback handlers.
|
|
8
|
+
*
|
|
9
|
+
* The implementation uses only the standard Web Request/Response APIs so the
|
|
10
|
+
* same handlers work in Next.js Route Handlers and other compatible runtimes.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_CHECKOUT_PATH = '/checkout';
|
|
13
|
+
const DEFAULT_MAX_BODY_BYTES = 64 * 1024;
|
|
14
|
+
/**
|
|
15
|
+
* Create GET and POST route handlers for payment callbacks.
|
|
16
|
+
* A fresh SDK client is created for each request so server-side guest
|
|
17
|
+
* credentials can never leak between concurrent callbacks.
|
|
18
|
+
*/
|
|
19
|
+
function SazitoCheckout(config) {
|
|
20
|
+
const { checkoutPath = DEFAULT_CHECKOUT_PATH, maxCallbackBodyBytes = DEFAULT_MAX_BODY_BYTES, gatewayResultMarkers, ...sdkConfig } = config;
|
|
21
|
+
validateConfig(sdkConfig, checkoutPath, maxCallbackBodyBytes);
|
|
22
|
+
const parserOptions = { gatewayResultMarkers };
|
|
23
|
+
const createHandler = (method) => async (request) => {
|
|
24
|
+
if (request.method.toUpperCase() !== method) {
|
|
25
|
+
return errorResponse(405, 'method_not_allowed', { Allow: method });
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const callback = next_paymentReturn.parsePaymentReturnUrl(request.url, parserOptions);
|
|
29
|
+
if (!callback || callback.resolution === 'status') {
|
|
30
|
+
return errorResponse(400, 'invalid_payment_callback');
|
|
31
|
+
}
|
|
32
|
+
const requestUrl = new URL(request.url);
|
|
33
|
+
const body = method === 'POST'
|
|
34
|
+
? await readCallbackBody(request, maxCallbackBodyBytes)
|
|
35
|
+
: undefined;
|
|
36
|
+
const query = fieldsFromSearchParams(requestUrl.searchParams);
|
|
37
|
+
const client = clientSdk.createSazitoClient(sdkConfig);
|
|
38
|
+
const verification = await client.payments.verifyPaymentCallback({
|
|
39
|
+
paymentId: callback.payment.id,
|
|
40
|
+
paymentIdentifier: callback.payment.identifier,
|
|
41
|
+
body,
|
|
42
|
+
query
|
|
43
|
+
});
|
|
44
|
+
if (verification.error || !verification.data) {
|
|
45
|
+
if (sdkConfig.debug) {
|
|
46
|
+
console.error('[Sazito Checkout] Payment callback verification failed:', {
|
|
47
|
+
paymentId: callback.payment.id,
|
|
48
|
+
error: verification.error
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return errorResponse(502, 'payment_verification_failed');
|
|
52
|
+
}
|
|
53
|
+
const redirectUrl = createStatusRedirectUrl(requestUrl, checkoutPath, callback.payment);
|
|
54
|
+
return new Response(null, {
|
|
55
|
+
status: 303,
|
|
56
|
+
headers: {
|
|
57
|
+
Location: redirectUrl.toString(),
|
|
58
|
+
'Cache-Control': 'no-store',
|
|
59
|
+
'Referrer-Policy': 'no-referrer'
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (config.debug) {
|
|
65
|
+
console.error('[Sazito Checkout] Invalid payment callback request:', error);
|
|
66
|
+
}
|
|
67
|
+
const status = error instanceof CallbackRequestError ? error.status : 500;
|
|
68
|
+
const code = error instanceof CallbackRequestError
|
|
69
|
+
? error.code
|
|
70
|
+
: 'payment_callback_failed';
|
|
71
|
+
return errorResponse(status, code);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return {
|
|
75
|
+
handlers: {
|
|
76
|
+
GET: createHandler('GET'),
|
|
77
|
+
POST: createHandler('POST')
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function validateConfig(config, checkoutPath, maxCallbackBodyBytes) {
|
|
82
|
+
if (!config.domain?.trim()) {
|
|
83
|
+
throw new Error('[@sazito/checkout] `domain` is required by the payment callback handler.');
|
|
84
|
+
}
|
|
85
|
+
if (!checkoutPath.trim()) {
|
|
86
|
+
throw new Error('[@sazito/checkout] `checkoutPath` cannot be empty.');
|
|
87
|
+
}
|
|
88
|
+
if (!Number.isSafeInteger(maxCallbackBodyBytes) || maxCallbackBodyBytes <= 0) {
|
|
89
|
+
throw new Error('[@sazito/checkout] `maxCallbackBodyBytes` must be a positive integer.');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function readCallbackBody(request, maxBodyBytes) {
|
|
93
|
+
const declaredLength = Number(request.headers.get('content-length') ?? 0);
|
|
94
|
+
if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {
|
|
95
|
+
throw new CallbackRequestError(413, 'payment_callback_too_large');
|
|
96
|
+
}
|
|
97
|
+
const bytes = await request.arrayBuffer();
|
|
98
|
+
if (bytes.byteLength > maxBodyBytes) {
|
|
99
|
+
throw new CallbackRequestError(413, 'payment_callback_too_large');
|
|
100
|
+
}
|
|
101
|
+
if (bytes.byteLength === 0)
|
|
102
|
+
return {};
|
|
103
|
+
const contentType = request.headers.get('content-type')?.toLowerCase() ?? '';
|
|
104
|
+
if (contentType.includes('application/json')) {
|
|
105
|
+
return fieldsFromJson(new TextDecoder().decode(bytes));
|
|
106
|
+
}
|
|
107
|
+
if (contentType.includes('multipart/form-data')) {
|
|
108
|
+
const form = await new Response(bytes, {
|
|
109
|
+
headers: { 'Content-Type': request.headers.get('content-type') ?? '' }
|
|
110
|
+
}).formData();
|
|
111
|
+
return fieldsFromFormData(form);
|
|
112
|
+
}
|
|
113
|
+
// Gateways commonly omit Content-Type or label URL-encoded data as text.
|
|
114
|
+
return fieldsFromSearchParams(new URLSearchParams(new TextDecoder().decode(bytes)));
|
|
115
|
+
}
|
|
116
|
+
function fieldsFromJson(source) {
|
|
117
|
+
let value;
|
|
118
|
+
try {
|
|
119
|
+
value = JSON.parse(source);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
throw new CallbackRequestError(400, 'invalid_payment_callback_body');
|
|
123
|
+
}
|
|
124
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
125
|
+
throw new CallbackRequestError(400, 'invalid_payment_callback_body');
|
|
126
|
+
}
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
function fieldsFromSearchParams(params) {
|
|
130
|
+
const fields = {};
|
|
131
|
+
for (const [name, value] of params)
|
|
132
|
+
appendField(fields, name, value);
|
|
133
|
+
return fields;
|
|
134
|
+
}
|
|
135
|
+
function fieldsFromFormData(form) {
|
|
136
|
+
const fields = {};
|
|
137
|
+
for (const [name, value] of form) {
|
|
138
|
+
if (typeof value !== 'string') {
|
|
139
|
+
throw new CallbackRequestError(400, 'unsupported_payment_callback_file');
|
|
140
|
+
}
|
|
141
|
+
appendField(fields, name, value);
|
|
142
|
+
}
|
|
143
|
+
return fields;
|
|
144
|
+
}
|
|
145
|
+
function appendField(fields, name, value) {
|
|
146
|
+
const current = fields[name];
|
|
147
|
+
if (current === undefined) {
|
|
148
|
+
fields[name] = value;
|
|
149
|
+
}
|
|
150
|
+
else if (Array.isArray(current)) {
|
|
151
|
+
fields[name] = [...current, value ?? null];
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
fields[name] = [current, value ?? null];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
function createStatusRedirectUrl(requestUrl, checkoutPath, payment) {
|
|
158
|
+
const redirectUrl = new URL(checkoutPath, requestUrl.origin);
|
|
159
|
+
redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.resolution, 'status');
|
|
160
|
+
redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));
|
|
161
|
+
redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier, payment.identifier);
|
|
162
|
+
return redirectUrl;
|
|
163
|
+
}
|
|
164
|
+
function errorResponse(status, code, extraHeaders = {}) {
|
|
165
|
+
return Response.json({ error: code }, {
|
|
166
|
+
status,
|
|
167
|
+
headers: {
|
|
168
|
+
'Cache-Control': 'no-store',
|
|
169
|
+
...extraHeaders
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
class CallbackRequestError extends Error {
|
|
174
|
+
constructor(status, code) {
|
|
175
|
+
super(code);
|
|
176
|
+
this.status = status;
|
|
177
|
+
this.code = code;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
exports.SazitoCheckout = SazitoCheckout;
|
|
182
|
+
//# sourceMappingURL=index.cjs.map
|