@bates-solutions/squareup 0.1.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/LICENSE +21 -0
- package/README.md +154 -0
- package/README.md.backup +292 -0
- package/dist/angular/__tests__/setup.d.ts +1 -0
- package/dist/angular/__tests__/setup.d.ts.map +1 -0
- package/dist/angular/__tests__/setup.js +5 -0
- package/dist/angular/__tests__/setup.js.map +1 -0
- package/dist/angular/components/index.d.ts +2 -0
- package/dist/angular/components/index.d.ts.map +1 -0
- package/dist/angular/components/index.js +2 -0
- package/dist/angular/components/index.js.map +1 -0
- package/dist/angular/components/payment-button.component.d.ts +49 -0
- package/dist/angular/components/payment-button.component.d.ts.map +1 -0
- package/dist/angular/components/payment-button.component.js +176 -0
- package/dist/angular/components/payment-button.component.js.map +1 -0
- package/dist/angular/directives/index.d.ts +2 -0
- package/dist/angular/directives/index.d.ts.map +1 -0
- package/dist/angular/directives/index.js +2 -0
- package/dist/angular/directives/index.js.map +1 -0
- package/dist/angular/directives/square-card.directive.d.ts +52 -0
- package/dist/angular/directives/square-card.directive.d.ts.map +1 -0
- package/dist/angular/directives/square-card.directive.js +98 -0
- package/dist/angular/directives/square-card.directive.js.map +1 -0
- package/dist/angular/index.d.ts +42 -0
- package/dist/angular/index.d.ts.map +1 -0
- package/dist/angular/index.js +45 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/angular/services/index.d.ts +6 -0
- package/dist/angular/services/index.d.ts.map +1 -0
- package/dist/angular/services/index.js +6 -0
- package/dist/angular/services/index.js.map +1 -0
- package/dist/angular/services/square-catalog.service.d.ts +60 -0
- package/dist/angular/services/square-catalog.service.d.ts.map +1 -0
- package/dist/angular/services/square-catalog.service.js +152 -0
- package/dist/angular/services/square-catalog.service.js.map +1 -0
- package/dist/angular/services/square-customers.service.d.ts +77 -0
- package/dist/angular/services/square-customers.service.d.ts.map +1 -0
- package/dist/angular/services/square-customers.service.js +187 -0
- package/dist/angular/services/square-customers.service.js.map +1 -0
- package/dist/angular/services/square-orders.service.d.ts +66 -0
- package/dist/angular/services/square-orders.service.d.ts.map +1 -0
- package/dist/angular/services/square-orders.service.js +170 -0
- package/dist/angular/services/square-orders.service.js.map +1 -0
- package/dist/angular/services/square-payments.service.d.ts +73 -0
- package/dist/angular/services/square-payments.service.d.ts.map +1 -0
- package/dist/angular/services/square-payments.service.js +167 -0
- package/dist/angular/services/square-payments.service.js.map +1 -0
- package/dist/angular/services/square-sdk.service.d.ts +45 -0
- package/dist/angular/services/square-sdk.service.d.ts.map +1 -0
- package/dist/angular/services/square-sdk.service.js +133 -0
- package/dist/angular/services/square-sdk.service.js.map +1 -0
- package/dist/angular/square.module.d.ts +36 -0
- package/dist/angular/square.module.d.ts.map +1 -0
- package/dist/angular/square.module.js +75 -0
- package/dist/angular/square.module.js.map +1 -0
- package/dist/angular/types.d.ts +189 -0
- package/dist/angular/types.d.ts.map +1 -0
- package/dist/angular/types.js +8 -0
- package/dist/angular/types.js.map +1 -0
- package/dist/core/builders/order.builder.d.ts +140 -0
- package/dist/core/builders/order.builder.d.ts.map +1 -0
- package/dist/core/builders/order.builder.js +185 -0
- package/dist/core/builders/order.builder.js.map +1 -0
- package/dist/core/client.d.ts +93 -0
- package/dist/core/client.d.ts.map +1 -0
- package/dist/core/client.js +99 -0
- package/dist/core/client.js.map +1 -0
- package/dist/core/errors.d.ts +55 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +118 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +17 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +18 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/services/catalog.service.d.ts +218 -0
- package/dist/core/services/catalog.service.d.ts.map +1 -0
- package/dist/core/services/catalog.service.js +274 -0
- package/dist/core/services/catalog.service.js.map +1 -0
- package/dist/core/services/customers.service.d.ts +197 -0
- package/dist/core/services/customers.service.d.ts.map +1 -0
- package/dist/core/services/customers.service.js +246 -0
- package/dist/core/services/customers.service.js.map +1 -0
- package/dist/core/services/inventory.service.d.ts +196 -0
- package/dist/core/services/inventory.service.d.ts.map +1 -0
- package/dist/core/services/inventory.service.js +266 -0
- package/dist/core/services/inventory.service.js.map +1 -0
- package/dist/core/services/invoices.service.d.ts +211 -0
- package/dist/core/services/invoices.service.d.ts.map +1 -0
- package/dist/core/services/invoices.service.js +297 -0
- package/dist/core/services/invoices.service.js.map +1 -0
- package/dist/core/services/loyalty.service.d.ts +282 -0
- package/dist/core/services/loyalty.service.d.ts.map +1 -0
- package/dist/core/services/loyalty.service.js +340 -0
- package/dist/core/services/loyalty.service.js.map +1 -0
- package/dist/core/services/orders.service.d.ts +121 -0
- package/dist/core/services/orders.service.d.ts.map +1 -0
- package/dist/core/services/orders.service.js +208 -0
- package/dist/core/services/orders.service.js.map +1 -0
- package/dist/core/services/payments.service.d.ts +121 -0
- package/dist/core/services/payments.service.d.ts.map +1 -0
- package/dist/core/services/payments.service.js +189 -0
- package/dist/core/services/payments.service.js.map +1 -0
- package/dist/core/services/subscriptions.service.d.ts +205 -0
- package/dist/core/services/subscriptions.service.d.ts.map +1 -0
- package/dist/core/services/subscriptions.service.js +265 -0
- package/dist/core/services/subscriptions.service.js.map +1 -0
- package/dist/core/types/index.d.ts +68 -0
- package/dist/core/types/index.d.ts.map +1 -0
- package/dist/core/types/index.js +2 -0
- package/dist/core/types/index.js.map +1 -0
- package/dist/core/utils.d.ts +74 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +96 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/react/SquareProvider.d.ts +50 -0
- package/dist/react/SquareProvider.d.ts.map +1 -0
- package/dist/react/SquareProvider.js +134 -0
- package/dist/react/SquareProvider.js.map +1 -0
- package/dist/react/__tests__/CardInput.test.d.ts +2 -0
- package/dist/react/__tests__/CardInput.test.d.ts.map +1 -0
- package/dist/react/__tests__/CardInput.test.js +218 -0
- package/dist/react/__tests__/CardInput.test.js.map +1 -0
- package/dist/react/__tests__/PaymentButton.test.d.ts +2 -0
- package/dist/react/__tests__/PaymentButton.test.d.ts.map +1 -0
- package/dist/react/__tests__/PaymentButton.test.js +400 -0
- package/dist/react/__tests__/PaymentButton.test.js.map +1 -0
- package/dist/react/__tests__/SquareProvider.test.d.ts +2 -0
- package/dist/react/__tests__/SquareProvider.test.d.ts.map +1 -0
- package/dist/react/__tests__/SquareProvider.test.js +126 -0
- package/dist/react/__tests__/SquareProvider.test.js.map +1 -0
- package/dist/react/__tests__/setup.d.ts +2 -0
- package/dist/react/__tests__/setup.d.ts.map +1 -0
- package/dist/react/__tests__/setup.js +3 -0
- package/dist/react/__tests__/setup.js.map +1 -0
- package/dist/react/__tests__/useCatalog.test.d.ts +2 -0
- package/dist/react/__tests__/useCatalog.test.d.ts.map +1 -0
- package/dist/react/__tests__/useCatalog.test.js +277 -0
- package/dist/react/__tests__/useCatalog.test.js.map +1 -0
- package/dist/react/__tests__/useCustomers.test.d.ts +2 -0
- package/dist/react/__tests__/useCustomers.test.d.ts.map +1 -0
- package/dist/react/__tests__/useCustomers.test.js +312 -0
- package/dist/react/__tests__/useCustomers.test.js.map +1 -0
- package/dist/react/__tests__/useOrders.test.d.ts +2 -0
- package/dist/react/__tests__/useOrders.test.d.ts.map +1 -0
- package/dist/react/__tests__/useOrders.test.js +216 -0
- package/dist/react/__tests__/useOrders.test.js.map +1 -0
- package/dist/react/__tests__/usePayments.test.d.ts +2 -0
- package/dist/react/__tests__/usePayments.test.d.ts.map +1 -0
- package/dist/react/__tests__/usePayments.test.js +235 -0
- package/dist/react/__tests__/usePayments.test.js.map +1 -0
- package/dist/react/__tests__/useSquarePayment.test.d.ts +2 -0
- package/dist/react/__tests__/useSquarePayment.test.d.ts.map +1 -0
- package/dist/react/__tests__/useSquarePayment.test.js +447 -0
- package/dist/react/__tests__/useSquarePayment.test.js.map +1 -0
- package/dist/react/components/CardInput.d.ts +69 -0
- package/dist/react/components/CardInput.d.ts.map +1 -0
- package/dist/react/components/CardInput.js +58 -0
- package/dist/react/components/CardInput.js.map +1 -0
- package/dist/react/components/PaymentButton.d.ts +71 -0
- package/dist/react/components/PaymentButton.d.ts.map +1 -0
- package/dist/react/components/PaymentButton.js +140 -0
- package/dist/react/components/PaymentButton.js.map +1 -0
- package/dist/react/components/index.d.ts +5 -0
- package/dist/react/components/index.d.ts.map +1 -0
- package/dist/react/components/index.js +3 -0
- package/dist/react/components/index.js.map +1 -0
- package/dist/react/hooks/index.d.ts +11 -0
- package/dist/react/hooks/index.d.ts.map +1 -0
- package/dist/react/hooks/index.js +6 -0
- package/dist/react/hooks/index.js.map +1 -0
- package/dist/react/hooks/useCatalog.d.ts +98 -0
- package/dist/react/hooks/useCatalog.d.ts.map +1 -0
- package/dist/react/hooks/useCatalog.js +134 -0
- package/dist/react/hooks/useCatalog.js.map +1 -0
- package/dist/react/hooks/useCustomers.d.ts +105 -0
- package/dist/react/hooks/useCustomers.d.ts.map +1 -0
- package/dist/react/hooks/useCustomers.js +174 -0
- package/dist/react/hooks/useCustomers.js.map +1 -0
- package/dist/react/hooks/useOrders.d.ts +112 -0
- package/dist/react/hooks/useOrders.d.ts.map +1 -0
- package/dist/react/hooks/useOrders.js +115 -0
- package/dist/react/hooks/useOrders.js.map +1 -0
- package/dist/react/hooks/usePayments.d.ts +98 -0
- package/dist/react/hooks/usePayments.d.ts.map +1 -0
- package/dist/react/hooks/usePayments.js +89 -0
- package/dist/react/hooks/usePayments.js.map +1 -0
- package/dist/react/hooks/useSquarePayment.d.ts +52 -0
- package/dist/react/hooks/useSquarePayment.d.ts.map +1 -0
- package/dist/react/hooks/useSquarePayment.js +146 -0
- package/dist/react/hooks/useSquarePayment.js.map +1 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +7 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/types.d.ts +183 -0
- package/dist/react/types.d.ts.map +1 -0
- package/dist/react/types.js +2 -0
- package/dist/react/types.js.map +1 -0
- package/dist/server/index.d.ts +43 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +45 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware/express.d.ts +77 -0
- package/dist/server/middleware/express.d.ts.map +1 -0
- package/dist/server/middleware/express.js +123 -0
- package/dist/server/middleware/express.js.map +1 -0
- package/dist/server/middleware/nextjs.d.ts +118 -0
- package/dist/server/middleware/nextjs.d.ts.map +1 -0
- package/dist/server/middleware/nextjs.js +172 -0
- package/dist/server/middleware/nextjs.js.map +1 -0
- package/dist/server/types.d.ts +89 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +7 -0
- package/dist/server/types.js.map +1 -0
- package/dist/server/webhook.d.ts +114 -0
- package/dist/server/webhook.d.ts.map +1 -0
- package/dist/server/webhook.js +190 -0
- package/dist/server/webhook.js.map +1 -0
- package/package.json +118 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { verifySignature, parseWebhookEvent, processWebhookEvent, SIGNATURE_HEADER, } from '../webhook.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create Express middleware for handling Square webhooks
|
|
4
|
+
*
|
|
5
|
+
* This middleware:
|
|
6
|
+
* 1. Captures the raw body for signature verification
|
|
7
|
+
* 2. Verifies the webhook signature
|
|
8
|
+
* 3. Parses the event and attaches it to the request
|
|
9
|
+
* 4. Calls the appropriate handler
|
|
10
|
+
*
|
|
11
|
+
* @param config - Webhook configuration
|
|
12
|
+
* @returns Express middleware function
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import express from 'express';
|
|
17
|
+
* import { createExpressWebhookHandler } from '@bates-solutions/squareup/server';
|
|
18
|
+
*
|
|
19
|
+
* const app = express();
|
|
20
|
+
*
|
|
21
|
+
* // IMPORTANT: Use raw body parser for webhook route
|
|
22
|
+
* app.use('/webhook', express.raw({ type: 'application/json' }));
|
|
23
|
+
*
|
|
24
|
+
* app.post('/webhook', createExpressWebhookHandler({
|
|
25
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
26
|
+
* handlers: {
|
|
27
|
+
* 'payment.created': async (event) => {
|
|
28
|
+
* console.log('Payment created:', event.data.id);
|
|
29
|
+
* },
|
|
30
|
+
* },
|
|
31
|
+
* }));
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function createExpressWebhookHandler(config) {
|
|
35
|
+
const { autoRespond = true, ...webhookConfig } = config;
|
|
36
|
+
return async (req, res, next) => {
|
|
37
|
+
try {
|
|
38
|
+
// Get raw body - Express with raw() parser stores it as Buffer
|
|
39
|
+
let rawBody;
|
|
40
|
+
if (Buffer.isBuffer(req.body)) {
|
|
41
|
+
rawBody = req.body.toString('utf8');
|
|
42
|
+
}
|
|
43
|
+
else if (typeof req.body === 'string') {
|
|
44
|
+
rawBody = req.body;
|
|
45
|
+
}
|
|
46
|
+
else if (req.rawBody) {
|
|
47
|
+
rawBody = req.rawBody;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Body might be parsed JSON, stringify it (not ideal for signature verification)
|
|
51
|
+
rawBody = JSON.stringify(req.body);
|
|
52
|
+
}
|
|
53
|
+
// Get signature from headers
|
|
54
|
+
const signature = req.headers[SIGNATURE_HEADER];
|
|
55
|
+
if (!signature || Array.isArray(signature)) {
|
|
56
|
+
if (autoRespond) {
|
|
57
|
+
res.status(401).json({ error: 'Missing or invalid signature header' });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
throw new Error('Missing or invalid signature header');
|
|
61
|
+
}
|
|
62
|
+
// Verify signature
|
|
63
|
+
const verification = verifySignature(rawBody, signature, webhookConfig.signatureKey, webhookConfig.notificationUrl);
|
|
64
|
+
if (!verification.valid) {
|
|
65
|
+
if (autoRespond) {
|
|
66
|
+
res.status(401).json({ error: verification.error });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
throw new Error(verification.error);
|
|
70
|
+
}
|
|
71
|
+
// Parse event
|
|
72
|
+
const event = parseWebhookEvent(rawBody);
|
|
73
|
+
// Attach to request for downstream middleware
|
|
74
|
+
req.rawBody = rawBody;
|
|
75
|
+
req.squareEvent = event;
|
|
76
|
+
// Process event with handlers
|
|
77
|
+
await processWebhookEvent(event, webhookConfig);
|
|
78
|
+
// Send success response
|
|
79
|
+
if (autoRespond) {
|
|
80
|
+
res.status(200).json({ received: true, eventId: event.event_id });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
next();
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
if (autoRespond) {
|
|
87
|
+
res.status(500).json({
|
|
88
|
+
error: error instanceof Error ? error.message : 'Webhook processing failed',
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
next(error);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Raw body parser middleware for Express
|
|
98
|
+
*
|
|
99
|
+
* Captures the raw body before JSON parsing for signature verification.
|
|
100
|
+
* Use this if you need to parse JSON but also need the raw body.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* import express from 'express';
|
|
105
|
+
* import { rawBodyMiddleware } from '@bates-solutions/squareup/server';
|
|
106
|
+
*
|
|
107
|
+
* const app = express();
|
|
108
|
+
* app.use('/webhook', rawBodyMiddleware);
|
|
109
|
+
* app.use('/webhook', express.json());
|
|
110
|
+
* ```
|
|
111
|
+
*/
|
|
112
|
+
export const rawBodyMiddleware = (req, _res, next) => {
|
|
113
|
+
const chunks = [];
|
|
114
|
+
req.on('data', (chunk) => {
|
|
115
|
+
chunks.push(chunk);
|
|
116
|
+
});
|
|
117
|
+
req.on('end', () => {
|
|
118
|
+
req.rawBody = Buffer.concat(chunks).toString('utf8');
|
|
119
|
+
next();
|
|
120
|
+
});
|
|
121
|
+
req.on('error', next);
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=express.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/server/middleware/express.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { WebhookConfig, WebhookEvent } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Response type for Next.js webhook handlers
|
|
4
|
+
*/
|
|
5
|
+
export interface WebhookResponse {
|
|
6
|
+
status: number;
|
|
7
|
+
body: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Node.js readable stream interface for raw body reading
|
|
11
|
+
*/
|
|
12
|
+
interface NodeReadable {
|
|
13
|
+
on(event: 'data', listener: (chunk: Buffer) => void): void;
|
|
14
|
+
on(event: 'end', listener: () => void): void;
|
|
15
|
+
on(event: 'error', listener: (err: Error) => void): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Next.js Pages Router request type
|
|
19
|
+
*/
|
|
20
|
+
interface NextPagesRequest extends NodeReadable {
|
|
21
|
+
method?: string;
|
|
22
|
+
headers: Record<string, string | string[] | undefined>;
|
|
23
|
+
body?: unknown;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Next.js Pages Router response type
|
|
27
|
+
*/
|
|
28
|
+
interface NextPagesResponse {
|
|
29
|
+
status: (code: number) => {
|
|
30
|
+
json: (body: unknown) => void;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a Next.js App Router webhook handler
|
|
35
|
+
*
|
|
36
|
+
* @param config - Webhook configuration
|
|
37
|
+
* @returns Route handler for POST requests
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // app/api/webhook/route.ts
|
|
42
|
+
* import { createNextWebhookHandler } from '@bates-solutions/squareup/server';
|
|
43
|
+
*
|
|
44
|
+
* export const POST = createNextWebhookHandler({
|
|
45
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
46
|
+
* handlers: {
|
|
47
|
+
* 'payment.created': async (event) => {
|
|
48
|
+
* console.log('Payment created:', event.data.id);
|
|
49
|
+
* },
|
|
50
|
+
* 'order.fulfillment.updated': async (event) => {
|
|
51
|
+
* await notifyCustomer(event.data.object);
|
|
52
|
+
* },
|
|
53
|
+
* },
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function createNextWebhookHandler(config: WebhookConfig): (request: Request) => Promise<Response>;
|
|
58
|
+
/**
|
|
59
|
+
* Create a Next.js Pages Router API handler
|
|
60
|
+
*
|
|
61
|
+
* @param config - Webhook configuration
|
|
62
|
+
* @returns API route handler
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // pages/api/webhook.ts
|
|
67
|
+
* import { createNextPagesWebhookHandler } from '@bates-solutions/squareup/server';
|
|
68
|
+
*
|
|
69
|
+
* export const config = {
|
|
70
|
+
* api: { bodyParser: false }, // Required for raw body
|
|
71
|
+
* };
|
|
72
|
+
*
|
|
73
|
+
* export default createNextPagesWebhookHandler({
|
|
74
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
75
|
+
* handlers: {
|
|
76
|
+
* 'payment.created': async (event) => {
|
|
77
|
+
* console.log('Payment:', event.data.id);
|
|
78
|
+
* },
|
|
79
|
+
* },
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function createNextPagesWebhookHandler(config: WebhookConfig): (req: NextPagesRequest, res: NextPagesResponse) => Promise<void>;
|
|
84
|
+
/**
|
|
85
|
+
* Utility to parse webhook event from Next.js request
|
|
86
|
+
*
|
|
87
|
+
* Use this for custom handling when you don't want automatic processing
|
|
88
|
+
*
|
|
89
|
+
* @param request - The incoming request
|
|
90
|
+
* @param signatureKey - Your webhook signature key
|
|
91
|
+
* @param notificationUrl - Optional URL for signature verification
|
|
92
|
+
* @returns Parsed webhook event
|
|
93
|
+
* @throws Error if verification fails
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // app/api/webhook/route.ts
|
|
98
|
+
* import { parseNextWebhook } from '@bates-solutions/squareup/server';
|
|
99
|
+
*
|
|
100
|
+
* export async function POST(request: Request) {
|
|
101
|
+
* const event = await parseNextWebhook(
|
|
102
|
+
* request,
|
|
103
|
+
* process.env.SQUARE_WEBHOOK_KEY!
|
|
104
|
+
* );
|
|
105
|
+
*
|
|
106
|
+
* // Custom handling
|
|
107
|
+
* switch (event.type) {
|
|
108
|
+
* case 'payment.created':
|
|
109
|
+
* // ...
|
|
110
|
+
* }
|
|
111
|
+
*
|
|
112
|
+
* return Response.json({ received: true });
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function parseNextWebhook(request: Request, signatureKey: string, notificationUrl?: string): Promise<WebhookEvent>;
|
|
117
|
+
export {};
|
|
118
|
+
//# sourceMappingURL=nextjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../../src/server/middleware/nextjs.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,UAAU,YAAY;IACpB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3D,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC7C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1D;AAED;;GAEG;AACH,UAAU,gBAAiB,SAAQ,YAAY;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,UAAU,iBAAiB;IACzB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK;QAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;KAAE,CAAC;CAC7D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,IAC9C,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CA4CnD;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,aAAa,IACnD,KAAK,gBAAgB,EAAE,KAAK,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC,CA8C5E;AAqBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,YAAY,CAAC,CAoBvB"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { verifySignature, parseWebhookEvent, processWebhookEvent, SIGNATURE_HEADER, } from '../webhook.js';
|
|
2
|
+
/**
|
|
3
|
+
* Create a Next.js App Router webhook handler
|
|
4
|
+
*
|
|
5
|
+
* @param config - Webhook configuration
|
|
6
|
+
* @returns Route handler for POST requests
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // app/api/webhook/route.ts
|
|
11
|
+
* import { createNextWebhookHandler } from '@bates-solutions/squareup/server';
|
|
12
|
+
*
|
|
13
|
+
* export const POST = createNextWebhookHandler({
|
|
14
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
15
|
+
* handlers: {
|
|
16
|
+
* 'payment.created': async (event) => {
|
|
17
|
+
* console.log('Payment created:', event.data.id);
|
|
18
|
+
* },
|
|
19
|
+
* 'order.fulfillment.updated': async (event) => {
|
|
20
|
+
* await notifyCustomer(event.data.object);
|
|
21
|
+
* },
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function createNextWebhookHandler(config) {
|
|
27
|
+
return async (request) => {
|
|
28
|
+
try {
|
|
29
|
+
// Get raw body
|
|
30
|
+
const rawBody = await request.text();
|
|
31
|
+
// Get signature from headers
|
|
32
|
+
const signature = request.headers.get(SIGNATURE_HEADER);
|
|
33
|
+
if (!signature) {
|
|
34
|
+
return Response.json({ error: 'Missing signature header' }, { status: 401 });
|
|
35
|
+
}
|
|
36
|
+
// Verify signature
|
|
37
|
+
const verification = verifySignature(rawBody, signature, config.signatureKey, config.notificationUrl);
|
|
38
|
+
if (!verification.valid) {
|
|
39
|
+
return Response.json({ error: verification.error }, { status: 401 });
|
|
40
|
+
}
|
|
41
|
+
// Parse and process event
|
|
42
|
+
const event = parseWebhookEvent(rawBody);
|
|
43
|
+
await processWebhookEvent(event, config);
|
|
44
|
+
return Response.json({ received: true, eventId: event.event_id }, { status: 200 });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
return Response.json({ error: error instanceof Error ? error.message : 'Webhook processing failed' }, { status: 500 });
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a Next.js Pages Router API handler
|
|
53
|
+
*
|
|
54
|
+
* @param config - Webhook configuration
|
|
55
|
+
* @returns API route handler
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* // pages/api/webhook.ts
|
|
60
|
+
* import { createNextPagesWebhookHandler } from '@bates-solutions/squareup/server';
|
|
61
|
+
*
|
|
62
|
+
* export const config = {
|
|
63
|
+
* api: { bodyParser: false }, // Required for raw body
|
|
64
|
+
* };
|
|
65
|
+
*
|
|
66
|
+
* export default createNextPagesWebhookHandler({
|
|
67
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
68
|
+
* handlers: {
|
|
69
|
+
* 'payment.created': async (event) => {
|
|
70
|
+
* console.log('Payment:', event.data.id);
|
|
71
|
+
* },
|
|
72
|
+
* },
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export function createNextPagesWebhookHandler(config) {
|
|
77
|
+
return async (req, res) => {
|
|
78
|
+
// Only allow POST
|
|
79
|
+
if (req.method !== 'POST') {
|
|
80
|
+
res.status(405).json({ error: 'Method not allowed' });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
try {
|
|
84
|
+
// Get raw body
|
|
85
|
+
const rawBody = await getRawBody(req);
|
|
86
|
+
// Get signature
|
|
87
|
+
const signatureHeader = req.headers[SIGNATURE_HEADER];
|
|
88
|
+
const signature = Array.isArray(signatureHeader)
|
|
89
|
+
? signatureHeader[0]
|
|
90
|
+
: signatureHeader;
|
|
91
|
+
if (!signature) {
|
|
92
|
+
res.status(401).json({ error: 'Missing signature header' });
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Verify signature
|
|
96
|
+
const verification = verifySignature(rawBody, signature, config.signatureKey, config.notificationUrl);
|
|
97
|
+
if (!verification.valid) {
|
|
98
|
+
res.status(401).json({ error: verification.error });
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Parse and process event
|
|
102
|
+
const event = parseWebhookEvent(rawBody);
|
|
103
|
+
await processWebhookEvent(event, config);
|
|
104
|
+
res.status(200).json({ received: true, eventId: event.event_id });
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
res.status(500).json({
|
|
108
|
+
error: error instanceof Error ? error.message : 'Webhook processing failed',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Read raw body from Node.js request stream
|
|
115
|
+
*/
|
|
116
|
+
function getRawBody(req) {
|
|
117
|
+
return new Promise((resolve, reject) => {
|
|
118
|
+
const chunks = [];
|
|
119
|
+
req.on('data', (chunk) => {
|
|
120
|
+
chunks.push(chunk);
|
|
121
|
+
});
|
|
122
|
+
req.on('end', () => {
|
|
123
|
+
resolve(Buffer.concat(chunks).toString('utf8'));
|
|
124
|
+
});
|
|
125
|
+
req.on('error', reject);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Utility to parse webhook event from Next.js request
|
|
130
|
+
*
|
|
131
|
+
* Use this for custom handling when you don't want automatic processing
|
|
132
|
+
*
|
|
133
|
+
* @param request - The incoming request
|
|
134
|
+
* @param signatureKey - Your webhook signature key
|
|
135
|
+
* @param notificationUrl - Optional URL for signature verification
|
|
136
|
+
* @returns Parsed webhook event
|
|
137
|
+
* @throws Error if verification fails
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // app/api/webhook/route.ts
|
|
142
|
+
* import { parseNextWebhook } from '@bates-solutions/squareup/server';
|
|
143
|
+
*
|
|
144
|
+
* export async function POST(request: Request) {
|
|
145
|
+
* const event = await parseNextWebhook(
|
|
146
|
+
* request,
|
|
147
|
+
* process.env.SQUARE_WEBHOOK_KEY!
|
|
148
|
+
* );
|
|
149
|
+
*
|
|
150
|
+
* // Custom handling
|
|
151
|
+
* switch (event.type) {
|
|
152
|
+
* case 'payment.created':
|
|
153
|
+
* // ...
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* return Response.json({ received: true });
|
|
157
|
+
* }
|
|
158
|
+
* ```
|
|
159
|
+
*/
|
|
160
|
+
export async function parseNextWebhook(request, signatureKey, notificationUrl) {
|
|
161
|
+
const rawBody = await request.text();
|
|
162
|
+
const signature = request.headers.get(SIGNATURE_HEADER);
|
|
163
|
+
if (!signature) {
|
|
164
|
+
throw new Error('Missing signature header');
|
|
165
|
+
}
|
|
166
|
+
const verification = verifySignature(rawBody, signature, signatureKey, notificationUrl);
|
|
167
|
+
if (!verification.valid) {
|
|
168
|
+
throw new Error(verification.error ?? 'Signature verification failed');
|
|
169
|
+
}
|
|
170
|
+
return parseWebhookEvent(rawBody);
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=nextjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../../src/server/middleware/nextjs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Square Webhook Event Types
|
|
3
|
+
*
|
|
4
|
+
* @see https://developer.squareup.com/reference/square/webhooks
|
|
5
|
+
*/
|
|
6
|
+
export type PaymentEventType = 'payment.created' | 'payment.updated';
|
|
7
|
+
export type RefundEventType = 'refund.created' | 'refund.updated';
|
|
8
|
+
export type OrderEventType = 'order.created' | 'order.updated' | 'order.fulfillment.updated';
|
|
9
|
+
export type CustomerEventType = 'customer.created' | 'customer.updated' | 'customer.deleted';
|
|
10
|
+
export type SubscriptionEventType = 'subscription.created' | 'subscription.updated';
|
|
11
|
+
export type InvoiceEventType = 'invoice.created' | 'invoice.updated' | 'invoice.published' | 'invoice.payment_made' | 'invoice.canceled';
|
|
12
|
+
export type LoyaltyEventType = 'loyalty.account.created' | 'loyalty.account.updated' | 'loyalty.program.created' | 'loyalty.promotion.created';
|
|
13
|
+
export type CatalogEventType = 'catalog.version.updated';
|
|
14
|
+
export type InventoryEventType = 'inventory.count.updated';
|
|
15
|
+
export type TeamEventType = 'team_member.created' | 'team_member.updated';
|
|
16
|
+
export type LaborEventType = 'labor.timecard.created' | 'labor.timecard.updated';
|
|
17
|
+
/**
|
|
18
|
+
* All Square webhook event types
|
|
19
|
+
*/
|
|
20
|
+
export type WebhookEventType = PaymentEventType | RefundEventType | OrderEventType | CustomerEventType | SubscriptionEventType | InvoiceEventType | LoyaltyEventType | CatalogEventType | InventoryEventType | TeamEventType | LaborEventType;
|
|
21
|
+
/**
|
|
22
|
+
* Base webhook event structure
|
|
23
|
+
*/
|
|
24
|
+
export interface WebhookEvent<T = unknown> {
|
|
25
|
+
/** Unique ID for this event */
|
|
26
|
+
event_id: string;
|
|
27
|
+
/** Merchant ID that triggered the event */
|
|
28
|
+
merchant_id: string;
|
|
29
|
+
/** Type of event */
|
|
30
|
+
type: WebhookEventType;
|
|
31
|
+
/** When the event was created */
|
|
32
|
+
created_at: string;
|
|
33
|
+
/** Event data payload */
|
|
34
|
+
data: {
|
|
35
|
+
/** Type of object in the event */
|
|
36
|
+
type: string;
|
|
37
|
+
/** Unique ID of the object */
|
|
38
|
+
id: string;
|
|
39
|
+
/** The actual object data */
|
|
40
|
+
object: T;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Handler function for webhook events
|
|
45
|
+
*/
|
|
46
|
+
export type WebhookHandler<T = unknown> = (event: WebhookEvent<T>) => void | Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Map of event types to their handlers
|
|
49
|
+
*/
|
|
50
|
+
export type WebhookHandlers = {
|
|
51
|
+
[K in WebhookEventType]?: WebhookHandler;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Configuration for webhook handling
|
|
55
|
+
*/
|
|
56
|
+
export interface WebhookConfig {
|
|
57
|
+
/** Square webhook signature key */
|
|
58
|
+
signatureKey: string;
|
|
59
|
+
/** Event handlers by type */
|
|
60
|
+
handlers: WebhookHandlers;
|
|
61
|
+
/** URL where webhooks are received (for signature verification) */
|
|
62
|
+
notificationUrl?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Whether to throw on signature verification failure
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
throwOnInvalidSignature?: boolean;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Result of webhook verification
|
|
71
|
+
*/
|
|
72
|
+
export interface WebhookVerificationResult {
|
|
73
|
+
/** Whether the signature is valid */
|
|
74
|
+
valid: boolean;
|
|
75
|
+
/** Error message if invalid */
|
|
76
|
+
error?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Parsed webhook request
|
|
80
|
+
*/
|
|
81
|
+
export interface ParsedWebhookRequest {
|
|
82
|
+
/** The raw request body */
|
|
83
|
+
rawBody: string;
|
|
84
|
+
/** The signature from headers */
|
|
85
|
+
signature: string;
|
|
86
|
+
/** Parsed event data */
|
|
87
|
+
event: WebhookEvent;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,MAAM,MAAM,gBAAgB,GAAG,iBAAiB,GAAG,iBAAiB,CAAC;AAGrE,MAAM,MAAM,eAAe,GAAG,gBAAgB,GAAG,gBAAgB,CAAC;AAGlE,MAAM,MAAM,cAAc,GACtB,eAAe,GACf,eAAe,GACf,2BAA2B,CAAC;AAGhC,MAAM,MAAM,iBAAiB,GACzB,kBAAkB,GAClB,kBAAkB,GAClB,kBAAkB,CAAC;AAGvB,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG,sBAAsB,CAAC;AAGpF,MAAM,MAAM,gBAAgB,GACxB,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,sBAAsB,GACtB,kBAAkB,CAAC;AAGvB,MAAM,MAAM,gBAAgB,GACxB,yBAAyB,GACzB,yBAAyB,GACzB,yBAAyB,GACzB,2BAA2B,CAAC;AAGhC,MAAM,MAAM,gBAAgB,GAAG,yBAAyB,CAAC;AAGzD,MAAM,MAAM,kBAAkB,GAAG,yBAAyB,CAAC;AAG3D,MAAM,MAAM,aAAa,GAAG,qBAAqB,GAAG,qBAAqB,CAAC;AAG1E,MAAM,MAAM,cAAc,GAAG,wBAAwB,GAAG,wBAAwB,CAAC;AAEjF;;GAEG;AACH,MAAM,MAAM,gBAAgB,GACxB,gBAAgB,GAChB,eAAe,GACf,cAAc,GACd,iBAAiB,GACjB,qBAAqB,GACrB,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,cAAc,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,GAAG,OAAO;IACvC,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB;IACpB,IAAI,EAAE,gBAAgB,CAAC;IACvB,iCAAiC;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,IAAI,EAAE;QACJ,kCAAkC;QAClC,IAAI,EAAE,MAAM,CAAC;QACb,8BAA8B;QAC9B,EAAE,EAAE,MAAM,CAAC;QACX,6BAA6B;QAC7B,MAAM,EAAE,CAAC,CAAC;KACX,CAAC;CACH;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,GAAG,OAAO,IAAI,CACxC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,KACnB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;KAC3B,CAAC,IAAI,gBAAgB,CAAC,CAAC,EAAE,cAAc;CACzC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,QAAQ,EAAE,eAAe,CAAC;IAC1B,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAC;IACf,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,KAAK,EAAE,YAAY,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { WebhookConfig, WebhookEvent, WebhookVerificationResult, ParsedWebhookRequest } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Header name for Square webhook signature
|
|
4
|
+
*/
|
|
5
|
+
export declare const SIGNATURE_HEADER = "x-square-hmacsha256-signature";
|
|
6
|
+
/**
|
|
7
|
+
* Verify a Square webhook signature using HMAC-SHA256
|
|
8
|
+
*
|
|
9
|
+
* @param rawBody - The raw request body as a string
|
|
10
|
+
* @param signature - The signature from the x-square-hmacsha256-signature header
|
|
11
|
+
* @param signatureKey - Your webhook signature key from Square
|
|
12
|
+
* @param notificationUrl - The URL where the webhook was sent (optional, for additional verification)
|
|
13
|
+
* @returns Verification result with valid flag and optional error
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { verifySignature } from '@bates-solutions/squareup/server';
|
|
18
|
+
*
|
|
19
|
+
* const result = verifySignature(
|
|
20
|
+
* rawBody,
|
|
21
|
+
* req.headers['x-square-hmacsha256-signature'],
|
|
22
|
+
* process.env.SQUARE_WEBHOOK_KEY!
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* if (!result.valid) {
|
|
26
|
+
* return res.status(401).json({ error: result.error });
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifySignature(rawBody: string, signature: string, signatureKey: string, notificationUrl?: string): WebhookVerificationResult;
|
|
31
|
+
/**
|
|
32
|
+
* Parse a webhook request body into a typed event
|
|
33
|
+
*
|
|
34
|
+
* @param rawBody - The raw request body string
|
|
35
|
+
* @returns Parsed webhook event
|
|
36
|
+
* @throws Error if parsing fails
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* const event = parseWebhookEvent(rawBody);
|
|
41
|
+
* console.log(event.type); // 'payment.completed'
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseWebhookEvent(rawBody: string): WebhookEvent;
|
|
45
|
+
/**
|
|
46
|
+
* Parse and verify a webhook request
|
|
47
|
+
*
|
|
48
|
+
* @param rawBody - The raw request body string
|
|
49
|
+
* @param signature - The signature from headers
|
|
50
|
+
* @param signatureKey - Your webhook signature key
|
|
51
|
+
* @param notificationUrl - Optional notification URL for verification
|
|
52
|
+
* @returns Parsed and verified webhook request
|
|
53
|
+
* @throws Error if verification or parsing fails
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const { event } = parseAndVerifyWebhook(
|
|
58
|
+
* rawBody,
|
|
59
|
+
* signature,
|
|
60
|
+
* process.env.SQUARE_WEBHOOK_KEY!
|
|
61
|
+
* );
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export declare function parseAndVerifyWebhook(rawBody: string, signature: string, signatureKey: string, notificationUrl?: string): ParsedWebhookRequest;
|
|
65
|
+
/**
|
|
66
|
+
* Process a webhook event by calling the appropriate handler
|
|
67
|
+
*
|
|
68
|
+
* @param event - The parsed webhook event
|
|
69
|
+
* @param config - Webhook configuration with handlers
|
|
70
|
+
* @returns Promise that resolves when handler completes
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* await processWebhookEvent(event, {
|
|
75
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
76
|
+
* handlers: {
|
|
77
|
+
* 'payment.created': async (event) => {
|
|
78
|
+
* console.log('Payment created:', event.data.id);
|
|
79
|
+
* },
|
|
80
|
+
* },
|
|
81
|
+
* });
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare function processWebhookEvent(event: WebhookEvent, config: WebhookConfig): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Create a webhook handler function that verifies and processes events
|
|
87
|
+
*
|
|
88
|
+
* @param config - Webhook configuration
|
|
89
|
+
* @returns Handler function that processes raw webhook requests
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const handleWebhook = createWebhookProcessor({
|
|
94
|
+
* signatureKey: process.env.SQUARE_WEBHOOK_KEY!,
|
|
95
|
+
* handlers: {
|
|
96
|
+
* 'payment.created': async (event) => {
|
|
97
|
+
* await sendReceipt(event.data.object.payment);
|
|
98
|
+
* },
|
|
99
|
+
* 'order.updated': async (event) => {
|
|
100
|
+
* await updateOrderStatus(event.data.object.order);
|
|
101
|
+
* },
|
|
102
|
+
* },
|
|
103
|
+
* });
|
|
104
|
+
*
|
|
105
|
+
* // Use in your route handler
|
|
106
|
+
* const result = await handleWebhook(rawBody, signature);
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
export declare function createWebhookProcessor(config: WebhookConfig): (rawBody: string, signature: string) => Promise<{
|
|
110
|
+
success: boolean;
|
|
111
|
+
event?: WebhookEvent;
|
|
112
|
+
error?: string;
|
|
113
|
+
}>;
|
|
114
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/server/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,gBAAgB,kCAAkC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,yBAAyB,CA6C3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,CAM/D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,EACpB,eAAe,CAAC,EAAE,MAAM,GACvB,oBAAoB,CActB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,YAAY,EACnB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAMf;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,IAExD,SAAS,MAAM,EACf,WAAW,MAAM,KAChB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA0BvE"}
|