@wix/himalaya-cli 0.1572.0 → 0.1574.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-module.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/message-format.d.ts +59 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/checkout/src/index.d.ts +4 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/index.d.ts +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/one-app-page.d.ts +61 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/social-feed/src/index.d.ts +34 -9
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/checkout.mjs +28 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +3 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/l10n.mjs +8 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +573 -73
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +3 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-social-feed.mjs +24 -1
- package/dist/cli.mjs +2708 -1182
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/himi-json-output.md +41 -2
- package/guides/himi-mcp.md +1 -1
- package/guides/himi-test.md +3 -2
- package/guides/iap-products.md +1 -1
- package/guides/importing-oneapp-translations.md +115 -0
- package/guides/index.json +6 -0
- package/guides/one-app-section-mappings.md +16 -4
- package/guides/one-app-to-himi-app.md +221 -10
- package/guides/qa-builds.md +21 -1
- package/guides/sdk-reference.json +28 -4
- package/guides/templates.md +3 -2
- package/guides/testing-himi-apps.md +1 -1
- package/guides/webview-page-sdk.md +68 -3
- package/package.json +3 -3
- package/templates/beauty-salon/dev/index.ts +22 -6
- package/templates/beauty-salon/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/beauty-salon/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/beauty-salon/tier5-src/himi-booking-time/index.ts +5 -2
- package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +5 -2
- package/templates/beauty-salon/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/beauty-salon-owner/dev/index.ts +22 -6
- package/templates/branded-lite/dev/index.ts +22 -6
- package/templates/branded-lite/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/branded-lite/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/branded-lite/tier5-src/himi-booking-time/index.ts +5 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +5 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +5 -2
- package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/community-club/dev/index.ts +22 -6
- package/templates/community-club/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/community-club/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/community-club/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/community-club-owner/dev/index.ts +22 -6
- package/templates/events-meetups/dev/index.ts +22 -6
- package/templates/events-meetups/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/events-meetups/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/events-meetups-owner/dev/index.ts +22 -6
- package/templates/gym-fitness/dev/index.ts +22 -6
- package/templates/gym-fitness/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/gym-fitness/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/gym-fitness/tier5-src/himi-booking-time/index.ts +5 -2
- package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +5 -2
- package/templates/gym-fitness/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/gym-fitness-owner/dev/index.ts +22 -6
- package/templates/himi-chat/dev/index.ts +22 -6
- package/templates/nonprofit-cause/dev/index.ts +22 -6
- package/templates/nonprofit-cause/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/nonprofit-cause/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/nonprofit-cause/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/nonprofit-cause-owner/dev/index.ts +22 -6
- package/templates/owner-lite/dev/index.ts +22 -6
- package/templates/podcast-creator/dev/index.ts +22 -6
- package/templates/podcast-creator/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/podcast-creator/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/podcast-creator/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/podcast-creator-owner/dev/index.ts +22 -6
- package/templates/portfolio-creative/dev/index.ts +22 -6
- package/templates/portfolio-creative/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/portfolio-creative/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +5 -2
- package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/portfolio-creative-owner/dev/index.ts +22 -6
- package/templates/restaurant/dev/index.ts +22 -6
- package/templates/restaurant/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/restaurant/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/restaurant/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/restaurant-owner/dev/index.ts +22 -6
- package/templates/retail-store/dev/index.ts +22 -6
- package/templates/retail-store/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/retail-store/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +5 -2
- package/templates/retail-store-owner/dev/index.ts +22 -6
- package/templates/surface-showcase/dev/index.ts +22 -6
- package/templates/yoga-studio/dev/index.ts +22 -6
- package/templates/yoga-studio/tier5-src/_shared/iap-worker.ts +2 -0
- package/templates/yoga-studio/tier5-src/_shared/payment-setup.ts +6 -0
- package/templates/yoga-studio/tier5-src/himi-booking-time/index.ts +5 -2
- package/templates/yoga-studio/tier5-src/himi-branded-lite-plans/index.ts +5 -2
- package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +5 -2
- package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +9 -4
- package/templates/yoga-studio-owner/dev/index.ts +22 -6
|
@@ -1799,15 +1799,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
1799
1799
|
|
|
1800
1800
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
1801
1801
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
1802
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
1803
|
-
//
|
|
1802
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
1803
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
1804
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
1805
|
+
// baked details, preview still live-resolves).
|
|
1806
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
1807
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
1808
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
1809
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
1810
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
1811
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
1812
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
1813
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
1814
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
1815
|
+
}
|
|
1816
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
1817
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
1818
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
1819
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
1820
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1804
1823
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
1805
1824
|
try {
|
|
1806
1825
|
const WIX = "https://www.wixapis.com";
|
|
1807
|
-
const
|
|
1808
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
1809
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
1810
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
1826
|
+
const token = await liveSeedToken(WIX);
|
|
1811
1827
|
if (!token) return [];
|
|
1812
1828
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
1813
1829
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -26721,15 +26721,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
26721
26721
|
|
|
26722
26722
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
26723
26723
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
26724
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
26725
|
-
//
|
|
26724
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
26725
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
26726
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
26727
|
+
// baked details, preview still live-resolves).
|
|
26728
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
26729
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
26730
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
26731
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
26732
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
26733
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
26734
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
26735
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
26736
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
26737
|
+
}
|
|
26738
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
26739
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
26740
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
26741
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
26742
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
26743
|
+
}
|
|
26744
|
+
|
|
26726
26745
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
26727
26746
|
try {
|
|
26728
26747
|
const WIX = "https://www.wixapis.com";
|
|
26729
|
-
const
|
|
26730
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
26731
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
26732
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
26748
|
+
const token = await liveSeedToken(WIX);
|
|
26733
26749
|
if (!token) return [];
|
|
26734
26750
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
26735
26751
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// SDK; this only supplies the copy and the hydration reset.
|
|
5
5
|
import { hostSessionFromGlobal, type IapPriceCopy } from "@himalaya/iap";
|
|
6
6
|
import type { IapCommerce, IapPurchaseCopy, IapRestoreResult } from "@himalaya/iap-checkout";
|
|
7
|
+
import { paymentSetupMessage } from "./payment-setup.js";
|
|
7
8
|
import { copyParam, copyTemplate } from "./himi-copy.js";
|
|
8
9
|
|
|
9
10
|
/** Price labels from the screen's copy pack (`<prefix>.priceLoadingText`, …). */
|
|
@@ -25,6 +26,7 @@ export function iapPurchaseCopy(prefix: string): IapPurchaseCopy {
|
|
|
25
26
|
awaitingApproval: copyParam(`${prefix}.purchaseAwaitingApprovalText`, "Waiting for approval"),
|
|
26
27
|
unavailable: copyParam(`${prefix}.purchaseTemporarilyUnavailableText`, "Purchasing is temporarily unavailable."),
|
|
27
28
|
signInRequired: copyParam(`${prefix}.purchaseSignInText`, "Sign in to buy."),
|
|
29
|
+
sitePaymentUnavailable: paymentSetupMessage(prefix),
|
|
28
30
|
retry: copyParam(`${prefix}.purchaseRetryText`, "Something went wrong. Try again."),
|
|
29
31
|
priceChanged: copyParam(`${prefix}.purchasePriceChangedText`, "The price changed. Check it and try again."),
|
|
30
32
|
support: copyParam(`${prefix}.purchaseSupportText`, "We couldn't finish this purchase. Contact support."),
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { copyParam } from "./himi-copy.js";
|
|
2
|
+
|
|
3
|
+
/** No provider or country guess: Wix only established that online payment is unavailable. */
|
|
4
|
+
export function paymentSetupMessage(prefix: string): string {
|
|
5
|
+
return copyParam(`${prefix}.paymentSetupUnavailable`, "This site is not accepting online payments. Go back or contact the business for other payment options.");
|
|
6
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
import { offlineWriteMessage, offlineWritesEnabled, withOnlineWrites } from "../_shared/online-actions.js";
|
|
2
3
|
import { connectivity } from "@himalaya/state";
|
|
3
4
|
import { defineService as registerService } from "../_shared/collection-service.js";
|
|
@@ -6,7 +7,7 @@ import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
|
6
7
|
import { open as openUrl } from "@himalaya/open-url";
|
|
7
8
|
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
9
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
9
|
-
import { activePlanIds, entitlement, payCashierOrder } from "@himalaya/checkout";
|
|
10
|
+
import { activePlanIds, entitlement, isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
10
11
|
import { hostSessionFromGlobal, iapPriceFields, type IapCatalogItem } from "@himalaya/iap";
|
|
11
12
|
import { createIapCommerce, pricingPlanOrders } from "@himalaya/iap-checkout";
|
|
12
13
|
import { iapPriceCopy, iapPurchaseCopy, resetUnhydratedKeysOnOlderRuntime } from "../_shared/iap-worker.js";
|
|
@@ -290,7 +291,9 @@ async function regularJoinMessage(row: PlanRow, reference: { kind: string; id: s
|
|
|
290
291
|
if (pay.kind === "cancelled") {
|
|
291
292
|
return copyParam("plans.joinCancelledMessage", "Payment cancelled — you haven't joined.");
|
|
292
293
|
}
|
|
293
|
-
|
|
294
|
+
if (isPaymentSetupFailure(pay)) return paymentSetupMessage("plans");
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (isPaymentSetupFailure(error)) return paymentSetupMessage("plans");
|
|
294
297
|
}
|
|
295
298
|
return copyTemplate("plans.joinOnSiteMessage", "Memberships are purchased on the website — visit the site to join {name}.", { name: row.name });
|
|
296
299
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
// Tier-5 bundle: himi-events — event detail.
|
|
2
3
|
import { calendarDay, formatClock, formatCurrency, formatWeekdayDateTime, formatWeekdayMonthDay, formatTimeZoneLabel } from "../_shared/engine-intl.js";
|
|
3
4
|
import { defineService as registerService } from "@himalaya/state";
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
type WixEvent,
|
|
19
20
|
} from "@himalaya/wix-events";
|
|
20
21
|
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
21
|
-
import { payCashierOrder } from "@himalaya/checkout";
|
|
22
|
+
import { isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
22
23
|
import { get, upsert, type DbEntity } from "@himalaya/local-db";
|
|
23
24
|
import {
|
|
24
25
|
currentInputId,
|
|
@@ -986,16 +987,18 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
986
987
|
if (pay.kind === "paid") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.ticketIssued", "You're in — your ticket is confirmed.") };
|
|
987
988
|
else if (pay.kind === "handoff") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") };
|
|
988
989
|
else if (pay.kind === "cancelled") result = { ...s, snackbarMessage: detailCopy("event.ticketCancelled", "Payment cancelled — no ticket was issued.") };
|
|
990
|
+
else if (isPaymentSetupFailure(pay)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
989
991
|
else throw new Error("Payment could not be completed");
|
|
990
992
|
}
|
|
991
993
|
}
|
|
992
994
|
}
|
|
993
|
-
} catch {
|
|
995
|
+
} catch (error) {
|
|
996
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
994
997
|
try {
|
|
995
998
|
// A public event page is not pinned to this selection or price. Only
|
|
996
999
|
// continue in hosted checkout when a reservation already holds it.
|
|
997
1000
|
const params = reservationId ? { reservationId } : undefined;
|
|
998
|
-
if (params) {
|
|
1001
|
+
if (params && !result) {
|
|
999
1002
|
const redirect = await createRedirectSession({ eventsCheckout: params });
|
|
1000
1003
|
const url = redirect.redirectSession?.fullUrl;
|
|
1001
1004
|
if (url) {
|
|
@@ -1003,7 +1006,9 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
1003
1006
|
result = { ...s, ticketSheetOpen: false, snackbarMessage: opened.opened ? detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") : detailCopy("event.registrationOpenFailed", "Could not open the registration page.") };
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
|
-
} catch {
|
|
1009
|
+
} catch (error) {
|
|
1010
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
1011
|
+
}
|
|
1007
1012
|
if (!result) result = { ...s, snackbarMessage: detailCopy("event.purchaseUnavailable", "Purchasing is temporarily unavailable.") };
|
|
1008
1013
|
} finally { ticketCheckoutInFlight = false; }
|
|
1009
1014
|
return derive(result!);
|
|
@@ -82115,15 +82115,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
82115
82115
|
|
|
82116
82116
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
82117
82117
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
82118
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
82119
|
-
//
|
|
82118
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
82119
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
82120
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
82121
|
+
// baked details, preview still live-resolves).
|
|
82122
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
82123
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
82124
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
82125
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
82126
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
82127
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
82128
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
82129
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
82130
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
82131
|
+
}
|
|
82132
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
82133
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
82134
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
82135
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
82136
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
82137
|
+
}
|
|
82138
|
+
|
|
82120
82139
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
82121
82140
|
try {
|
|
82122
82141
|
const WIX = "https://www.wixapis.com";
|
|
82123
|
-
const
|
|
82124
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
82125
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
82126
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
82142
|
+
const token = await liveSeedToken(WIX);
|
|
82127
82143
|
if (!token) return [];
|
|
82128
82144
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
82129
82145
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -93008,15 +93008,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
93008
93008
|
|
|
93009
93009
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
93010
93010
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
93011
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
93012
|
-
//
|
|
93011
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
93012
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
93013
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
93014
|
+
// baked details, preview still live-resolves).
|
|
93015
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
93016
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
93017
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
93018
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
93019
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
93020
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
93021
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
93022
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
93023
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
93024
|
+
}
|
|
93025
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
93026
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
93027
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
93028
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
93029
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
93030
|
+
}
|
|
93031
|
+
|
|
93013
93032
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
93014
93033
|
try {
|
|
93015
93034
|
const WIX = "https://www.wixapis.com";
|
|
93016
|
-
const
|
|
93017
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
93018
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
93019
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
93035
|
+
const token = await liveSeedToken(WIX);
|
|
93020
93036
|
if (!token) return [];
|
|
93021
93037
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
93022
93038
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -26770,15 +26770,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
26770
26770
|
|
|
26771
26771
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
26772
26772
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
26773
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
26774
|
-
//
|
|
26773
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
26774
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
26775
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
26776
|
+
// baked details, preview still live-resolves).
|
|
26777
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
26778
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
26779
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
26780
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
26781
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
26782
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
26783
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
26784
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
26785
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
26786
|
+
}
|
|
26787
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
26788
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
26789
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
26790
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
26791
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
26792
|
+
}
|
|
26793
|
+
|
|
26775
26794
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
26776
26795
|
try {
|
|
26777
26796
|
const WIX = "https://www.wixapis.com";
|
|
26778
|
-
const
|
|
26779
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
26780
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
26781
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
26797
|
+
const token = await liveSeedToken(WIX);
|
|
26782
26798
|
if (!token) return [];
|
|
26783
26799
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
26784
26800
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// SDK; this only supplies the copy and the hydration reset.
|
|
5
5
|
import { hostSessionFromGlobal, type IapPriceCopy } from "@himalaya/iap";
|
|
6
6
|
import type { IapCommerce, IapPurchaseCopy, IapRestoreResult } from "@himalaya/iap-checkout";
|
|
7
|
+
import { paymentSetupMessage } from "./payment-setup.js";
|
|
7
8
|
import { copyParam, copyTemplate } from "./himi-copy.js";
|
|
8
9
|
|
|
9
10
|
/** Price labels from the screen's copy pack (`<prefix>.priceLoadingText`, …). */
|
|
@@ -25,6 +26,7 @@ export function iapPurchaseCopy(prefix: string): IapPurchaseCopy {
|
|
|
25
26
|
awaitingApproval: copyParam(`${prefix}.purchaseAwaitingApprovalText`, "Waiting for approval"),
|
|
26
27
|
unavailable: copyParam(`${prefix}.purchaseTemporarilyUnavailableText`, "Purchasing is temporarily unavailable."),
|
|
27
28
|
signInRequired: copyParam(`${prefix}.purchaseSignInText`, "Sign in to buy."),
|
|
29
|
+
sitePaymentUnavailable: paymentSetupMessage(prefix),
|
|
28
30
|
retry: copyParam(`${prefix}.purchaseRetryText`, "Something went wrong. Try again."),
|
|
29
31
|
priceChanged: copyParam(`${prefix}.purchasePriceChangedText`, "The price changed. Check it and try again."),
|
|
30
32
|
support: copyParam(`${prefix}.purchaseSupportText`, "We couldn't finish this purchase. Contact support."),
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { copyParam } from "./himi-copy.js";
|
|
2
|
+
|
|
3
|
+
/** No provider or country guess: Wix only established that online payment is unavailable. */
|
|
4
|
+
export function paymentSetupMessage(prefix: string): string {
|
|
5
|
+
return copyParam(`${prefix}.paymentSetupUnavailable`, "This site is not accepting online payments. Go back or contact the business for other payment options.");
|
|
6
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
import { offlineWriteMessage, offlineWritesEnabled, withOnlineWrites } from "../_shared/online-actions.js";
|
|
2
3
|
import { connectivity } from "@himalaya/state";
|
|
3
4
|
import { defineService as registerService } from "../_shared/collection-service.js";
|
|
@@ -6,7 +7,7 @@ import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
|
6
7
|
import { open as openUrl } from "@himalaya/open-url";
|
|
7
8
|
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
8
9
|
import { copyParam, copyTemplate, stashCopy } from "../_shared/himi-copy.js";
|
|
9
|
-
import { activePlanIds, entitlement, payCashierOrder } from "@himalaya/checkout";
|
|
10
|
+
import { activePlanIds, entitlement, isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
10
11
|
import { hostSessionFromGlobal, iapPriceFields, type IapCatalogItem } from "@himalaya/iap";
|
|
11
12
|
import { createIapCommerce, pricingPlanOrders } from "@himalaya/iap-checkout";
|
|
12
13
|
import { iapPriceCopy, iapPurchaseCopy, resetUnhydratedKeysOnOlderRuntime } from "../_shared/iap-worker.js";
|
|
@@ -290,7 +291,9 @@ async function regularJoinMessage(row: PlanRow, reference: { kind: string; id: s
|
|
|
290
291
|
if (pay.kind === "cancelled") {
|
|
291
292
|
return copyParam("plans.joinCancelledMessage", "Payment cancelled — you haven't joined.");
|
|
292
293
|
}
|
|
293
|
-
|
|
294
|
+
if (isPaymentSetupFailure(pay)) return paymentSetupMessage("plans");
|
|
295
|
+
} catch (error) {
|
|
296
|
+
if (isPaymentSetupFailure(error)) return paymentSetupMessage("plans");
|
|
294
297
|
}
|
|
295
298
|
return copyTemplate("plans.joinOnSiteMessage", "Memberships are purchased on the website — visit the site to join {name}.", { name: row.name });
|
|
296
299
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
// Tier-5 bundle: himi-events — event detail.
|
|
2
3
|
import { calendarDay, formatClock, formatCurrency, formatWeekdayDateTime, formatWeekdayMonthDay, formatTimeZoneLabel } from "../_shared/engine-intl.js";
|
|
3
4
|
import { defineService as registerService } from "@himalaya/state";
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
type WixEvent,
|
|
19
20
|
} from "@himalaya/wix-events";
|
|
20
21
|
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
21
|
-
import { payCashierOrder } from "@himalaya/checkout";
|
|
22
|
+
import { isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
22
23
|
import { get, upsert, type DbEntity } from "@himalaya/local-db";
|
|
23
24
|
import {
|
|
24
25
|
currentInputId,
|
|
@@ -986,16 +987,18 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
986
987
|
if (pay.kind === "paid") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.ticketIssued", "You're in — your ticket is confirmed.") };
|
|
987
988
|
else if (pay.kind === "handoff") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") };
|
|
988
989
|
else if (pay.kind === "cancelled") result = { ...s, snackbarMessage: detailCopy("event.ticketCancelled", "Payment cancelled — no ticket was issued.") };
|
|
990
|
+
else if (isPaymentSetupFailure(pay)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
989
991
|
else throw new Error("Payment could not be completed");
|
|
990
992
|
}
|
|
991
993
|
}
|
|
992
994
|
}
|
|
993
|
-
} catch {
|
|
995
|
+
} catch (error) {
|
|
996
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
994
997
|
try {
|
|
995
998
|
// A public event page is not pinned to this selection or price. Only
|
|
996
999
|
// continue in hosted checkout when a reservation already holds it.
|
|
997
1000
|
const params = reservationId ? { reservationId } : undefined;
|
|
998
|
-
if (params) {
|
|
1001
|
+
if (params && !result) {
|
|
999
1002
|
const redirect = await createRedirectSession({ eventsCheckout: params });
|
|
1000
1003
|
const url = redirect.redirectSession?.fullUrl;
|
|
1001
1004
|
if (url) {
|
|
@@ -1003,7 +1006,9 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
1003
1006
|
result = { ...s, ticketSheetOpen: false, snackbarMessage: opened.opened ? detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") : detailCopy("event.registrationOpenFailed", "Could not open the registration page.") };
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
|
-
} catch {
|
|
1009
|
+
} catch (error) {
|
|
1010
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
1011
|
+
}
|
|
1007
1012
|
if (!result) result = { ...s, snackbarMessage: detailCopy("event.purchaseUnavailable", "Purchasing is temporarily unavailable.") };
|
|
1008
1013
|
} finally { ticketCheckoutInFlight = false; }
|
|
1009
1014
|
return derive(result!);
|
|
@@ -85003,15 +85003,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
85003
85003
|
|
|
85004
85004
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
85005
85005
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
85006
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
85007
|
-
//
|
|
85006
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
85007
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
85008
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
85009
|
+
// baked details, preview still live-resolves).
|
|
85010
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
85011
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
85012
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
85013
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
85014
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
85015
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
85016
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
85017
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
85018
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
85019
|
+
}
|
|
85020
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
85021
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
85022
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
85023
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
85024
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
85025
|
+
}
|
|
85026
|
+
|
|
85008
85027
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
85009
85028
|
try {
|
|
85010
85029
|
const WIX = "https://www.wixapis.com";
|
|
85011
|
-
const
|
|
85012
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
85013
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
85014
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
85030
|
+
const token = await liveSeedToken(WIX);
|
|
85015
85031
|
if (!token) return [];
|
|
85016
85032
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
85017
85033
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -36114,15 +36114,31 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
|
|
|
36114
36114
|
|
|
36115
36115
|
// Live seed-id enumeration: a published release serves only EXACT screens, so
|
|
36116
36116
|
// `himi push` bakes each templated detail route's CURRENT catalog ids as exact
|
|
36117
|
-
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId
|
|
36118
|
-
//
|
|
36117
|
+
// screens via `seedIds`. Anonymous visitor rung against this app's own clientId — or,
|
|
36118
|
+
// for an app bound through the One App visitor identity (`visitorSource: "one-app"`,
|
|
36119
|
+
// no client), that site's One App visitor instance. Best-effort (offline build → no
|
|
36120
|
+
// baked details, preview still live-resolves).
|
|
36121
|
+
async function liveSeedToken(WIX: string): Promise<string | undefined> {
|
|
36122
|
+
const auth = (config as { auth?: { config?: { clientId?: string; visitorSource?: string; metaSiteId?: string } } }).auth?.config;
|
|
36123
|
+
// A One App binding boots as the site's One App visitor, so the seed reads as that visitor too —
|
|
36124
|
+
// even beside a member-login clientId, and never repointed by a stray local WIX_CLIENT_ID.
|
|
36125
|
+
const oneApp = auth?.visitorSource === "one-app";
|
|
36126
|
+
const clientId = oneApp ? "" : process.env.WIX_CLIENT_ID ?? auth?.clientId ?? "";
|
|
36127
|
+
if (clientId && !clientId.startsWith("YOUR_")) {
|
|
36128
|
+
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
36129
|
+
return ((await mint.json()) as { access_token?: string }).access_token;
|
|
36130
|
+
}
|
|
36131
|
+
const msid = oneApp ? auth?.metaSiteId ?? "" : "";
|
|
36132
|
+
if (!/^[0-9a-fA-F-]{10,64}$/.test(msid)) return undefined;
|
|
36133
|
+
const mint = await fetch(`https://apps.wix.com/_api/one-app-session-web/v3/businesses/${msid}/signed-instance?signed_instance_type=Visitor`, { headers: { Accept: "application/json" }, redirect: "error" });
|
|
36134
|
+
const visitor = (await mint.json()) as { signedInstance?: string; signedInstanceType?: string };
|
|
36135
|
+
return visitor.signedInstanceType === "Visitor" ? visitor.signedInstance : undefined;
|
|
36136
|
+
}
|
|
36137
|
+
|
|
36119
36138
|
async function liveSeedIds(spec: LiveSeed): Promise<string[]> {
|
|
36120
36139
|
try {
|
|
36121
36140
|
const WIX = "https://www.wixapis.com";
|
|
36122
|
-
const
|
|
36123
|
-
if (!clientId || clientId.startsWith("YOUR_")) return [];
|
|
36124
|
-
const mint = await fetch(WIX + "/oauth2/token", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId, grantType: "anonymous" }) });
|
|
36125
|
-
const token = ((await mint.json()) as { access_token?: string }).access_token;
|
|
36141
|
+
const token = await liveSeedToken(WIX);
|
|
36126
36142
|
if (!token) return [];
|
|
36127
36143
|
const res = await fetch(WIX + spec.path, { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, body: JSON.stringify(spec.body) });
|
|
36128
36144
|
const json = (await res.json()) as Record<string, unknown>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// SDK; this only supplies the copy and the hydration reset.
|
|
5
5
|
import { hostSessionFromGlobal, type IapPriceCopy } from "@himalaya/iap";
|
|
6
6
|
import type { IapCommerce, IapPurchaseCopy, IapRestoreResult } from "@himalaya/iap-checkout";
|
|
7
|
+
import { paymentSetupMessage } from "./payment-setup.js";
|
|
7
8
|
import { copyParam, copyTemplate } from "./himi-copy.js";
|
|
8
9
|
|
|
9
10
|
/** Price labels from the screen's copy pack (`<prefix>.priceLoadingText`, …). */
|
|
@@ -25,6 +26,7 @@ export function iapPurchaseCopy(prefix: string): IapPurchaseCopy {
|
|
|
25
26
|
awaitingApproval: copyParam(`${prefix}.purchaseAwaitingApprovalText`, "Waiting for approval"),
|
|
26
27
|
unavailable: copyParam(`${prefix}.purchaseTemporarilyUnavailableText`, "Purchasing is temporarily unavailable."),
|
|
27
28
|
signInRequired: copyParam(`${prefix}.purchaseSignInText`, "Sign in to buy."),
|
|
29
|
+
sitePaymentUnavailable: paymentSetupMessage(prefix),
|
|
28
30
|
retry: copyParam(`${prefix}.purchaseRetryText`, "Something went wrong. Try again."),
|
|
29
31
|
priceChanged: copyParam(`${prefix}.purchasePriceChangedText`, "The price changed. Check it and try again."),
|
|
30
32
|
support: copyParam(`${prefix}.purchaseSupportText`, "We couldn't finish this purchase. Contact support."),
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { copyParam } from "./himi-copy.js";
|
|
2
|
+
|
|
3
|
+
/** No provider or country guess: Wix only established that online payment is unavailable. */
|
|
4
|
+
export function paymentSetupMessage(prefix: string): string {
|
|
5
|
+
return copyParam(`${prefix}.paymentSetupUnavailable`, "This site is not accepting online payments. Go back or contact the business for other payment options.");
|
|
6
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
import { withOnlineWrites } from "../_shared/online-actions.js";
|
|
2
3
|
import { defineService as registerState } from "@himalaya/state";
|
|
3
4
|
import { getStoreProduct } from "../_shared/himi-store.js";
|
|
@@ -7,7 +8,7 @@ import { withIapPresentation } from "../_shared/iap-presentation.js";
|
|
|
7
8
|
import { type IapCommerce, classifyCart } from "@himalaya/iap-checkout";
|
|
8
9
|
import { addCouponToCurrentCart, calculateCurrentCart, createCheckoutFromCurrentCart, getCurrentCart, removeCouponFromCurrentCart, removeLineItemsFromCurrentCart, updateLineItemsQuantity, type WixCartDetail, type WixCartLineItemDetail } from "@himalaya/wix-ecom";
|
|
9
10
|
import { createRedirectSession } from "@himalaya/wix-redirects";
|
|
10
|
-
import { payCashierOrder } from "@himalaya/checkout";
|
|
11
|
+
import { isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
11
12
|
import { hostedCheckoutOpener, isHostedWorker } from "../_shared/hosted-checkout.js";
|
|
12
13
|
import { formatCurrency } from "../_shared/engine-intl.js";
|
|
13
14
|
|
|
@@ -574,8 +575,10 @@ const svc = defineService<State, {
|
|
|
574
575
|
// only confirmed once it lands, so the cart must survive a bail-out.
|
|
575
576
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutOpenedMessage", "Checkout opened.") });
|
|
576
577
|
}
|
|
578
|
+
if (isPaymentSetupFailure(pay)) return derive({ ...state, checkoutHint: paymentSetupMessage("cart") });
|
|
577
579
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
578
|
-
} catch {
|
|
580
|
+
} catch (error) {
|
|
581
|
+
if (isPaymentSetupFailure(error)) return derive({ ...state, checkoutHint: paymentSetupMessage("cart") });
|
|
579
582
|
return derive({ ...state, checkoutHint: copyParam("cart.checkoutFailedMessage", "Checkout could not start.") });
|
|
580
583
|
}
|
|
581
584
|
},
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { paymentSetupMessage } from "../_shared/payment-setup.js";
|
|
1
2
|
// Tier-5 bundle: himi-events — event detail.
|
|
2
3
|
import { calendarDay, formatClock, formatCurrency, formatWeekdayDateTime, formatWeekdayMonthDay, formatTimeZoneLabel } from "../_shared/engine-intl.js";
|
|
3
4
|
import { defineService as registerService } from "@himalaya/state";
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
type WixEvent,
|
|
19
20
|
} from "@himalaya/wix-events";
|
|
20
21
|
import { session as wixPlatformSession } from "@himalaya/wix-platform";
|
|
21
|
-
import { payCashierOrder } from "@himalaya/checkout";
|
|
22
|
+
import { isPaymentSetupFailure, payCashierOrder } from "@himalaya/checkout";
|
|
22
23
|
import { get, upsert, type DbEntity } from "@himalaya/local-db";
|
|
23
24
|
import {
|
|
24
25
|
currentInputId,
|
|
@@ -986,16 +987,18 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
986
987
|
if (pay.kind === "paid") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.ticketIssued", "You're in — your ticket is confirmed.") };
|
|
987
988
|
else if (pay.kind === "handoff") result = { ...s, ticketSheetOpen: false, snackbarMessage: detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") };
|
|
988
989
|
else if (pay.kind === "cancelled") result = { ...s, snackbarMessage: detailCopy("event.ticketCancelled", "Payment cancelled — no ticket was issued.") };
|
|
990
|
+
else if (isPaymentSetupFailure(pay)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
989
991
|
else throw new Error("Payment could not be completed");
|
|
990
992
|
}
|
|
991
993
|
}
|
|
992
994
|
}
|
|
993
|
-
} catch {
|
|
995
|
+
} catch (error) {
|
|
996
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
994
997
|
try {
|
|
995
998
|
// A public event page is not pinned to this selection or price. Only
|
|
996
999
|
// continue in hosted checkout when a reservation already holds it.
|
|
997
1000
|
const params = reservationId ? { reservationId } : undefined;
|
|
998
|
-
if (params) {
|
|
1001
|
+
if (params && !result) {
|
|
999
1002
|
const redirect = await createRedirectSession({ eventsCheckout: params });
|
|
1000
1003
|
const url = redirect.redirectSession?.fullUrl;
|
|
1001
1004
|
if (url) {
|
|
@@ -1003,7 +1006,9 @@ const svc: ReturnType<typeof defineService<S, DetailActions>> = defineService<S,
|
|
|
1003
1006
|
result = { ...s, ticketSheetOpen: false, snackbarMessage: opened.opened ? detailCopy("event.checkoutOpened", "Complete checkout in the browser to get your tickets.") : detailCopy("event.registrationOpenFailed", "Could not open the registration page.") };
|
|
1004
1007
|
}
|
|
1005
1008
|
}
|
|
1006
|
-
} catch {
|
|
1009
|
+
} catch (error) {
|
|
1010
|
+
if (isPaymentSetupFailure(error)) result = { ...s, snackbarMessage: paymentSetupMessage("event") };
|
|
1011
|
+
}
|
|
1007
1012
|
if (!result) result = { ...s, snackbarMessage: detailCopy("event.purchaseUnavailable", "Purchasing is temporarily unavailable.") };
|
|
1008
1013
|
} finally { ticketCheckoutInFlight = false; }
|
|
1009
1014
|
return derive(result!);
|