@sazito/checkout 0.4.20 → 0.4.21

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.
Files changed (34) hide show
  1. package/README.md +3 -0
  2. package/dist/chunks/{labels-FNi3eq4p.cjs → labels-BYJQjaT_.cjs} +2 -2
  3. package/dist/chunks/labels-BYJQjaT_.cjs.map +1 -0
  4. package/dist/chunks/{labels-CwHBYso8.js → labels-Cqrb2MwA.js} +2 -2
  5. package/dist/chunks/labels-Cqrb2MwA.js.map +1 -0
  6. package/dist/chunks/{use-checkout-OyHfWeAh.js → use-checkout-BRDfZp4Z.js} +5 -7
  7. package/dist/chunks/use-checkout-BRDfZp4Z.js.map +1 -0
  8. package/dist/chunks/{use-checkout-DsTtOAMs.cjs → use-checkout-MM-Ld0Ew.cjs} +5 -7
  9. package/dist/chunks/use-checkout-MM-Ld0Ew.cjs.map +1 -0
  10. package/dist/core/index.cjs +1 -1
  11. package/dist/core/index.d.cts +1 -1
  12. package/dist/core/index.d.ts +1 -1
  13. package/dist/core/index.js +1 -1
  14. package/dist/next/index.cjs +3 -3
  15. package/dist/next/index.cjs.map +1 -1
  16. package/dist/next/index.js +4 -4
  17. package/dist/next/index.js.map +1 -1
  18. package/dist/next/payment-return.cjs +6 -4
  19. package/dist/next/payment-return.cjs.map +1 -1
  20. package/dist/next/payment-return.d.cts +1 -1
  21. package/dist/next/payment-return.d.ts +1 -1
  22. package/dist/next/payment-return.js +6 -4
  23. package/dist/next/payment-return.js.map +1 -1
  24. package/dist/react/index.cjs +2 -2
  25. package/dist/react/index.js +2 -2
  26. package/dist/server/index.cjs +34 -11
  27. package/dist/server/index.cjs.map +1 -1
  28. package/dist/server/index.js +34 -11
  29. package/dist/server/index.js.map +1 -1
  30. package/package.json +1 -1
  31. package/dist/chunks/labels-CwHBYso8.js.map +0 -1
  32. package/dist/chunks/labels-FNi3eq4p.cjs.map +0 -1
  33. package/dist/chunks/use-checkout-DsTtOAMs.cjs.map +0 -1
  34. package/dist/chunks/use-checkout-OyHfWeAh.js.map +0 -1
@@ -5,7 +5,7 @@ const SAZITO_PAYMENT_STATUS_QUERY = {
5
5
  paymentId: 'sazito_payment_id',
6
6
  paymentIdentifier: 'sazito_payment_identifier'
7
7
  };
8
- /** Remove server-return credentials from the visible URL after they are read. */
8
+ /** Remove internal payment-return credentials from the visible URL after they are read. */
9
9
  function stripPaymentStatusReturn(url) {
10
10
  let parsedUrl;
11
11
  try {
@@ -16,7 +16,8 @@ function stripPaymentStatusReturn(url) {
16
16
  catch {
17
17
  return undefined;
18
18
  }
19
- if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
19
+ const resolution = parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);
20
+ if (resolution !== 'status' && resolution !== 'callback') {
20
21
  return undefined;
21
22
  }
22
23
  parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);
@@ -101,7 +102,8 @@ function parsePaymentReturnUrl(url, options = {}) {
101
102
  return parsePaymentReturn(segments.slice(-5), searchParams, options);
102
103
  }
103
104
  function parsePaymentStatusReturn(url) {
104
- if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
105
+ const resolution = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);
106
+ if (resolution !== 'status' && resolution !== 'callback') {
105
107
  return undefined;
106
108
  }
107
109
  const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
@@ -118,7 +120,7 @@ function parsePaymentStatusReturn(url) {
118
120
  id: String(paymentId),
119
121
  paymentIdentifier: identifier
120
122
  },
121
- resolution: 'status'
123
+ resolution
122
124
  };
123
125
  }
124
126
  function decodePathSegment(segment) {
@@ -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_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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"}
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 internal payment-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 const resolution = parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n if (resolution !== 'status' && resolution !== 'callback') {\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 const resolution = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n if (resolution !== 'status' && resolution !== 'callback') {\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\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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"}
@@ -32,7 +32,7 @@ declare const SAZITO_PAYMENT_STATUS_QUERY: {
32
32
  readonly paymentId: "sazito_payment_id";
33
33
  readonly paymentIdentifier: "sazito_payment_identifier";
34
34
  };
35
- /** Remove server-return credentials from the visible URL after they are read. */
35
+ /** Remove internal payment-return credentials from the visible URL after they are read. */
36
36
  declare function stripPaymentStatusReturn(url: string | URL): string | undefined;
37
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"];
38
38
  /**
@@ -32,7 +32,7 @@ declare const SAZITO_PAYMENT_STATUS_QUERY: {
32
32
  readonly paymentId: "sazito_payment_id";
33
33
  readonly paymentIdentifier: "sazito_payment_identifier";
34
34
  };
35
- /** Remove server-return credentials from the visible URL after they are read. */
35
+ /** Remove internal payment-return credentials from the visible URL after they are read. */
36
36
  declare function stripPaymentStatusReturn(url: string | URL): string | undefined;
37
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"];
38
38
  /**
@@ -3,7 +3,7 @@ const SAZITO_PAYMENT_STATUS_QUERY = {
3
3
  paymentId: 'sazito_payment_id',
4
4
  paymentIdentifier: 'sazito_payment_identifier'
5
5
  };
6
- /** Remove server-return credentials from the visible URL after they are read. */
6
+ /** Remove internal payment-return credentials from the visible URL after they are read. */
7
7
  function stripPaymentStatusReturn(url) {
8
8
  let parsedUrl;
9
9
  try {
@@ -14,7 +14,8 @@ function stripPaymentStatusReturn(url) {
14
14
  catch {
15
15
  return undefined;
16
16
  }
17
- if (parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
17
+ const resolution = parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);
18
+ if (resolution !== 'status' && resolution !== 'callback') {
18
19
  return undefined;
19
20
  }
20
21
  parsedUrl.searchParams.delete(SAZITO_PAYMENT_STATUS_QUERY.resolution);
@@ -99,7 +100,8 @@ function parsePaymentReturnUrl(url, options = {}) {
99
100
  return parsePaymentReturn(segments.slice(-5), searchParams, options);
100
101
  }
101
102
  function parsePaymentStatusReturn(url) {
102
- if (url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution) !== 'status') {
103
+ const resolution = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);
104
+ if (resolution !== 'status' && resolution !== 'callback') {
103
105
  return undefined;
104
106
  }
105
107
  const rawPaymentId = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.paymentId);
@@ -116,7 +118,7 @@ function parsePaymentStatusReturn(url) {
116
118
  id: String(paymentId),
117
119
  paymentIdentifier: identifier
118
120
  },
119
- resolution: 'status'
121
+ resolution
120
122
  };
121
123
  }
122
124
  function decodePathSegment(segment) {
@@ -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_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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"}
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 internal payment-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 const resolution = parsedUrl.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n if (resolution !== 'status' && resolution !== 'callback') {\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 const resolution = url.searchParams.get(SAZITO_PAYMENT_STATUS_QUERY.resolution);\n if (resolution !== 'status' && resolution !== 'callback') {\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\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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"}
@@ -1,11 +1,11 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var useCheckout = require('../chunks/use-checkout-DsTtOAMs.cjs');
4
+ var useCheckout = require('../chunks/use-checkout-MM-Ld0Ew.cjs');
5
5
  require('react/jsx-runtime');
6
6
  require('react');
7
7
  require('../next/payment-return.cjs');
8
- require('../chunks/labels-FNi3eq4p.cjs');
8
+ require('../chunks/labels-BYJQjaT_.cjs');
9
9
  require('@sazito/client-sdk');
10
10
 
11
11
 
@@ -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-OyHfWeAh.js';
2
+ export { C as CheckoutProvider, S as SazitoProvider, u as useCheckout, a as useCheckoutEngine, b as useSazitoClient } from '../chunks/use-checkout-BRDfZp4Z.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
5
  import '../next/payment-return.js';
6
- import '../chunks/labels-CwHBYso8.js';
6
+ import '../chunks/labels-Cqrb2MwA.js';
7
7
  import '@sazito/client-sdk';
8
8
  //# sourceMappingURL=index.js.map
@@ -11,6 +11,7 @@ var next_paymentReturn = require('../next/payment-return.cjs');
11
11
  */
12
12
  const DEFAULT_CHECKOUT_PATH = '/checkout';
13
13
  const DEFAULT_MAX_BODY_BYTES = 64 * 1024;
14
+ const BROWSER_FINALIZED_RESULT_MARKERS = new Set(['paymentinplaceresult']);
14
15
  /**
15
16
  * Create GET and POST route handlers for payment callbacks.
16
17
  * A fresh SDK client is created for each request so server-side guest
@@ -34,6 +35,15 @@ function SazitoCheckout(config) {
34
35
  ? await readCallbackBody(request, maxCallbackBodyBytes)
35
36
  : undefined;
36
37
  const query = fieldsFromSearchParams(requestUrl.searchParams);
38
+ // Payment-in-place uses an empty POST only to return control to the
39
+ // storefront. Processing it on the server and then performing a status
40
+ // read in the browser calls process_payment_step twice; some deployments
41
+ // report the second call as failed even though the first one created the
42
+ // order. Redirect the empty first-party callback to the browser so the
43
+ // order is finalized exactly once and the returned order can be rendered.
44
+ if (shouldFinalizeInBrowser(requestUrl, body, query)) {
45
+ return redirectResponse(createPaymentReturnRedirectUrl(requestUrl, checkoutPath, callback.payment, 'callback'));
46
+ }
37
47
  const client = clientSdk.createSazitoClient(sdkConfig);
38
48
  const verification = await client.payments.verifyPaymentCallback({
39
49
  paymentId: callback.payment.id,
@@ -50,15 +60,8 @@ function SazitoCheckout(config) {
50
60
  }
51
61
  return errorResponse(502, 'payment_verification_failed');
52
62
  }
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
- });
63
+ const redirectUrl = createPaymentReturnRedirectUrl(requestUrl, checkoutPath, callback.payment, 'status');
64
+ return redirectResponse(redirectUrl);
62
65
  }
63
66
  catch (error) {
64
67
  if (config.debug) {
@@ -154,13 +157,33 @@ function appendField(fields, name, value) {
154
157
  fields[name] = [current, value ?? null];
155
158
  }
156
159
  }
157
- function createStatusRedirectUrl(requestUrl, checkoutPath, payment) {
160
+ function shouldFinalizeInBrowser(requestUrl, body, query) {
161
+ const pathSegments = requestUrl.pathname
162
+ .split('/')
163
+ .filter(Boolean);
164
+ const resultMarker = pathSegments[pathSegments.length - 5]?.toLowerCase();
165
+ return Boolean(resultMarker &&
166
+ BROWSER_FINALIZED_RESULT_MARKERS.has(resultMarker) &&
167
+ Object.keys(body ?? {}).length === 0 &&
168
+ Object.keys(query).length === 0);
169
+ }
170
+ function createPaymentReturnRedirectUrl(requestUrl, checkoutPath, payment, resolution) {
158
171
  const redirectUrl = new URL(checkoutPath, requestUrl.origin);
159
- redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.resolution, 'status');
172
+ redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.resolution, resolution);
160
173
  redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));
161
174
  redirectUrl.searchParams.set(next_paymentReturn.SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier, payment.identifier);
162
175
  return redirectUrl;
163
176
  }
177
+ function redirectResponse(url) {
178
+ return new Response(null, {
179
+ status: 303,
180
+ headers: {
181
+ Location: url.toString(),
182
+ 'Cache-Control': 'no-store',
183
+ 'Referrer-Policy': 'no-referrer'
184
+ }
185
+ });
186
+ }
164
187
  function errorResponse(status, code, extraHeaders = {}) {
165
188
  return Response.json({ error: code }, {
166
189
  status,
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * @sazito/checkout/server — server-only payment callback handlers.\n *\n * The implementation uses only the standard Web Request/Response APIs so the\n * same handlers work in Next.js Route Handlers and other compatible runtimes.\n */\nimport {\n createSazitoClient,\n type PaymentCallbackFieldValue,\n type PaymentCallbackFields,\n type SazitoConfig\n} from '@sazito/client-sdk';\nimport {\n parsePaymentReturnUrl,\n SAZITO_PAYMENT_STATUS_QUERY\n} from '../core/payment-return';\nimport type { PaymentReturnParserOptions } from '../core/types';\n\nconst DEFAULT_CHECKOUT_PATH = '/checkout';\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1024;\n\nexport type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;\n\nexport interface SazitoCheckoutServerConfig extends SazitoConfig {\n /** Page that renders `SazitoCheckoutPage` after server verification. */\n checkoutPath?: string;\n /** Maximum accepted gateway callback body size. Defaults to 64 KiB. */\n maxCallbackBodyBytes?: number;\n /** Replace the built-in gateway-result marker allowlist. */\n gatewayResultMarkers?: readonly string[];\n}\n\nexport interface SazitoCheckoutServer {\n handlers: {\n GET: SazitoPaymentRouteHandler;\n POST: SazitoPaymentRouteHandler;\n };\n}\n\n/**\n * Create GET and POST route handlers for payment callbacks.\n * A fresh SDK client is created for each request so server-side guest\n * credentials can never leak between concurrent callbacks.\n */\nexport function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer {\n const {\n checkoutPath = DEFAULT_CHECKOUT_PATH,\n maxCallbackBodyBytes = DEFAULT_MAX_BODY_BYTES,\n gatewayResultMarkers,\n ...sdkConfig\n } = config;\n\n validateConfig(sdkConfig, checkoutPath, maxCallbackBodyBytes);\n const parserOptions: PaymentReturnParserOptions = { gatewayResultMarkers };\n\n const createHandler = (method: 'GET' | 'POST'): SazitoPaymentRouteHandler =>\n async (request) => {\n if (request.method.toUpperCase() !== method) {\n return errorResponse(405, 'method_not_allowed', { Allow: method });\n }\n\n try {\n const callback = parsePaymentReturnUrl(request.url, parserOptions);\n if (!callback || callback.resolution === 'status') {\n return errorResponse(400, 'invalid_payment_callback');\n }\n\n const requestUrl = new URL(request.url);\n const body = method === 'POST'\n ? await readCallbackBody(request, maxCallbackBodyBytes)\n : undefined;\n const query = fieldsFromSearchParams(requestUrl.searchParams);\n const client = createSazitoClient(sdkConfig);\n const verification = await client.payments.verifyPaymentCallback({\n paymentId: callback.payment.id,\n paymentIdentifier: callback.payment.identifier,\n body,\n query\n });\n\n if (verification.error || !verification.data) {\n if (sdkConfig.debug) {\n console.error('[Sazito Checkout] Payment callback verification failed:', {\n paymentId: callback.payment.id,\n error: verification.error\n });\n }\n return errorResponse(502, 'payment_verification_failed');\n }\n\n const redirectUrl = createStatusRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment\n );\n return new Response(null, {\n status: 303,\n headers: {\n Location: redirectUrl.toString(),\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer'\n }\n });\n } catch (error) {\n if (config.debug) {\n console.error('[Sazito Checkout] Invalid payment callback request:', error);\n }\n const status = error instanceof CallbackRequestError ? error.status : 500;\n const code = error instanceof CallbackRequestError\n ? error.code\n : 'payment_callback_failed';\n return errorResponse(status, code);\n }\n };\n\n return {\n handlers: {\n GET: createHandler('GET'),\n POST: createHandler('POST')\n }\n };\n}\n\nfunction validateConfig(\n config: SazitoConfig,\n checkoutPath: string,\n maxCallbackBodyBytes: number\n): void {\n if (!config.domain?.trim()) {\n throw new Error('[@sazito/checkout] `domain` is required by the payment callback handler.');\n }\n if (!checkoutPath.trim()) {\n throw new Error('[@sazito/checkout] `checkoutPath` cannot be empty.');\n }\n if (!Number.isSafeInteger(maxCallbackBodyBytes) || maxCallbackBodyBytes <= 0) {\n throw new Error('[@sazito/checkout] `maxCallbackBodyBytes` must be a positive integer.');\n }\n}\n\nasync function readCallbackBody(\n request: Request,\n maxBodyBytes: number\n): Promise<PaymentCallbackFields> {\n const declaredLength = Number(request.headers.get('content-length') ?? 0);\n if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n\n const bytes = await request.arrayBuffer();\n if (bytes.byteLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n if (bytes.byteLength === 0) return {};\n\n const contentType = request.headers.get('content-type')?.toLowerCase() ?? '';\n if (contentType.includes('application/json')) {\n return fieldsFromJson(new TextDecoder().decode(bytes));\n }\n if (contentType.includes('multipart/form-data')) {\n const form = await new Response(bytes, {\n headers: { 'Content-Type': request.headers.get('content-type') ?? '' }\n }).formData();\n return fieldsFromFormData(form);\n }\n\n // Gateways commonly omit Content-Type or label URL-encoded data as text.\n return fieldsFromSearchParams(new URLSearchParams(new TextDecoder().decode(bytes)));\n}\n\nfunction fieldsFromJson(source: string): PaymentCallbackFields {\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n return value as PaymentCallbackFields;\n}\n\nfunction fieldsFromSearchParams(params: URLSearchParams): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of params) appendField(fields, name, value);\n return fields;\n}\n\nfunction fieldsFromFormData(form: FormData): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of form) {\n if (typeof value !== 'string') {\n throw new CallbackRequestError(400, 'unsupported_payment_callback_file');\n }\n appendField(fields, name, value);\n }\n return fields;\n}\n\nfunction appendField(\n fields: PaymentCallbackFields,\n name: string,\n value: PaymentCallbackFieldValue\n): void {\n const current = fields[name];\n if (current === undefined) {\n fields[name] = value;\n } else if (Array.isArray(current)) {\n fields[name] = [...current, value ?? null];\n } else {\n fields[name] = [current, value ?? null];\n }\n}\n\nfunction createStatusRedirectUrl(\n requestUrl: URL,\n checkoutPath: string,\n payment: { id: number; identifier: string }\n): URL {\n const redirectUrl = new URL(checkoutPath, requestUrl.origin);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, 'status');\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));\n redirectUrl.searchParams.set(\n SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier,\n payment.identifier\n );\n return redirectUrl;\n}\n\nfunction errorResponse(\n status: number,\n code: string,\n extraHeaders: Record<string, string> = {}\n): Response {\n return Response.json(\n { error: code },\n {\n status,\n headers: {\n 'Cache-Control': 'no-store',\n ...extraHeaders\n }\n }\n );\n}\n\nclass CallbackRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string\n ) {\n super(code);\n }\n}\n"],"names":["parsePaymentReturnUrl","createSazitoClient","SAZITO_PAYMENT_STATUS_QUERY"],"mappings":";;;;;AAAA;;;;;AAKG;AAaH,MAAM,qBAAqB,GAAG,WAAW;AACzC,MAAM,sBAAsB,GAAG,EAAE,GAAG,IAAI;AAoBxC;;;;AAIG;AACG,SAAU,cAAc,CAAC,MAAkC,EAAA;AAC/D,IAAA,MAAM,EACJ,YAAY,GAAG,qBAAqB,EACpC,oBAAoB,GAAG,sBAAsB,EAC7C,oBAAoB,EACpB,GAAG,SAAS,EACb,GAAG,MAAM;AAEV,IAAA,cAAc,CAAC,SAAS,EAAE,YAAY,EAAE,oBAAoB,CAAC;AAC7D,IAAA,MAAM,aAAa,GAA+B,EAAE,oBAAoB,EAAE;IAE1E,MAAM,aAAa,GAAG,CAAC,MAAsB,KAC3C,OAAO,OAAO,KAAI;QAChB,IAAI,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE;AAC3C,YAAA,OAAO,aAAa,CAAC,GAAG,EAAE,oBAAoB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QACpE;AAEA,QAAA,IAAI;YACF,MAAM,QAAQ,GAAGA,wCAAqB,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC;YAClE,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,KAAK,QAAQ,EAAE;AACjD,gBAAA,OAAO,aAAa,CAAC,GAAG,EAAE,0BAA0B,CAAC;YACvD;YAEA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;AACvC,YAAA,MAAM,IAAI,GAAG,MAAM,KAAK;AACtB,kBAAE,MAAM,gBAAgB,CAAC,OAAO,EAAE,oBAAoB;kBACpD,SAAS;YACb,MAAM,KAAK,GAAG,sBAAsB,CAAC,UAAU,CAAC,YAAY,CAAC;AAC7D,YAAA,MAAM,MAAM,GAAGC,4BAAkB,CAAC,SAAS,CAAC;YAC5C,MAAM,YAAY,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,qBAAqB,CAAC;AAC/D,gBAAA,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;AAC9B,gBAAA,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU;gBAC9C,IAAI;gBACJ;AACD,aAAA,CAAC;YAEF,IAAI,YAAY,CAAC,KAAK,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;AAC5C,gBAAA,IAAI,SAAS,CAAC,KAAK,EAAE;AACnB,oBAAA,OAAO,CAAC,KAAK,CAAC,yDAAyD,EAAE;AACvE,wBAAA,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE;wBAC9B,KAAK,EAAE,YAAY,CAAC;AACrB,qBAAA,CAAC;gBACJ;AACA,gBAAA,OAAO,aAAa,CAAC,GAAG,EAAE,6BAA6B,CAAC;YAC1D;AAEA,YAAA,MAAM,WAAW,GAAG,uBAAuB,CACzC,UAAU,EACV,YAAY,EACZ,QAAQ,CAAC,OAAO,CACjB;AACD,YAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;AACxB,gBAAA,MAAM,EAAE,GAAG;AACX,gBAAA,OAAO,EAAE;AACP,oBAAA,QAAQ,EAAE,WAAW,CAAC,QAAQ,EAAE;AAChC,oBAAA,eAAe,EAAE,UAAU;AAC3B,oBAAA,iBAAiB,EAAE;AACpB;AACF,aAAA,CAAC;QACJ;QAAE,OAAO,KAAK,EAAE;AACd,YAAA,IAAI,MAAM,CAAC,KAAK,EAAE;AAChB,gBAAA,OAAO,CAAC,KAAK,CAAC,qDAAqD,EAAE,KAAK,CAAC;YAC7E;AACA,YAAA,MAAM,MAAM,GAAG,KAAK,YAAY,oBAAoB,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG;AACzE,YAAA,MAAM,IAAI,GAAG,KAAK,YAAY;kBAC1B,KAAK,CAAC;kBACN,yBAAyB;AAC7B,YAAA,OAAO,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC;QACpC;AACF,IAAA,CAAC;IAEH,OAAO;AACL,QAAA,QAAQ,EAAE;AACR,YAAA,GAAG,EAAE,aAAa,CAAC,KAAK,CAAC;AACzB,YAAA,IAAI,EAAE,aAAa,CAAC,MAAM;AAC3B;KACF;AACH;AAEA,SAAS,cAAc,CACrB,MAAoB,EACpB,YAAoB,EACpB,oBAA4B,EAAA;IAE5B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;AAC1B,QAAA,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC;IAC7F;AACA,IAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE;AACxB,QAAA,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC;IACvE;AACA,IAAA,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,oBAAoB,CAAC,IAAI,oBAAoB,IAAI,CAAC,EAAE;AAC5E,QAAA,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC;IAC1F;AACF;AAEA,eAAe,gBAAgB,CAC7B,OAAgB,EAChB,YAAoB,EAAA;AAEpB,IAAA,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,cAAc,GAAG,YAAY,EAAE;AACpE,QAAA,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,4BAA4B,CAAC;IACnE;AAEA,IAAA,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE;AACzC,IAAA,IAAI,KAAK,CAAC,UAAU,GAAG,YAAY,EAAE;AACnC,QAAA,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,4BAA4B,CAAC;IACnE;AACA,IAAA,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC;AAAE,QAAA,OAAO,EAAE;AAErC,IAAA,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE;AAC5E,IAAA,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QAC5C,OAAO,cAAc,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxD;AACA,IAAA,IAAI,WAAW,CAAC,QAAQ,CAAC,qBAAqB,CAAC,EAAE;AAC/C,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,QAAQ,CAAC,KAAK,EAAE;AACrC,YAAA,OAAO,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;SACrE,CAAC,CAAC,QAAQ,EAAE;AACb,QAAA,OAAO,kBAAkB,CAAC,IAAI,CAAC;IACjC;;AAGA,IAAA,OAAO,sBAAsB,CAAC,IAAI,eAAe,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACrF;AAEA,SAAS,cAAc,CAAC,MAAc,EAAA;AACpC,IAAA,IAAI,KAAc;AAClB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC5B;AAAE,IAAA,MAAM;AACN,QAAA,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,+BAA+B,CAAC;IACtE;AACA,IAAA,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AAC/D,QAAA,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,+BAA+B,CAAC;IACtE;AACA,IAAA,OAAO,KAA8B;AACvC;AAEA,SAAS,sBAAsB,CAAC,MAAuB,EAAA;IACrD,MAAM,MAAM,GAA0B,EAAE;AACxC,IAAA,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM;AAAE,QAAA,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;AACpE,IAAA,OAAO,MAAM;AACf;AAEA,SAAS,kBAAkB,CAAC,IAAc,EAAA;IACxC,MAAM,MAAM,GAA0B,EAAE;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE;AAChC,QAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,YAAA,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,mCAAmC,CAAC;QAC1E;AACA,QAAA,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC;IAClC;AACA,IAAA,OAAO,MAAM;AACf;AAEA,SAAS,WAAW,CAClB,MAA6B,EAC7B,IAAY,EACZ,KAAgC,EAAA;AAEhC,IAAA,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;AAC5B,IAAA,IAAI,OAAO,KAAK,SAAS,EAAE;AACzB,QAAA,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK;IACtB;AAAO,SAAA,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;AACjC,QAAA,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC;IAC5C;SAAO;QACL,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,IAAI,CAAC;IACzC;AACF;AAEA,SAAS,uBAAuB,CAC9B,UAAe,EACf,YAAoB,EACpB,OAA2C,EAAA;IAE3C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,YAAY,EAAE,UAAU,CAAC,MAAM,CAAC;IAC5D,WAAW,CAAC,YAAY,CAAC,GAAG,CAACC,8CAA2B,CAAC,UAAU,EAAE,QAAQ,CAAC;AAC9E,IAAA,WAAW,CAAC,YAAY,CAAC,GAAG,CAACA,8CAA2B,CAAC,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AACvF,IAAA,WAAW,CAAC,YAAY,CAAC,GAAG,CAC1BA,8CAA2B,CAAC,iBAAiB,EAC7C,OAAO,CAAC,UAAU,CACnB;AACD,IAAA,OAAO,WAAW;AACpB;AAEA,SAAS,aAAa,CACpB,MAAc,EACd,IAAY,EACZ,eAAuC,EAAE,EAAA;IAEzC,OAAO,QAAQ,CAAC,IAAI,CAClB,EAAE,KAAK,EAAE,IAAI,EAAE,EACf;QACE,MAAM;AACN,QAAA,OAAO,EAAE;AACP,YAAA,eAAe,EAAE,UAAU;AAC3B,YAAA,GAAG;AACJ;AACF,KAAA,CACF;AACH;AAEA,MAAM,oBAAqB,SAAQ,KAAK,CAAA;IACtC,WAAA,CACW,MAAc,EACd,IAAY,EAAA;QAErB,KAAK,CAAC,IAAI,CAAC;QAHF,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,IAAI,GAAJ,IAAI;IAGf;AACD;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * @sazito/checkout/server — server-only payment callback handlers.\n *\n * The implementation uses only the standard Web Request/Response APIs so the\n * same handlers work in Next.js Route Handlers and other compatible runtimes.\n */\nimport {\n createSazitoClient,\n type PaymentCallbackFieldValue,\n type PaymentCallbackFields,\n type SazitoConfig\n} from '@sazito/client-sdk';\nimport {\n parsePaymentReturnUrl,\n SAZITO_PAYMENT_STATUS_QUERY\n} from '../core/payment-return';\nimport type { PaymentReturnParserOptions } from '../core/types';\n\nconst DEFAULT_CHECKOUT_PATH = '/checkout';\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1024;\nconst BROWSER_FINALIZED_RESULT_MARKERS = new Set(['paymentinplaceresult']);\n\nexport type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;\n\nexport interface SazitoCheckoutServerConfig extends SazitoConfig {\n /** Page that renders `SazitoCheckoutPage` after server verification. */\n checkoutPath?: string;\n /** Maximum accepted gateway callback body size. Defaults to 64 KiB. */\n maxCallbackBodyBytes?: number;\n /** Replace the built-in gateway-result marker allowlist. */\n gatewayResultMarkers?: readonly string[];\n}\n\nexport interface SazitoCheckoutServer {\n handlers: {\n GET: SazitoPaymentRouteHandler;\n POST: SazitoPaymentRouteHandler;\n };\n}\n\n/**\n * Create GET and POST route handlers for payment callbacks.\n * A fresh SDK client is created for each request so server-side guest\n * credentials can never leak between concurrent callbacks.\n */\nexport function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer {\n const {\n checkoutPath = DEFAULT_CHECKOUT_PATH,\n maxCallbackBodyBytes = DEFAULT_MAX_BODY_BYTES,\n gatewayResultMarkers,\n ...sdkConfig\n } = config;\n\n validateConfig(sdkConfig, checkoutPath, maxCallbackBodyBytes);\n const parserOptions: PaymentReturnParserOptions = { gatewayResultMarkers };\n\n const createHandler = (method: 'GET' | 'POST'): SazitoPaymentRouteHandler =>\n async (request) => {\n if (request.method.toUpperCase() !== method) {\n return errorResponse(405, 'method_not_allowed', { Allow: method });\n }\n\n try {\n const callback = parsePaymentReturnUrl(request.url, parserOptions);\n if (!callback || callback.resolution === 'status') {\n return errorResponse(400, 'invalid_payment_callback');\n }\n\n const requestUrl = new URL(request.url);\n const body = method === 'POST'\n ? await readCallbackBody(request, maxCallbackBodyBytes)\n : undefined;\n const query = fieldsFromSearchParams(requestUrl.searchParams);\n\n // Payment-in-place uses an empty POST only to return control to the\n // storefront. Processing it on the server and then performing a status\n // read in the browser calls process_payment_step twice; some deployments\n // report the second call as failed even though the first one created the\n // order. Redirect the empty first-party callback to the browser so the\n // order is finalized exactly once and the returned order can be rendered.\n if (shouldFinalizeInBrowser(requestUrl, body, query)) {\n return redirectResponse(createPaymentReturnRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment,\n 'callback'\n ));\n }\n\n const client = createSazitoClient(sdkConfig);\n const verification = await client.payments.verifyPaymentCallback({\n paymentId: callback.payment.id,\n paymentIdentifier: callback.payment.identifier,\n body,\n query\n });\n\n if (verification.error || !verification.data) {\n if (sdkConfig.debug) {\n console.error('[Sazito Checkout] Payment callback verification failed:', {\n paymentId: callback.payment.id,\n error: verification.error\n });\n }\n return errorResponse(502, 'payment_verification_failed');\n }\n\n const redirectUrl = createPaymentReturnRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment,\n 'status'\n );\n return redirectResponse(redirectUrl);\n } catch (error) {\n if (config.debug) {\n console.error('[Sazito Checkout] Invalid payment callback request:', error);\n }\n const status = error instanceof CallbackRequestError ? error.status : 500;\n const code = error instanceof CallbackRequestError\n ? error.code\n : 'payment_callback_failed';\n return errorResponse(status, code);\n }\n };\n\n return {\n handlers: {\n GET: createHandler('GET'),\n POST: createHandler('POST')\n }\n };\n}\n\nfunction validateConfig(\n config: SazitoConfig,\n checkoutPath: string,\n maxCallbackBodyBytes: number\n): void {\n if (!config.domain?.trim()) {\n throw new Error('[@sazito/checkout] `domain` is required by the payment callback handler.');\n }\n if (!checkoutPath.trim()) {\n throw new Error('[@sazito/checkout] `checkoutPath` cannot be empty.');\n }\n if (!Number.isSafeInteger(maxCallbackBodyBytes) || maxCallbackBodyBytes <= 0) {\n throw new Error('[@sazito/checkout] `maxCallbackBodyBytes` must be a positive integer.');\n }\n}\n\nasync function readCallbackBody(\n request: Request,\n maxBodyBytes: number\n): Promise<PaymentCallbackFields> {\n const declaredLength = Number(request.headers.get('content-length') ?? 0);\n if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n\n const bytes = await request.arrayBuffer();\n if (bytes.byteLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n if (bytes.byteLength === 0) return {};\n\n const contentType = request.headers.get('content-type')?.toLowerCase() ?? '';\n if (contentType.includes('application/json')) {\n return fieldsFromJson(new TextDecoder().decode(bytes));\n }\n if (contentType.includes('multipart/form-data')) {\n const form = await new Response(bytes, {\n headers: { 'Content-Type': request.headers.get('content-type') ?? '' }\n }).formData();\n return fieldsFromFormData(form);\n }\n\n // Gateways commonly omit Content-Type or label URL-encoded data as text.\n return fieldsFromSearchParams(new URLSearchParams(new TextDecoder().decode(bytes)));\n}\n\nfunction fieldsFromJson(source: string): PaymentCallbackFields {\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n return value as PaymentCallbackFields;\n}\n\nfunction fieldsFromSearchParams(params: URLSearchParams): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of params) appendField(fields, name, value);\n return fields;\n}\n\nfunction fieldsFromFormData(form: FormData): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of form) {\n if (typeof value !== 'string') {\n throw new CallbackRequestError(400, 'unsupported_payment_callback_file');\n }\n appendField(fields, name, value);\n }\n return fields;\n}\n\nfunction appendField(\n fields: PaymentCallbackFields,\n name: string,\n value: PaymentCallbackFieldValue\n): void {\n const current = fields[name];\n if (current === undefined) {\n fields[name] = value;\n } else if (Array.isArray(current)) {\n fields[name] = [...current, value ?? null];\n } else {\n fields[name] = [current, value ?? null];\n }\n}\n\nfunction shouldFinalizeInBrowser(\n requestUrl: URL,\n body: PaymentCallbackFields | undefined,\n query: PaymentCallbackFields\n): boolean {\n const pathSegments = requestUrl.pathname\n .split('/')\n .filter(Boolean);\n const resultMarker = pathSegments[pathSegments.length - 5]?.toLowerCase();\n\n return Boolean(\n resultMarker &&\n BROWSER_FINALIZED_RESULT_MARKERS.has(resultMarker) &&\n Object.keys(body ?? {}).length === 0 &&\n Object.keys(query).length === 0\n );\n}\n\nfunction createPaymentReturnRedirectUrl(\n requestUrl: URL,\n checkoutPath: string,\n payment: { id: number; identifier: string },\n resolution: 'callback' | 'status'\n): URL {\n const redirectUrl = new URL(checkoutPath, requestUrl.origin);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, resolution);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));\n redirectUrl.searchParams.set(\n SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier,\n payment.identifier\n );\n return redirectUrl;\n}\n\nfunction redirectResponse(url: URL): Response {\n return new Response(null, {\n status: 303,\n headers: {\n Location: url.toString(),\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer'\n }\n });\n}\n\nfunction errorResponse(\n status: number,\n code: string,\n extraHeaders: Record<string, string> = {}\n): Response {\n return Response.json(\n { error: code },\n {\n status,\n headers: {\n 'Cache-Control': 'no-store',\n ...extraHeaders\n }\n }\n );\n}\n\nclass CallbackRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string\n ) {\n super(code);\n }\n}\n"],"names":["parsePaymentReturnUrl","createSazitoClient","SAZITO_PAYMENT_STATUS_QUERY"],"mappings":"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"}
@@ -9,6 +9,7 @@ import { parsePaymentReturnUrl, SAZITO_PAYMENT_STATUS_QUERY } from '../next/paym
9
9
  */
10
10
  const DEFAULT_CHECKOUT_PATH = '/checkout';
11
11
  const DEFAULT_MAX_BODY_BYTES = 64 * 1024;
12
+ const BROWSER_FINALIZED_RESULT_MARKERS = new Set(['paymentinplaceresult']);
12
13
  /**
13
14
  * Create GET and POST route handlers for payment callbacks.
14
15
  * A fresh SDK client is created for each request so server-side guest
@@ -32,6 +33,15 @@ function SazitoCheckout(config) {
32
33
  ? await readCallbackBody(request, maxCallbackBodyBytes)
33
34
  : undefined;
34
35
  const query = fieldsFromSearchParams(requestUrl.searchParams);
36
+ // Payment-in-place uses an empty POST only to return control to the
37
+ // storefront. Processing it on the server and then performing a status
38
+ // read in the browser calls process_payment_step twice; some deployments
39
+ // report the second call as failed even though the first one created the
40
+ // order. Redirect the empty first-party callback to the browser so the
41
+ // order is finalized exactly once and the returned order can be rendered.
42
+ if (shouldFinalizeInBrowser(requestUrl, body, query)) {
43
+ return redirectResponse(createPaymentReturnRedirectUrl(requestUrl, checkoutPath, callback.payment, 'callback'));
44
+ }
35
45
  const client = createSazitoClient(sdkConfig);
36
46
  const verification = await client.payments.verifyPaymentCallback({
37
47
  paymentId: callback.payment.id,
@@ -48,15 +58,8 @@ function SazitoCheckout(config) {
48
58
  }
49
59
  return errorResponse(502, 'payment_verification_failed');
50
60
  }
51
- const redirectUrl = createStatusRedirectUrl(requestUrl, checkoutPath, callback.payment);
52
- return new Response(null, {
53
- status: 303,
54
- headers: {
55
- Location: redirectUrl.toString(),
56
- 'Cache-Control': 'no-store',
57
- 'Referrer-Policy': 'no-referrer'
58
- }
59
- });
61
+ const redirectUrl = createPaymentReturnRedirectUrl(requestUrl, checkoutPath, callback.payment, 'status');
62
+ return redirectResponse(redirectUrl);
60
63
  }
61
64
  catch (error) {
62
65
  if (config.debug) {
@@ -152,13 +155,33 @@ function appendField(fields, name, value) {
152
155
  fields[name] = [current, value ?? null];
153
156
  }
154
157
  }
155
- function createStatusRedirectUrl(requestUrl, checkoutPath, payment) {
158
+ function shouldFinalizeInBrowser(requestUrl, body, query) {
159
+ const pathSegments = requestUrl.pathname
160
+ .split('/')
161
+ .filter(Boolean);
162
+ const resultMarker = pathSegments[pathSegments.length - 5]?.toLowerCase();
163
+ return Boolean(resultMarker &&
164
+ BROWSER_FINALIZED_RESULT_MARKERS.has(resultMarker) &&
165
+ Object.keys(body ?? {}).length === 0 &&
166
+ Object.keys(query).length === 0);
167
+ }
168
+ function createPaymentReturnRedirectUrl(requestUrl, checkoutPath, payment, resolution) {
156
169
  const redirectUrl = new URL(checkoutPath, requestUrl.origin);
157
- redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, 'status');
170
+ redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, resolution);
158
171
  redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));
159
172
  redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier, payment.identifier);
160
173
  return redirectUrl;
161
174
  }
175
+ function redirectResponse(url) {
176
+ return new Response(null, {
177
+ status: 303,
178
+ headers: {
179
+ Location: url.toString(),
180
+ 'Cache-Control': 'no-store',
181
+ 'Referrer-Policy': 'no-referrer'
182
+ }
183
+ });
184
+ }
162
185
  function errorResponse(status, code, extraHeaders = {}) {
163
186
  return Response.json({ error: code }, {
164
187
  status,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * @sazito/checkout/server — server-only payment callback handlers.\n *\n * The implementation uses only the standard Web Request/Response APIs so the\n * same handlers work in Next.js Route Handlers and other compatible runtimes.\n */\nimport {\n createSazitoClient,\n type PaymentCallbackFieldValue,\n type PaymentCallbackFields,\n type SazitoConfig\n} from '@sazito/client-sdk';\nimport {\n parsePaymentReturnUrl,\n SAZITO_PAYMENT_STATUS_QUERY\n} from '../core/payment-return';\nimport type { PaymentReturnParserOptions } from '../core/types';\n\nconst DEFAULT_CHECKOUT_PATH = '/checkout';\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1024;\n\nexport type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;\n\nexport interface SazitoCheckoutServerConfig extends SazitoConfig {\n /** Page that renders `SazitoCheckoutPage` after server verification. */\n checkoutPath?: string;\n /** Maximum accepted gateway callback body size. Defaults to 64 KiB. */\n maxCallbackBodyBytes?: number;\n /** Replace the built-in gateway-result marker allowlist. */\n gatewayResultMarkers?: readonly string[];\n}\n\nexport interface SazitoCheckoutServer {\n handlers: {\n GET: SazitoPaymentRouteHandler;\n POST: SazitoPaymentRouteHandler;\n };\n}\n\n/**\n * Create GET and POST route handlers for payment callbacks.\n * A fresh SDK client is created for each request so server-side guest\n * credentials can never leak between concurrent callbacks.\n */\nexport function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer {\n const {\n checkoutPath = DEFAULT_CHECKOUT_PATH,\n maxCallbackBodyBytes = DEFAULT_MAX_BODY_BYTES,\n gatewayResultMarkers,\n ...sdkConfig\n } = config;\n\n validateConfig(sdkConfig, checkoutPath, maxCallbackBodyBytes);\n const parserOptions: PaymentReturnParserOptions = { gatewayResultMarkers };\n\n const createHandler = (method: 'GET' | 'POST'): SazitoPaymentRouteHandler =>\n async (request) => {\n if (request.method.toUpperCase() !== method) {\n return errorResponse(405, 'method_not_allowed', { Allow: method });\n }\n\n try {\n const callback = parsePaymentReturnUrl(request.url, parserOptions);\n if (!callback || callback.resolution === 'status') {\n return errorResponse(400, 'invalid_payment_callback');\n }\n\n const requestUrl = new URL(request.url);\n const body = method === 'POST'\n ? await readCallbackBody(request, maxCallbackBodyBytes)\n : undefined;\n const query = fieldsFromSearchParams(requestUrl.searchParams);\n const client = createSazitoClient(sdkConfig);\n const verification = await client.payments.verifyPaymentCallback({\n paymentId: callback.payment.id,\n paymentIdentifier: callback.payment.identifier,\n body,\n query\n });\n\n if (verification.error || !verification.data) {\n if (sdkConfig.debug) {\n console.error('[Sazito Checkout] Payment callback verification failed:', {\n paymentId: callback.payment.id,\n error: verification.error\n });\n }\n return errorResponse(502, 'payment_verification_failed');\n }\n\n const redirectUrl = createStatusRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment\n );\n return new Response(null, {\n status: 303,\n headers: {\n Location: redirectUrl.toString(),\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer'\n }\n });\n } catch (error) {\n if (config.debug) {\n console.error('[Sazito Checkout] Invalid payment callback request:', error);\n }\n const status = error instanceof CallbackRequestError ? error.status : 500;\n const code = error instanceof CallbackRequestError\n ? error.code\n : 'payment_callback_failed';\n return errorResponse(status, code);\n }\n };\n\n return {\n handlers: {\n GET: createHandler('GET'),\n POST: createHandler('POST')\n }\n };\n}\n\nfunction validateConfig(\n config: SazitoConfig,\n checkoutPath: string,\n maxCallbackBodyBytes: number\n): void {\n if (!config.domain?.trim()) {\n throw new Error('[@sazito/checkout] `domain` is required by the payment callback handler.');\n }\n if (!checkoutPath.trim()) {\n throw new Error('[@sazito/checkout] `checkoutPath` cannot be empty.');\n }\n if (!Number.isSafeInteger(maxCallbackBodyBytes) || maxCallbackBodyBytes <= 0) {\n throw new Error('[@sazito/checkout] `maxCallbackBodyBytes` must be a positive integer.');\n }\n}\n\nasync function readCallbackBody(\n request: Request,\n maxBodyBytes: number\n): Promise<PaymentCallbackFields> {\n const declaredLength = Number(request.headers.get('content-length') ?? 0);\n if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n\n const bytes = await request.arrayBuffer();\n if (bytes.byteLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n if (bytes.byteLength === 0) return {};\n\n const contentType = request.headers.get('content-type')?.toLowerCase() ?? '';\n if (contentType.includes('application/json')) {\n return fieldsFromJson(new TextDecoder().decode(bytes));\n }\n if (contentType.includes('multipart/form-data')) {\n const form = await new Response(bytes, {\n headers: { 'Content-Type': request.headers.get('content-type') ?? '' }\n }).formData();\n return fieldsFromFormData(form);\n }\n\n // Gateways commonly omit Content-Type or label URL-encoded data as text.\n return fieldsFromSearchParams(new URLSearchParams(new TextDecoder().decode(bytes)));\n}\n\nfunction fieldsFromJson(source: string): PaymentCallbackFields {\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n return value as PaymentCallbackFields;\n}\n\nfunction fieldsFromSearchParams(params: URLSearchParams): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of params) appendField(fields, name, value);\n return fields;\n}\n\nfunction fieldsFromFormData(form: FormData): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of form) {\n if (typeof value !== 'string') {\n throw new CallbackRequestError(400, 'unsupported_payment_callback_file');\n }\n appendField(fields, name, value);\n }\n return fields;\n}\n\nfunction appendField(\n fields: PaymentCallbackFields,\n name: string,\n value: PaymentCallbackFieldValue\n): void {\n const current = fields[name];\n if (current === undefined) {\n fields[name] = value;\n } else if (Array.isArray(current)) {\n fields[name] = [...current, value ?? null];\n } else {\n fields[name] = [current, value ?? null];\n }\n}\n\nfunction createStatusRedirectUrl(\n requestUrl: URL,\n checkoutPath: string,\n payment: { id: number; identifier: string }\n): URL {\n const redirectUrl = new URL(checkoutPath, requestUrl.origin);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, 'status');\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));\n redirectUrl.searchParams.set(\n SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier,\n payment.identifier\n );\n return redirectUrl;\n}\n\nfunction errorResponse(\n status: number,\n code: string,\n extraHeaders: Record<string, string> = {}\n): Response {\n return Response.json(\n { error: code },\n {\n status,\n headers: {\n 'Cache-Control': 'no-store',\n ...extraHeaders\n }\n }\n );\n}\n\nclass CallbackRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string\n ) {\n super(code);\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/server/index.ts"],"sourcesContent":["/**\n * @sazito/checkout/server — server-only payment callback handlers.\n *\n * The implementation uses only the standard Web Request/Response APIs so the\n * same handlers work in Next.js Route Handlers and other compatible runtimes.\n */\nimport {\n createSazitoClient,\n type PaymentCallbackFieldValue,\n type PaymentCallbackFields,\n type SazitoConfig\n} from '@sazito/client-sdk';\nimport {\n parsePaymentReturnUrl,\n SAZITO_PAYMENT_STATUS_QUERY\n} from '../core/payment-return';\nimport type { PaymentReturnParserOptions } from '../core/types';\n\nconst DEFAULT_CHECKOUT_PATH = '/checkout';\nconst DEFAULT_MAX_BODY_BYTES = 64 * 1024;\nconst BROWSER_FINALIZED_RESULT_MARKERS = new Set(['paymentinplaceresult']);\n\nexport type SazitoPaymentRouteHandler = (request: Request) => Promise<Response>;\n\nexport interface SazitoCheckoutServerConfig extends SazitoConfig {\n /** Page that renders `SazitoCheckoutPage` after server verification. */\n checkoutPath?: string;\n /** Maximum accepted gateway callback body size. Defaults to 64 KiB. */\n maxCallbackBodyBytes?: number;\n /** Replace the built-in gateway-result marker allowlist. */\n gatewayResultMarkers?: readonly string[];\n}\n\nexport interface SazitoCheckoutServer {\n handlers: {\n GET: SazitoPaymentRouteHandler;\n POST: SazitoPaymentRouteHandler;\n };\n}\n\n/**\n * Create GET and POST route handlers for payment callbacks.\n * A fresh SDK client is created for each request so server-side guest\n * credentials can never leak between concurrent callbacks.\n */\nexport function SazitoCheckout(config: SazitoCheckoutServerConfig): SazitoCheckoutServer {\n const {\n checkoutPath = DEFAULT_CHECKOUT_PATH,\n maxCallbackBodyBytes = DEFAULT_MAX_BODY_BYTES,\n gatewayResultMarkers,\n ...sdkConfig\n } = config;\n\n validateConfig(sdkConfig, checkoutPath, maxCallbackBodyBytes);\n const parserOptions: PaymentReturnParserOptions = { gatewayResultMarkers };\n\n const createHandler = (method: 'GET' | 'POST'): SazitoPaymentRouteHandler =>\n async (request) => {\n if (request.method.toUpperCase() !== method) {\n return errorResponse(405, 'method_not_allowed', { Allow: method });\n }\n\n try {\n const callback = parsePaymentReturnUrl(request.url, parserOptions);\n if (!callback || callback.resolution === 'status') {\n return errorResponse(400, 'invalid_payment_callback');\n }\n\n const requestUrl = new URL(request.url);\n const body = method === 'POST'\n ? await readCallbackBody(request, maxCallbackBodyBytes)\n : undefined;\n const query = fieldsFromSearchParams(requestUrl.searchParams);\n\n // Payment-in-place uses an empty POST only to return control to the\n // storefront. Processing it on the server and then performing a status\n // read in the browser calls process_payment_step twice; some deployments\n // report the second call as failed even though the first one created the\n // order. Redirect the empty first-party callback to the browser so the\n // order is finalized exactly once and the returned order can be rendered.\n if (shouldFinalizeInBrowser(requestUrl, body, query)) {\n return redirectResponse(createPaymentReturnRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment,\n 'callback'\n ));\n }\n\n const client = createSazitoClient(sdkConfig);\n const verification = await client.payments.verifyPaymentCallback({\n paymentId: callback.payment.id,\n paymentIdentifier: callback.payment.identifier,\n body,\n query\n });\n\n if (verification.error || !verification.data) {\n if (sdkConfig.debug) {\n console.error('[Sazito Checkout] Payment callback verification failed:', {\n paymentId: callback.payment.id,\n error: verification.error\n });\n }\n return errorResponse(502, 'payment_verification_failed');\n }\n\n const redirectUrl = createPaymentReturnRedirectUrl(\n requestUrl,\n checkoutPath,\n callback.payment,\n 'status'\n );\n return redirectResponse(redirectUrl);\n } catch (error) {\n if (config.debug) {\n console.error('[Sazito Checkout] Invalid payment callback request:', error);\n }\n const status = error instanceof CallbackRequestError ? error.status : 500;\n const code = error instanceof CallbackRequestError\n ? error.code\n : 'payment_callback_failed';\n return errorResponse(status, code);\n }\n };\n\n return {\n handlers: {\n GET: createHandler('GET'),\n POST: createHandler('POST')\n }\n };\n}\n\nfunction validateConfig(\n config: SazitoConfig,\n checkoutPath: string,\n maxCallbackBodyBytes: number\n): void {\n if (!config.domain?.trim()) {\n throw new Error('[@sazito/checkout] `domain` is required by the payment callback handler.');\n }\n if (!checkoutPath.trim()) {\n throw new Error('[@sazito/checkout] `checkoutPath` cannot be empty.');\n }\n if (!Number.isSafeInteger(maxCallbackBodyBytes) || maxCallbackBodyBytes <= 0) {\n throw new Error('[@sazito/checkout] `maxCallbackBodyBytes` must be a positive integer.');\n }\n}\n\nasync function readCallbackBody(\n request: Request,\n maxBodyBytes: number\n): Promise<PaymentCallbackFields> {\n const declaredLength = Number(request.headers.get('content-length') ?? 0);\n if (Number.isFinite(declaredLength) && declaredLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n\n const bytes = await request.arrayBuffer();\n if (bytes.byteLength > maxBodyBytes) {\n throw new CallbackRequestError(413, 'payment_callback_too_large');\n }\n if (bytes.byteLength === 0) return {};\n\n const contentType = request.headers.get('content-type')?.toLowerCase() ?? '';\n if (contentType.includes('application/json')) {\n return fieldsFromJson(new TextDecoder().decode(bytes));\n }\n if (contentType.includes('multipart/form-data')) {\n const form = await new Response(bytes, {\n headers: { 'Content-Type': request.headers.get('content-type') ?? '' }\n }).formData();\n return fieldsFromFormData(form);\n }\n\n // Gateways commonly omit Content-Type or label URL-encoded data as text.\n return fieldsFromSearchParams(new URLSearchParams(new TextDecoder().decode(bytes)));\n}\n\nfunction fieldsFromJson(source: string): PaymentCallbackFields {\n let value: unknown;\n try {\n value = JSON.parse(source);\n } catch {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new CallbackRequestError(400, 'invalid_payment_callback_body');\n }\n return value as PaymentCallbackFields;\n}\n\nfunction fieldsFromSearchParams(params: URLSearchParams): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of params) appendField(fields, name, value);\n return fields;\n}\n\nfunction fieldsFromFormData(form: FormData): PaymentCallbackFields {\n const fields: PaymentCallbackFields = {};\n for (const [name, value] of form) {\n if (typeof value !== 'string') {\n throw new CallbackRequestError(400, 'unsupported_payment_callback_file');\n }\n appendField(fields, name, value);\n }\n return fields;\n}\n\nfunction appendField(\n fields: PaymentCallbackFields,\n name: string,\n value: PaymentCallbackFieldValue\n): void {\n const current = fields[name];\n if (current === undefined) {\n fields[name] = value;\n } else if (Array.isArray(current)) {\n fields[name] = [...current, value ?? null];\n } else {\n fields[name] = [current, value ?? null];\n }\n}\n\nfunction shouldFinalizeInBrowser(\n requestUrl: URL,\n body: PaymentCallbackFields | undefined,\n query: PaymentCallbackFields\n): boolean {\n const pathSegments = requestUrl.pathname\n .split('/')\n .filter(Boolean);\n const resultMarker = pathSegments[pathSegments.length - 5]?.toLowerCase();\n\n return Boolean(\n resultMarker &&\n BROWSER_FINALIZED_RESULT_MARKERS.has(resultMarker) &&\n Object.keys(body ?? {}).length === 0 &&\n Object.keys(query).length === 0\n );\n}\n\nfunction createPaymentReturnRedirectUrl(\n requestUrl: URL,\n checkoutPath: string,\n payment: { id: number; identifier: string },\n resolution: 'callback' | 'status'\n): URL {\n const redirectUrl = new URL(checkoutPath, requestUrl.origin);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.resolution, resolution);\n redirectUrl.searchParams.set(SAZITO_PAYMENT_STATUS_QUERY.paymentId, String(payment.id));\n redirectUrl.searchParams.set(\n SAZITO_PAYMENT_STATUS_QUERY.paymentIdentifier,\n payment.identifier\n );\n return redirectUrl;\n}\n\nfunction redirectResponse(url: URL): Response {\n return new Response(null, {\n status: 303,\n headers: {\n Location: url.toString(),\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer'\n }\n });\n}\n\nfunction errorResponse(\n status: number,\n code: string,\n extraHeaders: Record<string, string> = {}\n): Response {\n return Response.json(\n { error: code },\n {\n status,\n headers: {\n 'Cache-Control': 'no-store',\n ...extraHeaders\n }\n }\n );\n}\n\nclass CallbackRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string\n ) {\n super(code);\n }\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sazito/checkout",
3
- "version": "0.4.20",
3
+ "version": "0.4.21",
4
4
  "description": "Headless checkout engine + React UI for the Sazito platform, powered by @sazito/client-sdk",
5
5
  "license": "MIT",
6
6
  "repository": {