@bunnyapp/api-client 3.1.0 → 3.2.1

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 CHANGED
@@ -377,35 +377,46 @@ When Bunny sends a webhook request it includes a `x-bunny-signature` header whic
377
377
 
378
378
  Bunny will provide a signing token which you will need to store in your application and use for validating the webhook.
379
379
 
380
+ > **Important:** You must pass the **raw request body** to `validate`, not the parsed `req.body`. The HMAC signature is computed against the exact bytes Bunny sent. If you pass a parsed and re-serialised body, characters like `&`, `<`, and `>` may be encoded differently, causing validation to fail.
381
+
382
+ Use `express.raw()` (or equivalent) to capture the raw body before any JSON parsing:
383
+
380
384
  **TypeScript:**
381
385
 
382
386
  ```typescript
383
- interface WebhookRequest {
384
- headers: {
385
- "x-bunny-signature": string;
386
- };
387
- body: unknown;
388
- }
387
+ import express from "express";
389
388
 
390
- const signature: string = req.headers["x-bunny-signature"];
391
- const payload: unknown = req.body;
392
- const signingToken: string = "<secret signing token>";
389
+ // Mount raw body middleware on your webhook route
390
+ app.use("/webhook", express.raw({ type: "application/json" }));
393
391
 
394
- const valid: boolean = bunny.webhooks.validate(
395
- signature,
396
- payload,
397
- signingToken
398
- );
392
+ app.post("/webhook", (req, res) => {
393
+ const signature: string = req.headers["x-bunny-signature"] as string;
394
+ const rawBody: Buffer = req.body; // Buffer of exact bytes from the wire
395
+ const signingToken: string = "<secret signing token>";
396
+
397
+ const valid: boolean = bunny.webhooks.validate(
398
+ signature,
399
+ rawBody,
400
+ signingToken
401
+ );
402
+ });
399
403
  ```
400
404
 
401
405
  **JavaScript:**
402
406
 
403
407
  ```javascript
404
- const signature = req.headers["x-bunny-signature"];
405
- const payload = req.body;
406
- const signingToken = "<secret signing token>";
408
+ const express = require("express");
409
+
410
+ // Mount raw body middleware on your webhook route
411
+ app.use("/webhook", express.raw({ type: "application/json" }));
407
412
 
408
- const valid = bunny.webhooks.validate(signature, payload, signingToken);
413
+ app.post("/webhook", (req, res) => {
414
+ const signature = req.headers["x-bunny-signature"];
415
+ const rawBody = req.body; // Buffer of exact bytes from the wire
416
+ const signingToken = "<secret signing token>";
417
+
418
+ const valid = bunny.webhooks.validate(signature, rawBody, signingToken);
419
+ });
409
420
  ```
410
421
 
411
422
  ## Test
@@ -1,7 +1,8 @@
1
+ import { Buffer } from 'buffer';
1
2
  declare class Webhooks {
2
3
  private signingToken;
3
4
  constructor(signingToken?: string | null);
4
- validate(signature: string, payload: unknown, signingToken?: string | null): boolean;
5
+ validate(signature: string, payload: string | Buffer, signingToken?: string | null): boolean;
5
6
  }
6
7
  export default Webhooks;
7
8
  //# sourceMappingURL=webhooks.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAGA,cAAM,QAAQ;IACZ,OAAO,CAAC,YAAY,CAAgB;gBAExB,YAAY,GAAE,MAAM,GAAG,IAAW;IAI9C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO;CAsB3F;AAED,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,cAAM,QAAQ;IACZ,OAAO,CAAC,YAAY,CAAgB;gBAExB,YAAY,GAAE,MAAM,GAAG,IAAW;IAI9C,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,YAAY,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO;CAsBnG;AAED,eAAe,QAAQ,CAAC"}
package/dist/webhooks.js CHANGED
@@ -16,7 +16,7 @@ class Webhooks {
16
16
  }
17
17
  const payloadSignature = crypto_1.default
18
18
  .createHmac('sha1', key)
19
- .update(JSON.stringify(payload))
19
+ .update(payload)
20
20
  .digest('hex');
21
21
  const ps = buffer_1.Buffer.from(payloadSignature, 'hex');
22
22
  const s = buffer_1.Buffer.from(signature, 'hex');
@@ -1 +1 @@
1
- {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":";;;;;AAAA,oDAA4B;AAC5B,mCAAgC;AAEhC,MAAM,QAAQ;IAGZ,YAAY,eAA8B,IAAI;QAC5C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,SAAiB,EAAE,OAAgB,EAAE,eAA8B,IAAI;QAC9E,MAAM,GAAG,GAAG,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC;QAE9C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,gBAAgB,GAAG,gBAAM;aAC5B,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC;aACvB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;aAC/B,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,MAAM,EAAE,GAAG,eAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,eAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAExC,uDAAuD;QACvD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,gBAAM,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;CACF;AAED,kBAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":";;;;;AAAA,oDAA4B;AAC5B,mCAAgC;AAEhC,MAAM,QAAQ;IAGZ,YAAY,eAA8B,IAAI;QAC5C,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAED,QAAQ,CAAC,SAAiB,EAAE,OAAwB,EAAE,eAA8B,IAAI;QACtF,MAAM,GAAG,GAAG,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC;QAE9C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,gBAAgB,GAAG,gBAAM;aAC5B,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC;aACvB,MAAM,CAAC,OAAO,CAAC;aACf,MAAM,CAAC,KAAK,CAAC,CAAC;QAEjB,MAAM,EAAE,GAAG,eAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,eAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAExC,uDAAuD;QACvD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAC3B,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,gBAAM,CAAC,eAAe,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACvC,CAAC;CACF;AAED,kBAAe,QAAQ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunnyapp/api-client",
3
- "version": "3.1.0",
3
+ "version": "3.2.1",
4
4
  "description": "Node.js client for Bunny CRM",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",