@v-office/website-sdk 2.5.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Pt as defineWebsiteSDKOptions, t as createWebsiteSDK } from "./client-Cnf-pbry.mjs";
2
+ import { Pt as defineWebsiteSDKOptions, t as createWebsiteSDK } from "./client-45_ofP_d.mjs";
3
3
  import { SearchSearchSortSchema } from "@v-office/sdk-core";
4
4
  import { Console, Effect, FileSystem, Layer, Option, Path, Schema, Stdio, Terminal } from "effect";
5
5
  import { Command, Flag } from "effect/unstable/cli";
@@ -16,7 +16,7 @@ var CLICheckFailed = class extends Error {
16
16
  const toCLIError = (message, cause) => cause instanceof Error ? new CLICheckFailed(`${message}: ${cause.message}`, { cause }) : new CLICheckFailed(message, { cause });
17
17
  //#endregion
18
18
  //#region package.json
19
- var version = "2.5.0";
19
+ var version = "2.7.0";
20
20
  //#endregion
21
21
  //#region src/cli/output.ts
22
22
  const toJson = (value) => Effect.try({
@@ -21,7 +21,7 @@ const toV9Options = (options) => ({
21
21
  });
22
22
  const defineWebsiteSDKOptions = (options) => options;
23
23
  //#endregion
24
- //#region src/payment/submit-payment-option.ts
24
+ //#region src/payment/browser.ts
25
25
  const getBrowser = () => Effect.gen(function* () {
26
26
  const globals = globalThis;
27
27
  if (globals.document === void 0 || globals.window === void 0) return yield* Effect.fail(new CoreSDKError({
@@ -40,6 +40,83 @@ const toPaymentSubmissionError = (cause) => cause instanceof CoreSDKError ? caus
40
40
  message: "Payment submission failed.",
41
41
  cause
42
42
  });
43
+ //#endregion
44
+ //#region src/payment/stripe-checkout.ts
45
+ /**
46
+ * vOffice `initStripePayment` returns only `sessionId` and `accountId`, never the
47
+ * Checkout Session URL, so the session has to be opened with Stripe.js. Sessions are
48
+ * created on connected accounts, which is why the platform publishable key is combined
49
+ * with the reservation's `accountId`. Remove this module once vOffice returns the URL.
50
+ */
51
+ const STRIPE_PUBLISHABLE_KEY_TEST = "pk_test_62sy8HrukNuTd7ko6lZcyJcv00CtNmm5oo";
52
+ const STRIPE_PUBLISHABLE_KEY_LIVE = "pk_live_lHTr8iFxjPqtC0aYmkQYZuzZ00qtUAATYP";
53
+ /**
54
+ * Must stay the unversioned bundle. Stripe gates `redirectToCheckout` behind a per-version
55
+ * feature flag that is on from the `clover` (2025-09-30) release train onwards, so pinning a
56
+ * version such as `https://js.stripe.com/clover/stripe.js` makes the method throw on call.
57
+ */
58
+ const STRIPE_JS_URL = "https://js.stripe.com/v3/";
59
+ let stripeJs;
60
+ const getStripeConstructor = () => globalThis.Stripe;
61
+ const createStripeJsLoader = (document) => new Promise((resolve, reject) => {
62
+ const alreadyLoaded = getStripeConstructor();
63
+ if (alreadyLoaded !== void 0) {
64
+ resolve(alreadyLoaded);
65
+ return;
66
+ }
67
+ const script = document.createElement("script");
68
+ script.src = STRIPE_JS_URL;
69
+ script.async = true;
70
+ script.addEventListener("load", () => {
71
+ const loaded = getStripeConstructor();
72
+ if (loaded === void 0) {
73
+ reject(/* @__PURE__ */ new Error("Stripe.js was loaded but window.Stripe is unavailable."));
74
+ return;
75
+ }
76
+ resolve(loaded);
77
+ });
78
+ script.addEventListener("error", () => {
79
+ reject(/* @__PURE__ */ new Error("Could not load Stripe.js."));
80
+ });
81
+ document.head.appendChild(script);
82
+ });
83
+ const loadStripeJs = () => Effect.gen(function* () {
84
+ const { document } = yield* getBrowser();
85
+ const pending = stripeJs ?? createStripeJsLoader(document);
86
+ stripeJs = pending;
87
+ return yield* Effect.tapError(Effect.tryPromise({
88
+ try: () => pending,
89
+ catch: toPaymentSubmissionError
90
+ }), () => Effect.sync(() => {
91
+ if (stripeJs === pending) stripeJs = void 0;
92
+ }));
93
+ });
94
+ /** A `cs_test_` session can only be opened with the test key, `cs_live_` only with the live key. */
95
+ const toPublishableKey = (sessionId) => sessionId.startsWith("cs_test_") ? STRIPE_PUBLISHABLE_KEY_TEST : STRIPE_PUBLISHABLE_KEY_LIVE;
96
+ const redirectToStripeCheckout = ({ accountId, sessionId }) => Effect.gen(function* () {
97
+ const createStripe = yield* loadStripeJs();
98
+ const stripe = yield* Effect.try({
99
+ try: () => createStripe(toPublishableKey(sessionId), accountId === void 0 ? void 0 : { stripeAccount: accountId }),
100
+ catch: toPaymentSubmissionError
101
+ });
102
+ const redirectToCheckout = stripe.redirectToCheckout;
103
+ if (typeof redirectToCheckout !== "function") return yield* Effect.fail(new CoreSDKError({
104
+ source: "core",
105
+ operation: "paymentSubmission",
106
+ message: "This Stripe.js build no longer provides redirectToCheckout, so a Checkout Session cannot be opened from its session id. This payment option requires a checkout session URL from vOffice."
107
+ }));
108
+ const { error } = yield* Effect.tryPromise({
109
+ try: () => redirectToCheckout.call(stripe, { sessionId }),
110
+ catch: toPaymentSubmissionError
111
+ });
112
+ if (error !== void 0) return yield* Effect.fail(new CoreSDKError({
113
+ source: "core",
114
+ operation: "paymentSubmission",
115
+ message: error.message ?? "Stripe rejected the Checkout redirect."
116
+ }));
117
+ });
118
+ //#endregion
119
+ //#region src/payment/submit-payment-option.ts
43
120
  const submitFormPost = (option) => Effect.gen(function* () {
44
121
  const { document } = yield* getBrowser();
45
122
  yield* Effect.try({
@@ -83,10 +160,14 @@ const submitPaymentOptionEffect = (option) => {
83
160
  case "form_post": return submitFormPost(option);
84
161
  case "stripe_checkout":
85
162
  if (option.url !== void 0) return redirectTo(option.url);
163
+ if (option.sessionId !== void 0) return redirectToStripeCheckout({
164
+ ...option.accountId === void 0 ? {} : { accountId: option.accountId },
165
+ sessionId: option.sessionId
166
+ });
86
167
  return Effect.fail(new CoreSDKError({
87
168
  source: "core",
88
169
  operation: "paymentSubmission",
89
- message: "Stripe Checkout requires a checkout session URL. The current payment option only contains session metadata."
170
+ message: "Stripe Checkout requires a checkout session URL or session id. The current payment option contains neither."
90
171
  }));
91
172
  default: {
92
173
  const runtimeKind = option.kind;
@@ -973,6 +1054,19 @@ const toOpenApiErrorRaw = (raw) => {
973
1054
  };
974
1055
  };
975
1056
  //#endregion
1057
+ //#region src/legacy-v9/openapi/trace-propagation.ts
1058
+ /**
1059
+ * Effect's `HttpClient` attaches `traceparent` and `b3` headers to every outgoing
1060
+ * request. Those headers are not CORS-safelisted, so from a browser they turn
1061
+ * otherwise-simple v9 requests into preflighted ones - and the v9 gateway answers
1062
+ * `OPTIONS` without any `Access-Control-Allow-*` headers, which fails the request.
1063
+ *
1064
+ * Suppressing propagation only drops the trace link into the v9 backend; client
1065
+ * spans are still created, and requests to our own services keep propagating.
1066
+ * Remove this once the v9 gateway handles preflights.
1067
+ */
1068
+ const withoutTracePropagation = HttpClient.transformResponse(Effect.provideService(HttpClient.TracerPropagationEnabled, false));
1069
+ //#endregion
976
1070
  //#region src/legacy-v9/openapi/v1-client.ts
977
1071
  const V1OpenApiClientErrorBase = Data.TaggedError("V1OpenApiClientError");
978
1072
  var V1OpenApiClientError = class extends V1OpenApiClientErrorBase {};
@@ -1030,7 +1124,7 @@ const readResponseBody$1 = (operationId, response, contentType) => {
1030
1124
  };
1031
1125
  var V1OpenApiClient = class extends Context.Service()("@v-office/website-sdk/legacy-v9/V1OpenApiClient") {};
1032
1126
  const makeV1OpenApiClientLive = (options) => Layer.effect(V1OpenApiClient, Effect.gen(function* () {
1033
- const client = yield* HttpClient.HttpClient;
1127
+ const client = withoutTracePropagation(yield* HttpClient.HttpClient);
1034
1128
  return V1OpenApiClient.of({ execute: (operationId, request) => Effect.gen(function* () {
1035
1129
  const runtimeRequest = request;
1036
1130
  const operation = V1_OPERATIONS[operationId];
@@ -3191,7 +3285,7 @@ const readResponseBody = (operationId, response, contentType) => {
3191
3285
  };
3192
3286
  var V0OpenApiClient = class extends Context.Service()("@v-office/website-sdk/legacy-v9/V0OpenApiClient") {};
3193
3287
  const makeV0OpenApiClientLive = (options) => Layer.effect(V0OpenApiClient, Effect.gen(function* () {
3194
- const client = yield* HttpClient.HttpClient;
3288
+ const client = withoutTracePropagation(yield* HttpClient.HttpClient);
3195
3289
  return V0OpenApiClient.of({ execute: (operationId, request) => Effect.gen(function* () {
3196
3290
  const runtimeRequest = request;
3197
3291
  const operation = V0_OPERATIONS[operationId];
@@ -4673,7 +4767,7 @@ const parseV9SearchCursor = (cursor) => Effect.gen(function* () {
4673
4767
  return page;
4674
4768
  });
4675
4769
  const loadV9SearchRuntime = Effect.tryPromise({
4676
- try: () => import("./search-D1_b2t11.mjs"),
4770
+ try: () => import("./search-wcoZw2rt.mjs"),
4677
4771
  catch: (cause) => new CoreSDKError({
4678
4772
  source: "v10",
4679
4773
  operation: "v9.search.runtime",
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as SetupResponseSchema, A as ErgoPolicyNumberRequestSchema, At as selectInsurancePaymentEffect, B as QuotePricesResponseSchema, C as ErgoAddressSchema, Ct as getStartDateSelectedAvailabilityEffect, D as ErgoCreatePreContractRequestSchema, Dt as searchEffect, E as ErgoCommonFieldsSchema, Et as removeAdditionalServiceEffect, F as OnOfficeUnitSchema, G as RegionListResponseSchema, H as QuoteServiceSchema, I as PaymentScheduleItemSchema, J as ServiceBeonDataSchema, K as RoomImageSchema, L as PaymentScheduleSchema, M as ErgoTripAndCustomerRequestSchema, Mt as submitPaymentOption, N as FacilityListResponseSchema, Nt as submitPaymentOptionEffect, O as ErgoPersonSchema, Ot as selectCancellationPolicyEffect, P as OnOfficeUnitCollectionResponseSchema, Pt as defineWebsiteSDKOptions, Q as SetupDataSchema, R as QuoteLineSchema, S as DocumentTypeSchema, St as getRentalsEffect, T as ErgoBookRequestSchema, Tt as quoteEffect, U as RawObjectResponseSchema, V as QuoteSchema, W as RawVofficeObjectSchema, X as ServiceLimitSchema, Y as ServiceImageSchema, Z as ServiceListResponseSchema, _ as DocumentResourceResponseSchema, _t as bookInsuranceEffect, a as makeV0OpenApiClientFetchLive, at as UnitIdsResponseSchema, b as DocumentStatusUpdateRequestSchema, bt as getFiltersEffect, c as V1OpenApiClientError, ct as UnitOfferSchema, d as ApiEnvelopeBaseSchema, dt as V1_BASE_URL, et as TileCollectionResponseSchema, f as CalendarDaySchema, ft as V1_OPERATIONS, g as DocumentCollectionResponseSchema, gt as bookEffect, h as CustomerUnitSummarySchema, ht as addAdditionalServiceEffect, i as V0OpenApiClientError, it as TravelInsuranceBookingStoreRequestSchema, j as ErgoReadPreContractRequestSchema, jt as submitContactEffect, k as ErgoPlanSearchRequestSchema, kt as selectInsuranceEffect, l as makeV1OpenApiClientFetchLive, lt as UnitResponseSchema, m as CurrentMemberResponseSchema, mt as decodeV1OperationResponse, nt as TileTagSchema, o as makeV0OpenApiClientLive, ot as UnitListItemSchema, p as CalendarResponseSchema, pt as VideoResponseSchema, q as SearchPropertiesResponseSchema, r as V0OpenApiClient, rt as TravelInsuranceBookingSchema, s as V1OpenApiClient, st as UnitListResponseSchema, t as createWebsiteSDK, tt as TileSchema, u as makeV1OpenApiClientLive, ut as UnitServicePriceSchema, v as DocumentResourceSchema, vt as clearAdditionalServicesEffect, w as ErgoBankSchema, wt as getTermsAndPrivacyPolicyEffect, x as DocumentSummarySchema, xt as getInitialAvailabilityEffect, y as DocumentStatusSchema, yt as createInsurancePreContractEffect, z as QuotePricesPayloadSchema } from "./client-Cnf-pbry.mjs";
1
+ import { $ as SetupResponseSchema, A as ErgoPolicyNumberRequestSchema, At as selectInsurancePaymentEffect, B as QuotePricesResponseSchema, C as ErgoAddressSchema, Ct as getStartDateSelectedAvailabilityEffect, D as ErgoCreatePreContractRequestSchema, Dt as searchEffect, E as ErgoCommonFieldsSchema, Et as removeAdditionalServiceEffect, F as OnOfficeUnitSchema, G as RegionListResponseSchema, H as QuoteServiceSchema, I as PaymentScheduleItemSchema, J as ServiceBeonDataSchema, K as RoomImageSchema, L as PaymentScheduleSchema, M as ErgoTripAndCustomerRequestSchema, Mt as submitPaymentOption, N as FacilityListResponseSchema, Nt as submitPaymentOptionEffect, O as ErgoPersonSchema, Ot as selectCancellationPolicyEffect, P as OnOfficeUnitCollectionResponseSchema, Pt as defineWebsiteSDKOptions, Q as SetupDataSchema, R as QuoteLineSchema, S as DocumentTypeSchema, St as getRentalsEffect, T as ErgoBookRequestSchema, Tt as quoteEffect, U as RawObjectResponseSchema, V as QuoteSchema, W as RawVofficeObjectSchema, X as ServiceLimitSchema, Y as ServiceImageSchema, Z as ServiceListResponseSchema, _ as DocumentResourceResponseSchema, _t as bookInsuranceEffect, a as makeV0OpenApiClientFetchLive, at as UnitIdsResponseSchema, b as DocumentStatusUpdateRequestSchema, bt as getFiltersEffect, c as V1OpenApiClientError, ct as UnitOfferSchema, d as ApiEnvelopeBaseSchema, dt as V1_BASE_URL, et as TileCollectionResponseSchema, f as CalendarDaySchema, ft as V1_OPERATIONS, g as DocumentCollectionResponseSchema, gt as bookEffect, h as CustomerUnitSummarySchema, ht as addAdditionalServiceEffect, i as V0OpenApiClientError, it as TravelInsuranceBookingStoreRequestSchema, j as ErgoReadPreContractRequestSchema, jt as submitContactEffect, k as ErgoPlanSearchRequestSchema, kt as selectInsuranceEffect, l as makeV1OpenApiClientFetchLive, lt as UnitResponseSchema, m as CurrentMemberResponseSchema, mt as decodeV1OperationResponse, nt as TileTagSchema, o as makeV0OpenApiClientLive, ot as UnitListItemSchema, p as CalendarResponseSchema, pt as VideoResponseSchema, q as SearchPropertiesResponseSchema, r as V0OpenApiClient, rt as TravelInsuranceBookingSchema, s as V1OpenApiClient, st as UnitListResponseSchema, t as createWebsiteSDK, tt as TileSchema, u as makeV1OpenApiClientLive, ut as UnitServicePriceSchema, v as DocumentResourceSchema, vt as clearAdditionalServicesEffect, w as ErgoBankSchema, wt as getTermsAndPrivacyPolicyEffect, x as DocumentSummarySchema, xt as getInitialAvailabilityEffect, y as DocumentStatusSchema, yt as createInsurancePreContractEffect, z as QuotePricesPayloadSchema } from "./client-45_ofP_d.mjs";
2
2
  import { AdditionalServiceLimitExceeded, CoreSDKError, CoreSDKError as CMSError, GuestQuoteSchema, InvalidAdditionalServiceQuantity, LocaleSchema, SearchSearchFieldOrderBySchema, SearchSearchFieldSortSchema, SearchSearchInputSchema, SearchSearchOutputSchema, SearchSearchPriceSortSchema, SearchSearchRandomSortSchema, SearchSearchRatingSortSchema, SearchSearchSortSchema, SearchSortDirectionSchema, UnknownAdditionalService, validateContactSubmitInput } from "@v-office/sdk-core";
3
3
  //#region codegen/v9/heuristic-generation/public-api.ts
4
4
  const customDataAttribute = (name) => name;
@@ -4,6 +4,7 @@ This file is the versioned changelog index for the website SDK instructions.
4
4
 
5
5
  ## Versions
6
6
 
7
+ - `versions/2.6.0/CHANGELOG.md`: `@v-office/website-sdk` 2.6.0 release notes.
7
8
  - `versions/2.5.0/CHANGELOG.md`: `@v-office/website-sdk` 2.5.0 release notes.
8
9
  - `versions/2.4.3/CHANGELOG.md`: `@v-office/website-sdk` 2.4.3 documentation release notes.
9
10
  - `versions/2.4.2/CHANGELOG.md`: `@v-office/website-sdk` 2.4.2 release notes.
@@ -4,6 +4,7 @@ This file is the versioned migration index for the website SDK instructions.
4
4
 
5
5
  ## Available Guides
6
6
 
7
+ - `versions/2.6.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.5.x to 2.6.0.
7
8
  - `versions/2.5.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.3 to 2.5.0.
8
9
  - `versions/2.4.3/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.2 to 2.4.3.
9
10
  - `versions/2.4.2/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.1 to 2.4.2.
@@ -1,6 +1,6 @@
1
1
  # Website SDK Instructions
2
2
 
3
- These instructions describe `@v-office/website-sdk` 2.5.0.
3
+ These instructions describe `@v-office/website-sdk` 2.6.0.
4
4
 
5
5
  Use this directory as the consumer-facing reference for the package:
6
6
 
@@ -15,6 +15,7 @@ Use this directory as the consumer-facing reference for the package:
15
15
  - `document-structured-json.md`: `sdk.static.documents.getTermsAndPrivacyPolicy` and structured document JSON rendering rules.
16
16
  - `CHANGELOG.md`: versioned changelog index.
17
17
  - `MIGRATION.md`: versioned migration index.
18
+ - `versions/2.6.0/`: 2.6.0 release notes and 2.5.x-to-2.6.0 migration guide.
18
19
  - `versions/2.5.0/`: 2.5.0 release notes and 2.4.3-to-2.5.0 migration guide.
19
20
  - `versions/2.4.3/`: 2.4.3 documentation release notes and migration guide.
20
21
  - `versions/2.4.2/`: 2.4.2 release notes and 2.4.1-to-2.4.2 migration guide.
@@ -68,4 +69,4 @@ website-sdk --backend v10 search --locale de-DE --query "adults=2"
68
69
  website-sdk --backend v10 search --locale de-DE --query "adults=2" --sort '{"by":"field","orderBy":{"label":"ASC"}}'
69
70
  ```
70
71
 
71
- Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.5.0. v10 config additionally requires `searchEndpoint` as of 2.5.0.
72
+ Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.6.0. v10 config additionally requires `searchEndpoint` as of 2.5.0.
@@ -100,6 +100,13 @@ Sample:
100
100
  "provider": "adyen",
101
101
  "label": "Credit card",
102
102
  "url": "https://checkout.example.com"
103
+ },
104
+ {
105
+ "kind": "stripe_checkout",
106
+ "provider": "stripe",
107
+ "label": "Credit card",
108
+ "sessionId": "cs_live_a1Upmvi1v62AdILeDZl4l",
109
+ "accountId": "acct_1MpAB7AFrTg9gw7b"
103
110
  }
104
111
  ]
105
112
  }
@@ -113,13 +120,42 @@ Payment option variants:
113
120
  - `bank_transfer`: display-only payment details.
114
121
  - `redirect`: redirect the browser to the payment URL.
115
122
  - `form_post`: submit a generated HTML form, currently used for PayPal-style flows.
116
- - `stripe_checkout`: redirect to Stripe Checkout when a `url` is present.
123
+ - `stripe_checkout`: open Stripe Checkout. Emitted on `v9` only.
124
+
125
+ ## Payment Submission
126
+
127
+ Use `sdk.live.booking.submitPaymentOption(option)` or the top-level `submitPaymentOption(option)` export for every option except `bank_transfer`, which is display-only. Submission requires a browser environment and fails outside one.
128
+
129
+ Render a button for every submittable option. Do not gate rendering on `url`: a `stripe_checkout` option is submittable as soon as it carries a `sessionId`.
130
+
131
+ Stripe Checkout is opened one of two ways:
132
+
133
+ - When the option has a `url`, the browser is redirected to it.
134
+ - Otherwise the SDK loads Stripe.js from `https://js.stripe.com/v3/` and opens the session with `sessionId`, passing `accountId` as the connected account. The vOffice platform publishable keys are built in, and test (`cs_test_`) and live (`cs_live_`) sessions are handled automatically, so Stripe needs no configuration.
135
+
136
+ Stripe.js is fetched on first use and reused afterwards, and an existing `window.Stripe` instance is reused when the page already provides one. A failed load is retried by the next submission instead of being remembered, so a guest can retry a Stripe payment without reloading the page. Sites with a Content-Security-Policy must allow `script-src https://js.stripe.com` and `frame-src https://js.stripe.com https://hooks.stripe.com`.
137
+
138
+ Booking creation and payment are separate steps. When a payment option is on screen the reservation already exists, so present a submission failure as an unpaid booking rather than a failed booking:
139
+
140
+ ```ts
141
+ try {
142
+ await sdk.live.booking.submitPaymentOption(option);
143
+ } catch (error) {
144
+ showPaymentFailure({ bookingNumber: booking.bookingNumber, error });
145
+ }
146
+ ```
147
+
148
+ ## Payment Return
149
+
150
+ Online payment providers return the guest to a URL derived from `relativeRedirectUrl`. Stripe returns to that path with `payment=stripe&success=true` after payment and `payment=stripe&cancel=true` after cancellation, so the path must exist in your site and should read those query parameters.
151
+
152
+ `relativeRedirectUrl` is supplied before the reservation exists, so the return URL cannot carry the booking number or guest token. Persist whatever the return page needs, for example in `sessionStorage`, before submitting a payment option.
117
153
 
118
- Use `sdk.live.booking.submitPaymentOption(option)` or the top-level `submitPaymentOption(option)` export for non-bank-transfer payment options in a browser environment.
154
+ A successful return means the provider sent the browser back, not that the payment has settled. Confirmation reaches vOffice through the provider's webhook.
119
155
 
120
156
  ## Configuration
121
157
 
122
- Booking requests are rate-limited to one backend request per second with a queue size of five. `v9` books through the v0 `book` action and can initialize Stripe payment data. `v10` books through GraphQL and initializes Adyen redirect payment options.
158
+ Booking requests are rate-limited to one backend request per second with a queue size of five. `v9` books through the v0 `book` action and initializes one Stripe Checkout Session per payment schedule option when the property has Stripe enabled. `v10` books through GraphQL and initializes Adyen redirect payment options.
123
159
 
124
160
  ## CLI Usage
125
161
 
@@ -0,0 +1,28 @@
1
+ # Changelog: 2.6.0
2
+
3
+ Release date: 2026-07-27
4
+
5
+ This release makes v9 `stripe_checkout` payment options submittable. The vOffice `initStripePayment` action returns only session metadata, so `submitPaymentOption` now opens the Checkout Session with Stripe.js when the backend omits the session URL. Config, service calls, and output types are unchanged.
6
+
7
+ ## Added
8
+
9
+ - `submitPaymentOption` and `submitPaymentOptionEffect` now complete `stripe_checkout` options that carry only `sessionId` and `accountId`. Previously these options failed with "Stripe Checkout requires a checkout session URL".
10
+ - Stripe.js is loaded from `https://js.stripe.com/v3/` on first use and reused for later submissions. A failed load is not kept, so the next submission retries it. An existing `window.Stripe` instance is used when the page already provides one, so no second script tag is added.
11
+ - The vOffice Stripe platform publishable keys are embedded in the SDK. Stripe Checkout requires no consumer configuration.
12
+
13
+ ## Changed
14
+
15
+ - `stripe_checkout` submission prefers the Checkout Session `url` and only falls back to Stripe.js when it is absent. Once vOffice returns the URL, the SDK uses it without a further release.
16
+ - The publishable key is selected from the session id, so tenants in Stripe test mode (`cs_test_`) and live mode (`cs_live_`) both work without configuration or environment detection.
17
+ - Stripe sessions are created on connected accounts, so the option's `accountId` is passed to Stripe.js as `stripeAccount`.
18
+ - The failure raised when a `stripe_checkout` option carries neither a URL nor a session id now names both.
19
+ - Browser access helpers used by payment submission moved into an internal module shared by redirect, form-post, and Stripe submission. This is internal only and does not change the public API.
20
+
21
+ ## Migration Impact
22
+
23
+ - Consumers that hid Stripe payment options because `url` was missing can render them again. Gate the button on the option being present rather than on `option.url`. See `versions/2.6.0/MIGRATION.md`.
24
+ - Sites with a Content-Security-Policy must allow `script-src https://js.stripe.com` and `frame-src https://js.stripe.com https://hooks.stripe.com`.
25
+ - Payment submission remains browser-only and still fails outside a browser environment.
26
+ - Stripe.js is fetched at submission time, so payment submission can now fail from a blocked or unavailable third-party script. Treat that as a payment failure, never as a booking failure: the reservation already exists when payment options are shown.
27
+ - No config, option, or output type changes. v10 Adyen `redirect` flows and all `bank_transfer` and `form_post` flows are unaffected.
28
+ - Stripe removed `redirectToCheckout` from its versioned Stripe.js release trains (`clover`, 2025-09-30, and later) and from the published `stripe-js` types. The method is still implemented in the unversioned `https://js.stripe.com/v3/` bundle that the SDK loads, which is why this fallback works. It is a bridge until vOffice returns the session URL and is expected to be removed afterwards. Should a future Stripe.js build drop the method entirely, submission fails with a message naming the missing session URL.
@@ -0,0 +1,74 @@
1
+ # Migration: 2.5.x to 2.6.0
2
+
3
+ This guide covers upgrading `@v-office/website-sdk` from 2.5.0 or 2.5.1 to 2.6.0.
4
+
5
+ 2.6.0 changes no config, no service call, and no output type. The only change is that `stripe_checkout` payment options can now be submitted on the v9 backend. If your site does not offer Stripe, upgrading requires no work at all.
6
+
7
+ ## What Changed
8
+
9
+ vOffice's `initStripePayment` action returns only `sessionId` and `accountId`, never the Checkout Session URL. Because `submitPaymentOption` redirected exclusively to a session URL, Stripe payment options could never be completed and failed with "Stripe Checkout requires a checkout session URL".
10
+
11
+ 2.6.0 keeps the URL redirect as the preferred path and adds a fallback: when a `stripe_checkout` option has a `sessionId` but no `url`, the SDK loads Stripe.js and opens the Checkout Session with it. This is the same mechanism the classic non-SDK vOffice websites use.
12
+
13
+ The fallback is self-retiring. When vOffice starts returning the session URL, the option gains a `url`, the URL redirect wins, and Stripe.js is never loaded. No SDK release is needed for that transition.
14
+
15
+ ## Remove Stripe Workarounds
16
+
17
+ Sites that hid the Stripe button because no URL was present should now render it. Gate on the option existing rather than on `option.url`:
18
+
19
+ ```ts
20
+ // Before: Stripe options were unusable, so they had to be hidden
21
+ const payable = option.kind !== "stripe_checkout" || option.url !== undefined;
22
+
23
+ // After: every submittable option can be submitted
24
+ const payable = true;
25
+ ```
26
+
27
+ Sites that implemented their own Stripe.js bridge with a publishable key can delete it, along with the key configuration. The SDK carries the vOffice platform keys and selects between test and live based on the session id, so a tenant in Stripe test mode and a tenant in live mode both work from the same build.
28
+
29
+ ## Content-Security-Policy
30
+
31
+ Stripe.js is fetched from Stripe at submission time. If your site sets a CSP, allow:
32
+
33
+ ```
34
+ script-src https://js.stripe.com
35
+ frame-src https://js.stripe.com https://hooks.stripe.com
36
+ ```
37
+
38
+ Without these directives the script is blocked and Stripe submission fails. Other payment kinds are unaffected.
39
+
40
+ ## Error Handling
41
+
42
+ Payment submission can now fail for new reasons: Stripe.js could not be loaded, the loaded Stripe.js build does not provide the Checkout redirect, or Stripe rejected the redirect. All surface as a `CoreSDKError` with `operation: "paymentSubmission"`, the same as existing submission failures.
43
+
44
+ Offering a retry is worthwhile for these failures. A failed Stripe.js load is not remembered, so the next submission fetches the script again and can succeed without a page reload.
45
+
46
+ The booking already exists by the time payment options are rendered, so a submission failure must never be presented as a failed booking:
47
+
48
+ ```ts
49
+ try {
50
+ await sdk.live.booking.submitPaymentOption(option);
51
+ } catch (error) {
52
+ // The reservation is created. Show the booking number and offer bank transfer.
53
+ showPaymentFailure({ bookingNumber: booking.bookingNumber, error });
54
+ }
55
+ ```
56
+
57
+ Submission is still browser-only and fails outside a browser environment, unchanged from earlier versions.
58
+
59
+ ## Payment Return
60
+
61
+ Unchanged from earlier versions, but worth confirming while testing Stripe end to end. The SDK derives the Stripe success and cancel URLs from the `relativeRedirectUrl` passed to `sdk.live.booking.book(...)` and appends `payment=stripe&success=true` or `payment=stripe&cancel=true`. That path must exist in your site and should read those query parameters.
62
+
63
+ Note that `relativeRedirectUrl` is supplied before the reservation exists, so the return URL cannot contain the booking number or guest token. Persist anything the return page needs, for example in `sessionStorage`, before submitting the payment option.
64
+
65
+ A `success=true` return means Stripe sent the browser back, not that payment has settled. Payment confirmation reaches vOffice through Stripe's webhook.
66
+
67
+ ## Recommended Steps
68
+
69
+ 1. Upgrade to `@v-office/website-sdk` 2.6.0.
70
+ 2. Remove any conditional that hides Stripe payment options when `option.url` is missing.
71
+ 3. Remove a site-level Stripe.js bridge and its publishable key configuration if you added one.
72
+ 4. Add the Stripe CSP directives if your site sets a Content-Security-Policy.
73
+ 5. Confirm payment submission errors are presented as payment failures with the booking number, not as booking failures.
74
+ 6. Smoke-test one booking against a Stripe test tenant and one against a live tenant, checking that Checkout opens and that the configured return path handles both `success=true` and `cancel=true`.
@@ -1,4 +1,4 @@
1
- import { n as stable_filters_default } from "./client-Cnf-pbry.mjs";
1
+ import { n as stable_filters_default } from "./client-45_ofP_d.mjs";
2
2
  import { a as searchQuery, c as VofficeUnitDataFieldSchemas, m as parseVofficeUnitData, n as toImages, r as toAddress, t as toRentalHighlights } from "./to-rental-highlights-CxWlq76f.mjs";
3
3
  import { CoreSDKError, STABLE_SEARCH_INPUTS, collectQueryParameters, daysBetweenLocalDates, expandCustomAttributeFilterCompositions, parseChildrenAges, parseOccupancyCount, parseQueryParameters, toCustomAttributeFilterLabel, toFormattedSearchPrice, toIsoDateFromPeriodQueryDate, toQueryString, toStableSearchInputBackendQueryKeys, toStableSearchInputParameterValues, toStableSearchInputQueryKeys, toUnusedFilterKeys } from "@v-office/sdk-core";
4
4
  import { Effect } from "effect";
@@ -4,6 +4,7 @@ This file is the versioned changelog index for the website SDK instructions.
4
4
 
5
5
  ## Versions
6
6
 
7
+ - `versions/2.6.0/CHANGELOG.md`: `@v-office/website-sdk` 2.6.0 release notes.
7
8
  - `versions/2.5.0/CHANGELOG.md`: `@v-office/website-sdk` 2.5.0 release notes.
8
9
  - `versions/2.4.3/CHANGELOG.md`: `@v-office/website-sdk` 2.4.3 documentation release notes.
9
10
  - `versions/2.4.2/CHANGELOG.md`: `@v-office/website-sdk` 2.4.2 release notes.
@@ -4,6 +4,7 @@ This file is the versioned migration index for the website SDK instructions.
4
4
 
5
5
  ## Available Guides
6
6
 
7
+ - `versions/2.6.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.5.x to 2.6.0.
7
8
  - `versions/2.5.0/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.3 to 2.5.0.
8
9
  - `versions/2.4.3/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.2 to 2.4.3.
9
10
  - `versions/2.4.2/MIGRATION.md`: migrate from `@v-office/website-sdk` 2.4.1 to 2.4.2.
@@ -1,6 +1,6 @@
1
1
  # Website SDK Instructions
2
2
 
3
- These instructions describe `@v-office/website-sdk` 2.5.0.
3
+ These instructions describe `@v-office/website-sdk` 2.6.0.
4
4
 
5
5
  Use this directory as the consumer-facing reference for the package:
6
6
 
@@ -15,6 +15,7 @@ Use this directory as the consumer-facing reference for the package:
15
15
  - `document-structured-json.md`: `sdk.static.documents.getTermsAndPrivacyPolicy` and structured document JSON rendering rules.
16
16
  - `CHANGELOG.md`: versioned changelog index.
17
17
  - `MIGRATION.md`: versioned migration index.
18
+ - `versions/2.6.0/`: 2.6.0 release notes and 2.5.x-to-2.6.0 migration guide.
18
19
  - `versions/2.5.0/`: 2.5.0 release notes and 2.4.3-to-2.5.0 migration guide.
19
20
  - `versions/2.4.3/`: 2.4.3 documentation release notes and migration guide.
20
21
  - `versions/2.4.2/`: 2.4.2 release notes and 2.4.1-to-2.4.2 migration guide.
@@ -68,4 +69,4 @@ website-sdk --backend v10 search --locale de-DE --query "adults=2"
68
69
  website-sdk --backend v10 search --locale de-DE --query "adults=2" --sort '{"by":"field","orderBy":{"label":"ASC"}}'
69
70
  ```
70
71
 
71
- Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.5.0. v10 config additionally requires `searchEndpoint` as of 2.5.0.
72
+ Config file examples in these docs use the flat `WebsiteSDKConfig` shape introduced in 2.0.0 and kept in 2.6.0. v10 config additionally requires `searchEndpoint` as of 2.5.0.
@@ -100,6 +100,13 @@ Sample:
100
100
  "provider": "adyen",
101
101
  "label": "Credit card",
102
102
  "url": "https://checkout.example.com"
103
+ },
104
+ {
105
+ "kind": "stripe_checkout",
106
+ "provider": "stripe",
107
+ "label": "Credit card",
108
+ "sessionId": "cs_live_a1Upmvi1v62AdILeDZl4l",
109
+ "accountId": "acct_1MpAB7AFrTg9gw7b"
103
110
  }
104
111
  ]
105
112
  }
@@ -113,13 +120,42 @@ Payment option variants:
113
120
  - `bank_transfer`: display-only payment details.
114
121
  - `redirect`: redirect the browser to the payment URL.
115
122
  - `form_post`: submit a generated HTML form, currently used for PayPal-style flows.
116
- - `stripe_checkout`: redirect to Stripe Checkout when a `url` is present.
123
+ - `stripe_checkout`: open Stripe Checkout. Emitted on `v9` only.
124
+
125
+ ## Payment Submission
126
+
127
+ Use `sdk.live.booking.submitPaymentOption(option)` or the top-level `submitPaymentOption(option)` export for every option except `bank_transfer`, which is display-only. Submission requires a browser environment and fails outside one.
128
+
129
+ Render a button for every submittable option. Do not gate rendering on `url`: a `stripe_checkout` option is submittable as soon as it carries a `sessionId`.
130
+
131
+ Stripe Checkout is opened one of two ways:
132
+
133
+ - When the option has a `url`, the browser is redirected to it.
134
+ - Otherwise the SDK loads Stripe.js from `https://js.stripe.com/v3/` and opens the session with `sessionId`, passing `accountId` as the connected account. The vOffice platform publishable keys are built in, and test (`cs_test_`) and live (`cs_live_`) sessions are handled automatically, so Stripe needs no configuration.
135
+
136
+ Stripe.js is fetched on first use and reused afterwards, and an existing `window.Stripe` instance is reused when the page already provides one. A failed load is retried by the next submission instead of being remembered, so a guest can retry a Stripe payment without reloading the page. Sites with a Content-Security-Policy must allow `script-src https://js.stripe.com` and `frame-src https://js.stripe.com https://hooks.stripe.com`.
137
+
138
+ Booking creation and payment are separate steps. When a payment option is on screen the reservation already exists, so present a submission failure as an unpaid booking rather than a failed booking:
139
+
140
+ ```ts
141
+ try {
142
+ await sdk.live.booking.submitPaymentOption(option);
143
+ } catch (error) {
144
+ showPaymentFailure({ bookingNumber: booking.bookingNumber, error });
145
+ }
146
+ ```
147
+
148
+ ## Payment Return
149
+
150
+ Online payment providers return the guest to a URL derived from `relativeRedirectUrl`. Stripe returns to that path with `payment=stripe&success=true` after payment and `payment=stripe&cancel=true` after cancellation, so the path must exist in your site and should read those query parameters.
151
+
152
+ `relativeRedirectUrl` is supplied before the reservation exists, so the return URL cannot carry the booking number or guest token. Persist whatever the return page needs, for example in `sessionStorage`, before submitting a payment option.
117
153
 
118
- Use `sdk.live.booking.submitPaymentOption(option)` or the top-level `submitPaymentOption(option)` export for non-bank-transfer payment options in a browser environment.
154
+ A successful return means the provider sent the browser back, not that the payment has settled. Confirmation reaches vOffice through the provider's webhook.
119
155
 
120
156
  ## Configuration
121
157
 
122
- Booking requests are rate-limited to one backend request per second with a queue size of five. `v9` books through the v0 `book` action and can initialize Stripe payment data. `v10` books through GraphQL and initializes Adyen redirect payment options.
158
+ Booking requests are rate-limited to one backend request per second with a queue size of five. `v9` books through the v0 `book` action and initializes one Stripe Checkout Session per payment schedule option when the property has Stripe enabled. `v10` books through GraphQL and initializes Adyen redirect payment options.
123
159
 
124
160
  ## CLI Usage
125
161
 
@@ -0,0 +1,28 @@
1
+ # Changelog: 2.6.0
2
+
3
+ Release date: 2026-07-27
4
+
5
+ This release makes v9 `stripe_checkout` payment options submittable. The vOffice `initStripePayment` action returns only session metadata, so `submitPaymentOption` now opens the Checkout Session with Stripe.js when the backend omits the session URL. Config, service calls, and output types are unchanged.
6
+
7
+ ## Added
8
+
9
+ - `submitPaymentOption` and `submitPaymentOptionEffect` now complete `stripe_checkout` options that carry only `sessionId` and `accountId`. Previously these options failed with "Stripe Checkout requires a checkout session URL".
10
+ - Stripe.js is loaded from `https://js.stripe.com/v3/` on first use and reused for later submissions. A failed load is not kept, so the next submission retries it. An existing `window.Stripe` instance is used when the page already provides one, so no second script tag is added.
11
+ - The vOffice Stripe platform publishable keys are embedded in the SDK. Stripe Checkout requires no consumer configuration.
12
+
13
+ ## Changed
14
+
15
+ - `stripe_checkout` submission prefers the Checkout Session `url` and only falls back to Stripe.js when it is absent. Once vOffice returns the URL, the SDK uses it without a further release.
16
+ - The publishable key is selected from the session id, so tenants in Stripe test mode (`cs_test_`) and live mode (`cs_live_`) both work without configuration or environment detection.
17
+ - Stripe sessions are created on connected accounts, so the option's `accountId` is passed to Stripe.js as `stripeAccount`.
18
+ - The failure raised when a `stripe_checkout` option carries neither a URL nor a session id now names both.
19
+ - Browser access helpers used by payment submission moved into an internal module shared by redirect, form-post, and Stripe submission. This is internal only and does not change the public API.
20
+
21
+ ## Migration Impact
22
+
23
+ - Consumers that hid Stripe payment options because `url` was missing can render them again. Gate the button on the option being present rather than on `option.url`. See `versions/2.6.0/MIGRATION.md`.
24
+ - Sites with a Content-Security-Policy must allow `script-src https://js.stripe.com` and `frame-src https://js.stripe.com https://hooks.stripe.com`.
25
+ - Payment submission remains browser-only and still fails outside a browser environment.
26
+ - Stripe.js is fetched at submission time, so payment submission can now fail from a blocked or unavailable third-party script. Treat that as a payment failure, never as a booking failure: the reservation already exists when payment options are shown.
27
+ - No config, option, or output type changes. v10 Adyen `redirect` flows and all `bank_transfer` and `form_post` flows are unaffected.
28
+ - Stripe removed `redirectToCheckout` from its versioned Stripe.js release trains (`clover`, 2025-09-30, and later) and from the published `stripe-js` types. The method is still implemented in the unversioned `https://js.stripe.com/v3/` bundle that the SDK loads, which is why this fallback works. It is a bridge until vOffice returns the session URL and is expected to be removed afterwards. Should a future Stripe.js build drop the method entirely, submission fails with a message naming the missing session URL.
@@ -0,0 +1,74 @@
1
+ # Migration: 2.5.x to 2.6.0
2
+
3
+ This guide covers upgrading `@v-office/website-sdk` from 2.5.0 or 2.5.1 to 2.6.0.
4
+
5
+ 2.6.0 changes no config, no service call, and no output type. The only change is that `stripe_checkout` payment options can now be submitted on the v9 backend. If your site does not offer Stripe, upgrading requires no work at all.
6
+
7
+ ## What Changed
8
+
9
+ vOffice's `initStripePayment` action returns only `sessionId` and `accountId`, never the Checkout Session URL. Because `submitPaymentOption` redirected exclusively to a session URL, Stripe payment options could never be completed and failed with "Stripe Checkout requires a checkout session URL".
10
+
11
+ 2.6.0 keeps the URL redirect as the preferred path and adds a fallback: when a `stripe_checkout` option has a `sessionId` but no `url`, the SDK loads Stripe.js and opens the Checkout Session with it. This is the same mechanism the classic non-SDK vOffice websites use.
12
+
13
+ The fallback is self-retiring. When vOffice starts returning the session URL, the option gains a `url`, the URL redirect wins, and Stripe.js is never loaded. No SDK release is needed for that transition.
14
+
15
+ ## Remove Stripe Workarounds
16
+
17
+ Sites that hid the Stripe button because no URL was present should now render it. Gate on the option existing rather than on `option.url`:
18
+
19
+ ```ts
20
+ // Before: Stripe options were unusable, so they had to be hidden
21
+ const payable = option.kind !== "stripe_checkout" || option.url !== undefined;
22
+
23
+ // After: every submittable option can be submitted
24
+ const payable = true;
25
+ ```
26
+
27
+ Sites that implemented their own Stripe.js bridge with a publishable key can delete it, along with the key configuration. The SDK carries the vOffice platform keys and selects between test and live based on the session id, so a tenant in Stripe test mode and a tenant in live mode both work from the same build.
28
+
29
+ ## Content-Security-Policy
30
+
31
+ Stripe.js is fetched from Stripe at submission time. If your site sets a CSP, allow:
32
+
33
+ ```
34
+ script-src https://js.stripe.com
35
+ frame-src https://js.stripe.com https://hooks.stripe.com
36
+ ```
37
+
38
+ Without these directives the script is blocked and Stripe submission fails. Other payment kinds are unaffected.
39
+
40
+ ## Error Handling
41
+
42
+ Payment submission can now fail for new reasons: Stripe.js could not be loaded, the loaded Stripe.js build does not provide the Checkout redirect, or Stripe rejected the redirect. All surface as a `CoreSDKError` with `operation: "paymentSubmission"`, the same as existing submission failures.
43
+
44
+ Offering a retry is worthwhile for these failures. A failed Stripe.js load is not remembered, so the next submission fetches the script again and can succeed without a page reload.
45
+
46
+ The booking already exists by the time payment options are rendered, so a submission failure must never be presented as a failed booking:
47
+
48
+ ```ts
49
+ try {
50
+ await sdk.live.booking.submitPaymentOption(option);
51
+ } catch (error) {
52
+ // The reservation is created. Show the booking number and offer bank transfer.
53
+ showPaymentFailure({ bookingNumber: booking.bookingNumber, error });
54
+ }
55
+ ```
56
+
57
+ Submission is still browser-only and fails outside a browser environment, unchanged from earlier versions.
58
+
59
+ ## Payment Return
60
+
61
+ Unchanged from earlier versions, but worth confirming while testing Stripe end to end. The SDK derives the Stripe success and cancel URLs from the `relativeRedirectUrl` passed to `sdk.live.booking.book(...)` and appends `payment=stripe&success=true` or `payment=stripe&cancel=true`. That path must exist in your site and should read those query parameters.
62
+
63
+ Note that `relativeRedirectUrl` is supplied before the reservation exists, so the return URL cannot contain the booking number or guest token. Persist anything the return page needs, for example in `sessionStorage`, before submitting the payment option.
64
+
65
+ A `success=true` return means Stripe sent the browser back, not that payment has settled. Payment confirmation reaches vOffice through Stripe's webhook.
66
+
67
+ ## Recommended Steps
68
+
69
+ 1. Upgrade to `@v-office/website-sdk` 2.6.0.
70
+ 2. Remove any conditional that hides Stripe payment options when `option.url` is missing.
71
+ 3. Remove a site-level Stripe.js bridge and its publishable key configuration if you added one.
72
+ 4. Add the Stripe CSP directives if your site sets a Content-Security-Policy.
73
+ 5. Confirm payment submission errors are presented as payment failures with the booking number, not as booking failures.
74
+ 6. Smoke-test one booking against a Stripe test tenant and one against a live tenant, checking that Checkout opens and that the configured return path handles both `success=true` and `cancel=true`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@v-office/website-sdk",
3
- "version": "2.5.0",
3
+ "version": "2.7.0",
4
4
  "description": "Website-facing SDK facade backed by @v-office/sdk-core",
5
5
  "bin": {
6
6
  "website-sdk": "./dist/cli.mjs"
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@graphql-typed-document-node/core": "3.2.0",
44
- "@v-office/sdk-core": "^1.6.0",
44
+ "@v-office/sdk-core": "^1.7.0",
45
45
  "effect": "4.0.0-beta.85",
46
46
  "graphql": "16.14.2",
47
47
  "yaml": "^2.9.0"