@debugged-development/ticketapp-sdk 0.0.3 → 1.0.2
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 +639 -153
- package/dist/graphql/generated.d.ts +320 -1
- package/dist/graphql/generated.d.ts.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1663 -1210
- package/dist/sdk.d.ts +28 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/services/basketService.d.ts +2 -5
- package/dist/services/basketService.d.ts.map +1 -1
- package/dist/services/eventService.d.ts +1 -0
- package/dist/services/eventService.d.ts.map +1 -1
- package/dist/services/packageService.d.ts +60 -0
- package/dist/services/packageService.d.ts.map +1 -0
- package/dist/services/paymentService.d.ts +1 -0
- package/dist/services/paymentService.d.ts.map +1 -1
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,196 +1,682 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ticketapp SDK
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for integrating Ticketapp's event ticketing and package management system into your application.
|
|
2
4
|
|
|
3
5
|
## Installation
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
|
-
npm install @
|
|
8
|
+
npm install @debugged-development/ticketapp-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { TicketappSDK } from '@ticketapp/sdk';
|
|
15
|
+
|
|
16
|
+
const sdk = new TicketappSDK({
|
|
17
|
+
organizationId: 'your-organization-id',
|
|
18
|
+
shopId: 'your-shop-id',
|
|
19
|
+
shopSlug: 'your-shop-slug',
|
|
20
|
+
debug: true, // Enable debug logging (optional)
|
|
21
|
+
});
|
|
7
22
|
```
|
|
8
23
|
|
|
9
|
-
##
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
- [Configuration](#configuration)
|
|
27
|
+
- [Events](#events)
|
|
28
|
+
- [Basket (Cart)](#basket-cart)
|
|
29
|
+
- [Packages](#packages)
|
|
30
|
+
- [Payment](#payment)
|
|
31
|
+
- [Examples](#examples)
|
|
32
|
+
|
|
33
|
+
---
|
|
10
34
|
|
|
11
|
-
|
|
35
|
+
## Configuration
|
|
36
|
+
|
|
37
|
+
### Basic Configuration
|
|
12
38
|
|
|
13
39
|
```typescript
|
|
14
|
-
|
|
15
|
-
|
|
40
|
+
const sdk = new TicketappSDK({
|
|
41
|
+
organizationId: 'eed7fb11-f5c4-4467-8393-6da072b7f752',
|
|
42
|
+
shopId: '1fbdf73d-6ee6-438b-b8e5-a76907a6d76b',
|
|
43
|
+
shopSlug: 'hvrmq',
|
|
44
|
+
debug: true,
|
|
45
|
+
});
|
|
46
|
+
```
|
|
16
47
|
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
useAddToOrderMutation,
|
|
20
|
-
useRemoveFromOrderMutation,
|
|
21
|
-
useConfigurePackageMutation,
|
|
22
|
-
useConfigureOrderDeliveryOptionMutation,
|
|
23
|
-
useCreateOrderCustomerMutation,
|
|
24
|
-
useDeleteOrderMutation,
|
|
25
|
-
} from './order-provider.generated';
|
|
48
|
+
### Advanced Configuration
|
|
26
49
|
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
```typescript
|
|
51
|
+
const sdk = new TicketappSDK({
|
|
52
|
+
organizationId: 'your-organization-id',
|
|
53
|
+
shopId: 'your-shop-id',
|
|
54
|
+
shopSlug: 'your-shop-slug',
|
|
55
|
+
debug: true,
|
|
56
|
+
filteredLocationIds: ['location-id-1', 'location-id-2'], // Optional: Filter events by location
|
|
57
|
+
filteredHostingIds: ['host-id-1', 'host-id-2'], // Optional: Filter events by host
|
|
58
|
+
enableDoorTickets: true, // Optional: Include door tickets
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Events
|
|
65
|
+
|
|
66
|
+
### Fetching Events
|
|
67
|
+
|
|
68
|
+
Load all available events for your organization:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
await sdk.event.fetchEvents();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Subscribing to Event Updates
|
|
75
|
+
|
|
76
|
+
Get real-time updates when events change:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
const unsubscribe = sdk.event.subscribe(() => {
|
|
80
|
+
const state = sdk.event.getState();
|
|
81
|
+
console.log('Events:', state.events);
|
|
82
|
+
console.log('Loading:', state.processing);
|
|
83
|
+
console.log('Error:', state.error);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Later, when you want to stop listening:
|
|
87
|
+
unsubscribe();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Getting Current Event State
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const state = sdk.event.getState();
|
|
94
|
+
|
|
95
|
+
// state structure:
|
|
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
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Fetching Products for an Event
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
// Fetch all ticket types
|
|
108
|
+
await sdk.event.fetchProductsForEvent(
|
|
109
|
+
'event-id',
|
|
110
|
+
['TICKET', 'DOOR', 'ADDON']
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Fetch only regular tickets
|
|
114
|
+
await sdk.event.fetchProductsForEvent(
|
|
115
|
+
'event-id',
|
|
116
|
+
['TICKET']
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Fetch with promo code
|
|
120
|
+
await sdk.event.fetchProductsForEvent(
|
|
121
|
+
'event-id',
|
|
122
|
+
['TICKET'],
|
|
123
|
+
'PROMO2024'
|
|
124
|
+
);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Event Object Structure
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
{
|
|
131
|
+
id: string,
|
|
132
|
+
name: string,
|
|
133
|
+
icon: string | null,
|
|
134
|
+
banner: string | null,
|
|
135
|
+
description: string | null,
|
|
136
|
+
startAt: DateTime, // Luxon DateTime object
|
|
137
|
+
endAt: DateTime,
|
|
138
|
+
timezone: string,
|
|
139
|
+
location: {
|
|
140
|
+
id: string,
|
|
141
|
+
name: string,
|
|
142
|
+
address: string | null
|
|
48
143
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
144
|
+
products: Product[] // Available after fetchProductsForEvent
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Basket (Cart)
|
|
151
|
+
|
|
152
|
+
The basket manages the user's shopping cart and order.
|
|
153
|
+
|
|
154
|
+
### Adding a Product
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
await sdk.basket.addProduct({
|
|
158
|
+
id: 'product-id',
|
|
159
|
+
name: 'VIP Ticket',
|
|
160
|
+
price: 50,
|
|
161
|
+
serviceFee: 5,
|
|
162
|
+
amount: 2,
|
|
163
|
+
currency: 'EUR',
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Adding a Product with Seat Assignment
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
await sdk.basket.addProduct({
|
|
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
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### Removing a Product
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
await sdk.basket.removeProduct({
|
|
189
|
+
id: 'product-id',
|
|
190
|
+
name: 'VIP Ticket',
|
|
191
|
+
currency: 'EUR',
|
|
192
|
+
amount: 1,
|
|
193
|
+
});
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Adding Customer Information
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
await sdk.basket.createCustomer({
|
|
200
|
+
email: 'customer@example.com',
|
|
201
|
+
firstName: 'John',
|
|
202
|
+
lastName: 'Doe',
|
|
203
|
+
age: 30, // Optional
|
|
204
|
+
gender: 'Male', // Optional
|
|
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
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Getting Current Order
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
const order = sdk.basket.getCurrentOrder();
|
|
218
|
+
|
|
219
|
+
// order structure:
|
|
220
|
+
{
|
|
221
|
+
id: string,
|
|
222
|
+
currency: string,
|
|
223
|
+
items: OrderItem[],
|
|
224
|
+
customer: Customer,
|
|
225
|
+
count: number, // Total number of items
|
|
226
|
+
expiredAt: string
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Subscribing to Basket Updates
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
const unsubscribe = sdk.basket.subscribe(() => {
|
|
234
|
+
const order = sdk.basket.getCurrentOrder();
|
|
235
|
+
console.log('Order updated:', order);
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Cleanup
|
|
239
|
+
unsubscribe();
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Canceling an Order
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
await sdk.basket.cancelOrder();
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Clearing Session
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
sdk.basket.clearOrderFromSession();
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Packages
|
|
257
|
+
|
|
258
|
+
Packages are bundled event tickets (e.g., weekend passes, season tickets).
|
|
259
|
+
|
|
260
|
+
### Fetching Packages
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const result = await sdk.package.getPackages();
|
|
264
|
+
|
|
265
|
+
console.log('Total packages:', result.count);
|
|
266
|
+
console.log('Packages:', result.data);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Fetching Package Items
|
|
270
|
+
|
|
271
|
+
Get the individual events/items that make up a package:
|
|
272
|
+
|
|
273
|
+
```typescript
|
|
274
|
+
const result = await sdk.package.getPackageItems(
|
|
275
|
+
'package-id',
|
|
276
|
+
['REGULAR', 'ADDITIONAL_EVENT']
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
console.log('Package items:', result.data);
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Configuring and Adding a Package to Order
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
await sdk.basket.configurePackage({
|
|
286
|
+
id: 'package-id',
|
|
287
|
+
name: 'Weekend Pass',
|
|
288
|
+
currency: 'EUR',
|
|
289
|
+
price: 200,
|
|
290
|
+
depositPrice: 200,
|
|
291
|
+
serviceFee: 20,
|
|
292
|
+
amount: 1, // Number of persons
|
|
293
|
+
items: [
|
|
294
|
+
{
|
|
295
|
+
packageItemId: 'item-1-id',
|
|
296
|
+
eventId: 'event-1-id',
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
packageItemId: 'item-2-id',
|
|
300
|
+
eventId: 'event-2-id',
|
|
301
|
+
}
|
|
302
|
+
]
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Adding Additional Package Items
|
|
307
|
+
|
|
308
|
+
Add extra events to an existing package order:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
const sessionId = sessionStorage.getItem('ORDER_ID_hvrmq');
|
|
312
|
+
|
|
313
|
+
await sdk.package.setAdditionalPackageItem(
|
|
314
|
+
sessionId,
|
|
315
|
+
'package-item-id',
|
|
316
|
+
'event-id',
|
|
317
|
+
1 // amount
|
|
318
|
+
);
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
### Package Object Structure
|
|
322
|
+
|
|
323
|
+
```typescript
|
|
324
|
+
{
|
|
325
|
+
id: string,
|
|
326
|
+
name: string,
|
|
327
|
+
shortDescription: string,
|
|
328
|
+
status: 'ACTIVE' | 'PAUSED' | 'SOLD_OUT' | 'CONCEPT',
|
|
329
|
+
prices: {
|
|
330
|
+
price: number,
|
|
331
|
+
discount: number | null
|
|
52
332
|
},
|
|
333
|
+
amountOfEvents: number,
|
|
334
|
+
maxAmountOfPersonsPerOrder: number | null
|
|
335
|
+
}
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## Payment
|
|
341
|
+
|
|
342
|
+
### Getting Payment Methods
|
|
343
|
+
|
|
344
|
+
Fetch available payment methods for an order:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
const paymentDetails = await sdk.payment.getPaymentMethods({
|
|
348
|
+
orderId: 'order-id',
|
|
349
|
+
orderItemId: 'item-id', // Optional
|
|
350
|
+
amountOfTickets: 2, // Optional
|
|
351
|
+
paymentMethodId: 'method-id' // Optional
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// paymentDetails structure:
|
|
355
|
+
{
|
|
356
|
+
transactionPrice: number,
|
|
357
|
+
baseTransactionFee: number | null,
|
|
358
|
+
additionalTransactionFee: number | null,
|
|
359
|
+
methods: PaymentMethod[]
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Payment Method Structure
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
{
|
|
367
|
+
id: number,
|
|
368
|
+
name: string,
|
|
369
|
+
image: string,
|
|
370
|
+
fee: {
|
|
371
|
+
type: 'FIXED' | 'PERCENTAGE',
|
|
372
|
+
value: number
|
|
373
|
+
} | null,
|
|
374
|
+
issuers: Array<{
|
|
375
|
+
id: number,
|
|
376
|
+
name: string,
|
|
377
|
+
image: string
|
|
378
|
+
}> | null
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
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 }
|
|
53
390
|
};
|
|
54
391
|
|
|
55
|
-
//
|
|
56
|
-
const
|
|
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
|
+
### Creating a Payment
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
const response = await sdk.payment.createPayment({
|
|
409
|
+
orderId: 'order-id',
|
|
410
|
+
paymentMethodId: '1',
|
|
411
|
+
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
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
// Open payment URL
|
|
430
|
+
window.open(response.paymentUrl, '_blank');
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Examples
|
|
436
|
+
|
|
437
|
+
### Complete Event Browsing Flow
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
import { TicketappSDK } from '@ticketapp/sdk';
|
|
441
|
+
|
|
442
|
+
const sdk = new TicketappSDK({
|
|
443
|
+
organizationId: 'your-org-id',
|
|
57
444
|
shopId: 'your-shop-id',
|
|
58
445
|
shopSlug: 'your-shop-slug',
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
await basketService.addProduct({
|
|
82
|
-
id: 'product-123',
|
|
83
|
-
name: 'My Product',
|
|
84
|
-
price: 29.99,
|
|
85
|
-
currency: Currency.EUR,
|
|
86
|
-
amount: 1,
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
return (
|
|
91
|
-
<div>
|
|
92
|
-
<h1>Basket</h1>
|
|
93
|
-
{order && (
|
|
94
|
-
<div>
|
|
95
|
-
<p>Order ID: {order.id}</p>
|
|
96
|
-
<p>Items: {order.items.length}</p>
|
|
97
|
-
</div>
|
|
98
|
-
)}
|
|
99
|
-
<button onClick={handleAddProduct}>Add Product</button>
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// 1. Fetch and display events
|
|
449
|
+
await sdk.event.fetchEvents();
|
|
450
|
+
const { events } = sdk.event.getState();
|
|
451
|
+
|
|
452
|
+
// 2. Load products for selected event
|
|
453
|
+
await sdk.event.fetchProductsForEvent(events[0].id, ['TICKET']);
|
|
454
|
+
|
|
455
|
+
// 3. Add product to basket
|
|
456
|
+
await sdk.basket.addProduct({
|
|
457
|
+
id: events[0].products[0].id,
|
|
458
|
+
name: events[0].products[0].name,
|
|
459
|
+
price: events[0].products[0].price,
|
|
460
|
+
serviceFee: events[0].products[0].serviceFee,
|
|
461
|
+
amount: 1,
|
|
462
|
+
currency: 'EUR',
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// 4. Check basket
|
|
466
|
+
const order = sdk.basket.getCurrentOrder();
|
|
467
|
+
console.log('Items in basket:', order.count);
|
|
103
468
|
```
|
|
104
469
|
|
|
105
|
-
|
|
470
|
+
### Complete Package Purchase Flow
|
|
106
471
|
|
|
107
472
|
```typescript
|
|
108
|
-
|
|
109
|
-
|
|
473
|
+
// 1. Fetch available packages
|
|
474
|
+
const packagesResult = await sdk.package.getPackages();
|
|
475
|
+
const selectedPackage = packagesResult.data[0];
|
|
476
|
+
|
|
477
|
+
// 2. Get package items
|
|
478
|
+
const itemsResult = await sdk.package.getPackageItems(
|
|
479
|
+
selectedPackage.id,
|
|
480
|
+
['REGULAR']
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
// 3. User selects events for each item
|
|
484
|
+
const items = itemsResult.data.map(item => ({
|
|
485
|
+
packageItemId: item.id,
|
|
486
|
+
eventId: item.activeEvents[0].id // User's selection
|
|
487
|
+
}));
|
|
488
|
+
|
|
489
|
+
// 4. Add package to basket
|
|
490
|
+
await sdk.basket.configurePackage({
|
|
491
|
+
id: selectedPackage.id,
|
|
492
|
+
name: selectedPackage.name,
|
|
493
|
+
currency: 'EUR',
|
|
494
|
+
price: selectedPackage.prices.discount ?? selectedPackage.prices.price,
|
|
495
|
+
depositPrice: selectedPackage.prices.discount ?? selectedPackage.prices.price,
|
|
496
|
+
serviceFee: 0,
|
|
497
|
+
amount: 1,
|
|
498
|
+
items: items,
|
|
499
|
+
});
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### Complete Payment Flow
|
|
503
|
+
|
|
504
|
+
```typescript
|
|
505
|
+
// 1. Get current order
|
|
506
|
+
const order = sdk.basket.getCurrentOrder();
|
|
507
|
+
|
|
508
|
+
// 2. Fetch payment methods
|
|
509
|
+
const paymentDetails = await sdk.payment.getPaymentMethods({
|
|
510
|
+
orderId: order.id,
|
|
511
|
+
});
|
|
110
512
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
513
|
+
// 3. User selects payment method
|
|
514
|
+
const selectedMethod = paymentDetails.methods[0];
|
|
515
|
+
|
|
516
|
+
// 4. Calculate total with fees
|
|
517
|
+
const total = sdk.payment.calculateTotalWithFee(
|
|
518
|
+
paymentDetails.transactionPrice,
|
|
519
|
+
selectedMethod
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
// 5. Add customer info if not already added
|
|
523
|
+
await sdk.basket.createCustomer({
|
|
524
|
+
email: 'customer@example.com',
|
|
525
|
+
firstName: 'John',
|
|
526
|
+
lastName: 'Doe',
|
|
527
|
+
extraInfo: [
|
|
528
|
+
{ key: 'phoneNumber', value: '+31612345678' }
|
|
529
|
+
]
|
|
530
|
+
});
|
|
115
531
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
532
|
+
// 6. Create payment
|
|
533
|
+
const paymentResponse = await sdk.payment.createPayment({
|
|
534
|
+
orderId: order.id,
|
|
535
|
+
paymentMethodId: selectedMethod.id.toString(),
|
|
536
|
+
redirectUrl: 'https://yoursite.com/payment/return',
|
|
537
|
+
customer: {
|
|
538
|
+
firstName: 'John',
|
|
539
|
+
lastName: 'Doe',
|
|
540
|
+
email: 'customer@example.com',
|
|
541
|
+
phone: '+31612345678',
|
|
542
|
+
},
|
|
543
|
+
issuerId: '1234', // If required by payment method
|
|
544
|
+
});
|
|
121
545
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
546
|
+
// 7. Redirect to payment page
|
|
547
|
+
window.location.href = paymentResponse.paymentUrl;
|
|
548
|
+
```
|
|
125
549
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
550
|
+
### Reactive UI Updates
|
|
551
|
+
|
|
552
|
+
```typescript
|
|
553
|
+
// Subscribe to basket changes
|
|
554
|
+
const unsubscribeBasket = sdk.basket.subscribe(() => {
|
|
555
|
+
const order = sdk.basket.getCurrentOrder();
|
|
556
|
+
updateBasketIcon(order?.count || 0);
|
|
557
|
+
updateOrderSummary(order);
|
|
558
|
+
});
|
|
135
559
|
|
|
136
|
-
|
|
560
|
+
// Subscribe to event changes
|
|
561
|
+
const unsubscribeEvents = sdk.event.subscribe(() => {
|
|
562
|
+
const state = sdk.event.getState();
|
|
563
|
+
|
|
564
|
+
if (state.processing) {
|
|
565
|
+
showLoadingSpinner();
|
|
566
|
+
} else if (state.error) {
|
|
567
|
+
showError(state.error);
|
|
568
|
+
} else {
|
|
569
|
+
displayEvents(state.events);
|
|
137
570
|
}
|
|
138
|
-
};
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Cleanup when component unmounts
|
|
574
|
+
function cleanup() {
|
|
575
|
+
unsubscribeBasket();
|
|
576
|
+
unsubscribeEvents();
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## TypeScript Support
|
|
583
|
+
|
|
584
|
+
The SDK is written in TypeScript and exports all necessary types:
|
|
585
|
+
|
|
586
|
+
```typescript
|
|
587
|
+
import {
|
|
588
|
+
TicketappSDK,
|
|
589
|
+
ProductInput,
|
|
590
|
+
PackageInput,
|
|
591
|
+
// ... other types
|
|
592
|
+
} from '@ticketapp/sdk';
|
|
139
593
|
```
|
|
140
594
|
|
|
141
|
-
|
|
595
|
+
However, if you prefer to avoid importing types, you can use `any`:
|
|
142
596
|
|
|
143
597
|
```typescript
|
|
144
|
-
|
|
598
|
+
const productInput: any = {
|
|
599
|
+
id: 'product-id',
|
|
600
|
+
name: 'Ticket',
|
|
601
|
+
price: 50,
|
|
602
|
+
// ...
|
|
603
|
+
};
|
|
604
|
+
```
|
|
145
605
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
orderElement.innerHTML = `
|
|
168
|
-
<p>Order ID: ${order.id}</p>
|
|
169
|
-
<p>Items: ${order.items.length}</p>
|
|
170
|
-
`;
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## Error Handling
|
|
609
|
+
|
|
610
|
+
All async methods can throw errors. Always wrap them in try-catch blocks:
|
|
611
|
+
|
|
612
|
+
```typescript
|
|
613
|
+
try {
|
|
614
|
+
await sdk.basket.addProduct(productInput);
|
|
615
|
+
} catch (error) {
|
|
616
|
+
console.error('Failed to add product:', error.message);
|
|
617
|
+
|
|
618
|
+
// Handle specific GraphQL errors
|
|
619
|
+
if (error.response?.errors) {
|
|
620
|
+
const graphQLError = error.response.errors[0];
|
|
621
|
+
console.error('GraphQL error:', graphQLError.message);
|
|
622
|
+
|
|
623
|
+
// Check for specific error codes
|
|
624
|
+
if (graphQLError.extensions?.status === 'SOLD_OUT') {
|
|
625
|
+
alert('This product is sold out');
|
|
626
|
+
}
|
|
171
627
|
}
|
|
172
628
|
}
|
|
173
629
|
```
|
|
174
630
|
|
|
175
|
-
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## Session Management
|
|
634
|
+
|
|
635
|
+
The SDK automatically manages sessions using `sessionStorage`:
|
|
636
|
+
|
|
637
|
+
- Order ID is stored as `ORDER_ID_{shopSlug}`
|
|
638
|
+
- Session persists across page reloads
|
|
639
|
+
- Use `sdk.basket.clearOrderFromSession()` to clear
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## Debug Mode
|
|
644
|
+
|
|
645
|
+
Enable debug mode to see detailed logs:
|
|
646
|
+
|
|
647
|
+
```typescript
|
|
648
|
+
const sdk = new TicketappSDK({
|
|
649
|
+
organizationId: 'your-org-id',
|
|
650
|
+
shopId: 'your-shop-id',
|
|
651
|
+
shopSlug: 'your-shop-slug',
|
|
652
|
+
debug: true, // Enable logging
|
|
653
|
+
});
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
Debug logs will appear in the browser console with prefixes like:
|
|
657
|
+
- `[EventService]`
|
|
658
|
+
- `[BasketService]`
|
|
659
|
+
- `[PackageService]`
|
|
660
|
+
- `[PaymentService]`
|
|
661
|
+
|
|
662
|
+
---
|
|
663
|
+
|
|
664
|
+
## Browser Support
|
|
176
665
|
|
|
177
|
-
|
|
178
|
-
|
|
666
|
+
The SDK works in all modern browsers that support:
|
|
667
|
+
- ES6+
|
|
668
|
+
- Fetch API
|
|
669
|
+
- sessionStorage
|
|
670
|
+
- Promise
|
|
179
671
|
|
|
180
|
-
|
|
181
|
-
Remove a product from the basket.
|
|
672
|
+
---
|
|
182
673
|
|
|
183
|
-
|
|
184
|
-
Configure a package in the basket.
|
|
674
|
+
## License
|
|
185
675
|
|
|
186
|
-
|
|
187
|
-
Set or remove delivery option.
|
|
676
|
+
MIT
|
|
188
677
|
|
|
189
|
-
|
|
190
|
-
Add customer information to the order.
|
|
678
|
+
---
|
|
191
679
|
|
|
192
|
-
|
|
193
|
-
Cancel the current order.
|
|
680
|
+
## Support
|
|
194
681
|
|
|
195
|
-
|
|
196
|
-
Clear the order from session storage and state.
|
|
682
|
+
For issues, questions, or feature requests, please contact support or open an issue on GitHub.
|