Skip to content

Commit ac2bed3

Browse files
committed
Add WebhooksHelper.ts
1 parent 0def7b2 commit ac2bed3

File tree

2 files changed

+54
-1
lines changed

2 files changed

+54
-1
lines changed

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * as Square from "./api";
2+
export * as serialization from "./serialization";
23
export { SquareClient } from "./Client";
34
export { SquareEnvironment } from "./environments";
45
export { SquareError, SquareTimeoutError } from "./errors";
5-
export * as serialization from "./serialization";
6+
export { WebhooksHelper } from "./wrapper/WebhooksHelper";

src/wrapper/WebhooksHelper.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { createHmacOverride } from '../core/crypto/createHmacOverride';
2+
import { SquareError } from '../errors';
3+
4+
/**
5+
* Utility to help with {@link https://developer.squareup.com/docs/webhooks/overview Square Webhooks }
6+
*/
7+
export class WebhooksHelper {
8+
/**
9+
* Verifies and validates an event notification.
10+
* See the {@link https://developer.squareup.com/docs/webhooks/step3validate documentation} for more details.
11+
*
12+
* @param requestBody The JSON body of the request.
13+
* @param signatureHeader The value for the `x-square-hmacsha256-signature` header.
14+
* @param signatureKey The signature key from the {@link https://developer.squareup.com/apps Square Developer portal} for the webhook subscription.
15+
* @param notificationUrl The notification endpoint URL as defined in the {@link https://developer.squareup.com/apps Square Developer portal} for the webhook subscription.
16+
* @returns `true` if the signature is valid, indicating that the event can be trusted as it came from Square. `false` if the signature validation fails, indicating that the event did not come from Square, so it may be malicious and should be discarded.
17+
*/
18+
static async verifySignature({
19+
requestBody,
20+
signatureHeader,
21+
signatureKey,
22+
notificationUrl
23+
}: {
24+
requestBody: string,
25+
signatureHeader: string,
26+
signatureKey: string,
27+
notificationUrl: string
28+
}): Promise<boolean> {
29+
if (requestBody == null) {
30+
return false;
31+
}
32+
if (signatureKey == null || signatureKey.length == 0) {
33+
throw new SquareError({
34+
message: 'signatureKey is null or empty'
35+
});
36+
}
37+
if (notificationUrl == null || notificationUrl.length == 0) {
38+
throw new SquareError({
39+
message: 'notificationUrl is null or empty'
40+
});
41+
}
42+
try {
43+
const payload = notificationUrl + requestBody;
44+
const hashBase64 = await createHmacOverride(payload, signatureKey);
45+
return hashBase64 === signatureHeader;
46+
} catch (error) {
47+
throw new SquareError({
48+
message: `Failed to validate webhook signature: ${error instanceof Error ? error.message : String(error)}`
49+
});
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)