@debugged-development/ticketapp-sdk 1.0.9 → 1.0.10-dev.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/README.md +620 -339
- package/dist/index.js +1949 -2025
- package/dist/sdk.d.ts +9 -14
- package/dist/sdk.d.ts.map +1 -1
- package/dist/services/basket/basket.service.d.ts +39 -0
- package/dist/services/basket/basket.service.d.ts.map +1 -0
- package/dist/services/basket/basket.service.generated.d.ts +202 -0
- package/dist/services/basket/basket.service.generated.d.ts.map +1 -0
- package/dist/services/category/category.service.d.ts +15 -0
- package/dist/services/category/category.service.d.ts.map +1 -0
- package/dist/services/category/category.service.generated.d.ts +41 -0
- package/dist/services/category/category.service.generated.d.ts.map +1 -0
- package/dist/services/event/event.service.d.ts +31 -0
- package/dist/services/event/event.service.d.ts.map +1 -0
- package/dist/services/event/event.service.generated.d.ts +122 -0
- package/dist/services/event/event.service.generated.d.ts.map +1 -0
- package/dist/services/package/package.service.d.ts +29 -0
- package/dist/services/package/package.service.d.ts.map +1 -0
- package/dist/services/package/package.service.generated.d.ts +122 -0
- package/dist/services/package/package.service.generated.d.ts.map +1 -0
- package/dist/services/payment/payment.service.d.ts +14 -0
- package/dist/services/payment/payment.service.d.ts.map +1 -0
- package/dist/services/payment/payment.service.generated.d.ts +53 -0
- package/dist/services/payment/payment.service.generated.d.ts.map +1 -0
- package/dist/store/store.d.ts +3132 -11
- package/dist/store/store.d.ts.map +1 -1
- package/dist/types/index.d.ts +105 -27
- package/dist/types/index.d.ts.map +1 -1
- package/dist/{graphql/generated.d.ts → types/types.generated.d.ts} +263 -903
- package/dist/types/types.generated.d.ts.map +1 -0
- package/package.json +14 -12
- package/dist/graphql/generated.d.ts.map +0 -1
- package/dist/services/basketService.d.ts +0 -39
- package/dist/services/basketService.d.ts.map +0 -1
- package/dist/services/eventService.d.ts +0 -37
- package/dist/services/eventService.d.ts.map +0 -1
- package/dist/services/packageService.d.ts +0 -66
- package/dist/services/packageService.d.ts.map +0 -1
- package/dist/services/paymentService.d.ts +0 -18
- package/dist/services/paymentService.d.ts.map +0 -1
- package/dist/store/basketSlice.d.ts +0 -55
- package/dist/store/basketSlice.d.ts.map +0 -1
- package/dist/store/eventSlice.d.ts +0 -75
- package/dist/store/eventSlice.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Ticketapp SDK
|
|
2
2
|
|
|
3
|
-
A TypeScript SDK for integrating Ticketapp's event ticketing and
|
|
3
|
+
A TypeScript SDK for integrating Ticketapp's event ticketing, package, and category management system into your application.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,20 +15,34 @@ import { TicketappSDK } from '@ticketapp/sdk';
|
|
|
15
15
|
|
|
16
16
|
const sdk = new TicketappSDK({
|
|
17
17
|
organizationId: 'your-organization-id',
|
|
18
|
-
shopId: 'your-shop-id',
|
|
19
|
-
shopSlug: 'your-shop-slug',
|
|
20
18
|
debug: true, // Enable debug logging (optional)
|
|
21
19
|
});
|
|
22
20
|
```
|
|
23
21
|
|
|
22
|
+
> Who is this for?
|
|
23
|
+
> - Teams who want to show events, let visitors pick tickets, and pay online.
|
|
24
|
+
> - You don’t need to be a developer to follow the examples below—each step is explained in plain English.
|
|
25
|
+
>
|
|
26
|
+
> Core concepts in 60 seconds:
|
|
27
|
+
> - Organization: your brand or company in Ticketapp.
|
|
28
|
+
> - Event: something you sell tickets for (e.g., Friday Night Show).
|
|
29
|
+
> - Product: a sellable ticket or add-on (e.g., Regular Ticket, VIP, Door ticket).
|
|
30
|
+
> - Basket: the visitor’s shopping cart (we keep it in the browser so it survives page reloads).
|
|
31
|
+
> - Package: a bundle of tickets/events (e.g., Weekend Pass with several included events).
|
|
32
|
+
> - Category: a label to group products or events (e.g., Music, Sports).
|
|
33
|
+
> - Payment: the step where the visitor selects a method (iDEAL, card, etc.) and pays.
|
|
34
|
+
|
|
24
35
|
## Table of Contents
|
|
25
36
|
|
|
26
37
|
- [Configuration](#configuration)
|
|
27
38
|
- [Events](#events)
|
|
28
|
-
- [
|
|
39
|
+
- [Categories](#categories)
|
|
29
40
|
- [Packages](#packages)
|
|
41
|
+
- [Basket](#basket)
|
|
30
42
|
- [Payment](#payment)
|
|
31
43
|
- [Examples](#examples)
|
|
44
|
+
- [Services Overview](#services-overview)
|
|
45
|
+
- [FAQ and Troubleshooting](#faq-and-troubleshooting)
|
|
32
46
|
|
|
33
47
|
---
|
|
34
48
|
|
|
@@ -39,8 +53,6 @@ const sdk = new TicketappSDK({
|
|
|
39
53
|
```typescript
|
|
40
54
|
const sdk = new TicketappSDK({
|
|
41
55
|
organizationId: 'eed7fb11-f5c4-4467-8393-6da072b7f752',
|
|
42
|
-
shopId: '1fbdf73d-6ee6-438b-b8e5-a76907a6d76b',
|
|
43
|
-
shopSlug: 'hvrmq',
|
|
44
56
|
debug: true,
|
|
45
57
|
});
|
|
46
58
|
```
|
|
@@ -50,12 +62,8 @@ const sdk = new TicketappSDK({
|
|
|
50
62
|
```typescript
|
|
51
63
|
const sdk = new TicketappSDK({
|
|
52
64
|
organizationId: 'your-organization-id',
|
|
53
|
-
shopId: 'your-shop-id',
|
|
54
|
-
shopSlug: 'your-shop-slug',
|
|
55
65
|
debug: true,
|
|
56
|
-
|
|
57
|
-
filteredHostingIds: ['host-id-1', 'host-id-2'], // Optional: Filter events by host
|
|
58
|
-
enableDoorTickets: true, // Optional: Include door tickets
|
|
66
|
+
// Optionally add shopId, shopSlug, filteredLocationIds, filteredHostingIds, enableDoorTickets, etc.
|
|
59
67
|
});
|
|
60
68
|
```
|
|
61
69
|
|
|
@@ -63,68 +71,90 @@ const sdk = new TicketappSDK({
|
|
|
63
71
|
|
|
64
72
|
## Events
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
// In plain English: Use EventService to show a list of events, open one event’s details, and load its ticket types (products). You can filter by date or status, and sort or paginate results.
|
|
75
|
+
|
|
76
|
+
### EventService overview
|
|
77
|
+
|
|
78
|
+
Methods:
|
|
79
|
+
- fetchEvents(options?): Promise<[Event[], number]>
|
|
80
|
+
- options.statuses?: EventStatus[]
|
|
81
|
+
- options.hostingIds?: string[]
|
|
82
|
+
- options.dateRange?: { from: DateTime; till: DateTime }
|
|
83
|
+
- options.page?: { index: number; size: number }
|
|
84
|
+
- options.sorts?: { field: string; order: SortOrder }[]
|
|
85
|
+
- fetchEvent(eventId: string): Promise<Event | undefined>
|
|
86
|
+
- fetchProducts(eventId: string, productTypes?: ProductType[], promoCode?: string): Promise<Product[] | undefined>
|
|
67
87
|
|
|
68
|
-
|
|
88
|
+
Types available from the SDK:
|
|
89
|
+
- EventStatus: ACTIVE | INACTIVE | PAUSED | SOLD_OUT
|
|
90
|
+
- ProductType: TICKET | DOOR | ADDON | ...
|
|
91
|
+
- SortOrder: ASC | DESC
|
|
92
|
+
|
|
93
|
+
You can import these enums directly:
|
|
69
94
|
|
|
70
95
|
```typescript
|
|
71
|
-
|
|
96
|
+
import { EventStatus, ProductType, SortOrder } from '@ticketapp/sdk';
|
|
97
|
+
import { DateTime } from 'luxon';
|
|
72
98
|
```
|
|
73
99
|
|
|
74
|
-
###
|
|
100
|
+
### Fetching Events (with options)
|
|
75
101
|
|
|
76
|
-
|
|
102
|
+
Load events with optional filters, pagination, and sorting. Returns a tuple: [events, totalCount].
|
|
77
103
|
|
|
78
104
|
```typescript
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
import { DateTime } from 'luxon';
|
|
106
|
+
import { EventStatus, SortOrder } from '@ticketapp/sdk';
|
|
107
|
+
|
|
108
|
+
// 1) Ask the server: "give me events that are ACTIVE, starting in the next 3 months"
|
|
109
|
+
const [events, total] = await sdk.event.fetchEvents({
|
|
110
|
+
statuses: [EventStatus.Active], // Only active events
|
|
111
|
+
hostingIds: undefined, // Or filter by specific locations/hosts
|
|
112
|
+
dateRange: { // Time window
|
|
113
|
+
from: DateTime.local(),
|
|
114
|
+
till: DateTime.local().plus({ months: 3 })
|
|
115
|
+
},
|
|
116
|
+
page: { index: 0, size: 20 }, // First page, 20 items
|
|
117
|
+
sorts: [{ field: 'startAt', order: SortOrder.Asc }], // Soonest first
|
|
84
118
|
});
|
|
85
119
|
|
|
86
|
-
//
|
|
87
|
-
|
|
120
|
+
// 2) You can now render these events in a grid or list
|
|
121
|
+
console.log(`Found ${total} events`, events.map(e => e.name));
|
|
88
122
|
```
|
|
89
123
|
|
|
90
|
-
###
|
|
124
|
+
### Fetching a Single Event
|
|
91
125
|
|
|
92
126
|
```typescript
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
events: Event[], // Array of events
|
|
98
|
-
processing: boolean, // Loading state
|
|
99
|
-
error: string | null, // Error message if any
|
|
100
|
-
loadingProducts: {} // Products loading state per event
|
|
127
|
+
// When a visitor clicks an event, load its extra details (like sales times)
|
|
128
|
+
const event = await sdk.event.fetchEvent('event-id');
|
|
129
|
+
if (!event) {
|
|
130
|
+
// No event found (maybe it was removed)
|
|
101
131
|
}
|
|
102
132
|
```
|
|
103
133
|
|
|
104
134
|
### Fetching Products for an Event
|
|
105
135
|
|
|
106
136
|
```typescript
|
|
107
|
-
|
|
108
|
-
await sdk.event.fetchProductsForEvent(
|
|
109
|
-
'event-id',
|
|
110
|
-
['TICKET', 'DOOR', 'ADDON']
|
|
111
|
-
);
|
|
137
|
+
import { ProductType } from '@ticketapp/sdk';
|
|
112
138
|
|
|
113
|
-
//
|
|
114
|
-
await sdk.event.
|
|
139
|
+
// Load all ticket types for a chosen event
|
|
140
|
+
const products = await sdk.event.fetchProducts(
|
|
115
141
|
'event-id',
|
|
116
|
-
[
|
|
142
|
+
[ProductType.Ticket, ProductType.Door, ProductType.Addon], // Which types to include
|
|
143
|
+
'PROMO2024' // Optional discount code
|
|
117
144
|
);
|
|
118
145
|
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
'event-id',
|
|
122
|
-
['TICKET'],
|
|
123
|
-
'PROMO2024'
|
|
124
|
-
);
|
|
146
|
+
// Show each product with price so visitors can pick one
|
|
147
|
+
products?.forEach(p => console.log(p.name, p.price));
|
|
125
148
|
```
|
|
126
149
|
|
|
127
|
-
### Event
|
|
150
|
+
### Event object shapes
|
|
151
|
+
|
|
152
|
+
There are two event shapes depending on the call you use.
|
|
153
|
+
|
|
154
|
+
- Overview events (from `fetchEvents`) are lightweight for listing
|
|
155
|
+
- Detailed event (from `fetchEvent`) contains full metadata
|
|
156
|
+
|
|
157
|
+
Overview (fetchEvents):
|
|
128
158
|
|
|
129
159
|
```typescript
|
|
130
160
|
{
|
|
@@ -133,153 +163,302 @@ await sdk.event.fetchProductsForEvent(
|
|
|
133
163
|
icon: string | null,
|
|
134
164
|
banner: string | null,
|
|
135
165
|
description: string | null,
|
|
136
|
-
|
|
166
|
+
addonDescription?: string | null,
|
|
167
|
+
startAt: DateTime,
|
|
137
168
|
endAt: DateTime,
|
|
138
169
|
timezone: string,
|
|
139
|
-
|
|
170
|
+
slug: string,
|
|
171
|
+
status: string,
|
|
172
|
+
location?: {
|
|
140
173
|
id: string,
|
|
141
174
|
name: string,
|
|
142
175
|
address: string | null
|
|
143
176
|
},
|
|
144
|
-
|
|
177
|
+
infoDescription?: string | null
|
|
145
178
|
}
|
|
146
179
|
```
|
|
147
180
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
## Basket (Cart)
|
|
181
|
+
Detail (fetchEvent):
|
|
151
182
|
|
|
152
|
-
|
|
183
|
+
```typescript
|
|
184
|
+
{
|
|
185
|
+
id: string,
|
|
186
|
+
name: string,
|
|
187
|
+
icon: string | null,
|
|
188
|
+
banner: string | null,
|
|
189
|
+
description: string | null,
|
|
190
|
+
addonDescription?: string | null,
|
|
191
|
+
startAt: DateTime,
|
|
192
|
+
endAt: DateTime,
|
|
193
|
+
timezone: string,
|
|
194
|
+
startSalesAt: string | null,
|
|
195
|
+
endSalesAt: string | null,
|
|
196
|
+
slug: string,
|
|
197
|
+
facebookPixelId: string | null,
|
|
198
|
+
status: string,
|
|
199
|
+
location?: {
|
|
200
|
+
id: string,
|
|
201
|
+
name: string,
|
|
202
|
+
address: string | null
|
|
203
|
+
},
|
|
204
|
+
infoDescription?: string | null
|
|
205
|
+
}
|
|
206
|
+
```
|
|
153
207
|
|
|
154
|
-
###
|
|
208
|
+
### Product Object Structure (from fetchProducts)
|
|
155
209
|
|
|
156
210
|
```typescript
|
|
157
|
-
|
|
158
|
-
id:
|
|
159
|
-
name:
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
211
|
+
{
|
|
212
|
+
id: string,
|
|
213
|
+
name: string,
|
|
214
|
+
category?: {
|
|
215
|
+
id: string,
|
|
216
|
+
name: string,
|
|
217
|
+
description?: string
|
|
218
|
+
},
|
|
219
|
+
currency: 'EUR' | 'USD' | string, // see Currency in types
|
|
220
|
+
depositPrice?: number,
|
|
221
|
+
description?: string,
|
|
222
|
+
discountPrice?: number,
|
|
223
|
+
startSalesAt?: string,
|
|
224
|
+
endSalesAt?: string,
|
|
225
|
+
icon?: string,
|
|
226
|
+
maxAmountOfAddons?: number,
|
|
227
|
+
minAmountOfAddons?: number,
|
|
228
|
+
maxAmountPerOrder?: number,
|
|
229
|
+
price?: number,
|
|
230
|
+
serviceFee?: number,
|
|
231
|
+
showEndSalesAtTag: boolean,
|
|
232
|
+
status: ProductStatus,
|
|
233
|
+
type: ProductType
|
|
234
|
+
}
|
|
165
235
|
```
|
|
166
236
|
|
|
167
|
-
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Categories
|
|
240
|
+
|
|
241
|
+
// In plain English: Categories are simple labels you can show to help people browse. You can list them or open one category by its id.
|
|
242
|
+
|
|
243
|
+
### CategoryService overview
|
|
244
|
+
|
|
245
|
+
Methods:
|
|
246
|
+
- getCategories(): Promise<Category[]>
|
|
247
|
+
- getCategory(categoryId: string): Promise<Category | null>
|
|
248
|
+
|
|
249
|
+
Types available from the SDK:
|
|
250
|
+
- Category
|
|
251
|
+
|
|
252
|
+
You can import the Category type directly:
|
|
168
253
|
|
|
169
254
|
```typescript
|
|
170
|
-
|
|
171
|
-
id: 'product-id',
|
|
172
|
-
name: 'VIP Ticket',
|
|
173
|
-
price: 50,
|
|
174
|
-
serviceFee: 5,
|
|
175
|
-
amount: 1,
|
|
176
|
-
currency: 'EUR',
|
|
177
|
-
seat: {
|
|
178
|
-
id: 'seat-a1',
|
|
179
|
-
label: 'A1',
|
|
180
|
-
holdToken: 'hold-token-123'
|
|
181
|
-
}
|
|
182
|
-
});
|
|
255
|
+
import { Category } from '@ticketapp/sdk';
|
|
183
256
|
```
|
|
184
257
|
|
|
185
|
-
###
|
|
258
|
+
### Fetching Categories
|
|
259
|
+
|
|
260
|
+
Load all available categories for your organization:
|
|
186
261
|
|
|
187
262
|
```typescript
|
|
188
|
-
await sdk.
|
|
189
|
-
|
|
190
|
-
name: 'VIP Ticket',
|
|
191
|
-
currency: 'EUR',
|
|
192
|
-
amount: 1,
|
|
193
|
-
});
|
|
263
|
+
const categories: Category[] = await sdk.category.getCategories();
|
|
264
|
+
console.log('Categories:', categories.map(c => c.name));
|
|
194
265
|
```
|
|
195
266
|
|
|
196
|
-
###
|
|
267
|
+
### Fetching a Single Category by ID
|
|
197
268
|
|
|
198
269
|
```typescript
|
|
199
|
-
await sdk.
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
residence: 'Amsterdam', // Optional
|
|
206
|
-
extraInfo: [ // Optional: Custom key-value pairs
|
|
207
|
-
{ key: 'dietaryRestrictions', value: 'Vegetarian' },
|
|
208
|
-
{ key: 'tshirtSize', value: 'L' },
|
|
209
|
-
{ key: 'emergencyContact', value: '+31612345678' }
|
|
210
|
-
]
|
|
211
|
-
});
|
|
270
|
+
const category = await sdk.category.getCategory('category-id');
|
|
271
|
+
if (category) {
|
|
272
|
+
console.log('Category:', category.name);
|
|
273
|
+
} else {
|
|
274
|
+
console.log('Category not found');
|
|
275
|
+
}
|
|
212
276
|
```
|
|
213
277
|
|
|
214
|
-
###
|
|
278
|
+
### Category Object Structure
|
|
215
279
|
|
|
216
280
|
```typescript
|
|
217
|
-
const order = sdk.basket.getCurrentOrder();
|
|
218
|
-
|
|
219
|
-
// order structure:
|
|
220
281
|
{
|
|
221
282
|
id: string,
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
customer: Customer,
|
|
225
|
-
count: number, // Total number of items
|
|
226
|
-
expiredAt: string
|
|
283
|
+
name: string,
|
|
284
|
+
icon?: string | null
|
|
227
285
|
}
|
|
228
286
|
```
|
|
229
287
|
|
|
230
|
-
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Packages
|
|
291
|
+
|
|
292
|
+
// In plain English: Packages are bundles (like a Weekend Pass) that include multiple events. You can show all packages, open one, and list the events inside it.
|
|
293
|
+
|
|
294
|
+
### PackageService overview
|
|
295
|
+
|
|
296
|
+
Methods:
|
|
297
|
+
- getPackages(options?: { page?: { index?: number; size?: number }; tab?: PackageTabType; statuses?: PackageStatus[] }): Promise<{ count: number; data: any[] } | null>
|
|
298
|
+
- getPackage(packageId: string): Promise<any | null>
|
|
299
|
+
- getPackageItems(packageId: string, types?: PackageItemType[]): Promise<{ count: number; data: any[] } | null>
|
|
300
|
+
|
|
301
|
+
Types available from the SDK:
|
|
302
|
+
- PackageItemType: REGULAR | ADDITIONAL_EVENT
|
|
303
|
+
- PackageStatus: ACTIVE | CONCEPT | PAUSED | SOLD_OUT
|
|
304
|
+
- PackageTabType: ACTIVE | INACTIVE
|
|
305
|
+
|
|
306
|
+
You can import these enums directly:
|
|
231
307
|
|
|
232
308
|
```typescript
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
console.log('Order updated:', order);
|
|
236
|
-
});
|
|
309
|
+
import { PackageItemType, PackageStatus, PackageTabType } from '@ticketapp/sdk';
|
|
310
|
+
```
|
|
237
311
|
|
|
238
|
-
|
|
239
|
-
|
|
312
|
+
### Fetching Packages (with options)
|
|
313
|
+
|
|
314
|
+
```typescript
|
|
315
|
+
// Example: show available bundles on your homepage
|
|
316
|
+
const result = await sdk.package.getPackages();
|
|
317
|
+
if (result) {
|
|
318
|
+
console.log('We have these bundles:', result.data.map(p => p.name));
|
|
319
|
+
}
|
|
240
320
|
```
|
|
241
321
|
|
|
242
|
-
###
|
|
322
|
+
### Fetch a Single Package by ID
|
|
243
323
|
|
|
244
324
|
```typescript
|
|
245
|
-
await sdk.
|
|
325
|
+
const pkg = await sdk.package.getPackage('package-id');
|
|
326
|
+
console.log('Package:', pkg);
|
|
246
327
|
```
|
|
247
328
|
|
|
248
|
-
###
|
|
329
|
+
### Fetch Package Items (by types)
|
|
249
330
|
|
|
250
331
|
```typescript
|
|
251
|
-
|
|
332
|
+
// Default: REGULAR and ADDITIONAL_EVENT
|
|
333
|
+
const itemsDefault = await sdk.package.getPackageItems('package-id');
|
|
334
|
+
console.log('Items:', itemsDefault?.data);
|
|
335
|
+
|
|
336
|
+
// Explicit types
|
|
337
|
+
const items = await sdk.package.getPackageItems('package-id', [
|
|
338
|
+
PackageItemType.Regular,
|
|
339
|
+
PackageItemType.AdditionalEvent,
|
|
340
|
+
]);
|
|
341
|
+
console.log('Filtered items:', items?.data);
|
|
252
342
|
```
|
|
253
343
|
|
|
254
|
-
|
|
344
|
+
### Package Object Structure
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
{
|
|
348
|
+
id: string,
|
|
349
|
+
name: string,
|
|
350
|
+
shortDescription: string,
|
|
351
|
+
status: 'ACTIVE' | 'PAUSED' | 'SOLD_OUT' | 'CONCEPT',
|
|
352
|
+
prices: {
|
|
353
|
+
price: number,
|
|
354
|
+
discount: number | null
|
|
355
|
+
},
|
|
356
|
+
amountOfEvents: number,
|
|
357
|
+
maxAmountOfPersonsPerOrder: number | null
|
|
358
|
+
}
|
|
359
|
+
```
|
|
255
360
|
|
|
256
|
-
## Packages
|
|
257
361
|
|
|
258
|
-
Packages are bundled event tickets (e.g., weekend passes, season tickets).
|
|
259
362
|
|
|
260
|
-
|
|
363
|
+
## Basket
|
|
364
|
+
|
|
365
|
+
The basket manages the user's shopping cart and order. It maintains internal state and restores active orders from session automatically.
|
|
366
|
+
|
|
367
|
+
// In plain English: Think of the basket like a shopping cart. When someone clicks “Add to cart” we reserve that ticket for a short time (so nobody else can grab it). If they refresh the page, we restore the cart from the browser.
|
|
368
|
+
|
|
369
|
+
### BasketService overview
|
|
370
|
+
|
|
371
|
+
Methods:
|
|
372
|
+
- subscribe(listener: () => void): () => void
|
|
373
|
+
- getCurrentOrder(): { id: string; currency: string; items: OrderItem[]; count: number; expiredAt?: DateTime | null } | null
|
|
374
|
+
- getSelectedPackageEvent(): string[]
|
|
375
|
+
- addProduct(input: ProductInput): Promise<void>
|
|
376
|
+
- removeProduct(input: ProductInput): Promise<void>
|
|
377
|
+
- configurePackage(input: ConfigurePackageInput): Promise<{ error: unknown } | null>
|
|
378
|
+
- configureDelivery(input?: ConfigureDeliveryInput): Promise<void>
|
|
379
|
+
- configureCustomer(input: ConfigureCustomerInput): Promise<void>
|
|
380
|
+
- reserveAdditionalPackageItem(input: ReserveAdditionalPackageItemInput): Promise<{ error: unknown } | null>
|
|
381
|
+
- cancelOrder(): Promise<void>
|
|
382
|
+
- clearOrderFromSession(): void
|
|
383
|
+
|
|
384
|
+
Types available from the SDK:
|
|
385
|
+
- ProductInput, ConfigurePackageInput, ConfigureDeliveryInput, ConfigureCustomerInput, ReserveAdditionalPackageItemInput, OrderItem
|
|
386
|
+
|
|
387
|
+
You can import these types directly:
|
|
261
388
|
|
|
262
389
|
```typescript
|
|
263
|
-
|
|
390
|
+
import {
|
|
391
|
+
ProductInput,
|
|
392
|
+
ConfigurePackageInput,
|
|
393
|
+
ConfigureDeliveryInput,
|
|
394
|
+
ConfigureCustomerInput,
|
|
395
|
+
ReserveAdditionalPackageItemInput,
|
|
396
|
+
} from '@ticketapp/sdk';
|
|
397
|
+
```
|
|
264
398
|
|
|
265
|
-
|
|
266
|
-
|
|
399
|
+
### Subscribing to Basket Updates
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
// This runs every time the basket changes (e.g., added/removed a ticket)
|
|
403
|
+
const unsubscribe = sdk.basket.subscribe(() => {
|
|
404
|
+
const order = sdk.basket.getCurrentOrder();
|
|
405
|
+
console.log('Order updated:', order);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
// Later: stop listening
|
|
409
|
+
unsubscribe();
|
|
267
410
|
```
|
|
268
411
|
|
|
269
|
-
###
|
|
412
|
+
### Getting Current Order
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
// Ask: what’s currently in the cart?
|
|
416
|
+
const order = sdk.basket.getCurrentOrder();
|
|
417
|
+
if (order) {
|
|
418
|
+
console.log('Total items:', order.count);
|
|
419
|
+
console.log('Expires at:', order.expiredAt?.toISO()); // Tickets are held for a limited time
|
|
420
|
+
}
|
|
421
|
+
```
|
|
270
422
|
|
|
271
|
-
|
|
423
|
+
### Add and Remove Products
|
|
272
424
|
|
|
273
425
|
```typescript
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
426
|
+
// Add a regular ticket
|
|
427
|
+
await sdk.basket.addProduct({
|
|
428
|
+
id: 'product-id', // Ticket/product id from fetchProducts
|
|
429
|
+
name: 'VIP Ticket',
|
|
430
|
+
price: 50,
|
|
431
|
+
serviceFee: 5,
|
|
432
|
+
amount: 2, // How many
|
|
433
|
+
currency: 'EUR',
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Add a seated ticket (we also pass a seat)
|
|
437
|
+
await sdk.basket.addProduct({
|
|
438
|
+
id: 'seated-ticket-id',
|
|
439
|
+
name: 'Seated Ticket',
|
|
440
|
+
price: 75,
|
|
441
|
+
serviceFee: 5,
|
|
442
|
+
amount: 1,
|
|
443
|
+
currency: 'EUR',
|
|
444
|
+
seat: { id: 'seat-a1', label: 'A1', holdToken: 'hold-abc' },
|
|
445
|
+
});
|
|
278
446
|
|
|
279
|
-
|
|
447
|
+
// Remove one from the basket
|
|
448
|
+
await sdk.basket.removeProduct({
|
|
449
|
+
id: 'product-id',
|
|
450
|
+
name: 'VIP Ticket',
|
|
451
|
+
currency: 'EUR',
|
|
452
|
+
amount: 1,
|
|
453
|
+
});
|
|
280
454
|
```
|
|
281
455
|
|
|
282
|
-
|
|
456
|
+
Notes:
|
|
457
|
+
- When you add the first item, we create an order and remember it in the browser.
|
|
458
|
+
- If you remove everything, we automatically cancel the order on the server and clear the browser.
|
|
459
|
+
- If you see SOLD_OUT or RATE_LIMIT errors, it means the product is gone or you clicked too fast—try again.
|
|
460
|
+
|
|
461
|
+
### Configure a Package
|
|
283
462
|
|
|
284
463
|
```typescript
|
|
285
464
|
await sdk.basket.configurePackage({
|
|
@@ -291,60 +470,77 @@ await sdk.basket.configurePackage({
|
|
|
291
470
|
serviceFee: 20,
|
|
292
471
|
amount: 1, // Number of persons
|
|
293
472
|
items: [
|
|
294
|
-
{
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
473
|
+
{ packageItemId: 'item-1-id', eventId: 'event-1-id' },
|
|
474
|
+
{ packageItemId: 'item-2-id', eventId: 'event-2-id' },
|
|
475
|
+
],
|
|
476
|
+
});
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
- Returns null on success; returns an error object if no items are reserved.
|
|
480
|
+
|
|
481
|
+
### Reserve Additional Package Items
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
await sdk.basket.reserveAdditionalPackageItem({
|
|
485
|
+
packageId: 'package-id',
|
|
486
|
+
packageItemId: 'package-item-id',
|
|
487
|
+
eventId: 'event-id',
|
|
488
|
+
amount: 1,
|
|
489
|
+
currency: 'EUR',
|
|
303
490
|
});
|
|
304
491
|
```
|
|
305
492
|
|
|
306
|
-
|
|
493
|
+
- Use this to add additional events to an existing package reservation.
|
|
307
494
|
|
|
308
|
-
|
|
495
|
+
### Configure Delivery and Customer
|
|
309
496
|
|
|
310
497
|
```typescript
|
|
311
|
-
|
|
498
|
+
// Delivery: use this to show “e-ticket” or “pickup” in your order summary
|
|
499
|
+
sdk.basket.configureDelivery({ id: 'delivery-id', name: 'E-ticket', serviceFee: 0, currency: 'EUR' });
|
|
312
500
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
'
|
|
316
|
-
'
|
|
317
|
-
|
|
318
|
-
|
|
501
|
+
// Customer: minimum is email, but more fields help customer support
|
|
502
|
+
await sdk.basket.configureCustomer({
|
|
503
|
+
email: 'customer@example.com',
|
|
504
|
+
firstName: 'John',
|
|
505
|
+
lastName: 'Doe',
|
|
506
|
+
age: 30,
|
|
507
|
+
});
|
|
319
508
|
```
|
|
320
509
|
|
|
321
|
-
### Package
|
|
510
|
+
### Get Selected Package Event IDs
|
|
322
511
|
|
|
323
512
|
```typescript
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
513
|
+
const selectedEventIds = sdk.basket.getSelectedPackageEvent();
|
|
514
|
+
// e.g., ['event-1', 'event-2']
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### Cancel and Clear Order
|
|
518
|
+
|
|
519
|
+
```typescript
|
|
520
|
+
// Cancel current order on server (if ORDER_ID exists) and clear local session
|
|
521
|
+
await sdk.basket.cancelOrder();
|
|
522
|
+
|
|
523
|
+
// Clear local basket state and session key without contacting the server
|
|
524
|
+
sdk.basket.clearOrderFromSession();
|
|
336
525
|
```
|
|
337
526
|
|
|
527
|
+
Behavior notes:
|
|
528
|
+
- On page load, we try to restore a previous order (if it still exists) so your visitors don’t lose their cart.
|
|
529
|
+
- Each reserved ticket has an expiration. We track the earliest one and show it as the order’s expiration time.
|
|
530
|
+
- You can “listen” for changes with subscribe() to keep your UI in sync (e.g., update the cart icon).
|
|
531
|
+
|
|
338
532
|
---
|
|
339
533
|
|
|
340
534
|
## Payment
|
|
341
535
|
|
|
342
|
-
|
|
536
|
+
// In plain English: First ask “what payment methods are available for this order?”, then create the payment and send the visitor to the checkout page.
|
|
537
|
+
|
|
538
|
+
### Getting Payment Details
|
|
343
539
|
|
|
344
|
-
Fetch available payment methods for an order:
|
|
540
|
+
Fetch available payment methods and details for an order:
|
|
345
541
|
|
|
346
542
|
```typescript
|
|
347
|
-
const paymentDetails = await sdk.payment.
|
|
543
|
+
const paymentDetails = await sdk.payment.getPaymentDetails({
|
|
348
544
|
orderId: 'order-id',
|
|
349
545
|
orderItemId: 'item-id', // Optional
|
|
350
546
|
amountOfTickets: 2, // Optional
|
|
@@ -354,9 +550,10 @@ const paymentDetails = await sdk.payment.getPaymentMethods({
|
|
|
354
550
|
// paymentDetails structure:
|
|
355
551
|
{
|
|
356
552
|
transactionPrice: number,
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
553
|
+
transactionDiscount?: number | null,
|
|
554
|
+
transactionFee?: number | null,
|
|
555
|
+
paymentSpesificTransactionFee?: number | null,
|
|
556
|
+
methods?: PaymentMethod[] | null
|
|
360
557
|
}
|
|
361
558
|
```
|
|
362
559
|
|
|
@@ -379,202 +576,261 @@ const paymentDetails = await sdk.payment.getPaymentMethods({
|
|
|
379
576
|
}
|
|
380
577
|
```
|
|
381
578
|
|
|
382
|
-
### Calculating Payment Fees
|
|
383
|
-
|
|
384
|
-
```typescript
|
|
385
|
-
const paymentMethod = {
|
|
386
|
-
id: 1,
|
|
387
|
-
name: 'iDEAL',
|
|
388
|
-
image: 'https://...',
|
|
389
|
-
fee: { type: 'FIXED', value: 0.29 }
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
// Calculate fee amount
|
|
393
|
-
const fee = sdk.payment.calculateFee(50, paymentMethod);
|
|
394
|
-
console.log('Fee:', fee); // 0.29
|
|
395
|
-
|
|
396
|
-
// Calculate total with fee
|
|
397
|
-
const total = sdk.payment.calculateTotalWithFee(50, paymentMethod);
|
|
398
|
-
console.log('Total:', total); // 50.29
|
|
399
|
-
|
|
400
|
-
// Format fee for display
|
|
401
|
-
const formatted = sdk.payment.formatFee(paymentMethod);
|
|
402
|
-
console.log('Fee:', formatted); // "€0.29"
|
|
403
|
-
```
|
|
404
|
-
|
|
405
579
|
### Creating a Payment
|
|
406
580
|
|
|
407
581
|
```typescript
|
|
582
|
+
// 1) Ask for details and methods
|
|
583
|
+
const details = await sdk.payment.getPaymentDetails({ orderId: 'order-id' });
|
|
584
|
+
const method = details.methods?.[0]; // e.g., iDEAL, Credit Card
|
|
585
|
+
|
|
586
|
+
// 2) Start the payment. The server gives back a URL.
|
|
408
587
|
const response = await sdk.payment.createPayment({
|
|
409
588
|
orderId: 'order-id',
|
|
410
|
-
paymentMethodId:
|
|
589
|
+
paymentMethodId: String(method?.id),
|
|
411
590
|
redirectUrl: 'https://yoursite.com/payment/return',
|
|
412
|
-
customer: {
|
|
413
|
-
firstName: 'John',
|
|
414
|
-
lastName: 'Doe',
|
|
415
|
-
email: 'john@example.com',
|
|
416
|
-
phone: '+31612345678',
|
|
417
|
-
gender: 'Male',
|
|
418
|
-
company: { // Optional
|
|
419
|
-
name: 'Company BV',
|
|
420
|
-
cocNumber: '12345678',
|
|
421
|
-
vatNumber: 'NL123456789B01'
|
|
422
|
-
}
|
|
423
|
-
},
|
|
424
|
-
issuerId: '1234', // Required for bank selection (iDEAL, etc.)
|
|
425
|
-
orderItemId: 'item-id', // Optional
|
|
426
|
-
amountOfTickets: 2, // Optional
|
|
591
|
+
customer: { firstName: 'John', lastName: 'Doe', email: 'john@example.com' },
|
|
427
592
|
});
|
|
428
593
|
|
|
429
|
-
//
|
|
430
|
-
window.
|
|
594
|
+
// 3) Send the visitor to the payment page
|
|
595
|
+
window.location.href = response.paymentUrl;
|
|
431
596
|
```
|
|
432
597
|
|
|
433
598
|
---
|
|
434
599
|
|
|
435
600
|
## Examples
|
|
436
601
|
|
|
437
|
-
|
|
602
|
+
// End-to-end example: Browse → Pick ticket → Pay
|
|
438
603
|
|
|
439
604
|
```typescript
|
|
440
|
-
import { TicketappSDK } from '@ticketapp/sdk';
|
|
605
|
+
import { TicketappSDK, ProductType, SortOrder, EventStatus } from '@ticketapp/sdk';
|
|
606
|
+
import { DateTime } from 'luxon';
|
|
441
607
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
shopId: 'your-shop-id',
|
|
445
|
-
shopSlug: 'your-shop-slug',
|
|
446
|
-
});
|
|
608
|
+
// Create the SDK once
|
|
609
|
+
const sdk = new TicketappSDK({ organizationId: 'your-org-id' });
|
|
447
610
|
|
|
448
|
-
// 1
|
|
449
|
-
await sdk.event.fetchEvents(
|
|
450
|
-
|
|
611
|
+
// 1) List upcoming events for the next month
|
|
612
|
+
const [events] = await sdk.event.fetchEvents({
|
|
613
|
+
statuses: [EventStatus.Active],
|
|
614
|
+
dateRange: { from: DateTime.local(), till: DateTime.local().plus({ months: 1 }) },
|
|
615
|
+
sorts: [{ field: 'startAt', order: SortOrder.Asc }]
|
|
616
|
+
});
|
|
451
617
|
|
|
452
|
-
// 2
|
|
453
|
-
await sdk.event.
|
|
618
|
+
// 2) Let the visitor pick an event, then load its tickets
|
|
619
|
+
const products = await sdk.event.fetchProducts(events[0].id, [ProductType.Ticket]);
|
|
454
620
|
|
|
455
|
-
// 3
|
|
621
|
+
// 3) Add the first ticket to the basket
|
|
456
622
|
await sdk.basket.addProduct({
|
|
457
|
-
id:
|
|
458
|
-
name:
|
|
459
|
-
price:
|
|
460
|
-
serviceFee:
|
|
623
|
+
id: products![0].id,
|
|
624
|
+
name: products![0].name,
|
|
625
|
+
price: products![0].price!,
|
|
626
|
+
serviceFee: products![0].serviceFee ?? 0,
|
|
461
627
|
amount: 1,
|
|
462
628
|
currency: 'EUR',
|
|
463
629
|
});
|
|
464
630
|
|
|
465
|
-
// 4
|
|
466
|
-
const order = sdk.basket.getCurrentOrder()
|
|
467
|
-
|
|
631
|
+
// 4) Ask for payment methods and create a payment
|
|
632
|
+
const order = sdk.basket.getCurrentOrder()!;
|
|
633
|
+
const details = await sdk.payment.getPaymentDetails({ orderId: order.id });
|
|
634
|
+
const method = details.methods?.[0];
|
|
635
|
+
const payment = await sdk.payment.createPayment({
|
|
636
|
+
orderId: order.id,
|
|
637
|
+
paymentMethodId: String(method?.id),
|
|
638
|
+
redirectUrl: 'https://yoursite.com/payment/return',
|
|
639
|
+
});
|
|
640
|
+
|
|
641
|
+
// 5) Redirect the visitor to pay
|
|
642
|
+
window.location.href = payment.paymentUrl;
|
|
468
643
|
```
|
|
469
644
|
|
|
470
|
-
|
|
645
|
+
---
|
|
471
646
|
|
|
472
|
-
|
|
473
|
-
// 1. Fetch available packages
|
|
474
|
-
const packagesResult = await sdk.package.getPackages();
|
|
475
|
-
const selectedPackage = packagesResult.data[0];
|
|
647
|
+
## Services Overview
|
|
476
648
|
|
|
477
|
-
|
|
478
|
-
const itemsResult = await sdk.package.getPackageItems(
|
|
479
|
-
selectedPackage.id,
|
|
480
|
-
['REGULAR']
|
|
481
|
-
);
|
|
649
|
+
Below are the available services with their methods, options, and usage examples.
|
|
482
650
|
|
|
483
|
-
|
|
484
|
-
const items = itemsResult.data.map(item => ({
|
|
485
|
-
packageItemId: item.id,
|
|
486
|
-
eventId: item.activeEvents[0].id // User's selection
|
|
487
|
-
}));
|
|
651
|
+
---
|
|
488
652
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
653
|
+
## EventService
|
|
654
|
+
|
|
655
|
+
Methods:
|
|
656
|
+
- fetchEvents(options?): Promise<[Event[], number]>
|
|
657
|
+
- options.statuses?: EventStatus[]
|
|
658
|
+
- options.hostingIds?: string[]
|
|
659
|
+
- options.dateRange?: { from: DateTime; till: DateTime }
|
|
660
|
+
- options.page?: { index: number; size: number }
|
|
661
|
+
- options.sorts?: { field: string; order: SortOrder }[]
|
|
662
|
+
- fetchEvent(eventId: string): Promise<Event | undefined>
|
|
663
|
+
- fetchProducts(eventId: string, productTypes?: ProductType[], promoCode?: string): Promise<Product[] | undefined>
|
|
664
|
+
|
|
665
|
+
Examples:
|
|
666
|
+
```typescript
|
|
667
|
+
import { DateTime } from 'luxon';
|
|
668
|
+
|
|
669
|
+
// Fetch events with filters and pagination
|
|
670
|
+
const [events, total] = await sdk.event.fetchEvents({
|
|
671
|
+
statuses: ['ACTIVE'],
|
|
672
|
+
hostingIds: ['host-1'],
|
|
673
|
+
dateRange: { from: DateTime.local(), till: DateTime.local().plus({ weeks: 8 }) },
|
|
674
|
+
page: { index: 0, size: 20 },
|
|
675
|
+
sorts: [{ field: 'startAt', order: 'ASC' }],
|
|
499
676
|
});
|
|
677
|
+
|
|
678
|
+
// Fetch a single event
|
|
679
|
+
const event = await sdk.event.fetchEvent('event-id');
|
|
680
|
+
|
|
681
|
+
// Fetch products for an event
|
|
682
|
+
const products = await sdk.event.fetchProducts('event-id', ['TICKET', 'DOOR'], 'PROMO2024');
|
|
500
683
|
```
|
|
501
684
|
|
|
502
|
-
|
|
685
|
+
---
|
|
686
|
+
|
|
687
|
+
## CategoryService
|
|
688
|
+
|
|
689
|
+
Methods:
|
|
690
|
+
- getCategories(): Promise<Category[]>
|
|
691
|
+
- getCategory(categoryId: string): Promise<Category | null>
|
|
503
692
|
|
|
693
|
+
Examples:
|
|
504
694
|
```typescript
|
|
505
|
-
//
|
|
506
|
-
const
|
|
695
|
+
// Fetch all categories
|
|
696
|
+
const categories = await sdk.category.getCategories();
|
|
507
697
|
|
|
508
|
-
//
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
698
|
+
// Fetch a single category
|
|
699
|
+
const category = await sdk.category.getCategory('category-id');
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
---
|
|
512
703
|
|
|
513
|
-
|
|
514
|
-
const selectedMethod = paymentDetails.methods[0];
|
|
704
|
+
## BasketService
|
|
515
705
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
)
|
|
706
|
+
Methods:
|
|
707
|
+
- subscribe(listener: () => void): () => void
|
|
708
|
+
- getCurrentOrder(): { id: string; currency: string; items: OrderItem[]; count: number; expiredAt?: DateTime | null } | null
|
|
709
|
+
- getSelectedPackageEvent(): string[]
|
|
710
|
+
- addProduct(input: ProductInput): Promise<void>
|
|
711
|
+
- removeProduct(input: ProductInput): Promise<void>
|
|
712
|
+
- configurePackage(input: ConfigurePackageInput): Promise<{ error: unknown } | null>
|
|
713
|
+
- configureDelivery(input?: ConfigureDeliveryInput): Promise<void>
|
|
714
|
+
- configureCustomer(input: ConfigureCustomerInput): Promise<void>
|
|
715
|
+
- reserveAdditionalPackageItem(input: ReserveAdditionalPackageItemInput): Promise<{ error: unknown } | null>
|
|
716
|
+
- cancelOrder(): Promise<void>
|
|
717
|
+
- clearOrderFromSession(): void
|
|
521
718
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
{ key: 'phoneNumber', value: '+31612345678' }
|
|
529
|
-
]
|
|
719
|
+
Examples:
|
|
720
|
+
```typescript
|
|
721
|
+
// Subscribe to basket changes
|
|
722
|
+
const unsubscribe = sdk.basket.subscribe(() => {
|
|
723
|
+
const order = sdk.basket.getCurrentOrder();
|
|
724
|
+
console.log('Order updated:', order);
|
|
530
725
|
});
|
|
531
726
|
|
|
532
|
-
//
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
email: 'customer@example.com',
|
|
541
|
-
phone: '+31612345678',
|
|
542
|
-
},
|
|
543
|
-
issuerId: '1234', // If required by payment method
|
|
727
|
+
// Add a product
|
|
728
|
+
await sdk.basket.addProduct({
|
|
729
|
+
id: 'product-id',
|
|
730
|
+
name: 'VIP Ticket',
|
|
731
|
+
price: 50,
|
|
732
|
+
serviceFee: 5,
|
|
733
|
+
amount: 2,
|
|
734
|
+
currency: 'EUR',
|
|
544
735
|
});
|
|
545
736
|
|
|
546
|
-
//
|
|
547
|
-
|
|
737
|
+
// Remove a product
|
|
738
|
+
await sdk.basket.removeProduct({
|
|
739
|
+
id: 'product-id',
|
|
740
|
+
name: 'VIP Ticket',
|
|
741
|
+
currency: 'EUR',
|
|
742
|
+
amount: 1,
|
|
743
|
+
});
|
|
744
|
+
|
|
745
|
+
// Configure a package
|
|
746
|
+
await sdk.basket.configurePackage({
|
|
747
|
+
id: 'package-id',
|
|
748
|
+
name: 'Weekend Pass',
|
|
749
|
+
currency: 'EUR',
|
|
750
|
+
price: 200,
|
|
751
|
+
depositPrice: 200,
|
|
752
|
+
serviceFee: 20,
|
|
753
|
+
amount: 1,
|
|
754
|
+
items: [
|
|
755
|
+
{ packageItemId: 'item-1', eventId: 'event-1' },
|
|
756
|
+
{ packageItemId: 'item-2', eventId: 'event-2' },
|
|
757
|
+
],
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
// Set delivery option
|
|
761
|
+
await sdk.basket.configureDelivery({ id: 'delivery-id', name: 'E-ticket', serviceFee: 0, currency: 'EUR' });
|
|
762
|
+
|
|
763
|
+
// Set customer information
|
|
764
|
+
await sdk.basket.configureCustomer({ email: 'customer@example.com', firstName: 'John', lastName: 'Doe' });
|
|
765
|
+
|
|
766
|
+
// Cancel order
|
|
767
|
+
await sdk.basket.cancelOrder();
|
|
768
|
+
|
|
769
|
+
// Clear session
|
|
770
|
+
sdk.basket.clearOrderFromSession();
|
|
548
771
|
```
|
|
549
772
|
|
|
550
|
-
|
|
773
|
+
---
|
|
774
|
+
|
|
775
|
+
## PackageService
|
|
551
776
|
|
|
777
|
+
Methods:
|
|
778
|
+
- getPackages(options?: { page?: { index?: number; size?: number }; tab?: PackageTabType; statuses?: PackageStatus[] }): Promise<{ count: number; data: any[] } | null>
|
|
779
|
+
- getPackage(packageId: string): Promise<any | null>
|
|
780
|
+
- getPackageItems(packageId: string, types?: PackageItemType[]): Promise<{ count: number; data: any[] } | null>
|
|
781
|
+
|
|
782
|
+
Examples:
|
|
552
783
|
```typescript
|
|
553
|
-
//
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
784
|
+
// Basic
|
|
785
|
+
const result = await sdk.package.getPackages();
|
|
786
|
+
console.log('Total packages:', result?.count);
|
|
787
|
+
console.log('Packages:', result?.data);
|
|
788
|
+
|
|
789
|
+
// With options (pagination, tab, statuses)
|
|
790
|
+
const paged = await sdk.package.getPackages({
|
|
791
|
+
page: { index: 0, size: 20 },
|
|
792
|
+
tab: PackageTabType.Active,
|
|
793
|
+
statuses: [PackageStatus.Active, PackageStatus.Paused],
|
|
558
794
|
});
|
|
795
|
+
console.log('Paged packages:', paged?.data);
|
|
559
796
|
|
|
560
|
-
//
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (state.processing) {
|
|
565
|
-
showLoadingSpinner();
|
|
566
|
-
} else if (state.error) {
|
|
567
|
-
showError(state.error);
|
|
568
|
-
} else {
|
|
569
|
-
displayEvents(state.events);
|
|
570
|
-
}
|
|
571
|
-
});
|
|
797
|
+
// Fetch a single package
|
|
798
|
+
const pkg = await sdk.package.getPackage('package-id');
|
|
799
|
+
console.log('Package:', pkg);
|
|
572
800
|
|
|
573
|
-
//
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
801
|
+
// Fetch package items
|
|
802
|
+
const itemsDefault = await sdk.package.getPackageItems('package-id');
|
|
803
|
+
console.log('Items:', itemsDefault?.data);
|
|
804
|
+
|
|
805
|
+
const items = await sdk.package.getPackageItems('package-id', [
|
|
806
|
+
PackageItemType.Regular,
|
|
807
|
+
PackageItemType.AdditionalEvent,
|
|
808
|
+
]);
|
|
809
|
+
console.log('Filtered items:', items?.data);
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
---
|
|
813
|
+
|
|
814
|
+
## PaymentService
|
|
815
|
+
|
|
816
|
+
Methods:
|
|
817
|
+
- getPaymentDetails(options: { orderId: string; orderItemId?: string; amountOfTickets?: number; paymentMethodId?: string }): Promise<PaymentDetails>
|
|
818
|
+
- createPayment(input: CreatePaymentInput): Promise<{ paymentUrl: string }>
|
|
819
|
+
|
|
820
|
+
Examples:
|
|
821
|
+
```typescript
|
|
822
|
+
// Fetch payment details
|
|
823
|
+
const details = await sdk.payment.getPaymentDetails({ orderId: 'order-id' });
|
|
824
|
+
console.log(details.methods);
|
|
825
|
+
|
|
826
|
+
// Create a payment
|
|
827
|
+
const response = await sdk.payment.createPayment({
|
|
828
|
+
orderId: 'order-id',
|
|
829
|
+
paymentMethodId: '1',
|
|
830
|
+
redirectUrl: 'https://yoursite.com/payment/return',
|
|
831
|
+
customer: { firstName: 'John', lastName: 'Doe', email: 'john@example.com' },
|
|
832
|
+
});
|
|
833
|
+
window.location.href = response.paymentUrl;
|
|
578
834
|
```
|
|
579
835
|
|
|
580
836
|
---
|
|
@@ -587,7 +843,7 @@ The SDK is written in TypeScript and exports all necessary types:
|
|
|
587
843
|
import {
|
|
588
844
|
TicketappSDK,
|
|
589
845
|
ProductInput,
|
|
590
|
-
|
|
846
|
+
ConfigurePackageInput,
|
|
591
847
|
// ... other types
|
|
592
848
|
} from '@ticketapp/sdk';
|
|
593
849
|
```
|
|
@@ -634,49 +890,74 @@ try {
|
|
|
634
890
|
|
|
635
891
|
The SDK automatically manages sessions using `sessionStorage`:
|
|
636
892
|
|
|
637
|
-
- Order ID is stored as `
|
|
893
|
+
- Order ID is stored as `ORDER_ID`
|
|
638
894
|
- Session persists across page reloads
|
|
639
895
|
- Use `sdk.basket.clearOrderFromSession()` to clear
|
|
640
896
|
|
|
641
897
|
---
|
|
642
898
|
|
|
643
|
-
##
|
|
899
|
+
## Tracker (Attribution)
|
|
644
900
|
|
|
645
|
-
|
|
901
|
+
Some marketing tools add a tracker id (for example, when a visitor arrives from a campaign). The SDK helps you keep this id during the visitor’s journey so conversions can be attributed.
|
|
902
|
+
|
|
903
|
+
How it works:
|
|
904
|
+
- The SDK looks for a tracker id in three places (in this order):
|
|
905
|
+
1) Explicitly passed in the SDK config as `trackerId`
|
|
906
|
+
2) The page URL as `?trackerId=abc123`
|
|
907
|
+
3) The browser session storage under `TIC_TRACKER_ID`
|
|
908
|
+
- When found via config or URL, the SDK stores it in `sessionStorage` so it persists across page reloads.
|
|
909
|
+
- The tracker id is automatically sent with Event- and Basket-related calls to the backend when supported, so your analytics remains consistent.
|
|
910
|
+
|
|
911
|
+
Typical ways to use it:
|
|
646
912
|
|
|
647
913
|
```typescript
|
|
914
|
+
// A) Let campaigns append ?trackerId=abc123 to your landing page URL
|
|
915
|
+
// The SDK will pick it up automatically and persist it.
|
|
916
|
+
|
|
917
|
+
// B) Pass it explicitly when creating the SDK (overrides URL/session for the first load)
|
|
648
918
|
const sdk = new TicketappSDK({
|
|
649
|
-
organizationId: 'your-org
|
|
650
|
-
|
|
651
|
-
shopSlug: 'your-shop-slug',
|
|
652
|
-
debug: true, // Enable logging
|
|
919
|
+
organizationId: 'your-org',
|
|
920
|
+
trackerId: 'newsletter-jan',
|
|
653
921
|
});
|
|
922
|
+
|
|
923
|
+
// C) Read the stored value later if you need it (optional)
|
|
924
|
+
const stored = sessionStorage.getItem('TIC_TRACKER_ID');
|
|
925
|
+
console.log('trackerId:', stored);
|
|
654
926
|
```
|
|
655
927
|
|
|
656
|
-
|
|
657
|
-
-
|
|
658
|
-
-
|
|
659
|
-
-
|
|
660
|
-
- `[PaymentService]`
|
|
928
|
+
Notes:
|
|
929
|
+
- If you don’t use trackers, you can ignore this section—everything works without it.
|
|
930
|
+
- If your links already include `?trackerId=...`, no extra setup is needed.
|
|
931
|
+
- For best results, use simple, URL-safe tracker ids (letters, numbers, dashes/underscores).
|
|
661
932
|
|
|
662
933
|
---
|
|
663
934
|
|
|
664
|
-
##
|
|
935
|
+
## Debug Mode
|
|
665
936
|
|
|
666
|
-
|
|
667
|
-
- ES6+
|
|
668
|
-
- Fetch API
|
|
669
|
-
- sessionStorage
|
|
670
|
-
- Promise
|
|
937
|
+
Enable debug mode to see detailed logs:
|
|
671
938
|
|
|
672
|
-
|
|
939
|
+
```typescript
|
|
940
|
+
const sdk = new TicketappSDK({
|
|
941
|
+
organizationId: 'your-org',
|
|
942
|
+
debug: true, // Enable debug logs
|
|
943
|
+
});
|
|
944
|
+
```
|
|
673
945
|
|
|
674
|
-
|
|
946
|
+
- Logs appear in the browser console.
|
|
947
|
+
- Includes request/response details for SDK methods.
|
|
948
|
+
- Great for troubleshooting issues.
|
|
675
949
|
|
|
676
|
-
|
|
950
|
+
Remember to disable or remove debug mode in production to avoid exposing sensitive data in logs.
|
|
677
951
|
|
|
678
952
|
---
|
|
679
953
|
|
|
680
|
-
##
|
|
954
|
+
## FAQ and Troubleshooting
|
|
681
955
|
|
|
682
|
-
|
|
956
|
+
- I reloaded the page and my cart is gone.
|
|
957
|
+
- The basket only restores an order if it still exists on the server and contains valid items. If all items expired or were removed, we clear the session.
|
|
958
|
+
- I see “SOLD_OUT” when adding a ticket.
|
|
959
|
+
- Someone else reserved the last ticket just before you. Try again or pick another product.
|
|
960
|
+
- Prices look different after some time.
|
|
961
|
+
- A promo code may have changed the price or the event’s prices were updated. Refresh products using `sdk.event.fetchProducts(eventId)`.
|
|
962
|
+
- My payment didn’t start.
|
|
963
|
+
- Make sure you picked a payment method from `getPaymentDetails()`. Some methods (like iDEAL) require an issuer/bank id.
|