Skip to content

Commit 2595d75

Browse files
committed
refactor(idevaffiliate): use FoxyWebhook validate
1 parent 0e6491f commit 2595d75

File tree

5 files changed

+44
-48
lines changed

5 files changed

+44
-48
lines changed

src/foxy/FoxyWebhook.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ function validFoxyRequest(requestEvent) {
182182
} else if (!verifyWebhookSignature(requestEvent)) {
183183
err = 'Forbidden';
184184
}
185+
try {
186+
JSON.parse(requestEvent.body);
187+
} catch (e) {
188+
console.log('body' , requestEvent.body);
189+
err = 'Payload is not valid JSON.';
190+
}
185191
return err;
186192
}
187193

src/functions/idevaffiliate-marketplace/idevaffiliate-marketplace.js

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
require("dotenv").config();
22
const config = require("../../../config.js");
33
const fetch = require("node-fetch");
4+
const FoxyWebhook = require("../../foxy/FoxyWebhook.js");
45

56
const { URLSearchParams } = require("url");
67
const { FoxyApi } = require("@foxy.io/node-api");
78

8-
const foxy = new FoxyApi();
9-
const store = foxy.follow("fx:store");
109

1110
const idevApiUrl = config.idevAffiliate.apiUrl || "";
1211
const idevSecretKey = config.idevAffiliate.secretKey || "";
1312
const foxyWebhookEncryptionKey = config.foxy.webhook.encryptionKey || "";
1413

14+
const getFoxyApi = () => new FoxyApi();
15+
1516
const getAffiliateIdFromProduct = (productCode) => {
1617
if (productCode.match(/\-a(\d+)$/i)) {
1718
return productCode.match(/\-a(\d+)$/i)[1];
@@ -27,12 +28,10 @@ const pushToIdev = async (item, webhook) => {
2728
if (!item.name || !item.code || !item.price) {
2829
return false;
2930
}
30-
3131
const params = new URLSearchParams();
3232
params.append("affiliate_id", getAffiliateIdFromProduct(item.code));
3333
params.append("idev_saleamt", item.price);
3434
params.append("idev_ordernum", webhook.id);
35-
3635
// TODO: Check an existing attribute to see if this has already been done.
3736
// Upsert a Foxy API attribute on the product after pushing so it's not duplicated
3837
// with a re-run of the webhook.
@@ -62,43 +61,23 @@ const processTransaction = async (message) => {
6261
*/
6362

6463
exports.handler = async (event, context) => {
65-
// Verify the Foxy webhook is valid
66-
const foxyWebhookIsVerified = FoxyApi.webhook.verify({
67-
signature: event.headers["foxy-webhook-signature"],
68-
payload: event.body,
69-
key: config.foxy.webhook.encryptionKey,
70-
});
71-
72-
// Parse the body
73-
let payload;
74-
try {
75-
payload = JSON.parse(event.body);
76-
} catch (error) {
77-
console.log("ERROR: Payload is not a valid Foxy webhook.");
78-
return {
79-
statusCode: 400,
80-
body: JSON.stringify({ message: "Cannot parse body." }),
81-
};
64+
const foxy = getFoxyApi();
65+
const err = FoxyWebhook.validFoxyRequest(event);
66+
if (err) {
67+
return FoxyWebhook.response(err);
8268
}
83-
69+
const payload = JSON.parse(event.body);
8470
// Make sure everything looks ok
8571
if (
86-
!foxyWebhookIsVerified ||
8772
event.headers["foxy-webhook-event"] !== "transaction/created" ||
8873
!payload._embedded ||
8974
!payload._embedded["fx:items"] ||
9075
!payload._embedded["fx:items"].length > 0
9176
) {
92-
console.log("ERROR: Payload is not a valid Foxy webhook.");
93-
return {
94-
statusCode: 400,
95-
body: JSON.stringify({ message: "Invalid signature." }),
96-
};
77+
return FoxyWebhook.response("Invalid payload.");
9778
}
98-
9979
return processTransaction(payload)
10080
.then((data) => {
101-
console.log(data);
10281
return {
10382
statusCode: 200,
10483
body: JSON.stringify({ message: "success." }),

test/functions/datastore-integration-orderdesk/index.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe("Order Desk Pre-payment Webhook", function() {
5353
});
5454

5555
it ("Should return a Foxy Prepayment Webhook Response", async function () {
56-
const responsePromise = odHandler.handler();
56+
const responsePromise = odHandler.handler('');
5757
expect(responsePromise).to.be.a("Promise");
5858
const response = await responsePromise;
5959
expect(response.statusCode).to.exist;

test/functions/datastore-integration-webflow/index.test.js

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ describe("Initialize and validate the webhook", () => {
6262
config.datastore.provider.webflow.token = undefined;
6363
await prePayment.handler(null, null, noToken);
6464
config.datastore.provider.webflow.token = "FOOBAR";
65-
await prePayment.handler(null, null, withToken);
65+
await prePayment.handler({}, null, withToken);
6666
});
6767

6868
it("Extracts the items from FoxyCart payload", async () => {
@@ -453,22 +453,6 @@ describe("Verifies the price of an item in a Webflow collection", () => {
453453
});
454454
});
455455

456-
it("Returns Bad Request when no body is provided", async () => {
457-
let response;
458-
const event = MockFoxyRequests.validRequest();
459-
injectedWebflow.items = () =>
460-
Promise.resolve(
461-
mockWebflow.arbitrary(JSON.parse(event.body)._embedded["fx:items"])({}, {})
462-
);
463-
delete event.body;
464-
response = await prePayment.handler(event);
465-
expect(response.statusCode).to.equal(400);
466-
expect(JSON.parse(response.body)).to.deep.equal({
467-
details: "Empty request.",
468-
ok: false,
469-
});
470-
});
471-
472456
it("Returns Rate limit exceeded when Webflow limit is exceeded", async () => {
473457
let response;
474458
const event = mockFoxyCart.request();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,28 @@
1+
const { after, afterEach, before, beforeEach, describe, it } = require("mocha");
2+
const {expect} = require("chai");
3+
const rewire = require("rewire");
14

5+
6+
const chaiHttp = require('chai-http');
7+
const handler = rewire('../../../src/functions/idevaffiliate-marketplace/idevaffiliate-marketplace.js');
8+
const config = handler.__get__('config');
9+
10+
11+
12+
function setConfig() {
13+
}
14+
15+
describe("Idev Affiliate", function() {
16+
17+
before(
18+
function () {
19+
config.foxy.api.clientId = 'foo';
20+
}
21+
);
22+
23+
it ("Should require Foxy Client Id", async function () {
24+
expect(async () => {await handler({})}).to.throw;
25+
});
26+
27+
28+
});

0 commit comments

Comments
 (0)