tf-checkout-react 2.0.0-beta.25 → 2.0.0-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +550 -102
- package/docs/API.html +1002 -0
- package/docs/API.md +73 -12
- package/docs/GUIDE.html +2194 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,25 +7,46 @@ components, plus the shared API and React Query hooks. Which paths a buyer can
|
|
|
7
7
|
actually use depend on the event, the deployed API, the buyer's session and the
|
|
8
8
|
payment provider.
|
|
9
9
|
|
|
10
|
-
This reference describes **2.0.0-beta.
|
|
10
|
+
This reference describes **2.0.0-beta.27**. It is a prerelease with a different
|
|
11
11
|
API from 1.x. Pin the version while evaluating it. npm's `latest` and `beta`
|
|
12
12
|
tags can move independently and an unqualified install may select 1.x:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
npm view tf-checkout-react dist-tags
|
|
16
|
-
npm install tf-checkout-react@2.0.0-beta.
|
|
16
|
+
npm install tf-checkout-react@2.0.0-beta.27 @tanstack/react-query react react-dom
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
The [API reference](https://unpkg.com/tf-checkout-react@2.0.0-beta.
|
|
20
|
-
is included as `docs/API.md` in this package.
|
|
19
|
+
The [API reference](https://unpkg.com/tf-checkout-react@2.0.0-beta.27/docs/API.html)
|
|
20
|
+
is included as `docs/API.md` and `docs/API.html` in this package. A
|
|
21
|
+
[standalone guide](https://unpkg.com/tf-checkout-react@2.0.0-beta.27/docs/GUIDE.html)
|
|
22
|
+
is also available.
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
[
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
If the HTML has not reached the CDN yet, open the packaged `docs/API.md` in a
|
|
25
|
+
Markdown viewer or read the [plain-text API Markdown](https://cdn.jsdelivr.net/npm/tf-checkout-react@2.0.0-beta.27/docs/API.md).
|
|
26
|
+
The full guide is also shown on this npm page.
|
|
27
|
+
|
|
28
|
+
## Choose a checkout layout
|
|
29
|
+
|
|
30
|
+
| Your goal | Start here | What the SDK renders |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| Add a complete checkout to an event page | [`EmbeddedCheckout`](#embeddedcheckout) | A ready-made ticket or seat selection view followed by add-ons, buyer details, waiver and payment when applicable. |
|
|
33
|
+
| Continue a cart created by an earlier flow | [`ResumedCheckout`](#resume-a-server-cart) | Ready-made buyer details, waiver and payment for the current session's existing cart. |
|
|
34
|
+
| Keep the checkout on one page and arrange the sections yourself | [Single-page composition](#single-page-checkout) | Ticket selection, seats, add-ons, billing and payment sections in the host's layout. |
|
|
35
|
+
| Show progressive steps or connect routes | [Step-by-step composition](#step-by-step-checkout) | The same sections; your application controls what is visible and how the buyer moves between steps. |
|
|
36
|
+
| Organize the form as an accordion | [Accordion composition](#accordion-checkout) | Native HTML disclosure sections around the SDK's checkout components. |
|
|
37
|
+
| Build your own checkout UI | [Headless APIs](#headless-apis) | The shared engine, hooks and API; your application owns the UI and navigation. |
|
|
38
|
+
|
|
39
|
+
`EmbeddedCheckout` and `ResumedCheckout` are the ready-made flows in this
|
|
40
|
+
version. The 1.x `*Container` components and named single-page/accordion
|
|
41
|
+
examples are not drop-in 2.x exports. The [migration guide](#migrating-from-1x)
|
|
42
|
+
shows how to reproduce those layouts with the current components.
|
|
43
|
+
|
|
44
|
+
[Requirements](#requirements) · [Quick start](#quick-start) ·
|
|
45
|
+
[Configure sessions](#configuration-and-sessions) · [Ready-made checkout](#embeddedcheckout) ·
|
|
46
|
+
[Custom layouts](#compose-sections) · [Payments](#payments) ·
|
|
47
|
+
[Authentication](#authentication) · [Component reference](#component-reference) ·
|
|
27
48
|
[Styling](#styling-and-localization) · [Migration](#migrating-from-1x) ·
|
|
28
|
-
[
|
|
49
|
+
[Troubleshooting](#testing-and-troubleshooting)
|
|
29
50
|
|
|
30
51
|
## Requirements
|
|
31
52
|
|
|
@@ -50,17 +71,25 @@ Its `dist/styles` files and referenced assets are part of the npm package.
|
|
|
50
71
|
|
|
51
72
|
## Quick start
|
|
52
73
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
This example puts the ready-made checkout on one event page. You need a test
|
|
75
|
+
event ID and the matching **public** SDK client ID. Ask your Ticket Fairy
|
|
76
|
+
integration contact for these values and the appropriate environment.
|
|
77
|
+
|
|
78
|
+
1. Install the package and its peers using the command above.
|
|
79
|
+
2. Replace `EVENT_ID` and `PUBLIC_SDK_CLIENT_ID` below. Configure the SDK once
|
|
80
|
+
in your browser entry, before rendering the checkout.
|
|
81
|
+
3. Mount `App` in your React application. The package entry imports its CSS;
|
|
82
|
+
the bundler must process CSS imports and their assets.
|
|
56
83
|
|
|
57
84
|
```tsx
|
|
58
85
|
import { useState } from 'react'
|
|
59
86
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
60
|
-
import {
|
|
87
|
+
import {
|
|
88
|
+
configureCheckout, EmbeddedCheckout, type PlaceOrderResult,
|
|
89
|
+
} from 'tf-checkout-react'
|
|
61
90
|
|
|
62
91
|
configureCheckout({
|
|
63
|
-
env: '
|
|
92
|
+
env: 'STAG',
|
|
64
93
|
clientId: 'PUBLIC_SDK_CLIENT_ID',
|
|
65
94
|
clientSecret: '',
|
|
66
95
|
cookieAuth: true,
|
|
@@ -69,30 +98,41 @@ configureCheckout({
|
|
|
69
98
|
const queryClient = new QueryClient()
|
|
70
99
|
|
|
71
100
|
export function App() {
|
|
72
|
-
const [
|
|
101
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
102
|
+
|
|
73
103
|
return (
|
|
74
104
|
<QueryClientProvider client={queryClient}>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
{order ? (
|
|
106
|
+
<section role="status">
|
|
107
|
+
<h1>Checking your order</h1>
|
|
108
|
+
<p>Check your order status before making another purchase.</p>
|
|
109
|
+
{order.pending && <p>Your payment is pending.</p>}
|
|
110
|
+
{order.needIdVerification && <p>Identity verification may be required.</p>}
|
|
111
|
+
</section>
|
|
112
|
+
) : (
|
|
113
|
+
<EmbeddedCheckout
|
|
114
|
+
eventId="EVENT_ID"
|
|
115
|
+
confirmationMode="redirect"
|
|
116
|
+
onComplete={setOrder}
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
82
119
|
</QueryClientProvider>
|
|
83
120
|
)
|
|
84
121
|
}
|
|
85
122
|
```
|
|
86
123
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
124
|
+
The buyer first chooses tickets or seats. After reservation, the checkout shows
|
|
125
|
+
applicable add-ons, buyer details, waiver and payment. `onComplete` hands the
|
|
126
|
+
result to the host; the example displays a neutral status instead of claiming
|
|
127
|
+
that tickets are ready. Connect that screen to **your backend's authoritative
|
|
128
|
+
order status** using `order.orderHash`, handle any required ID verification and
|
|
129
|
+
pending voucher, and provide support if the status cannot be established. The
|
|
130
|
+
callback alone is not proof of settlement or ticket issuance.
|
|
91
131
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
[
|
|
132
|
+
Use `env: 'PROD'` with the matching production public client ID when your
|
|
133
|
+
integration is ready. This beta's stock payment UI can ask a buyer to retry an
|
|
134
|
+
unconfirmed payment; that wording does not establish that retrying is safe. See
|
|
135
|
+
[Payments](#payments) before using the stock flow in production.
|
|
96
136
|
|
|
97
137
|
## Configuration and sessions
|
|
98
138
|
|
|
@@ -147,7 +187,31 @@ third-party dependencies should be tested in that framework.
|
|
|
147
187
|
seat selection, add-ons, billing, waivers, payment and inline completion as the
|
|
148
188
|
flow requires. It must be under `QueryClientProvider`.
|
|
149
189
|
|
|
150
|
-
Only `eventId` is required. Callbacks and options are optional.
|
|
190
|
+
Only `eventId` is required. Callbacks and options are optional. The component
|
|
191
|
+
owns its checkout provider; do not wrap it in another `CheckoutProvider` to
|
|
192
|
+
control its internal steps. The host still supplies `QueryClientProvider`.
|
|
193
|
+
|
|
194
|
+
### What the buyer sees
|
|
195
|
+
|
|
196
|
+
1. **Tickets:** the event's catalog, quantities, applicable codes and any
|
|
197
|
+
organizer-configured waiting list. Seated events can open a seat map.
|
|
198
|
+
2. **Checkout:** a selection summary and the applicable add-ons, buyer/holder
|
|
199
|
+
details, waiver and payment. The reservation timer is displayed when available.
|
|
200
|
+
3. **Completion:** `inline` shows the SDK's confirmation view; `redirect` calls
|
|
201
|
+
`onComplete` and leaves the host to show the next screen. The quick start uses
|
|
202
|
+
`redirect` so the host can check order status before presenting a receipt.
|
|
203
|
+
|
|
204
|
+
`initialView="seats"` opens the seat-selection view first for an applicable
|
|
205
|
+
seated event. `onViewChange` reports `tickets`, `seats` or `checkout`; it does
|
|
206
|
+
not turn the component into a controlled router. For custom paths or step
|
|
207
|
+
arrangements, use [section composition](#compose-sections).
|
|
208
|
+
|
|
209
|
+
When choosing `confirmationMode="redirect"`, provide `onComplete` to receive
|
|
210
|
+
the result and navigate to your status page. Although the prop is optional in
|
|
211
|
+
the type, without that handoff the checkout remains mounted and no host status
|
|
212
|
+
page is reached.
|
|
213
|
+
|
|
214
|
+
### Options and callbacks
|
|
151
215
|
|
|
152
216
|
| Prop | Type / default | Description |
|
|
153
217
|
| --- | --- | --- |
|
|
@@ -179,98 +243,408 @@ session authorities; use the one appropriate to your configured journey.
|
|
|
179
243
|
for the public checkout registration or account-completion journey; those
|
|
180
244
|
paths force it on in this version.
|
|
181
245
|
|
|
246
|
+
### Example: brand the ready-made checkout
|
|
247
|
+
|
|
248
|
+
Use the same `QueryClientProvider` and one-time configuration as the quick
|
|
249
|
+
start. Here `onViewChange` can update surrounding page content; `onComplete`
|
|
250
|
+
passes the order result to the host's status screen.
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { useState } from 'react'
|
|
254
|
+
import { EmbeddedCheckout, type PlaceOrderResult } from 'tf-checkout-react'
|
|
255
|
+
|
|
256
|
+
export function BrandedCheckout() {
|
|
257
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
258
|
+
const [view, setView] = useState('tickets')
|
|
259
|
+
|
|
260
|
+
if (order) return <p role="status">Checking your order status…</p>
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<main>
|
|
264
|
+
<p>Checkout step: {view}</p>
|
|
265
|
+
<EmbeddedCheckout
|
|
266
|
+
eventId="EVENT_ID"
|
|
267
|
+
confirmationMode="redirect"
|
|
268
|
+
onComplete={setOrder}
|
|
269
|
+
onViewChange={setView}
|
|
270
|
+
initialPromoCode="WELCOME"
|
|
271
|
+
referrer="REFERRER_ID"
|
|
272
|
+
readAttributionFromUrl={false}
|
|
273
|
+
locale="en-US"
|
|
274
|
+
messages={{ 'tickets.getTickets': 'Continue to checkout' }}
|
|
275
|
+
theme={{ colorScheme: 'light', accent: '#6b2bd9', radiusCard: '16px' }}
|
|
276
|
+
className="festival-checkout"
|
|
277
|
+
/>
|
|
278
|
+
</main>
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Use a promo or referral only when it belongs to this visit. Remove those props
|
|
284
|
+
when they do not apply. By default the component also reads `promo` /
|
|
285
|
+
`promo_code` and `ttf_r` / `referrer_id` from the URL. The example disables
|
|
286
|
+
that behavior so the host controls attribution. `initialPromoCode` is applied
|
|
287
|
+
once when the catalog mounts. It is not a guarantee that a code is valid.
|
|
288
|
+
`theme` changes SDK design tokens, `className` lets your stylesheet target this
|
|
289
|
+
instance, and `messages` overrides individual SDK copy keys. `locale` and
|
|
290
|
+
`messages` do not automatically translate the event's own content or an
|
|
291
|
+
external payment-provider page. See [Styling and localization](#styling-and-localization)
|
|
292
|
+
for the available theme tokens and locales.
|
|
293
|
+
|
|
294
|
+
### Example: connect host navigation and sign-in
|
|
295
|
+
|
|
296
|
+
Pass callbacks when the surrounding application owns these actions. For
|
|
297
|
+
example, `openSignIn` can open your sign-in UI, and `onOrder` can hand the
|
|
298
|
+
result to your order-status screen. `onViewChange` is a notification, not a
|
|
299
|
+
way to force the checkout to a particular step.
|
|
300
|
+
|
|
301
|
+
```tsx
|
|
302
|
+
import { EmbeddedCheckout, type PlaceOrderResult } from 'tf-checkout-react'
|
|
303
|
+
|
|
304
|
+
type View = 'tickets' | 'seats' | 'checkout'
|
|
305
|
+
|
|
306
|
+
export function HostCheckout(props: {
|
|
307
|
+
eventId: string
|
|
308
|
+
openSignIn: (email?: string) => void
|
|
309
|
+
showOrderStatus: (order: PlaceOrderResult) => void
|
|
310
|
+
reportView: (view: View) => void
|
|
311
|
+
}) {
|
|
312
|
+
return (
|
|
313
|
+
<EmbeddedCheckout
|
|
314
|
+
eventId={props.eventId}
|
|
315
|
+
onLogin={props.openSignIn}
|
|
316
|
+
onViewChange={props.reportView}
|
|
317
|
+
confirmationMode="redirect"
|
|
318
|
+
onComplete={props.showOrderStatus}
|
|
319
|
+
/>
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The email passed to `openSignIn` can be absent. Supplying `onLogin` replaces
|
|
325
|
+
the built-in login modal; your host must complete the appropriate sign-in
|
|
326
|
+
journey. An event-scoped checkout identity is not automatically a full
|
|
327
|
+
account session. `showOrderStatus` must check the order and provider rather
|
|
328
|
+
than treating the callback as a paid receipt.
|
|
329
|
+
|
|
182
330
|
### Resume a server cart
|
|
183
331
|
|
|
184
|
-
`ResumedCheckout`
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
332
|
+
`ResumedCheckout` is a ready-made layout for a cart that **already exists in
|
|
333
|
+
the current session**, such as one created by a preceding resale flow. It
|
|
334
|
+
starts with buyer details and payment; it does not show ticket selection, create
|
|
335
|
+
the cart, or accept a cart ID. Its `confirmationMode` defaults to `redirect`.
|
|
336
|
+
Provide `onComplete` for the redirect/status handoff: without it the successful
|
|
337
|
+
flow remains on its loading transition. Alternatively select `inline` and
|
|
338
|
+
account for the confirmation and verification-copy limitations below.
|
|
189
339
|
|
|
190
340
|
```tsx
|
|
191
341
|
import { useState } from 'react'
|
|
192
|
-
import { ResumedCheckout } from 'tf-checkout-react'
|
|
342
|
+
import { ResumedCheckout, type PlaceOrderResult } from 'tf-checkout-react'
|
|
193
343
|
|
|
344
|
+
// Mount only after your preceding flow created a cart in this session.
|
|
194
345
|
export function ResumePage() {
|
|
195
|
-
const [
|
|
346
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
347
|
+
if (order) return <p role="status">Checking your order status…</p>
|
|
348
|
+
|
|
196
349
|
return (
|
|
197
|
-
<>
|
|
198
350
|
<ResumedCheckout
|
|
199
351
|
eventId="EVENT_ID"
|
|
200
352
|
isFromResale
|
|
201
|
-
confirmationMode="
|
|
202
|
-
onComplete={
|
|
353
|
+
confirmationMode="redirect"
|
|
354
|
+
onComplete={setOrder}
|
|
203
355
|
/>
|
|
204
|
-
<p role="status">{notice}</p>
|
|
205
|
-
</>
|
|
206
356
|
)
|
|
207
357
|
}
|
|
208
358
|
```
|
|
209
359
|
|
|
360
|
+
Wrap this page in the same `QueryClientProvider` as the quick start. Set
|
|
361
|
+
`isFromResale` only for the resale path. Check the result with your backend,
|
|
362
|
+
including any verification or pending-payment requirements. If the preceding
|
|
363
|
+
flow did not create a cart, or the session changed, return the buyer to that
|
|
364
|
+
flow instead of assuming a cart can be resumed.
|
|
365
|
+
|
|
210
366
|
Props are `eventId` (required), `isFromResale` (default `false`),
|
|
211
|
-
`onComplete`, `confirmationMode`
|
|
212
|
-
`
|
|
213
|
-
|
|
214
|
-
`
|
|
215
|
-
|
|
216
|
-
`EmbeddedCheckout`, this component does not accept `locale`, `messages`,
|
|
217
|
-
`auth` or `onLogin` props in this version.
|
|
367
|
+
`onComplete`, `confirmationMode`, `requireEmailConfirmation`,
|
|
368
|
+
`collectTicketHolders`, `collectHolderContact` (each default `true`),
|
|
369
|
+
`privacyPolicy`, `brandOptInLabel`, `additionalConditions`, `theme` and
|
|
370
|
+
`className`. Unlike `EmbeddedCheckout`, this component does not accept
|
|
371
|
+
`locale`, `messages`, `auth` or `onLogin` props in this version.
|
|
218
372
|
|
|
219
373
|
## Compose sections
|
|
220
374
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
independent carts.
|
|
226
|
-
|
|
375
|
+
Use sections when the ready-made flow does not fit your page. Put all sections
|
|
376
|
+
for one checkout inside a single `CheckoutProvider`, under the host's
|
|
377
|
+
`QueryClientProvider`. The provider shares one checkout instance with its
|
|
378
|
+
children. The default store is app-wide: mounting two flows does not create two
|
|
379
|
+
independent carts. Configure the SDK once, before mounting the provider.
|
|
380
|
+
|
|
381
|
+
The examples below assume the quick start's `configureCheckout` and
|
|
382
|
+
`QueryClientProvider` setup. They demonstrate page layout and section wiring;
|
|
383
|
+
your host still needs to implement order-status reconciliation, expiry and
|
|
384
|
+
recovery for its event and enabled payment methods.
|
|
385
|
+
|
|
386
|
+
These are wiring recipes, not complete buyer navigation. Each includes a return
|
|
387
|
+
from the seat view and keeps `Tickets` mounted while switching views. The host
|
|
388
|
+
still needs to implement Edit and Back from checkout (including payment to
|
|
389
|
+
billing), preserve entered details, handle seat holds and cart expiry, and
|
|
390
|
+
guard event/session changes and in-flight or retained payments. Use
|
|
391
|
+
`EmbeddedCheckout` for its built-in Back and guarded Edit behavior.
|
|
392
|
+
The seat-view Back button only changes views: it does not itself release reserved
|
|
393
|
+
seats or cancel an already-started reservation or cart priming. Coordinate any
|
|
394
|
+
in-flight work and the hold's expiry or release under your deployed backend
|
|
395
|
+
contract before permitting a conflicting selection.
|
|
396
|
+
|
|
397
|
+
### Single-page checkout
|
|
398
|
+
|
|
399
|
+
This layout keeps the buyer on one browser page. Selecting tickets or seats
|
|
400
|
+
reveals a single combined form with add-ons, buyer details, waiver and payment.
|
|
401
|
+
The host supplies the status view after `onComplete`.
|
|
227
402
|
|
|
228
403
|
```tsx
|
|
229
404
|
import { useState } from 'react'
|
|
230
405
|
import {
|
|
231
|
-
AddOns, BillingInfo, CheckoutProvider,
|
|
232
|
-
Tickets, WaiverSigning,
|
|
406
|
+
AddOns, BillingInfo, CheckoutProvider, Payment, SeatMap,
|
|
407
|
+
Tickets, TimerBanner, WaiverSigning, useCheckoutContext, type PlaceOrderResult,
|
|
233
408
|
} from 'tf-checkout-react'
|
|
234
409
|
|
|
235
|
-
|
|
236
|
-
const
|
|
237
|
-
const [
|
|
410
|
+
function SinglePageContents({ eventId }: { eventId: string }) {
|
|
411
|
+
const checkout = useCheckoutContext()
|
|
412
|
+
const [view, setView] = useState<'tickets' | 'seats' | 'checkout'>('tickets')
|
|
413
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
414
|
+
|
|
415
|
+
if (order) return <p role="status">Checking your order status…</p>
|
|
416
|
+
|
|
417
|
+
return (
|
|
418
|
+
<main>
|
|
419
|
+
<div hidden={view !== 'tickets'}>
|
|
420
|
+
<Tickets
|
|
421
|
+
eventId={eventId}
|
|
422
|
+
onContinue={() => setView('checkout')}
|
|
423
|
+
onSelectSeats={() => setView('seats')}
|
|
424
|
+
/>
|
|
425
|
+
</div>
|
|
426
|
+
{view === 'seats' && (
|
|
427
|
+
<>
|
|
428
|
+
<button type="button" onClick={() => setView('tickets')}>Back to tickets</button>
|
|
429
|
+
<SeatMap eventId={eventId} onContinue={() => setView('checkout')} />
|
|
430
|
+
</>
|
|
431
|
+
)}
|
|
432
|
+
{view === 'checkout' && (
|
|
433
|
+
<>
|
|
434
|
+
<TimerBanner seconds={checkout.secondsLeft} />
|
|
435
|
+
<AddOns eventId={eventId} />
|
|
436
|
+
<BillingInfo
|
|
437
|
+
eventId={eventId}
|
|
438
|
+
requireEmailConfirmation
|
|
439
|
+
collectTicketHolders
|
|
440
|
+
collectHolderContact
|
|
441
|
+
/>
|
|
442
|
+
<WaiverSigning eventId={eventId} />
|
|
443
|
+
<Payment
|
|
444
|
+
eventId={eventId}
|
|
445
|
+
requireEmailConfirmation
|
|
446
|
+
collectTicketHolders
|
|
447
|
+
requireHolderContact
|
|
448
|
+
onComplete={setOrder}
|
|
449
|
+
/>
|
|
450
|
+
</>
|
|
451
|
+
)}
|
|
452
|
+
</main>
|
|
453
|
+
)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function SinglePageCheckout({ eventId }: { eventId: string }) {
|
|
238
457
|
return (
|
|
239
458
|
<CheckoutProvider theme={{ colorScheme: 'light', accent: '#2458d3' }}>
|
|
240
|
-
<
|
|
241
|
-
<AddOns eventId={eventId} />
|
|
242
|
-
<BillingInfo eventId={eventId} requireEmailConfirmation />
|
|
243
|
-
<WaiverSigning eventId={eventId} />
|
|
244
|
-
<OrderSummary eventId={eventId} />
|
|
245
|
-
<Payment
|
|
246
|
-
eventId={eventId}
|
|
247
|
-
requireEmailConfirmation
|
|
248
|
-
onComplete={(order) => setNotice(order.pending ? 'Payment pending' : 'Order submitted')}
|
|
249
|
-
/>
|
|
250
|
-
<p role="status">{notice}</p>
|
|
459
|
+
<SinglePageContents eventId={eventId} />
|
|
251
460
|
</CheckoutProvider>
|
|
252
461
|
)
|
|
253
462
|
}
|
|
254
463
|
```
|
|
255
464
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
465
|
+
`Tickets.onContinue` fires after the cart is primed. `onSelectSeats` opens the
|
|
466
|
+
seat view; without it the seat-selection button is hidden in a composed
|
|
467
|
+
`Tickets` section. `SeatMap.onContinue` runs after seats are added and priced.
|
|
468
|
+
Without an `onContinue` prop, `BillingInfo` and `AddOns` use their combined-form
|
|
469
|
+
behavior instead of showing a separate Continue button. Match the billing and
|
|
470
|
+
payment email/holder settings, as shown. `AddOns` renders nothing when the
|
|
471
|
+
event has no applicable add-ons; do not skip a required one.
|
|
472
|
+
|
|
473
|
+
### Step-by-step checkout
|
|
474
|
+
|
|
475
|
+
To make billing and payment separate steps, give `BillingInfo` an `onContinue`
|
|
476
|
+
callback. It then validates and saves the buyer details before moving on. This
|
|
477
|
+
example keeps the checkout provider mounted for the whole flow; it does not
|
|
478
|
+
change URLs or assume a browser refresh can resume the in-memory layout.
|
|
479
|
+
|
|
480
|
+
```tsx
|
|
481
|
+
import { useState } from 'react'
|
|
482
|
+
import {
|
|
483
|
+
AddOns, BillingInfo, CheckoutProvider, Payment, SeatMap,
|
|
484
|
+
Tickets, TimerBanner, WaiverSigning, useCheckoutContext, type PlaceOrderResult,
|
|
485
|
+
} from 'tf-checkout-react'
|
|
486
|
+
|
|
487
|
+
type Step = 'tickets' | 'seats' | 'details' | 'payment'
|
|
488
|
+
|
|
489
|
+
function StepContents({ eventId }: { eventId: string }) {
|
|
490
|
+
const checkout = useCheckoutContext()
|
|
491
|
+
const [step, setStep] = useState<Step>('tickets')
|
|
492
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
493
|
+
|
|
494
|
+
if (order) return <p role="status">Checking your order status…</p>
|
|
495
|
+
|
|
496
|
+
return (
|
|
497
|
+
<main>
|
|
498
|
+
{(step === 'details' || step === 'payment') && (
|
|
499
|
+
<TimerBanner seconds={checkout.secondsLeft} />
|
|
500
|
+
)}
|
|
501
|
+
<div hidden={step !== 'tickets'}>
|
|
502
|
+
<Tickets
|
|
503
|
+
eventId={eventId}
|
|
504
|
+
onContinue={() => setStep('details')}
|
|
505
|
+
onSelectSeats={() => setStep('seats')}
|
|
506
|
+
/>
|
|
507
|
+
</div>
|
|
508
|
+
{step === 'seats' && (
|
|
509
|
+
<>
|
|
510
|
+
<button type="button" onClick={() => setStep('tickets')}>Back to tickets</button>
|
|
511
|
+
<SeatMap eventId={eventId} onContinue={() => setStep('details')} />
|
|
512
|
+
</>
|
|
513
|
+
)}
|
|
514
|
+
{step === 'details' && (
|
|
515
|
+
<BillingInfo
|
|
516
|
+
eventId={eventId}
|
|
517
|
+
requireEmailConfirmation
|
|
518
|
+
collectTicketHolders
|
|
519
|
+
collectHolderContact
|
|
520
|
+
onContinue={() => setStep('payment')}
|
|
521
|
+
/>
|
|
522
|
+
)}
|
|
523
|
+
{step === 'payment' && (
|
|
524
|
+
<>
|
|
525
|
+
<AddOns eventId={eventId} />
|
|
526
|
+
<WaiverSigning eventId={eventId} />
|
|
527
|
+
<Payment
|
|
528
|
+
eventId={eventId}
|
|
529
|
+
requireEmailConfirmation
|
|
530
|
+
collectTicketHolders
|
|
531
|
+
requireHolderContact
|
|
532
|
+
onComplete={setOrder}
|
|
533
|
+
/>
|
|
534
|
+
</>
|
|
535
|
+
)}
|
|
536
|
+
</main>
|
|
537
|
+
)
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
export function StepCheckout({ eventId }: { eventId: string }) {
|
|
541
|
+
return <CheckoutProvider><StepContents eventId={eventId} /></CheckoutProvider>
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
For separate routes, keep the provider above the routed pages and connect the
|
|
546
|
+
callbacks to your router. A full page reload is a different session/navigation
|
|
547
|
+
problem: `ResumedCheckout` can attach only to an existing cart in the current
|
|
548
|
+
session, and the old 1.x localStorage state is not a migration format. Handle
|
|
549
|
+
expired reservations, browser Back, buyer changes and unconfirmed payments
|
|
550
|
+
before enabling navigation or a new purchase. Do not unmount or reset an
|
|
551
|
+
in-flight payment merely to move between steps.
|
|
552
|
+
|
|
553
|
+
The step example is a progressive layout: the next step appears after a
|
|
554
|
+
successful callback. A router can replace `setStep`, but the SDK does not
|
|
555
|
+
supply a route-based checkout or implement your browser Back handling. Do not
|
|
556
|
+
assume that a successful TypeScript build verifies route, refresh or payment
|
|
557
|
+
behavior; test those flows with your own backend and providers.
|
|
558
|
+
|
|
559
|
+
### Accordion checkout
|
|
560
|
+
|
|
561
|
+
The SDK does not export a named accordion component. This host-built layout
|
|
562
|
+
uses native HTML disclosures to group the same SDK sections. The payment field
|
|
563
|
+
stays outside the disclosures so it remains visible while the buyer pays.
|
|
564
|
+
It uses the configuration and `QueryClientProvider` from the quick start.
|
|
565
|
+
|
|
566
|
+
```tsx
|
|
567
|
+
import { useState } from 'react'
|
|
568
|
+
import {
|
|
569
|
+
AddOns, BillingInfo, CheckoutProvider, Payment, SeatMap,
|
|
570
|
+
Tickets, TimerBanner, WaiverSigning, useCheckoutContext, type PlaceOrderResult,
|
|
571
|
+
} from 'tf-checkout-react'
|
|
572
|
+
|
|
573
|
+
function AccordionContents({ eventId }: { eventId: string }) {
|
|
574
|
+
const checkout = useCheckoutContext()
|
|
575
|
+
const [view, setView] = useState<'tickets' | 'seats' | 'checkout'>('tickets')
|
|
576
|
+
const [order, setOrder] = useState<PlaceOrderResult | null>(null)
|
|
577
|
+
|
|
578
|
+
if (order) return <p role="status">Checking your order status…</p>
|
|
579
|
+
|
|
580
|
+
return (
|
|
581
|
+
<main>
|
|
582
|
+
<div hidden={view !== 'tickets'}>
|
|
583
|
+
<Tickets
|
|
584
|
+
eventId={eventId}
|
|
585
|
+
onContinue={() => setView('checkout')}
|
|
586
|
+
onSelectSeats={() => setView('seats')}
|
|
587
|
+
/>
|
|
588
|
+
</div>
|
|
589
|
+
{view === 'seats' && (
|
|
590
|
+
<>
|
|
591
|
+
<button type="button" onClick={() => setView('tickets')}>Back to tickets</button>
|
|
592
|
+
<SeatMap eventId={eventId} onContinue={() => setView('checkout')} />
|
|
593
|
+
</>
|
|
594
|
+
)}
|
|
595
|
+
{view === 'checkout' && (
|
|
596
|
+
<>
|
|
597
|
+
<TimerBanner seconds={checkout.secondsLeft} />
|
|
598
|
+
<details open>
|
|
599
|
+
<summary>Add-ons</summary>
|
|
600
|
+
<AddOns eventId={eventId} />
|
|
601
|
+
</details>
|
|
602
|
+
<details open>
|
|
603
|
+
<summary>Buyer and ticket holders</summary>
|
|
604
|
+
<BillingInfo
|
|
605
|
+
eventId={eventId}
|
|
606
|
+
requireEmailConfirmation
|
|
607
|
+
collectTicketHolders
|
|
608
|
+
collectHolderContact
|
|
609
|
+
/>
|
|
610
|
+
</details>
|
|
611
|
+
<details open>
|
|
612
|
+
<summary>Waiver</summary>
|
|
613
|
+
<WaiverSigning eventId={eventId} />
|
|
614
|
+
</details>
|
|
615
|
+
<Payment
|
|
616
|
+
eventId={eventId}
|
|
617
|
+
requireEmailConfirmation
|
|
618
|
+
collectTicketHolders
|
|
619
|
+
requireHolderContact
|
|
620
|
+
onComplete={setOrder}
|
|
621
|
+
/>
|
|
622
|
+
</>
|
|
623
|
+
)}
|
|
624
|
+
</main>
|
|
625
|
+
)
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
export function AccordionCheckout({ eventId }: { eventId: string }) {
|
|
629
|
+
return <CheckoutProvider><AccordionContents eventId={eventId} /></CheckoutProvider>
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
The buyer reserves tickets or seats, then can open or close the form groups.
|
|
634
|
+
Closing a `<details>` element hides its contents without unmounting them. In a
|
|
635
|
+
production accordion, open the relevant group when validation needs the buyer's
|
|
636
|
+
attention, and make sure required add-ons, fields and waivers cannot be missed.
|
|
637
|
+
Do not hide or replace the active payment field during a payment attempt.
|
|
638
|
+
As with the other examples, replace the status placeholder with your own
|
|
639
|
+
verified order-status and support flow.
|
|
640
|
+
|
|
641
|
+
`CheckoutProvider` props are `children` (required), `value?: UseCheckout`,
|
|
267
642
|
`theme?: CheckoutTheme`, `locale?: LocaleCode`,
|
|
268
643
|
`messages?: Partial<Messages>`, and `className?: string`. Use
|
|
269
|
-
`useCheckoutContext()` inside the provider
|
|
270
|
-
`
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
ports you need when creating that checkout.
|
|
644
|
+
`useCheckoutContext()` inside the provider to read the current checkout and
|
|
645
|
+
`useCheckoutValidation()` to coordinate validation between sections. The
|
|
646
|
+
provider's default checkout includes the installment picker. If supplying your
|
|
647
|
+
own `value`, wire any custom payment ports you need when creating that checkout.
|
|
274
648
|
|
|
275
649
|
## Checkout lifecycle
|
|
276
650
|
|
|
@@ -309,6 +683,18 @@ error or closed provider page means the charge failed. A custom provider page mu
|
|
|
309
683
|
settle with `{ event: 'dismiss' }` on close/unmount, and other custom payment
|
|
310
684
|
ports must settle, or a waiting reset cannot finish.
|
|
311
685
|
|
|
686
|
+
The beta.27 declaration comments for `reset` and `PAID_ORDER_PENDING_MESSAGE`
|
|
687
|
+
say pressing Pay again finishes an unconfirmed order; the `resetWhenSettled`
|
|
688
|
+
comment also omits retired checkouts as a reason for `false`. Those comments do
|
|
689
|
+
not establish that a retry is safe. Use the session and reconciliation guidance
|
|
690
|
+
above.
|
|
691
|
+
|
|
692
|
+
Stock `Payment` can display an engine message telling the buyer to press Pay
|
|
693
|
+
again when payment is unconfirmed. That wording does not establish that a retry
|
|
694
|
+
is safe. If neutral buyer guidance is required for uncertain outcomes, use a
|
|
695
|
+
custom payment flow with host-controlled error UI, retain the order and reconcile
|
|
696
|
+
the current session and authoritative order/provider status before recovery.
|
|
697
|
+
|
|
312
698
|
### Tickets, codes, seats and waiting lists
|
|
313
699
|
|
|
314
700
|
`Tickets` reads the catalog, presents the event's promo/access-code controls and
|
|
@@ -354,7 +740,7 @@ holder's answers in `ticketDataCapture`, and add-on answers via
|
|
|
354
740
|
the opaque catalog ID. Use backend country/state IDs for `countryId` and
|
|
355
741
|
`stateId`; `countryCode` / `stateCode` are payment billing codes.
|
|
356
742
|
|
|
357
|
-
In beta.
|
|
743
|
+
In beta.27 conditional custom-field requiredness is left to the backend and
|
|
358
744
|
not all hosted-checkout conditional visibility is reproduced. Verify the
|
|
359
745
|
actual event against the deployed checkout, including blanks, images, holder
|
|
360
746
|
scoping and validation errors; do not claim parity from the presence of a
|
|
@@ -362,11 +748,20 @@ field alone. Terms and `additionalConditions` are client-side acceptance gates;
|
|
|
362
748
|
respect the server's own requirements. `Payment` renders condition `content`,
|
|
363
749
|
or `name` as a fallback, as HTML. Only supply trusted or appropriately sanitized
|
|
364
750
|
content, and verify the source and handling of server-provided conditions too.
|
|
365
|
-
|
|
366
|
-
|
|
751
|
+
|
|
752
|
+
During cart priming, failed custom-field, checkout-config, add-on or event
|
|
753
|
+
condition reads fall back to empty/default data. The stock UI cannot show or
|
|
754
|
+
gate requirements it did not load. Do not treat an empty list as proof that no
|
|
755
|
+
requirement exists; verify deployment/failure behavior and add tested host
|
|
756
|
+
safeguards for mandatory fields and acknowledgments. Server validation of
|
|
757
|
+
required answers is not proof that a condition was acknowledged. Only failed
|
|
758
|
+
waiver reads other than a 404 are recorded in `unavailableDetails`. Before money
|
|
759
|
+
may have moved, placement retries an unavailable waiver and blocks if it remains
|
|
760
|
+
unknown; `reloadCheckoutDetails()` can also retry the waiver read. A retained
|
|
761
|
+
order with a possible payment follows separate recovery and needs reconciliation.
|
|
367
762
|
`WaiverSigning` handles the SDK's signing flow.
|
|
368
763
|
|
|
369
|
-
**Consent limitation in beta.
|
|
764
|
+
**Consent limitation in beta.27:** when `privacyPolicy` is supplied, the
|
|
370
765
|
stock `BillingInfo` replaces the Ticket Fairy marketing checkbox with the
|
|
371
766
|
required privacy checkbox, but both use `consent.ttfOptIn`; the order sends
|
|
372
767
|
that value as `ttf_opt_in`. The privacy acknowledgement and Ticket Fairy
|
|
@@ -406,6 +801,19 @@ for authoritative confirmation before showing a paid receipt or fulfilling.
|
|
|
406
801
|
ID verification may still be required after payment. An ID-verification failure
|
|
407
802
|
is not a reason to repeat the charge.
|
|
408
803
|
|
|
804
|
+
The stock in-flow `Confirmation` displays confirmed/ticket-available copy when
|
|
805
|
+
`pending` is absent or false; it does not independently verify final settlement.
|
|
806
|
+
For both paid and free orders, use `confirmationMode="redirect"` with a
|
|
807
|
+
host-owned status page, or a custom composed confirmation gated on authoritative
|
|
808
|
+
order and provider status. Arrange ID verification on the host route when
|
|
809
|
+
`needIdVerification` is true; redirect does not render the inline verification.
|
|
810
|
+
The stock `IDVerification` and routed `OrderIDVerification` verified messages
|
|
811
|
+
say tickets are on their way; they do not check final settlement or issuance.
|
|
812
|
+
Use host-owned neutral verification and status UI when that copy is premature.
|
|
813
|
+
If `onComplete` navigates away or unmounts the checkout, its inline verification
|
|
814
|
+
cannot appear: keep the provider mounted or handle verification at the destination.
|
|
815
|
+
For a custom flow, see [host-owned ID verification](#host-owned-id-verification).
|
|
816
|
+
|
|
409
817
|
**Zero-total orders:** this SDK ignores the free-registration response body and
|
|
410
818
|
reports `needIdVerification: false`. Verification or approval may still be
|
|
411
819
|
required, and `free: true` is not proof tickets were issued. The default inline
|
|
@@ -421,7 +829,8 @@ order's payment status before showing its default confirmed/ticket-availability
|
|
|
421
829
|
copy. Gate it on an authoritative status appropriate for that page. When
|
|
422
830
|
`onComplete` reports `pending`, show a pending page (and any voucher) instead;
|
|
423
831
|
do not route directly to `OrderConfirmation` as a paid receipt. The in-flow
|
|
424
|
-
`Confirmation` component reads the current result and has a pending state
|
|
832
|
+
`Confirmation` component reads the current result and has a pending state, but
|
|
833
|
+
the absence of `pending` is not proof of settlement.
|
|
425
834
|
|
|
426
835
|
`CardInput` renders Stripe Elements and uses the checkout's default card owner;
|
|
427
836
|
`StripePaymentElement` is the deferred Elements option when its server config
|
|
@@ -452,6 +861,24 @@ three only when the provider confirms nothing was charged. An unclassified
|
|
|
452
861
|
error is treated as unknown. Avoid automatic blind retries and never promise
|
|
453
862
|
exactly-once charging across your app, backend and provider.
|
|
454
863
|
|
|
864
|
+
### Host-owned ID verification
|
|
865
|
+
|
|
866
|
+
`runIdVerification(orderHash, options)` does not open the provider on its own.
|
|
867
|
+
Supply `openUrl` to validate the URL against your provider and scheme policy
|
|
868
|
+
and open it in the browser; handle a missing URL or blocked/failed opening in
|
|
869
|
+
your UI. The engine swallows asynchronous `openUrl` rejections, so catch and
|
|
870
|
+
record opening failures inside the callback: polling can otherwise continue
|
|
871
|
+
without a handoff. Use `onPhase` for polling state and handle browser returns;
|
|
872
|
+
`registerForegroundListener` can trigger a recheck on return and must return an
|
|
873
|
+
unsubscribe function.
|
|
874
|
+
|
|
875
|
+
Alternatively, `onRequired` receives the order hash and possibly null URL; if
|
|
876
|
+
it returns `true`, the engine resolves `undefined` without opening or polling,
|
|
877
|
+
and your host owns both steps. A timeout or poll error rejects with a message
|
|
878
|
+
promising that payment is safe and tickets will be emailed. Replace that text
|
|
879
|
+
with neutral status and reconcile authoritative payment, verification and
|
|
880
|
+
issuance. Verification alone does not prove settlement or issuance.
|
|
881
|
+
|
|
455
882
|
## Authentication
|
|
456
883
|
|
|
457
884
|
The embedded checkout supplies the event to its built-in `AuthModal`. A
|
|
@@ -520,7 +947,7 @@ package are the authoritative detail for callback payloads and DTOs.
|
|
|
520
947
|
| `BillingInfo` | `eventId?`, `onContinue?`, `heading?`, `buttonLabel?`, `onLogin?`, `skipWhenProfileComplete?`, `requireEmailConfirmation?`, `collectTicketHolders?`, `collectHolderContact?`, `ttfOptInLabel?`, `brandOptInLabel?`, `privacyPolicy?`, `showPrivacyError?`, `step?`, `className?`. Standalone holder collection follows backend gates unless explicitly enabled. |
|
|
521
948
|
| `WaiverSigning` | `eventId`, `className?`. Render before payment for an event requiring a waiver. |
|
|
522
949
|
| `Payment` | `onComplete?`, `eventId?`, `requireEmailConfirmation?`, `collectTicketHolders?`, `requireHolderContact?`, `additionalConditions?`, `requirePrivacyPolicy?`, `onPrivacyRequired?`, `showTestCardHint?`, `className?`. Match the paired billing policies. |
|
|
523
|
-
| `OrderSummary` | `eventId?`, `className?`. Uses the current checkout's pricing. |
|
|
950
|
+
| `OrderSummary` | `eventId?`, `className?`. Uses the current checkout's pricing. `Payment` already renders it; use it separately when you need a summary elsewhere. |
|
|
524
951
|
| `IDVerification` | `className?`. Uses the current checkout/order. |
|
|
525
952
|
| `Confirmation` | `shareUrl?`, `shareMessage?`, `viewOrderUrl?`, `children?`, `className?`. Uses the current checkout result and handles pending presentation. The default share URL and eligibility have the limitations below. |
|
|
526
953
|
| `OrderConfirmation` | `orderHash`, `title?`, `message?`, `helper?`, `eventTitle?`, `eventDate?`, `eventLocation?`, `viewOrderUrl?` (string or function), `showReferral?`, `showShareButtons?`, `showRewards?`, `snapchat?`, `onLoaded?`, `onError?`, `className?`. Reloads confirmation by hash; the host must gate it on appropriate payment status. The three `show*` options default to true; Snapchat defaults to false. |
|
|
@@ -688,7 +1115,7 @@ as the final order amount.
|
|
|
688
1115
|
| `setAcceptedConditions(map)`, `acceptCondition(id, accepted)`, `setAddonDataCapture(map)` | Record condition acceptance and add-on answers. |
|
|
689
1116
|
| `setWaiverSignature(index, signature, hold?)`, `holdWaiverSigning(index)` | Coordinate a signature save with the cart/holder it belongs to; release a hold when finished. Prefer `WaiverSigning` for standard UI. |
|
|
690
1117
|
| `reloadCheckoutDetails()`, `syncCurrency(eventId, code?, options?)` | Retry unavailable details or switch/seed event currency. Refresh selection and prices after changing currency. |
|
|
691
|
-
| `placeOrder(method?, options?)`, `runIdVerification(orderHash, options?)` | Place/pay; optionally run verification separately. `placeOrder` accepts `autoRunIdVerification`, `idVerification` and `claimCard` options. |
|
|
1118
|
+
| `placeOrder(method?, options?)`, `runIdVerification(orderHash, options?)` | Place/pay; optionally run verification separately with a host URL opener or takeover. See [host-owned ID verification](#host-owned-id-verification). `placeOrder` accepts `autoRunIdVerification`, `idVerification` and `claimCard` options. |
|
|
692
1119
|
| `applyPromoCode(eventId, code)`, `attributeReferrer(eventId, referrer)`, `joinWaitingList(eventId, entry)` | Helpers return promises. Refetch catalog after a code changes availability. |
|
|
693
1120
|
| `reset()`, `resetWhenSettled()` | Restart subject to payment-settlement protection; see [lifecycle](#checkout-lifecycle). |
|
|
694
1121
|
| `snapshot`, `store`, `isLoggedIn` | Entire state, shared store, and whether the hook sees an authenticated or checkout buyer session. The latter does not imply private-account authority. |
|
|
@@ -721,11 +1148,13 @@ for a different gateway.
|
|
|
721
1148
|
|
|
722
1149
|
The package re-exports the shared core: `ttf` is a configured domain facade,
|
|
723
1150
|
`api` contains raw calls, `hooks` contains React bindings, and DTOs, logic,
|
|
724
|
-
`createEngine` and `createCheckoutStore` are named exports.
|
|
725
|
-
promises;
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
1151
|
+
`createEngine` and `createCheckoutStore` are named exports. Network calls usually
|
|
1152
|
+
return promises; `ttf.events.filterAddonsForTickets` and
|
|
1153
|
+
`ttf.order.mapProfileToBilling` are synchronous helpers. They do not render UI
|
|
1154
|
+
or replace the engine's sequencing, payment ownership and preflight. Use them
|
|
1155
|
+
directly only when your application owns the corresponding workflow. The
|
|
1156
|
+
installed `dist/index.d.ts` includes the complete exported signatures. Avoid
|
|
1157
|
+
importing a private shared-core package.
|
|
729
1158
|
|
|
730
1159
|
```tsx
|
|
731
1160
|
import { hooks } from 'tf-checkout-react'
|
|
@@ -819,7 +1248,7 @@ existing 1.x integration pinned until the new flow and backend are verified.
|
|
|
819
1248
|
There is no automatic translation of old URLs, component props, account
|
|
820
1249
|
sessions or persisted 1.x state.
|
|
821
1250
|
|
|
822
|
-
| 1.x integration | 2.0.0-beta.
|
|
1251
|
+
| 1.x integration | 2.0.0-beta.27 approach |
|
|
823
1252
|
| --- | --- |
|
|
824
1253
|
| `setConfigs({ BASE_URL, ... })` | `configureCheckout({ env` or `baseUrl`, `clientId`, `clientSecret: ''`, ... `})`; public client registration and session setup are required. |
|
|
825
1254
|
| `TicketsContainer`, `SeatMapContainer`, `AddOnsContainer` | `EmbeddedCheckout` or `Tickets`, `SeatMap`, `AddOns` under `CheckoutProvider`. Adapt callbacks and navigation. |
|
|
@@ -832,6 +1261,25 @@ sessions or persisted 1.x state.
|
|
|
832
1261
|
| Promo/access, waiting list, pixel and referral behavior | Re-check catalog metadata, code/attribution precedence, waiting-list contract and explicit tracking. Do not infer numeric `?r=`. |
|
|
833
1262
|
| Legacy single-page state in localStorage | Use the 2.x checkout store/engine and server cart; do not copy sensitive state or assume 1.x persisted state can be resumed. |
|
|
834
1263
|
|
|
1264
|
+
### Migrating layout callbacks
|
|
1265
|
+
|
|
1266
|
+
A callback name change can also change what the host receives. In particular,
|
|
1267
|
+
`onContinue` does not pass the old callback's response payload:
|
|
1268
|
+
|
|
1269
|
+
| 1.x usage | 2.x replacement |
|
|
1270
|
+
| --- | --- |
|
|
1271
|
+
| `TicketsContainer`'s `getTicketsLabel` | `Tickets`'s `buttonLabel`. |
|
|
1272
|
+
| `TicketsContainer`'s `onAddToCartSuccess(data)` | `Tickets.onContinue()` after reservation; read the current cart through `useCheckoutContext()` under the provider. |
|
|
1273
|
+
| `BillingInfoContainer`'s `handleSubmit(values, helpers, eventId, response)` | `BillingInfo.onContinue()` after validation and save; read the current billing and holders from the checkout context. Omit the callback for combined-form behavior. |
|
|
1274
|
+
| `AddOnsContainer` timer | Render `TimerBanner` with `useCheckoutContext().secondsLeft` in the host layout. |
|
|
1275
|
+
| Separate 1.x page URLs and localStorage state | Keep the 2.x provider mounted across host steps; implement route/refresh handling and verify any existing server cart in the current session. |
|
|
1276
|
+
|
|
1277
|
+
These are migration starting points, not prop-compatible aliases. In 2.x
|
|
1278
|
+
`eventId` is a string; convert a numeric ID before passing it. Old Material UI
|
|
1279
|
+
theme options, callback payloads and optional page behavior need explicit host
|
|
1280
|
+
work. For the two complete flows see [Choose a checkout layout](#choose-a-checkout-layout);
|
|
1281
|
+
for single-page and stepped alternatives see [Compose sections](#compose-sections).
|
|
1282
|
+
|
|
835
1283
|
Compare the exact event's ticket types, dated pricing, seats, add-ons, holder
|
|
836
1284
|
questions, conditional fields, consent, waivers, fees, currencies, payment
|
|
837
1285
|
methods, account and post-purchase behavior before switching. Backend rollout
|