@unchainedshop/ticketing 4.3.4 → 4.4.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 +168 -0
- package/lib/express.d.ts +0 -1
- package/lib/express.js +3 -4
- package/lib/fastify.d.ts +0 -1
- package/lib/fastify.js +3 -4
- package/lib/index.d.ts +6 -7
- package/lib/index.js +4 -5
- package/lib/magic-key.d.ts +0 -1
- package/lib/magic-key.js +0 -4
- package/lib/mobile-tickets/apple-handler-express.d.ts +1 -2
- package/lib/mobile-tickets/apple-handler-express.js +1 -8
- package/lib/mobile-tickets/apple-handler-fastify.d.ts +0 -1
- package/lib/mobile-tickets/apple-handler-fastify.js +1 -8
- package/lib/mobile-tickets/apple-wallet.d.ts +0 -1
- package/lib/mobile-tickets/apple-wallet.js +0 -1
- package/lib/mobile-tickets/google-handler-express.d.ts +1 -2
- package/lib/mobile-tickets/google-handler-express.js +0 -1
- package/lib/mobile-tickets/google-handler-fastify.d.ts +0 -1
- package/lib/mobile-tickets/google-handler-fastify.js +0 -1
- package/lib/module.d.ts +4 -5
- package/lib/module.js +3 -10
- package/lib/pdf-tickets/print-handler-express.d.ts +1 -2
- package/lib/pdf-tickets/print-handler-express.js +1 -2
- package/lib/pdf-tickets/print-handler-fastify.d.ts +0 -1
- package/lib/pdf-tickets/print-handler-fastify.js +1 -2
- package/lib/services.d.ts +2 -3
- package/lib/services.js +0 -1
- package/lib/template-registry.d.ts +10 -10
- package/lib/template-registry.js +5 -7
- package/lib/types.d.ts +3 -4
- package/lib/types.js +0 -1
- package/package.json +17 -15
- package/lib/express.d.ts.map +0 -1
- package/lib/express.js.map +0 -1
- package/lib/fastify.d.ts.map +0 -1
- package/lib/fastify.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/magic-key.d.ts.map +0 -1
- package/lib/magic-key.js.map +0 -1
- package/lib/mobile-tickets/apple-handler-express.d.ts.map +0 -1
- package/lib/mobile-tickets/apple-handler-express.js.map +0 -1
- package/lib/mobile-tickets/apple-handler-fastify.d.ts.map +0 -1
- package/lib/mobile-tickets/apple-handler-fastify.js.map +0 -1
- package/lib/mobile-tickets/apple-wallet.d.ts.map +0 -1
- package/lib/mobile-tickets/apple-wallet.js.map +0 -1
- package/lib/mobile-tickets/google-handler-express.d.ts.map +0 -1
- package/lib/mobile-tickets/google-handler-express.js.map +0 -1
- package/lib/mobile-tickets/google-handler-fastify.d.ts.map +0 -1
- package/lib/mobile-tickets/google-handler-fastify.js.map +0 -1
- package/lib/module.d.ts.map +0 -1
- package/lib/module.js.map +0 -1
- package/lib/pdf-tickets/print-handler-express.d.ts.map +0 -1
- package/lib/pdf-tickets/print-handler-express.js.map +0 -1
- package/lib/pdf-tickets/print-handler-fastify.d.ts.map +0 -1
- package/lib/pdf-tickets/print-handler-fastify.js.map +0 -1
- package/lib/services.d.ts.map +0 -1
- package/lib/services.js.map +0 -1
- package/lib/template-registry.d.ts.map +0 -1
- package/lib/template-registry.js.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- package/readme.md +0 -118
- package/src/express.ts +0 -35
- package/src/fastify.ts +0 -30
- package/src/index.ts +0 -66
- package/src/magic-key.ts +0 -43
- package/src/mobile-tickets/apple-handler-express.ts +0 -237
- package/src/mobile-tickets/apple-handler-fastify.ts +0 -279
- package/src/mobile-tickets/apple-wallet.ts +0 -31
- package/src/mobile-tickets/google-handler-express.ts +0 -57
- package/src/mobile-tickets/google-handler-fastify.ts +0 -69
- package/src/module.ts +0 -251
- package/src/pdf-tickets/print-handler-express.ts +0 -34
- package/src/pdf-tickets/print-handler-fastify.ts +0 -43
- package/src/services.ts +0 -35
- package/src/template-registry.ts +0 -48
- package/src/types.ts +0 -8
- package/tsconfig.json +0 -10
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
[](https://npmjs.com/package/@unchainedshop/ticketing)
|
|
2
|
+
[](https://opensource.org/licenses/EUPL-1.2)
|
|
3
|
+
|
|
4
|
+
# @unchainedshop/ticketing
|
|
5
|
+
|
|
6
|
+
Event ticketing extension for the Unchained Engine. Provides PDF ticket generation, Apple Wallet passes, Google Wallet passes, and magic key order access.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @unchainedshop/ticketing
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { startPlatform } from '@unchainedshop/platform';
|
|
18
|
+
import setupTicketing, { ticketingModules, ticketingServices } from '@unchainedshop/ticketing';
|
|
19
|
+
import { connect } from '@unchainedshop/api/express';
|
|
20
|
+
|
|
21
|
+
const app = express();
|
|
22
|
+
|
|
23
|
+
const engine = await startPlatform({
|
|
24
|
+
modules: ticketingModules,
|
|
25
|
+
services: ticketingServices,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
connect(app, engine, { corsOrigins: [] });
|
|
29
|
+
|
|
30
|
+
// Setup ticketing with your renderers
|
|
31
|
+
setupTicketing(engine.unchainedAPI, {
|
|
32
|
+
renderOrderPDF,
|
|
33
|
+
createAppleWalletPass,
|
|
34
|
+
createGoogleWalletPass,
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## API Overview
|
|
39
|
+
|
|
40
|
+
### Setup Functions
|
|
41
|
+
|
|
42
|
+
| Export | Description |
|
|
43
|
+
|--------|-------------|
|
|
44
|
+
| `setupTicketing` | Initialize ticketing with all renderers |
|
|
45
|
+
| `setupPDFTickets` | Setup only PDF rendering |
|
|
46
|
+
| `setupMobileTickets` | Setup only wallet passes |
|
|
47
|
+
|
|
48
|
+
### Modules
|
|
49
|
+
|
|
50
|
+
| Export | Description |
|
|
51
|
+
|--------|-------------|
|
|
52
|
+
| `ticketingModules` | Additional modules for ticketing |
|
|
53
|
+
| `ticketingServices` | Additional services for ticketing |
|
|
54
|
+
|
|
55
|
+
### Server Adapters
|
|
56
|
+
|
|
57
|
+
| Import Path | Description |
|
|
58
|
+
|-------------|-------------|
|
|
59
|
+
| `@unchainedshop/ticketing/express` | Express route handlers |
|
|
60
|
+
| `@unchainedshop/ticketing/fastify` | Fastify route handlers |
|
|
61
|
+
|
|
62
|
+
### Renderer Types
|
|
63
|
+
|
|
64
|
+
| Type | Description |
|
|
65
|
+
|------|-------------|
|
|
66
|
+
| `ORDER_PDF` | PDF ticket/receipt rendering |
|
|
67
|
+
| `APPLE_WALLET` | Apple Wallet pass generation |
|
|
68
|
+
| `GOOGLE_WALLET` | Google Wallet pass generation |
|
|
69
|
+
|
|
70
|
+
### Types
|
|
71
|
+
|
|
72
|
+
| Export | Description |
|
|
73
|
+
|--------|-------------|
|
|
74
|
+
| `TicketingAPI` | Ticketing API context type |
|
|
75
|
+
| `TicketingModule` | Module interface type |
|
|
76
|
+
| `TicketingServices` | Services interface type |
|
|
77
|
+
| `RendererTypes` | Renderer type constants |
|
|
78
|
+
|
|
79
|
+
## Apple Wallet Setup
|
|
80
|
+
|
|
81
|
+
1. Add a new Pass Type ID on [developer.apple.com](https://developer.apple.com/account), then generate a production certificate. Download and import into Keychain.
|
|
82
|
+
|
|
83
|
+
2. Export with Keychain: Select "Certificates" tab, select the Pass Type ID, select both ID and key, export in p12 format.
|
|
84
|
+
|
|
85
|
+
3. Convert to PEM (set a PEM passphrase as required):
|
|
86
|
+
```bash
|
|
87
|
+
openssl pkcs12 -in Certificates.p12 -legacy -clcerts -out cert_and_key.pem
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
4. Configure via environment variables:
|
|
91
|
+
```bash
|
|
92
|
+
PASS_CERTIFICATE_PATH=./cert_and_key.pem
|
|
93
|
+
PASS_CERTIFICATE_SECRET=YOUR_PEM_PASSPHRASE
|
|
94
|
+
PASS_TEAM_ID=SSCB95CV6U
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Renderer Implementation
|
|
98
|
+
|
|
99
|
+
### PDF Renderer
|
|
100
|
+
|
|
101
|
+
```tsx
|
|
102
|
+
import React from 'react';
|
|
103
|
+
import ReactPDF, { Document } from '@react-pdf/renderer';
|
|
104
|
+
|
|
105
|
+
const TicketTemplate = ({ tickets }) => (
|
|
106
|
+
<Document>
|
|
107
|
+
{/* Your ticket layout */}
|
|
108
|
+
</Document>
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
export default async ({ orderId, variant }, { modules }) => {
|
|
112
|
+
const order = await modules.orders.findOrder({ orderId });
|
|
113
|
+
// ... prepare data
|
|
114
|
+
return ReactPDF.renderToStream(<TicketTemplate tickets={tickets} />);
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Apple Wallet Renderer
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
import { Template, constants } from '@walletpass/pass-js';
|
|
122
|
+
|
|
123
|
+
export default async (token, unchainedAPI) => {
|
|
124
|
+
const template = new Template('eventTicket', /* ... */);
|
|
125
|
+
const pass = await template.createPass(/* ... */);
|
|
126
|
+
return pass;
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Google Wallet Renderer
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { google } from 'googleapis';
|
|
134
|
+
import jwt from 'jsonwebtoken';
|
|
135
|
+
|
|
136
|
+
export default async (token, unchainedAPI) => {
|
|
137
|
+
// Upsert class and object
|
|
138
|
+
const asURL = async () => createJwtNewObjects(issuerId, productId, token.tokenSerialNumber);
|
|
139
|
+
return { asURL };
|
|
140
|
+
};
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Magic Key Order Access
|
|
144
|
+
|
|
145
|
+
Allow users to access orders and tickets without logging in via a one-time magic key:
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
// Generate magic key
|
|
149
|
+
const magicKey = await modules.passes.buildMagicKey(orderId);
|
|
150
|
+
|
|
151
|
+
// Use in URL: https://my-shop/:orderId?otp=:magicKey
|
|
152
|
+
// Send via x-magic-key HTTP header for API access
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Protected actions: `viewOrder`, `updateToken`, `viewToken`
|
|
156
|
+
|
|
157
|
+
## Environment Variables
|
|
158
|
+
|
|
159
|
+
| Variable | Description |
|
|
160
|
+
|----------|-------------|
|
|
161
|
+
| `UNCHAINED_SECRET` | Required for magic key encryption |
|
|
162
|
+
| `PASS_CERTIFICATE_PATH` | Path to Apple pass certificate |
|
|
163
|
+
| `PASS_CERTIFICATE_SECRET` | PEM passphrase |
|
|
164
|
+
| `PASS_TEAM_ID` | Apple Developer Team ID |
|
|
165
|
+
|
|
166
|
+
## License
|
|
167
|
+
|
|
168
|
+
EUPL-1.2
|
package/lib/express.d.ts
CHANGED
package/lib/express.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import appleWalletHandler from
|
|
3
|
-
import googleWalletHandler from
|
|
4
|
-
import printTicketsHandler from
|
|
2
|
+
import appleWalletHandler from "./mobile-tickets/apple-handler-express.js";
|
|
3
|
+
import googleWalletHandler from "./mobile-tickets/google-handler-express.js";
|
|
4
|
+
import printTicketsHandler from "./pdf-tickets/print-handler-express.js";
|
|
5
5
|
export default (app) => {
|
|
6
6
|
const { APPLE_WALLET_WEBSERVICE_PATH = '/rest/apple-wallet', GOOGLE_WALLET_WEBSERVICE_PATH = '/rest/google-wallet', UNCHAINED_PDF_PRINT_HANDLER_PATH = '/rest/print_tickets', } = process.env;
|
|
7
7
|
app.use(UNCHAINED_PDF_PRINT_HANDLER_PATH, express.json({
|
|
@@ -14,4 +14,3 @@ export default (app) => {
|
|
|
14
14
|
type: 'application/json',
|
|
15
15
|
}), googleWalletHandler);
|
|
16
16
|
};
|
|
17
|
-
//# sourceMappingURL=express.js.map
|
package/lib/fastify.d.ts
CHANGED
package/lib/fastify.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import appleWalletHandler from
|
|
2
|
-
import googleWalletHandler from
|
|
3
|
-
import printTicketsHandler from
|
|
1
|
+
import appleWalletHandler from "./mobile-tickets/apple-handler-fastify.js";
|
|
2
|
+
import googleWalletHandler from "./mobile-tickets/google-handler-fastify.js";
|
|
3
|
+
import printTicketsHandler from "./pdf-tickets/print-handler-fastify.js";
|
|
4
4
|
export default (app) => {
|
|
5
5
|
const { APPLE_WALLET_WEBSERVICE_PATH = '/rest/apple-wallet', GOOGLE_WALLET_WEBSERVICE_PATH = '/rest/google-wallet', UNCHAINED_PDF_PRINT_HANDLER_PATH = '/rest/print_tickets', } = process.env;
|
|
6
6
|
app.route({
|
|
@@ -19,4 +19,3 @@ export default (app) => {
|
|
|
19
19
|
handler: printTicketsHandler,
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
|
-
//# sourceMappingURL=fastify.js.map
|
package/lib/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { RendererTypes } from './template-registry.
|
|
2
|
-
import ticketingModules, { TicketingModule } from './module.
|
|
3
|
-
import { TicketingAPI } from './types.
|
|
4
|
-
import ticketingServices, { TicketingServices } from './services.
|
|
5
|
-
export type { TicketingAPI, RendererTypes };
|
|
6
|
-
export { ticketingServices, ticketingModules
|
|
1
|
+
import { RendererTypes } from './template-registry.ts';
|
|
2
|
+
import ticketingModules, { type TicketingModule } from './module.ts';
|
|
3
|
+
import type { TicketingAPI } from './types.ts';
|
|
4
|
+
import ticketingServices, { type TicketingServices } from './services.ts';
|
|
5
|
+
export type { TicketingAPI, RendererTypes, TicketingModule, TicketingServices };
|
|
6
|
+
export { ticketingServices, ticketingModules };
|
|
7
7
|
export declare function setupPDFTickets({ renderOrderPDF }: {
|
|
8
8
|
renderOrderPDF: any;
|
|
9
9
|
}): void;
|
|
@@ -16,4 +16,3 @@ export default function setupTicketing(unchainedAPI: TicketingAPI, { renderOrder
|
|
|
16
16
|
createAppleWalletPass: any;
|
|
17
17
|
createGoogleWalletPass: any;
|
|
18
18
|
}): void;
|
|
19
|
-
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { subscribe } from '@unchainedshop/events';
|
|
2
2
|
import { WorkerEventTypes } from '@unchainedshop/core-worker';
|
|
3
|
-
import { RendererTypes, registerRenderer } from
|
|
4
|
-
import ticketingModules from
|
|
5
|
-
import setupMagicKey from
|
|
6
|
-
import ticketingServices from
|
|
3
|
+
import { RendererTypes, registerRenderer } from "./template-registry.js";
|
|
4
|
+
import ticketingModules, {} from "./module.js";
|
|
5
|
+
import setupMagicKey from "./magic-key.js";
|
|
6
|
+
import ticketingServices, {} from "./services.js";
|
|
7
7
|
export { ticketingServices, ticketingModules };
|
|
8
8
|
export function setupPDFTickets({ renderOrderPDF }) {
|
|
9
9
|
registerRenderer(RendererTypes.ORDER_PDF, renderOrderPDF);
|
|
@@ -32,4 +32,3 @@ export default function setupTicketing(unchainedAPI, { renderOrderPDF, createApp
|
|
|
32
32
|
}
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
//# sourceMappingURL=index.js.map
|
package/lib/magic-key.d.ts
CHANGED
package/lib/magic-key.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { roles } from '@unchainedshop/api';
|
|
2
2
|
const isMagicKeyValidForOrder = async (obj, { orderId }, { modules, getHeader }) => {
|
|
3
3
|
const order = await modules.orders.findOrder({ orderId });
|
|
4
|
-
// always return true if orderId leads to nothing to show potentially allowed actions
|
|
5
4
|
if (!order)
|
|
6
5
|
return true;
|
|
7
6
|
const magicKey = await modules.passes.buildMagicKey(order._id);
|
|
@@ -10,13 +9,11 @@ const isMagicKeyValidForOrder = async (obj, { orderId }, { modules, getHeader })
|
|
|
10
9
|
const isMagicKeyValidForToken = async (root, params, { modules, getHeader }) => {
|
|
11
10
|
const tokenId = params?.tokenId || (root && 'tokenSerialNumber' in root && root._id) || null;
|
|
12
11
|
const token = await modules.warehousing.findToken({ tokenId });
|
|
13
|
-
// always return true if tokenId leads to nothing to show potentially allowed actions
|
|
14
12
|
if (!token)
|
|
15
13
|
return true;
|
|
16
14
|
const order = await modules.orders.findOrder({ orderId: token.meta.orderId });
|
|
17
15
|
if (!order)
|
|
18
16
|
return false;
|
|
19
|
-
// Restrict access if token does not belong to the original user anymore (for ex. web3 owned)
|
|
20
17
|
if (order.userId !== token.userId)
|
|
21
18
|
return false;
|
|
22
19
|
const magicKey = await modules.passes.buildMagicKey(order._id);
|
|
@@ -27,4 +24,3 @@ export default () => {
|
|
|
27
24
|
roles.allRoles?.ALL?.allow(roles.actions.viewToken, isMagicKeyValidForToken);
|
|
28
25
|
roles.allRoles?.ALL?.allow(roles.actions.updateToken, isMagicKeyValidForToken);
|
|
29
26
|
};
|
|
30
|
-
//# sourceMappingURL=magic-key.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Request, Response } from 'express';
|
|
2
|
-
import { TicketingAPI } from '../types.
|
|
2
|
+
import type { TicketingAPI } from '../types.ts';
|
|
3
3
|
declare const appleWalletHandler: (req: Request & {
|
|
4
4
|
unchainedContext: TicketingAPI;
|
|
5
5
|
}, res: Response) => Promise<void>;
|
|
6
6
|
export default appleWalletHandler;
|
|
7
|
-
//# sourceMappingURL=apple-handler-express.d.ts.map
|
|
@@ -58,10 +58,9 @@ const appleWalletHandler = async (req, res) => {
|
|
|
58
58
|
res.status(500).end();
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
-
const [, apiVersion, endpoint, ...pathComponents] = req.path.split("/");
|
|
61
|
+
const [, apiVersion, endpoint, ...pathComponents] = req.path.split("/");
|
|
62
62
|
if (endpoint === 'devices') {
|
|
63
63
|
if (req.method === 'POST') {
|
|
64
|
-
// Register Device
|
|
65
64
|
const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
|
|
66
65
|
const { pushToken } = req.body;
|
|
67
66
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
@@ -83,7 +82,6 @@ const appleWalletHandler = async (req, res) => {
|
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
else if (req.method === 'GET') {
|
|
86
|
-
// Get the List of Updatable Passes
|
|
87
85
|
const lastUpdated = new Date();
|
|
88
86
|
const [deviceLibraryIdentifier, , passTypeIdentifier] = pathComponents;
|
|
89
87
|
const passesUpdatedSince = req.query?.passesUpdatedSince && new Date(req.query.passesUpdatedSince);
|
|
@@ -97,7 +95,6 @@ const appleWalletHandler = async (req, res) => {
|
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
97
|
else if (req.method === 'DELETE') {
|
|
100
|
-
// Unregister Device
|
|
101
98
|
const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
|
|
102
99
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
103
100
|
if (pass) {
|
|
@@ -106,14 +103,12 @@ const appleWalletHandler = async (req, res) => {
|
|
|
106
103
|
return;
|
|
107
104
|
}
|
|
108
105
|
await modules.passes.unregisterDeviceForAppleWalletPass(passTypeIdentifier, serialNumber, deviceLibraryIdentifier);
|
|
109
|
-
// Unregistered
|
|
110
106
|
res.status(200).end();
|
|
111
107
|
return;
|
|
112
108
|
}
|
|
113
109
|
}
|
|
114
110
|
}
|
|
115
111
|
else if (endpoint === 'log') {
|
|
116
|
-
// Log Mesage
|
|
117
112
|
const { logs } = req.body;
|
|
118
113
|
logs?.forEach((log) => {
|
|
119
114
|
if (typeof log === 'string') {
|
|
@@ -125,7 +120,6 @@ const appleWalletHandler = async (req, res) => {
|
|
|
125
120
|
}
|
|
126
121
|
else if (endpoint === 'passes') {
|
|
127
122
|
if (req.method === 'GET') {
|
|
128
|
-
// Get an updated Pass
|
|
129
123
|
const [passTypeIdentifier, serialNumber] = pathComponents;
|
|
130
124
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
131
125
|
if (!pass) {
|
|
@@ -171,4 +165,3 @@ const appleWalletHandler = async (req, res) => {
|
|
|
171
165
|
res.status(404).end();
|
|
172
166
|
};
|
|
173
167
|
export default appleWalletHandler;
|
|
174
|
-
//# sourceMappingURL=apple-handler-express.js.map
|
|
@@ -67,10 +67,9 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
|
-
const [, apiVersion, endpoint, ...pathComponents] = path.split("/");
|
|
70
|
+
const [, apiVersion, endpoint, ...pathComponents] = path.split("/");
|
|
71
71
|
if (endpoint === 'devices') {
|
|
72
72
|
if (req.method === 'POST') {
|
|
73
|
-
// Register Device
|
|
74
73
|
const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
|
|
75
74
|
const { pushToken } = req.body;
|
|
76
75
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
@@ -97,7 +96,6 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
98
|
else if (req.method === 'GET') {
|
|
100
|
-
// Get the List of Updatable Passes
|
|
101
99
|
const lastUpdated = new Date();
|
|
102
100
|
const [deviceLibraryIdentifier, , passTypeIdentifier] = pathComponents;
|
|
103
101
|
const passesUpdatedSince = req.query?.passesUpdatedSince &&
|
|
@@ -116,7 +114,6 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
116
114
|
return reply.send({ success: true });
|
|
117
115
|
}
|
|
118
116
|
else if (req.method === 'DELETE') {
|
|
119
|
-
// Unregister Device
|
|
120
117
|
const [deviceLibraryIdentifier, , passTypeIdentifier, serialNumber] = pathComponents;
|
|
121
118
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
122
119
|
if (pass) {
|
|
@@ -130,7 +127,6 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
130
127
|
});
|
|
131
128
|
}
|
|
132
129
|
await modules.passes.unregisterDeviceForAppleWalletPass(passTypeIdentifier, serialNumber, deviceLibraryIdentifier);
|
|
133
|
-
// Unregistered
|
|
134
130
|
reply.status(200);
|
|
135
131
|
return reply.send({
|
|
136
132
|
success: true,
|
|
@@ -139,7 +135,6 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
139
135
|
}
|
|
140
136
|
}
|
|
141
137
|
else if (endpoint === 'log') {
|
|
142
|
-
// Log Mesage
|
|
143
138
|
const { logs } = req.body;
|
|
144
139
|
logs?.forEach((log) => {
|
|
145
140
|
if (typeof log === 'string') {
|
|
@@ -153,7 +148,6 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
153
148
|
}
|
|
154
149
|
else if (endpoint === 'passes') {
|
|
155
150
|
if (req.method === 'GET') {
|
|
156
|
-
// Get an updated Pass
|
|
157
151
|
const [passTypeIdentifier, serialNumber] = pathComponents;
|
|
158
152
|
const pass = await modules.passes.findAppleWalletPass(passTypeIdentifier, serialNumber);
|
|
159
153
|
if (!pass) {
|
|
@@ -206,4 +200,3 @@ const appleWalletHandler = async (req, reply) => {
|
|
|
206
200
|
return reply.send();
|
|
207
201
|
};
|
|
208
202
|
export default appleWalletHandler;
|
|
209
|
-
//# sourceMappingURL=apple-handler-fastify.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Request, Response } from 'express';
|
|
2
|
-
import { TicketingAPI } from '../types.
|
|
2
|
+
import type { TicketingAPI } from '../types.ts';
|
|
3
3
|
export declare const googleWalletHandler: (req: Request & {
|
|
4
4
|
unchainedContext: TicketingAPI;
|
|
5
5
|
}, res: Response) => Promise<void>;
|
|
6
6
|
export default googleWalletHandler;
|
|
7
|
-
//# sourceMappingURL=google-handler-express.d.ts.map
|
package/lib/module.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ModuleInput } from '@unchainedshop/mongodb';
|
|
2
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
3
|
-
import { TokenSurrogate } from '@unchainedshop/core-warehousing';
|
|
4
|
-
import { File } from '@unchainedshop/core-files';
|
|
1
|
+
import { type ModuleInput } from '@unchainedshop/mongodb';
|
|
2
|
+
import type { UnchainedCore } from '@unchainedshop/core';
|
|
3
|
+
import type { TokenSurrogate } from '@unchainedshop/core-warehousing';
|
|
4
|
+
import type { File } from '@unchainedshop/core-files';
|
|
5
5
|
export declare const APPLE_WALLET_PASSES_FILE_DIRECTORY = "apple-wallet-passes";
|
|
6
6
|
declare const configurePasses: ({ db }: ModuleInput<Record<string, never>>) => Promise<{
|
|
7
7
|
upsertAppleWalletPass: (token: TokenSurrogate, unchainedAPI: UnchainedCore) => Promise<File>;
|
|
@@ -61,4 +61,3 @@ declare const _default: {
|
|
|
61
61
|
};
|
|
62
62
|
};
|
|
63
63
|
export default _default;
|
|
64
|
-
//# sourceMappingURL=module.d.ts.map
|
package/lib/module.js
CHANGED
|
@@ -2,8 +2,8 @@ import { createLogger } from '@unchainedshop/logger';
|
|
|
2
2
|
import { buildDbIndexes } from '@unchainedshop/mongodb';
|
|
3
3
|
import { MediaObjectsCollection } from '@unchainedshop/core-files';
|
|
4
4
|
import { TokenSurrogateCollection } from '@unchainedshop/core-warehousing';
|
|
5
|
-
import { RendererTypes, getRenderer } from
|
|
6
|
-
import { buildPassBinary, pushToApplePushNotificationService } from
|
|
5
|
+
import { RendererTypes, getRenderer } from "./template-registry.js";
|
|
6
|
+
import { buildPassBinary, pushToApplePushNotificationService } from "./mobile-tickets/apple-wallet.js";
|
|
7
7
|
export const APPLE_WALLET_PASSES_FILE_DIRECTORY = 'apple-wallet-passes';
|
|
8
8
|
const logger = createLogger('unchained:apple-wallet-webservice');
|
|
9
9
|
const configurePasses = async ({ db }) => {
|
|
@@ -25,9 +25,7 @@ const configurePasses = async ({ db }) => {
|
|
|
25
25
|
const upsertAppleWalletPass = async (token, unchainedAPI) => {
|
|
26
26
|
const createAppleWalletPass = getRenderer(RendererTypes.APPLE_WALLET);
|
|
27
27
|
const pass = await createAppleWalletPass(token, unchainedAPI);
|
|
28
|
-
const rawFile = Promise.resolve(
|
|
29
|
-
// wrap in promise to make stream upload work
|
|
30
|
-
await buildPassBinary(token.tokenSerialNumber, pass));
|
|
28
|
+
const rawFile = Promise.resolve(await buildPassBinary(token.tokenSerialNumber, pass));
|
|
31
29
|
const previousFile = await MediaObjects.findOne({
|
|
32
30
|
path: APPLE_WALLET_PASSES_FILE_DIRECTORY,
|
|
33
31
|
'meta.passTypeIdentifier': pass.passTypeIdentifier,
|
|
@@ -49,7 +47,6 @@ const configurePasses = async ({ db }) => {
|
|
|
49
47
|
fileIds: [previousFile._id],
|
|
50
48
|
});
|
|
51
49
|
}
|
|
52
|
-
// Push updates!
|
|
53
50
|
if (registrations?.length) {
|
|
54
51
|
try {
|
|
55
52
|
const pushTokens = registrations.map(({ pushToken }) => pushToken);
|
|
@@ -131,12 +128,10 @@ const configurePasses = async ({ db }) => {
|
|
|
131
128
|
}).toArray();
|
|
132
129
|
const allTokens = await TokenSurrogates.find({}).toArray();
|
|
133
130
|
for (const pass of allPasses) {
|
|
134
|
-
// Check if binary is already invalidated, if so, skip
|
|
135
131
|
const rawData = pass.meta?.rawData;
|
|
136
132
|
if (rawData.invalidatedDate)
|
|
137
133
|
continue;
|
|
138
134
|
const redeemedToken = allTokens.find((t) => t._id === rawData._id && t.invalidatedDate);
|
|
139
|
-
// Find invalidated token for the binary, if found, invalidate binary
|
|
140
135
|
if (redeemedToken) {
|
|
141
136
|
logger.info('Ticket redeemed, void pass', rawData);
|
|
142
137
|
await upsertAppleWalletPass(redeemedToken, unchainedAPI);
|
|
@@ -146,7 +141,6 @@ const configurePasses = async ({ db }) => {
|
|
|
146
141
|
const buildMagicKey = async (orderId) => {
|
|
147
142
|
const msgUint8 = new TextEncoder().encode([orderId, process.env.UNCHAINED_SECRET].join(''));
|
|
148
143
|
const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8);
|
|
149
|
-
// Convert ArrayBuffer to hex string without using Buffer
|
|
150
144
|
return Array.from(new Uint8Array(hashBuffer))
|
|
151
145
|
.map((b) => b.toString(16).padStart(2, '0'))
|
|
152
146
|
.join('');
|
|
@@ -187,4 +181,3 @@ export default {
|
|
|
187
181
|
configure: configurePasses,
|
|
188
182
|
},
|
|
189
183
|
};
|
|
190
|
-
//# sourceMappingURL=module.js.map
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Context } from '@unchainedshop/api';
|
|
1
|
+
import type { Context } from '@unchainedshop/api';
|
|
2
2
|
import type { Request, Response } from 'express';
|
|
3
3
|
export declare function printTicketsHandler(req: Request & {
|
|
4
4
|
unchainedContext: Context;
|
|
5
5
|
}, res: Response): Promise<void>;
|
|
6
6
|
export default printTicketsHandler;
|
|
7
|
-
//# sourceMappingURL=print-handler-express.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkAction } from '@unchainedshop/api/lib/acl.js';
|
|
2
2
|
import { actions } from '@unchainedshop/api/lib/roles/index.js';
|
|
3
|
-
import { RendererTypes, getRenderer } from
|
|
3
|
+
import { RendererTypes, getRenderer } from "../template-registry.js";
|
|
4
4
|
import { createLogger } from '@unchainedshop/logger';
|
|
5
5
|
const logger = createLogger('unchained:ticketing');
|
|
6
6
|
export async function printTicketsHandler(req, res) {
|
|
@@ -22,4 +22,3 @@ export async function printTicketsHandler(req, res) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
export default printTicketsHandler;
|
|
25
|
-
//# sourceMappingURL=print-handler-express.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { checkAction } from '@unchainedshop/api/lib/acl.js';
|
|
2
2
|
import { actions } from '@unchainedshop/api/lib/roles/index.js';
|
|
3
|
-
import { RendererTypes, getRenderer } from
|
|
3
|
+
import { RendererTypes, getRenderer } from "../template-registry.js";
|
|
4
4
|
import { createLogger } from '@unchainedshop/logger';
|
|
5
5
|
const logger = createLogger('unchained:ticketing:print-handler');
|
|
6
6
|
const printTicketsHandler = async (req, reply) => {
|
|
@@ -27,4 +27,3 @@ const printTicketsHandler = async (req, reply) => {
|
|
|
27
27
|
}
|
|
28
28
|
};
|
|
29
29
|
export default printTicketsHandler;
|
|
30
|
-
//# sourceMappingURL=print-handler-fastify.js.map
|
package/lib/services.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TicketingModule } from './module.
|
|
2
|
-
import { Bound, UnchainedCore } from '@unchainedshop/core';
|
|
1
|
+
import type { TicketingModule } from './module.ts';
|
|
2
|
+
import type { Bound, UnchainedCore } from '@unchainedshop/core';
|
|
3
3
|
declare function cancelTicketsForProduct(this: TicketingModule & UnchainedCore['modules'], productId: string): Promise<number>;
|
|
4
4
|
declare const _default: {
|
|
5
5
|
ticketing: {
|
|
@@ -12,4 +12,3 @@ export interface TicketingServices {
|
|
|
12
12
|
cancelTicketsForProduct: Bound<typeof cancelTicketsForProduct>;
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
|
-
//# sourceMappingURL=services.d.ts.map
|
package/lib/services.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
-
import { TokenSurrogate } from '@unchainedshop/core-warehousing';
|
|
1
|
+
import type { UnchainedCore } from '@unchainedshop/core';
|
|
2
|
+
import type { TokenSurrogate } from '@unchainedshop/core-warehousing';
|
|
3
3
|
export type PDFRenderer = ({ orderId, variant, }: {
|
|
4
4
|
orderId: string;
|
|
5
5
|
variant?: string;
|
|
@@ -10,14 +10,14 @@ export type PassRenderer = (token: TokenSurrogate, context: UnchainedCore) => Pr
|
|
|
10
10
|
serialNumber?: string;
|
|
11
11
|
passTypeIdentifier?: string;
|
|
12
12
|
}>;
|
|
13
|
-
export declare
|
|
14
|
-
GOOGLE_WALLET
|
|
15
|
-
APPLE_WALLET
|
|
16
|
-
ORDER_PDF
|
|
17
|
-
}
|
|
13
|
+
export declare const RendererTypes: {
|
|
14
|
+
readonly GOOGLE_WALLET: "google-wallet";
|
|
15
|
+
readonly APPLE_WALLET: "apple-wallet";
|
|
16
|
+
readonly ORDER_PDF: "order";
|
|
17
|
+
};
|
|
18
|
+
export type RendererTypes = (typeof RendererTypes)[keyof typeof RendererTypes];
|
|
18
19
|
export declare const renderers: Map<string, PDFRenderer | PassRenderer>;
|
|
19
|
-
export type RegisterRendererFn = ((type: RendererTypes.ORDER_PDF, renderer: PDFRenderer) => void) & ((type: RendererTypes.GOOGLE_WALLET | RendererTypes.APPLE_WALLET, renderer: PassRenderer) => void);
|
|
20
|
+
export type RegisterRendererFn = ((type: typeof RendererTypes.ORDER_PDF, renderer: PDFRenderer) => void) & ((type: typeof RendererTypes.GOOGLE_WALLET | typeof RendererTypes.APPLE_WALLET, renderer: PassRenderer) => void);
|
|
20
21
|
export declare const registerRenderer: RegisterRendererFn;
|
|
21
|
-
export type GetRendererFn = ((type: RendererTypes.ORDER_PDF) => PDFRenderer) & ((type: RendererTypes.GOOGLE_WALLET | RendererTypes.APPLE_WALLET) => PassRenderer);
|
|
22
|
+
export type GetRendererFn = ((type: typeof RendererTypes.ORDER_PDF) => PDFRenderer) & ((type: typeof RendererTypes.GOOGLE_WALLET | typeof RendererTypes.APPLE_WALLET) => PassRenderer);
|
|
22
23
|
export declare const getRenderer: GetRendererFn;
|
|
23
|
-
//# sourceMappingURL=template-registry.d.ts.map
|
package/lib/template-registry.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
})(RendererTypes || (RendererTypes = {}));
|
|
1
|
+
export const RendererTypes = {
|
|
2
|
+
GOOGLE_WALLET: 'google-wallet',
|
|
3
|
+
APPLE_WALLET: 'apple-wallet',
|
|
4
|
+
ORDER_PDF: 'order',
|
|
5
|
+
};
|
|
7
6
|
export const renderers = new Map();
|
|
8
7
|
export const registerRenderer = function registerRenderer(type, renderer) {
|
|
9
8
|
renderers.set(type, renderer);
|
|
@@ -11,4 +10,3 @@ export const registerRenderer = function registerRenderer(type, renderer) {
|
|
|
11
10
|
export const getRenderer = function getRenderer(type) {
|
|
12
11
|
return renderers.get(type);
|
|
13
12
|
};
|
|
14
|
-
//# sourceMappingURL=template-registry.js.map
|