@wix/himalaya-cli 0.1496.0 → 0.1497.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/sdk/iap/src/attendance-classifier.d.ts +37 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/catalog-pricing-contract.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/index.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/iap/src/wix-payments-contract.d.ts +11 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +27 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/attendance.d.ts +10 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/iap-verticals/index.d.ts +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/index.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +33 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +346 -26
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap.mjs +132 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +366 -48
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +5 -0
- package/dist/cli.mjs +816 -666
- package/guides/iap-products.md +7 -1
- package/guides/sdk-reference.json +376 -27
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +394 -0
- package/templates/beauty-salon/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/beauty-salon/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/beauty-salon/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/beauty-salon/tier5-src/himi-booking-time/index.ts +52 -7
- package/templates/branded-lite/dev/index.ts +1073 -284
- package/templates/branded-lite/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/branded-lite/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/branded-lite/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/branded-lite/tier5-src/himi-booking-time/index.ts +52 -7
- package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/community-club/dev/index.ts +397 -2
- package/templates/community-club/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/community-club/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/community-club/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/community-club/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/events-meetups/dev/index.ts +397 -2
- package/templates/events-meetups/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/events-meetups/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/events-meetups/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/gym-fitness/dev/index.ts +828 -39
- package/templates/gym-fitness/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/gym-fitness/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/gym-fitness/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/gym-fitness/tier5-src/himi-booking-time/index.ts +52 -7
- package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/nonprofit-cause/dev/index.ts +397 -2
- package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/nonprofit-cause/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/podcast-creator/dev/index.ts +397 -2
- package/templates/podcast-creator/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/podcast-creator/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/podcast-creator/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/portfolio-creative/dev/index.ts +397 -2
- package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/portfolio-creative/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/portfolio-creative/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/restaurant/dev/index.ts +397 -2
- package/templates/restaurant/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/restaurant/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/restaurant/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/restaurant/tier5-src/himi-events-detail/index.ts +112 -21
- package/templates/yoga-studio/dev/index.ts +828 -39
- package/templates/yoga-studio/tier5-src/_shared/iap-attendance-form.ts +106 -0
- package/templates/yoga-studio/tier5-src/_shared/iap-attendance-purchase.ts +211 -0
- package/templates/yoga-studio/tier5-src/_shared/iap-attendance.ts +38 -0
- package/templates/yoga-studio/tier5-src/himi-booking-time/index.ts +52 -7
- package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +112 -21
|
@@ -135,9 +135,9 @@ function createPurchaseCoordinator(deps) {
|
|
|
135
135
|
if (session.kind !== "member") return requireSignIn();
|
|
136
136
|
if (listing === "listed") clearReconcileProblem();
|
|
137
137
|
const now = deps.clock.now();
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
await settleDelivery(session, await deliver(session,
|
|
138
|
+
const eligible2 = itemsWhere((item) => isAwaitingDelivery(item) && (item.state.nextAttemptAt === null || item.state.nextAttemptAt <= now));
|
|
139
|
+
eligible2.forEach(restartAttemptBudget);
|
|
140
|
+
await settleDelivery(session, await deliver(session, eligible2));
|
|
141
141
|
}
|
|
142
142
|
async function settleDelivery(session, delivered) {
|
|
143
143
|
applyDelivered(delivered);
|
|
@@ -667,7 +667,8 @@ function applePrice(mapping, products) {
|
|
|
667
667
|
const matches = products.filter((value) => isObject2(value) && value.id === mapping.productId);
|
|
668
668
|
const product = matches[0];
|
|
669
669
|
if (matches.length !== 1 || !nonempty(product?.displayPrice)) return unavailable(mapping.reference, "priceUnavailable");
|
|
670
|
-
|
|
670
|
+
const attendance = mapping.reference.kind === "bookingsService" || mapping.reference.kind === "eventsTicket";
|
|
671
|
+
if (product?.type !== (attendance ? "consumable" : "nonConsumable")) return unavailable(mapping.reference, "unsupportedProductType");
|
|
671
672
|
return {
|
|
672
673
|
reference: mapping.reference,
|
|
673
674
|
status: "ready",
|
|
@@ -686,6 +687,9 @@ var sameReference = (value, reference) => isObject2(value) && value.kind === ref
|
|
|
686
687
|
|
|
687
688
|
// ../../core/sdk/iap/src/wix-payments-contract.ts
|
|
688
689
|
var HIMALAYA_SERVE_IAP_ROUTE = { prefix: "/himalaya-serve/v1/iap" };
|
|
690
|
+
var BOOKINGS_APPLE_SALES_ENABLED = false;
|
|
691
|
+
var EVENTS_APPLE_SALES_ENABLED = false;
|
|
692
|
+
var ATTENDANCE_SALE_RULE = { appProductId: (id) => id, productType: "CONSUMABLE" };
|
|
689
693
|
var STORES_ITEM_PAYMENT_ENABLED = false;
|
|
690
694
|
var STORES_APPLE_SALES_ENABLED = true;
|
|
691
695
|
var STORES_PRODUCT_SALE_RULE = { appProductId: (id) => id, productType: "NON_CONSUMABLE" };
|
|
@@ -696,10 +700,17 @@ function appleSaleRules(options = {}) {
|
|
|
696
700
|
return {
|
|
697
701
|
onlineProgram: ONLINE_PROGRAM_SALE_RULE,
|
|
698
702
|
...(options.storesAppleSalesEnabled ?? STORES_APPLE_SALES_ENABLED) || (options.storesItemPaymentEnabled ?? STORES_ITEM_PAYMENT_ENABLED) ? { storesProduct: STORES_PRODUCT_SALE_RULE } : {},
|
|
699
|
-
...options.pricingPlanAppleSalesEnabled ?? PRICING_PLAN_APPLE_SALES_ENABLED ? { pricingPlan: PRICING_PLAN_SALE_RULE } : {}
|
|
703
|
+
...options.pricingPlanAppleSalesEnabled ?? PRICING_PLAN_APPLE_SALES_ENABLED ? { pricingPlan: PRICING_PLAN_SALE_RULE } : {},
|
|
704
|
+
...options.bookingsAppleSalesEnabled ?? BOOKINGS_APPLE_SALES_ENABLED ? { bookingsService: ATTENDANCE_SALE_RULE } : {},
|
|
705
|
+
...options.eventsAppleSalesEnabled ?? EVENTS_APPLE_SALES_ENABLED ? { eventsTicket: ATTENDANCE_SALE_RULE } : {}
|
|
700
706
|
};
|
|
701
707
|
}
|
|
702
708
|
var APPLE_SALE_RULES = appleSaleRules();
|
|
709
|
+
var APPLE_PROVISIONING_RULES = {
|
|
710
|
+
...APPLE_SALE_RULES,
|
|
711
|
+
bookingsService: ATTENDANCE_SALE_RULE,
|
|
712
|
+
eventsTicket: ATTENDANCE_SALE_RULE
|
|
713
|
+
};
|
|
703
714
|
|
|
704
715
|
// ../../core/sdk/iap/src/mapping-source.ts
|
|
705
716
|
function iapMappingSource() {
|
|
@@ -1338,6 +1349,109 @@ var COMPLETE_PAYMENT_CODES = [
|
|
|
1338
1349
|
];
|
|
1339
1350
|
var GET_PAYMENT_CODES = ["NOT_FOUND"];
|
|
1340
1351
|
|
|
1352
|
+
// ../../core/sdk/iap/src/attendance-classifier.ts
|
|
1353
|
+
function classifyForApple(item, currency) {
|
|
1354
|
+
if (item.hidden !== false || item.attendance === "hybrid") return "decide";
|
|
1355
|
+
if (item.kind === "bookingsService") return bookingRoute(item, currency);
|
|
1356
|
+
return ticketRoute(item, currency);
|
|
1357
|
+
}
|
|
1358
|
+
function bookingRoute(item, currency) {
|
|
1359
|
+
if (item.onlineBooking !== true) return "decide";
|
|
1360
|
+
if (item.conferencing === false && item.locations?.length && item.locations.every((type) => type === "BUSINESS" || type === "CUSTOMER" || type === "CUSTOM")) {
|
|
1361
|
+
return item.attendance === "online" ? "decide" : "wixPayments";
|
|
1362
|
+
}
|
|
1363
|
+
if (item.conferencing !== true || item.attendance === "physical") return "decide";
|
|
1364
|
+
if (item.attendance !== "online" && (!item.locations || item.locations.length > 0)) return "decide";
|
|
1365
|
+
if (item.type === "APPOINTMENT") {
|
|
1366
|
+
return item.capacity === 1 && item.maxParticipantsPerBooking === 1 ? "wixPayments" : "decide";
|
|
1367
|
+
}
|
|
1368
|
+
if (item.type !== "CLASS" && item.type !== "COURSE" || !item.capacity || item.capacity <= 1) return "decide";
|
|
1369
|
+
if (item.priceType === "NO_FEE" || zeroPrice(item.amount)) return "wixPayments";
|
|
1370
|
+
if (item.onlinePayment !== true || item.deposit !== false || item.priceType !== "FIXED") return "decide";
|
|
1371
|
+
return fixedPriceRoute(item, currency);
|
|
1372
|
+
}
|
|
1373
|
+
function ticketRoute(item, currency) {
|
|
1374
|
+
if (item.location === "VENUE") return item.attendance === "online" ? "decide" : "wixPayments";
|
|
1375
|
+
if (item.location !== "ONLINE" || item.attendance === "physical" || item.registration !== "TICKETING") return "decide";
|
|
1376
|
+
if (item.eventStatus !== "UPCOMING" && item.eventStatus !== "STARTED") return "decide";
|
|
1377
|
+
if (item.saleStatus !== "SALE_STARTED") return "decide";
|
|
1378
|
+
if (zeroPrice(item.amount)) return "wixPayments";
|
|
1379
|
+
return item.priceType === "STANDARD" ? fixedPriceRoute(item, currency) : "decide";
|
|
1380
|
+
}
|
|
1381
|
+
function fixedPriceRoute(item, currency) {
|
|
1382
|
+
const amount = item.amount;
|
|
1383
|
+
return typeof amount === "string" && /^\d+(?:\.\d+)?$/.test(amount) && Number.isFinite(Number(amount)) && Number(amount) > 0 && /^[A-Z]{3}$/.test(currency) && item.currency === currency ? "appleIap" : "decide";
|
|
1384
|
+
}
|
|
1385
|
+
function bookingAttendanceOf(raw) {
|
|
1386
|
+
const s = object(raw);
|
|
1387
|
+
const payment = object(s.payment);
|
|
1388
|
+
const fixed = object(payment.fixed);
|
|
1389
|
+
const price = object(fixed.price);
|
|
1390
|
+
const options = object(payment.options);
|
|
1391
|
+
const policy = object(object(s.bookingPolicy).participantsPolicy);
|
|
1392
|
+
return {
|
|
1393
|
+
kind: "bookingsService",
|
|
1394
|
+
type: text(s.type),
|
|
1395
|
+
capacity: numeric(s.defaultCapacity),
|
|
1396
|
+
maxParticipantsPerBooking: policy.enabled === true ? numeric(policy.maxParticipantsPerBooking) : void 0,
|
|
1397
|
+
hidden: boolean(s.hidden),
|
|
1398
|
+
conferencing: boolean(object(s.conferencing).enabled),
|
|
1399
|
+
locations: Array.isArray(s.locations) ? s.locations.map((l) => text(object(l).type) ?? "UNKNOWN") : void 0,
|
|
1400
|
+
onlineBooking: boolean(object(s.onlineBooking).enabled),
|
|
1401
|
+
onlinePayment: boolean(options.online),
|
|
1402
|
+
deposit: options.deposit === true || fixed.deposit !== void 0,
|
|
1403
|
+
priceType: text(payment.rateType),
|
|
1404
|
+
amount: text(price.value),
|
|
1405
|
+
currency: text(price.currency)
|
|
1406
|
+
};
|
|
1407
|
+
}
|
|
1408
|
+
function ticketAttendanceOf(event, definition) {
|
|
1409
|
+
const e = object(event);
|
|
1410
|
+
const t = object(definition);
|
|
1411
|
+
const pricing = object(t.pricingMethod);
|
|
1412
|
+
const price = object(pricing.fixedPrice);
|
|
1413
|
+
const registration = object(e.registration);
|
|
1414
|
+
const type = text(registration.type) ?? text(registration.initialType) ?? text(e.eventType);
|
|
1415
|
+
const status = text(e.status) ?? text(e.eventStatus);
|
|
1416
|
+
return {
|
|
1417
|
+
kind: "eventsTicket",
|
|
1418
|
+
location: text(object(e.location).type),
|
|
1419
|
+
registration: type === "TICKETS" || type === "RSVP_AND_TICKETS" ? "TICKETING" : type,
|
|
1420
|
+
eventStatus: status === "SCHEDULED" ? "UPCOMING" : status,
|
|
1421
|
+
saleStatus: text(t.saleStatus),
|
|
1422
|
+
hidden: boolean(t.hidden),
|
|
1423
|
+
priceType: text(pricing.pricingType),
|
|
1424
|
+
amount: text(price.value),
|
|
1425
|
+
currency: text(price.currency)
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
function availableTicketAttendanceOf(event, ticket) {
|
|
1429
|
+
const e = object(event);
|
|
1430
|
+
const t = object(ticket);
|
|
1431
|
+
const pricing = object(t.pricing);
|
|
1432
|
+
const fixed = object(pricing.fixedPrice);
|
|
1433
|
+
const price = object(t.price);
|
|
1434
|
+
const visible = Array.isArray(t.state) && t.state.length === 0 && object(t.dashboard).hidden !== true && typeof t.id === "string" && t.id.length > 0 && typeof e.id === "string" && e.id.length > 0 && t.eventId === e.id;
|
|
1435
|
+
const fixedPrice = t.free === false && pricing.pricingType === "STANDARD" && sameTicketAmount(fixed.amount, price.amount) && fixed.currency === price.currency;
|
|
1436
|
+
return ticketAttendanceOf(e, {
|
|
1437
|
+
hidden: visible ? false : void 0,
|
|
1438
|
+
saleStatus: t.saleStatus,
|
|
1439
|
+
pricingMethod: { pricingType: fixedPrice ? "STANDARD" : void 0, fixedPrice: { value: fixed.amount, currency: fixed.currency } }
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
function sameTicketAmount(left, right) {
|
|
1443
|
+
const valid = (value) => typeof value === "string" && /^\d+(?:\.\d+)?$/.test(value);
|
|
1444
|
+
const normalized = (value) => value.replace(/^0+(?=\d)/, "").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
|
|
1445
|
+
return valid(left) && valid(right) && normalized(left) === normalized(right);
|
|
1446
|
+
}
|
|
1447
|
+
function object(value) {
|
|
1448
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1449
|
+
}
|
|
1450
|
+
var text = (value) => typeof value === "string" ? value : void 0;
|
|
1451
|
+
var numeric = (value) => typeof value === "number" ? value : void 0;
|
|
1452
|
+
var boolean = (value) => typeof value === "boolean" ? value : void 0;
|
|
1453
|
+
var zeroPrice = (value) => typeof value === "string" && /^0+(?:\.0+)?$/.test(value);
|
|
1454
|
+
|
|
1341
1455
|
// ../../core/sdk/iap/src/index.ts
|
|
1342
1456
|
async function getProducts(productIds) {
|
|
1343
1457
|
if (!productIds || productIds.length === 0) return [];
|
|
@@ -1641,11 +1755,11 @@ function partitionKey(key) {
|
|
|
1641
1755
|
return `${PREFIX}.${key.purchasesAppId}.${key.siteId}.${memberKey(key.memberId)}`;
|
|
1642
1756
|
}
|
|
1643
1757
|
function memberKey(memberId) {
|
|
1644
|
-
const
|
|
1758
|
+
const text2 = memberId.toLowerCase();
|
|
1645
1759
|
let h1 = 3735928559;
|
|
1646
1760
|
let h2 = 1103547991;
|
|
1647
|
-
for (let i = 0; i <
|
|
1648
|
-
const code =
|
|
1761
|
+
for (let i = 0; i < text2.length; i++) {
|
|
1762
|
+
const code = text2.charCodeAt(i);
|
|
1649
1763
|
h1 = Math.imul(h1 ^ code, 2654435761);
|
|
1650
1764
|
h2 = Math.imul(h2 ^ code, 1597334677);
|
|
1651
1765
|
}
|
|
@@ -1684,9 +1798,9 @@ function isUUID3(value) {
|
|
|
1684
1798
|
}
|
|
1685
1799
|
var VERSION = 1;
|
|
1686
1800
|
var PREFIX = "himi.iap.wix-checkout.v1";
|
|
1687
|
-
var STAGES = /* @__PURE__ */ new Set(["startingItem", "ordered", "charged", "started", "submitted", "held", "needsSupport"]);
|
|
1801
|
+
var STAGES = /* @__PURE__ */ new Set(["startingItem", "openingOrder", "ordered", "charged", "started", "submitted", "fulfilled", "held", "needsSupport"]);
|
|
1688
1802
|
var HOLD_MS = { held: NEEDS_SUPPORT_HOLD_MS, needsSupport: NEEDS_SUPPORT_HOLD_MS, startingItem: ITEM_START_HOLD_MS };
|
|
1689
|
-
var EVICTABLE = /* @__PURE__ */ new Set(["ordered", "charged", "started"]);
|
|
1803
|
+
var EVICTABLE = /* @__PURE__ */ new Set(["fulfilled", "ordered", "charged", "started"]);
|
|
1690
1804
|
|
|
1691
1805
|
// ../../stdlib/flows/iap-checkout/src/wix-bridge.ts
|
|
1692
1806
|
function bindBridge(session, provider, bridge) {
|
|
@@ -1727,10 +1841,10 @@ function isLiveHost(bridge) {
|
|
|
1727
1841
|
}
|
|
1728
1842
|
function refusalOf(error) {
|
|
1729
1843
|
const message = error?.message;
|
|
1730
|
-
const
|
|
1731
|
-
if (BRIDGE_REFUSAL2.test(
|
|
1732
|
-
if (PRINCIPAL_CHANGED2.test(
|
|
1733
|
-
const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(
|
|
1844
|
+
const text2 = typeof message === "string" ? message : "";
|
|
1845
|
+
if (BRIDGE_REFUSAL2.test(text2)) return { status: "notEnabled" };
|
|
1846
|
+
if (PRINCIPAL_CHANGED2.test(text2)) return SESSION_CHANGED;
|
|
1847
|
+
const http = /^HTTP (\d{3})(?: \[([^\]]+)\])?:/.exec(text2);
|
|
1734
1848
|
if (!http) return { status: "unavailable" };
|
|
1735
1849
|
return httpRefusal(Number(http[1]), http[2] ?? "");
|
|
1736
1850
|
}
|
|
@@ -1786,12 +1900,19 @@ function createWixOrderBackend(deps) {
|
|
|
1786
1900
|
const stage = refAt(sale.partition, sale.catalogRef)?.stage;
|
|
1787
1901
|
const failure3 = stage && BLOCKING_STAGES[stage];
|
|
1788
1902
|
if (failure3) return stopWith("rejected", failure3);
|
|
1903
|
+
if (sale.adapter.repeatable) {
|
|
1904
|
+
const prefix = `${sale.item.reference.kind}:${sale.item.reference.id}#`;
|
|
1905
|
+
const unresolved = sale.partition.refs().find((ref) => ref.key.startsWith(prefix) && ["openingOrder", "held", "needsSupport"].includes(ref.stage));
|
|
1906
|
+
if (unresolved) return stopWith("rejected", unresolved.stage === "openingOrder" ? "outcomeUnknown" : "needsSupport");
|
|
1907
|
+
}
|
|
1789
1908
|
return deps.productBusy?.(sale.appleProduct.productId) ? stopWith("rejected", "paymentInProgress") : null;
|
|
1790
1909
|
}
|
|
1791
1910
|
async function saleFor(session, catalogRef) {
|
|
1792
1911
|
const sold = deps.itemFor(catalogRef);
|
|
1793
1912
|
const adapter = sold && adapterFor(sold.item.reference.kind);
|
|
1794
1913
|
if (!sold || !adapter) return stopWith("rejected", "unsupportedItem");
|
|
1914
|
+
if (adapter.repeatable && !sold.item.attemptId) return stopWith("rejected", "unsupportedItem");
|
|
1915
|
+
if (!adapter.repeatable && sold.item.attemptId) return stopWith("rejected", "unsupportedItem");
|
|
1795
1916
|
const eligibility2 = adapter.eligibility(sold.item);
|
|
1796
1917
|
if (!eligibility2.eligible) return stopWith("rejected", eligibility2.reason);
|
|
1797
1918
|
const member = await memberOf(session);
|
|
@@ -1811,15 +1932,37 @@ function createWixOrderBackend(deps) {
|
|
|
1811
1932
|
}
|
|
1812
1933
|
async function orderFor(sale) {
|
|
1813
1934
|
const existing = refAt(sale.partition, sale.catalogRef);
|
|
1814
|
-
|
|
1815
|
-
|
|
1935
|
+
let prevented;
|
|
1936
|
+
const beforeCreate = () => {
|
|
1937
|
+
if (!sale.adapter.repeatable || existing) return true;
|
|
1938
|
+
if (!sale.bridge.isCurrent()) {
|
|
1939
|
+
prevented = STALE2;
|
|
1940
|
+
return false;
|
|
1941
|
+
}
|
|
1942
|
+
const blocked = saleBlocked(sale);
|
|
1943
|
+
if (blocked) {
|
|
1944
|
+
prevented = blocked;
|
|
1945
|
+
return false;
|
|
1946
|
+
}
|
|
1947
|
+
const opening = persist(sale, { key: sale.catalogRef, kind: sale.adapter.kind, stage: "openingOrder", updatedAt: now() });
|
|
1948
|
+
if (isStop(opening)) {
|
|
1949
|
+
prevented = opening;
|
|
1950
|
+
return false;
|
|
1951
|
+
}
|
|
1952
|
+
return true;
|
|
1953
|
+
};
|
|
1954
|
+
const attempt3 = existing?.cashierOrderId && existing.verticalRef ? await reopenOrOpen(sale, { cashierOrderId: existing.cashierOrderId, verticalRef: existing.verticalRef }) : await sale.adapter.openOrder(sale.item, sale.bridge, beforeCreate);
|
|
1955
|
+
return prevented ?? recordOrder(sale, existing, attempt3);
|
|
1816
1956
|
}
|
|
1817
1957
|
async function reopenOrOpen(sale, order) {
|
|
1818
1958
|
const reopened = await sale.adapter.reopenOrder(order, sale.bridge);
|
|
1819
1959
|
const closed = reopened.status === "refused" && reopened.reason === "orderClosed";
|
|
1820
|
-
return closed ? sale.adapter.openOrder(sale.item, sale.bridge) : reopened;
|
|
1960
|
+
return closed && !sale.adapter.repeatable ? sale.adapter.openOrder(sale.item, sale.bridge) : reopened;
|
|
1821
1961
|
}
|
|
1822
1962
|
function recordOrder(sale, existing, attempt3) {
|
|
1963
|
+
if (attempt3.noOrderCreated && refAt(sale.partition, sale.catalogRef)?.stage === "openingOrder" && !sale.partition.remove(sale.catalogRef)) {
|
|
1964
|
+
return stopWith("rejected", "storageUnavailable");
|
|
1965
|
+
}
|
|
1823
1966
|
if (attempt3.status === "granted") return alreadyOwned(sale);
|
|
1824
1967
|
if (attempt3.status === "refused") return stopWith("rejected", attempt3.reason);
|
|
1825
1968
|
if (attempt3.status !== "open") return attempt3.status === "sessionChanged" ? STALE2 : retry("unavailable");
|
|
@@ -1857,6 +2000,7 @@ function createWixOrderBackend(deps) {
|
|
|
1857
2000
|
}
|
|
1858
2001
|
}
|
|
1859
2002
|
async function reorder(sale) {
|
|
2003
|
+
if (sale.adapter.repeatable) return stopWith("rejected", "orderClosed");
|
|
1860
2004
|
if (!forget(sale, sale.catalogRef)) return stopWith("rejected", "storageUnavailable");
|
|
1861
2005
|
const recorded = recordOrder(sale, void 0, await sale.adapter.openOrder(sale.item, sale.bridge));
|
|
1862
2006
|
return isStop(recorded) ? recorded : chargeFor(sale, recorded, { reordered: true });
|
|
@@ -1933,7 +2077,7 @@ function createWixOrderBackend(deps) {
|
|
|
1933
2077
|
return stopWith("rejected", failure3.code === "NOT_PENDING" ? "orderClosed" : "paymentRefused");
|
|
1934
2078
|
}
|
|
1935
2079
|
function alreadyOwned(sale) {
|
|
1936
|
-
forget(sale, sale.catalogRef);
|
|
2080
|
+
if (!sale.adapter.repeatable) forget(sale, sale.catalogRef);
|
|
1937
2081
|
return stopWith("rejected", "alreadyOwned");
|
|
1938
2082
|
}
|
|
1939
2083
|
function persist(sale, ref) {
|
|
@@ -1983,7 +2127,9 @@ function createWixOrderBackend(deps) {
|
|
|
1983
2127
|
return access === "granted";
|
|
1984
2128
|
}
|
|
1985
2129
|
function processed(proof, ref) {
|
|
1986
|
-
|
|
2130
|
+
if (adapterFor(ref.kind)?.repeatable) {
|
|
2131
|
+
if (!proof.member.partition?.put({ ...ref, stage: "fulfilled", updatedAt: now() })) return RETRYABLE;
|
|
2132
|
+
} else proof.member.partition?.remove(ref.key);
|
|
1987
2133
|
deps.report({ key: ref.key, access: "granted" });
|
|
1988
2134
|
return { status: "processed", acknowledgement: proof.acknowledgement };
|
|
1989
2135
|
}
|
|
@@ -2050,6 +2196,7 @@ var UNAVAILABLE = { stop: true, result: "retryable", failure: "unavailable" };
|
|
|
2050
2196
|
var OUTCOME_UNKNOWN = { stop: true, result: "rejected", failure: "outcomeUnknown" };
|
|
2051
2197
|
var BLOCKING_STAGES = {
|
|
2052
2198
|
startingItem: "outcomeUnknown",
|
|
2199
|
+
openingOrder: "outcomeUnknown",
|
|
2053
2200
|
submitted: "paymentInProgress",
|
|
2054
2201
|
held: "paymentHeld",
|
|
2055
2202
|
needsSupport: "needsSupport"
|
|
@@ -2308,6 +2455,12 @@ function enabledCheckout(deps) {
|
|
|
2308
2455
|
for (const ref of tracked.partition.refs()) {
|
|
2309
2456
|
if (!isCurrent(session)) return;
|
|
2310
2457
|
if (ref.stage === "needsSupport") setPayment(ref.key, "needsSupport");
|
|
2458
|
+
if (ref.stage === "fulfilled" && !options.dueOnly) {
|
|
2459
|
+
const access = await accessOf3(session, ref);
|
|
2460
|
+
if (!isCurrent(session)) return;
|
|
2461
|
+
if (access === "granted") setPayment(ref.key, "granted");
|
|
2462
|
+
else if (access === "none") payments.delete(ref.key);
|
|
2463
|
+
}
|
|
2311
2464
|
if (ref.stage !== "submitted" || !ref.paymentId) continue;
|
|
2312
2465
|
if (!options.dueOnly) restartBudget(ref.key);
|
|
2313
2466
|
if (isDue(ref.key, options.dueOnly)) await trackOne(session, tracked.partition, ref);
|
|
@@ -2362,7 +2515,10 @@ function enabledCheckout(deps) {
|
|
|
2362
2515
|
backOff(partition, ref, access === "none");
|
|
2363
2516
|
}
|
|
2364
2517
|
function grant(partition, ref) {
|
|
2365
|
-
|
|
2518
|
+
const repeatable = deps.adapters.some((adapter) => adapter.kind === ref.kind && adapter.repeatable);
|
|
2519
|
+
if (repeatable) {
|
|
2520
|
+
if (!partition.put({ ...ref, stage: "fulfilled", updatedAt: deps.clock.now() })) return backOff(partition, ref, false);
|
|
2521
|
+
} else partition.remove(ref.key);
|
|
2366
2522
|
setPayment(ref.key, "granted");
|
|
2367
2523
|
}
|
|
2368
2524
|
function settleUnassociated(partition, ref) {
|
|
@@ -2431,7 +2587,8 @@ function isInFlight(item) {
|
|
|
2431
2587
|
return item.access === "processing" || item.access === "confirming" || item.access === "pending" || item.access === "waitingToRetry";
|
|
2432
2588
|
}
|
|
2433
2589
|
function itemKey(item) {
|
|
2434
|
-
|
|
2590
|
+
const key = `${item.reference.kind}:${item.reference.id}`;
|
|
2591
|
+
return item.attemptId ? `${key}#${encodeURIComponent(item.attemptId)}` : key;
|
|
2435
2592
|
}
|
|
2436
2593
|
function labelOf(key) {
|
|
2437
2594
|
return key.startsWith("payment:") ? "payment" : key;
|
|
@@ -2460,10 +2617,20 @@ var OVERLAY_PHASES = /* @__PURE__ */ new Set(["purchasing", "awaitingApproval",
|
|
|
2460
2617
|
// ../../stdlib/flows/iap-checkout/src/purchase-fields.ts
|
|
2461
2618
|
function iapPurchaseFields(view, state, readiness, copy) {
|
|
2462
2619
|
const key = `${view.reference.kind}:${view.reference.id}`;
|
|
2620
|
+
const repeatable = view.reference.kind === "bookingsService" || view.reference.kind === "eventsTicket";
|
|
2463
2621
|
if (view.route !== "appleIap" && !holdsSale(state, key)) return { ...action(copy, "enabled", ""), appleRoute: false };
|
|
2464
2622
|
if (readiness.status !== "ready") return action(copy, "disabled", readiness.status === "checking" ? "" : copy.unavailable);
|
|
2465
|
-
const own = state.item
|
|
2466
|
-
const
|
|
2623
|
+
const own = sameItem(state.item, key);
|
|
2624
|
+
const matching = state.payments.filter((tracked) => sameItem(tracked.item, key));
|
|
2625
|
+
const payment = matching.find((p) => p.access === "needsSupport")?.access ?? matching.find((p) => p.access === "processing")?.access ?? matching[matching.length - 1]?.access;
|
|
2626
|
+
if (repeatable && payment === "needsSupport") return action(copy, "disabled", copy.support);
|
|
2627
|
+
if (repeatable && IN_FLIGHT.has(state.phase)) return action(copy, "busy", own ? copy.processing : "");
|
|
2628
|
+
if (repeatable && payment === "processing") return action(copy, "busy", copy.processing);
|
|
2629
|
+
if (repeatable && own && state.phase !== "accessReady" && state.phase !== "idle") {
|
|
2630
|
+
if (state.failure === "orderClosed") return action(copy, "disabled", copy.support);
|
|
2631
|
+
return outcomeAction(state, copy);
|
|
2632
|
+
}
|
|
2633
|
+
if (repeatable && (own && state.phase === "accessReady" || payment === "granted")) return action({ ...copy, buy: copy.buyAnother ?? copy.buy }, "enabled", "");
|
|
2467
2634
|
if (own && state.phase === "accessReady" || payment === "granted") return { ...action(copy, "disabled", ""), accessReady: true };
|
|
2468
2635
|
if (IN_FLIGHT.has(state.phase)) return action(copy, "busy", own ? copy.processing : "");
|
|
2469
2636
|
if (own) return outcomeAction(state, copy);
|
|
@@ -2472,8 +2639,11 @@ function iapPurchaseFields(view, state, readiness, copy) {
|
|
|
2472
2639
|
return action(copy, "enabled", "");
|
|
2473
2640
|
}
|
|
2474
2641
|
function holdsSale(state, key) {
|
|
2475
|
-
if (state.payments.some((tracked) => tracked.item
|
|
2476
|
-
return state.item
|
|
2642
|
+
if (state.payments.some((tracked) => sameItem(tracked.item, key))) return true;
|
|
2643
|
+
return sameItem(state.item, key) && (SALE_PHASES.has(state.phase) || state.purchase.phase === "awaitingApproval");
|
|
2644
|
+
}
|
|
2645
|
+
function sameItem(item, key) {
|
|
2646
|
+
return item === key || item?.startsWith(`${key}#`) === true;
|
|
2477
2647
|
}
|
|
2478
2648
|
function outcomeAction(state, copy) {
|
|
2479
2649
|
if (state.purchase.phase === "awaitingApproval") return action(copy, "disabled", copy.awaitingApproval);
|
|
@@ -2494,7 +2664,7 @@ function outcomeAction(state, copy) {
|
|
|
2494
2664
|
}
|
|
2495
2665
|
function refusalAction(failure3, copy) {
|
|
2496
2666
|
const [mode, note] = REFUSALS[failure3 ?? "unavailable"] ?? ["enabled", "retry"];
|
|
2497
|
-
return action(copy, mode, note ? copy[note] : "");
|
|
2667
|
+
return action(copy, mode, note ? copy[note] ?? "" : "");
|
|
2498
2668
|
}
|
|
2499
2669
|
function action(copy, mode, note) {
|
|
2500
2670
|
return { appleRoute: true, accessReady: false, buyLabel: copy.buy, buyDisabled: mode !== "enabled", buyBusy: mode === "busy", buyNote: note };
|
|
@@ -3104,11 +3274,161 @@ async function placedOrder(body, bridge) {
|
|
|
3104
3274
|
}
|
|
3105
3275
|
var PAYMENT_UNDER_WAY2 = /* @__PURE__ */ new Set(["NOT_PAID", "PENDING", "PENDING_MERCHANT", "PARTIALLY_PAID"]);
|
|
3106
3276
|
var NO_ACCESS2 = /* @__PURE__ */ new Set(["FULLY_REFUNDED", "PARTIALLY_REFUNDED", "CANCELED", "DECLINED", "VOIDED"]);
|
|
3277
|
+
|
|
3278
|
+
// ../../stdlib/flows/iap-checkout/src/iap-verticals/attendance.ts
|
|
3279
|
+
var BOOKING = "bookingsService";
|
|
3280
|
+
var TICKET = "eventsTicket";
|
|
3281
|
+
var NOT_ENABLED = { status: "refused", reason: "notEnabled" };
|
|
3282
|
+
var CHANGED = { status: "refused", reason: "productChanged" };
|
|
3283
|
+
function attendanceOrdersWith(options) {
|
|
3284
|
+
const now = options.now ?? Date.now;
|
|
3285
|
+
return {
|
|
3286
|
+
bookingOrders: {
|
|
3287
|
+
kind: BOOKING,
|
|
3288
|
+
repeatable: true,
|
|
3289
|
+
eligibility: (item) => eligible(item, BOOKING, options.bookingsEnabled),
|
|
3290
|
+
openOrder: (item, bridge, beforeCreate) => options.bookingsEnabled ? openBooking(item, bridge, beforeCreate) : Promise.resolve(NOT_ENABLED),
|
|
3291
|
+
readAccess: bookingAccess,
|
|
3292
|
+
reopenOrder: (order, bridge) => reopen(order, bridge, bookingAccess)
|
|
3293
|
+
},
|
|
3294
|
+
eventTicketOrders: {
|
|
3295
|
+
kind: TICKET,
|
|
3296
|
+
repeatable: true,
|
|
3297
|
+
eligibility: (item) => eligible(item, TICKET, options.eventsEnabled),
|
|
3298
|
+
openOrder: (item, bridge, beforeCreate) => options.eventsEnabled ? openTicket(item, bridge, now, beforeCreate) : Promise.resolve(NOT_ENABLED),
|
|
3299
|
+
readAccess: ticketAccess,
|
|
3300
|
+
reopenOrder: (order, bridge) => reopen(order, bridge, ticketAccess, now)
|
|
3301
|
+
}
|
|
3302
|
+
};
|
|
3303
|
+
}
|
|
3304
|
+
var { bookingOrders, eventTicketOrders } = /* @__PURE__ */ attendanceOrdersWith({ bookingsEnabled: BOOKINGS_APPLE_SALES_ENABLED, eventsEnabled: EVENTS_APPLE_SALES_ENABLED });
|
|
3305
|
+
function eligible(item, kind, enabled) {
|
|
3306
|
+
if (!enabled) return { eligible: false, reason: "notEnabled" };
|
|
3307
|
+
if (!singleUnitOf(kind, item).eligible || !isNonEmpty3(item.attemptId) || !item.attendance) return UNSUPPORTED;
|
|
3308
|
+
const selection = kind === BOOKING ? item.attendance.booking : item.attendance.ticket;
|
|
3309
|
+
return selection ? { eligible: true } : UNSUPPORTED;
|
|
3310
|
+
}
|
|
3311
|
+
async function openBooking(item, bridge, beforeCreate) {
|
|
3312
|
+
if (!eligible(item, BOOKING, true).eligible) return notCreated(ORDER_REFUSED);
|
|
3313
|
+
const selected = item.attendance.booking;
|
|
3314
|
+
if (selected.slot.serviceId !== item.reference.id || !isNonEmpty3(selected.slot.startDate) || !isNonEmpty3(selected.slot.endDate)) return notCreated(ORDER_REFUSED);
|
|
3315
|
+
const read2 = await bridge.call("GET", `/bookings/v2/services/${encodeURIComponent(item.reference.id)}`);
|
|
3316
|
+
if (isRefusal(read2)) return notCreated(attemptRefused(read2));
|
|
3317
|
+
const service = bodyObject(read2, "service");
|
|
3318
|
+
const metadata = bookingAttendanceOf(service);
|
|
3319
|
+
if (classifyForApple(metadata, item.attendance.currency) !== "appleIap" || !samePrice({ amount: metadata.amount, currency: metadata.currency }, item)) return notCreated(CHANGED);
|
|
3320
|
+
if (isObject7(service?.onlineBooking) && service.onlineBooking.requireManualApproval === true) return notCreated({ status: "refused", reason: "approvalRequired" });
|
|
3321
|
+
const availability = await bridge.call("POST", "/bookings/v1/availability/query", { query: { filter: { serviceId: [item.reference.id], startDate: selected.slot.startDate, endDate: selected.slot.endDate, bookable: true } } });
|
|
3322
|
+
if (isRefusal(availability)) return notCreated(attemptRefused(availability));
|
|
3323
|
+
const entries = isObject7(availability.body) ? availability.body.availabilityEntries : void 0;
|
|
3324
|
+
if (!Array.isArray(entries) || !entries.some((entry) => isObject7(entry) && entry.bookable === true && matchesSlot(entry.slot, selected.slot))) return notCreated(CHANGED);
|
|
3325
|
+
if (beforeCreate && !beforeCreate()) return notCreated({ status: "refused", reason: "storageUnavailable" });
|
|
3326
|
+
const created = await bridge.call("POST", "/bookings/v2/bookings", { booking: { bookedEntity: { slot: selected.slot }, contactDetails: selected.contactDetails, totalParticipants: 1, selectedPaymentOption: "ONLINE", ...selected.formInfo ? { formInfo: selected.formInfo } : {} } });
|
|
3327
|
+
if (isRefusal(created)) return creationRefused(created);
|
|
3328
|
+
const bookingId = bodyObject(created, "booking")?.id;
|
|
3329
|
+
return isNonEmpty3(bookingId) ? bookingCheckout(item, bookingId, bridge) : ORDER_REFUSED;
|
|
3330
|
+
}
|
|
3331
|
+
async function bookingCheckout(item, bookingId, bridge) {
|
|
3332
|
+
const checkout = await bridge.call("POST", "/ecom/v1/checkouts", { lineItems: [{ quantity: 1, catalogReference: { appId: "13d21c63-b5ec-5912-8397-c3a5ddb27a97", catalogItemId: bookingId } }], channelType: "OTHER_PLATFORM" });
|
|
3333
|
+
if (isRefusal(checkout)) return attemptRefused(checkout);
|
|
3334
|
+
const entity = bodyObject(checkout, "checkout");
|
|
3335
|
+
const total = isObject7(entity?.priceSummary) ? entity.priceSummary.total : void 0;
|
|
3336
|
+
if (!isObject7(total) || !samePrice({ amount: total.amount, currency: entity?.currency }, item)) return CHANGED;
|
|
3337
|
+
if (!isNonEmpty3(entity?.id)) return ORDER_REFUSED;
|
|
3338
|
+
const placed = await bridge.call("POST", `/ecom/v1/checkouts/${encodeURIComponent(entity.id)}/create-order`, {});
|
|
3339
|
+
if (isRefusal(placed)) return attemptRefused(placed);
|
|
3340
|
+
const body = placed.body;
|
|
3341
|
+
if (!isObject7(body) || !isNonEmpty3(body.orderId) || !isNonEmpty3(body.paymentGatewayOrderId)) return ORDER_REFUSED;
|
|
3342
|
+
return { status: "open", cashierOrderId: body.paymentGatewayOrderId, verticalRef: { serviceId: item.reference.id, bookingId, orderId: body.orderId } };
|
|
3343
|
+
}
|
|
3344
|
+
async function bookingAccess(ref, bridge) {
|
|
3345
|
+
if (!ref.bookingId || !ref.orderId) return "unavailable";
|
|
3346
|
+
const order = await bridge.call("GET", `/ecom/v1/orders/${encodeURIComponent(ref.orderId)}`);
|
|
3347
|
+
if (isRefusal(order)) return accessRefused(order);
|
|
3348
|
+
const payment = bodyObject(order, "order")?.paymentStatus;
|
|
3349
|
+
if (payment === "FULLY_REFUNDED" || payment === "PARTIALLY_REFUNDED") return "none";
|
|
3350
|
+
const read2 = await bridge.call("POST", "/bookings/v2/bookings/query", { query: { filter: { id: { $eq: ref.bookingId } } } });
|
|
3351
|
+
if (isRefusal(read2)) return accessRefused(read2);
|
|
3352
|
+
const rows = isObject7(read2.body) ? read2.body.bookings : void 0;
|
|
3353
|
+
const booking = Array.isArray(rows) ? rows.find((b) => isObject7(b) && b.id === ref.bookingId) : void 0;
|
|
3354
|
+
if (!isObject7(booking)) return "unavailable";
|
|
3355
|
+
if (booking.status === "CANCELED" || booking.status === "CANCELLED" || booking.status === "DECLINED") return "none";
|
|
3356
|
+
return payment === "PAID" && booking.status === "CONFIRMED" && booking.paymentStatus === "PAID" ? "granted" : "pending";
|
|
3357
|
+
}
|
|
3358
|
+
async function openTicket(item, bridge, now, beforeCreate) {
|
|
3359
|
+
if (!eligible(item, TICKET, true).eligible) return notCreated(ORDER_REFUSED);
|
|
3360
|
+
const selected = item.attendance.ticket;
|
|
3361
|
+
if (!isNonEmpty3(selected.eventId)) return notCreated(ORDER_REFUSED);
|
|
3362
|
+
const read2 = await bridge.call("GET", `/events/v3/events/${encodeURIComponent(selected.eventId)}?fields=REGISTRATION&fields=DETAILS&fields=FORM`);
|
|
3363
|
+
if (isRefusal(read2)) return notCreated(attemptRefused(read2));
|
|
3364
|
+
const available = await bridge.call("POST", "/events/v1/checkout/available-tickets/query", { filter: { eventId: selected.eventId }, limit: 100, offset: 0 });
|
|
3365
|
+
if (isRefusal(available)) return notCreated(attemptRefused(available));
|
|
3366
|
+
const definitions = isObject7(available.body) ? available.body.definitions : void 0;
|
|
3367
|
+
const live = Array.isArray(definitions) ? definitions.find((t) => isObject7(t) && t.id === item.reference.id && t.saleStatus === "SALE_STARTED") : void 0;
|
|
3368
|
+
if (!isObject7(live) || !samePrice(live.price, item)) return notCreated(CHANGED);
|
|
3369
|
+
if (live.eventId !== selected.eventId || classifyForApple(availableTicketAttendanceOf(bodyObject(read2, "event"), live), item.attendance.currency) !== "appleIap") return notCreated(ORDER_REFUSED);
|
|
3370
|
+
if (beforeCreate && !beforeCreate()) return notCreated({ status: "refused", reason: "storageUnavailable" });
|
|
3371
|
+
return reserveTicket(item, bridge, now);
|
|
3372
|
+
}
|
|
3373
|
+
async function reserveTicket(item, bridge, now) {
|
|
3374
|
+
const selected = item.attendance.ticket;
|
|
3375
|
+
const held = await bridge.call("POST", "/events/v1/checkout/reservations", { eventId: selected.eventId, ticketQuantities: [{ ticketDefinitionId: item.reference.id, quantity: 1 }], ignoreLimits: false, allowHiddenTickets: false });
|
|
3376
|
+
if (isRefusal(held)) return creationRefused(held);
|
|
3377
|
+
const reservation = held.body;
|
|
3378
|
+
if (!isObject7(reservation) || !isNonEmpty3(reservation.id) || !future(reservation.expires, now)) return ORDER_CLOSED;
|
|
3379
|
+
const invoice = isObject7(reservation.invoice) ? reservation.invoice : {};
|
|
3380
|
+
if (!samePrice(invoice.grandTotal ?? invoice.total, item)) return CHANGED;
|
|
3381
|
+
const placed = await bridge.call("POST", "/events/v1/checkout", { eventId: selected.eventId, reservationId: reservation.id, buyer: selected.buyer, ...selected.guests ? { guests: selected.guests } : {}, ...selected.buyerSubmission ? { buyerSubmission: selected.buyerSubmission } : {}, ...selected.guestSubmissions ? { guestSubmissions: selected.guestSubmissions } : {}, options: { silent: false, payInPerson: false, ignoreFormValidation: false, markAsPaid: false } });
|
|
3382
|
+
if (isRefusal(placed)) return attemptRefused(placed);
|
|
3383
|
+
const order = bodyObject(placed, "order");
|
|
3384
|
+
if (!samePrice(order?.totalPrice, item)) return CHANGED;
|
|
3385
|
+
const expires = isObject7(placed.body) && placed.body.expires || reservation.expires;
|
|
3386
|
+
if (!future(expires, now) || !isNonEmpty3(order?.snapshotId) || !isNonEmpty3(order?.orderNumber)) return ORDER_CLOSED;
|
|
3387
|
+
return { status: "open", cashierOrderId: order.snapshotId, verticalRef: { eventId: selected.eventId, ticketDefinitionId: item.reference.id, reservationId: reservation.id, orderNumber: order.orderNumber, expires: String(expires) } };
|
|
3388
|
+
}
|
|
3389
|
+
async function ticketAccess(ref, bridge) {
|
|
3390
|
+
if (!ref.eventId || !ref.orderNumber || !ref.ticketDefinitionId) return "unavailable";
|
|
3391
|
+
const read2 = await bridge.call("GET", `/events/v1/events/${encodeURIComponent(ref.eventId)}/orders/${encodeURIComponent(ref.orderNumber)}?fieldset=DETAILS&fieldset=TICKETS`);
|
|
3392
|
+
if (isRefusal(read2)) return accessRefused(read2);
|
|
3393
|
+
const order = bodyObject(read2, "order");
|
|
3394
|
+
if (order?.status === "CANCELED" || order?.status === "CANCELLED" || order?.status === "REFUNDED") return "none";
|
|
3395
|
+
const issued = Array.isArray(order?.tickets) && order.tickets.some((t) => isObject7(t) && isNonEmpty3(t.ticketNumber) && t.orderStatus === "PAID" && t.ticketDefinitionId === ref.ticketDefinitionId);
|
|
3396
|
+
return order?.status === "PAID" && issued ? "granted" : order ? "pending" : "unavailable";
|
|
3397
|
+
}
|
|
3398
|
+
async function reopen(order, bridge, accessOf3, now) {
|
|
3399
|
+
const access = await accessOf3(order.verticalRef, bridge);
|
|
3400
|
+
if (access === "granted") return GRANTED;
|
|
3401
|
+
if (access === "unavailable" || access === "sessionChanged") return { status: access };
|
|
3402
|
+
if (access === "none" || now && !future(order.verticalRef.expires, now)) return ORDER_CLOSED;
|
|
3403
|
+
return { status: "open", ...order };
|
|
3404
|
+
}
|
|
3405
|
+
function samePrice(value, item) {
|
|
3406
|
+
return isObject7(value) && value.currency === item.attendance?.currency && decimal(value.amount) !== null && decimal(value.amount) === decimal(item.attendance?.amount);
|
|
3407
|
+
}
|
|
3408
|
+
function decimal(value) {
|
|
3409
|
+
if (typeof value !== "string" || !/^\d+(?:\.\d+)?$/.test(value)) return null;
|
|
3410
|
+
return value.replace(/^0+(?=\d)/, "").replace(/(\.\d*?)0+$/, "$1").replace(/\.$/, "");
|
|
3411
|
+
}
|
|
3412
|
+
function future(value, now) {
|
|
3413
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value)) && Date.parse(value) > now();
|
|
3414
|
+
}
|
|
3415
|
+
function matchesSlot(value, selected) {
|
|
3416
|
+
return isObject7(value) && ["serviceId", "sessionId"].every((key) => value[key] === selected[key]) && ["startDate", "endDate"].every((key) => typeof value[key] === "string" && Date.parse(value[key]) === Date.parse(String(selected[key])));
|
|
3417
|
+
}
|
|
3418
|
+
function creationRefused(refusal) {
|
|
3419
|
+
const attempt3 = attemptRefused(refusal);
|
|
3420
|
+
return refusal.status === "http" && [400, 401, 403, 404, 405, 409, 410, 415, 422].includes(refusal.httpStatus) ? notCreated(attempt3) : attempt3;
|
|
3421
|
+
}
|
|
3422
|
+
function notCreated(attempt3) {
|
|
3423
|
+
return { ...attempt3, noOrderCreated: true };
|
|
3424
|
+
}
|
|
3107
3425
|
export {
|
|
3426
|
+
bookingOrders,
|
|
3108
3427
|
classifyCart,
|
|
3109
3428
|
createAppleIapCheckout,
|
|
3110
3429
|
createIapCommerce,
|
|
3111
3430
|
createWorkerOrderRefStore,
|
|
3431
|
+
eventTicketOrders,
|
|
3112
3432
|
iapPurchaseFields,
|
|
3113
3433
|
itemPaymentEnabled,
|
|
3114
3434
|
onlineProgramOrders,
|