@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 +29 -18
- package/dist/webhooks.d.ts +2 -1
- package/dist/webhooks.d.ts.map +1 -1
- package/dist/webhooks.js +1 -1
- package/dist/webhooks.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
384
|
-
headers: {
|
|
385
|
-
"x-bunny-signature": string;
|
|
386
|
-
};
|
|
387
|
-
body: unknown;
|
|
388
|
-
}
|
|
387
|
+
import express from "express";
|
|
389
388
|
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
395
|
-
signature
|
|
396
|
-
|
|
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
|
|
405
|
-
|
|
406
|
-
|
|
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
|
-
|
|
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
|
package/dist/webhooks.d.ts
CHANGED
|
@@ -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:
|
|
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
|
package/dist/webhooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"
|
|
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(
|
|
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');
|
package/dist/webhooks.js.map
CHANGED
|
@@ -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,
|
|
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"}
|