Why back-end methods fail on received webhook but succeed when run manually/supervised

Hello,

I’m tasked with integrating a third-party e-commerce/restaurant platform with WiX for a client (they’re a premium WiX customer). Development went more or less smoothly until we moved on to automatization via webhooks.

I configured the restaurant platform to send webhooks when things change over there (products being added/changed, stock updates, etc) and I put together code to handle this and apply the changes within WiX. The problem is with the following routines: importing/updating products and updating their stock quantities. These functions fail with ‘undefined’ message when a webhook arrives. Yet, when I try to run the same functions with exactly the same parameters as the received webhooks, they work as expected: things get updated/added and there are no errors. It is very frustrating…

The code is quite complex to be presented here. I’ve already sent an email last week to velo-platform at wix.com to no response. I carefully read Velo manuals and forums, googled extensively, scoured stackoverflow for relevant topics, but nothing solved the issue so far. So I’m here to ask how to approach this issue

Hey Max, let’s see what we can do. May I ask you to confirm the following:

  • you have an external app sending data to a Wix endpoint, using Wix-https functions (post/put)?
  • the code on the wix-side results in the “undefined” error;
  • when you run the code outside the http-function it works.

Please negate/confirm above.

Secondly, we all understand that posting complex code here is troublesome. Thing is, when we run into this kind of problems, we try to setup some test function with minimal code, to illustrate the problem to others and getting rid of (for this problem), non-relevant code.

So my question to you is: could you give us some skeleton code which triggers this problem and publish it here? Maybe we see something in the code, maybe we see something that points to a bug (that “undefined” thing has been popping up lately, but, alas, not always due to a bug): all cows are animals, but not all animals are cows.

If you can provide us with some skeleton code and some screen shots of the problem FROM that skeleton code, that would be very useful.

Thank you for prompt reply — I appreciate that!
To answer your questions:

  1. An external app is POSTing data to our WiX endpoint, we’re handling it using wix-https functions
  2. The code on the WiX side results in the “undefined” error
  3. The same data is handled correctly if we run the same code outside the http-function

I will have to clean up the code before I can publish it

I am also going to try and test the hook handling by sending one from my test host using CURL and let you know

Yup, or PostMan, which has better debugging.

Here’s a plot twist: things just started working right after I made this post… Can’t help but think that there WAS an issue on WiX side. While I’m tremendously relieved that it’s fixed now (as I’ve been pulling hair for two long weeks because of that), it still is very frustrating that we might never hear any explanation why and what was broken.

Thank you @giri-zano for taking time to respond.

Nope, today everything’s back to being broken with ‘undefined’ errors. One thing, though:
if I resend exactly the same webhook, which has just failed, with CURL, it’s handled properly and without any errors.

What is this mystery? And can we have someone to take a look into our account?

Max, it’s strange, I am stuck. I will try to bump this up. I especially find it strange that it suddenly started working and then stopped.

What is “undefined” error? What is the exact error log? Can you at least post part of the code (the function declaration, the returns…)

Max, we really need code, so we can see where exactly the undefined occurs. Can you do that? I mean skeleton code.

@mx1 , echoing Giri that we’d definitely be able to help better with a code snippet.

I did have an experience before where webhooks specifically were not firing from a 3rd party, but the endpoint directly did work via Postman. We had come to the conclusion that it was possibly the IP addresses of the 3rd party servers being temporarily blacklisted. Unfortunately, my solution was to use Pipedream to be the middleman between the requests.

So it went 3rd Party Webhook Request :arrow_right: Pipedream to send the message on :arrow_right: Wix HTTP

Ok, sorry about the delay - had to take a break and patch against the latest vulnerability in a ubiquitous logging framework…

I’ve taken time to put together relevant portions of the current code base. It’s a bit inconsistent in style and relies on both async/await and raw promises because I began the project with the latter, but quickly realized that the former suits my needs better.

[Oh wow, turns out pasting code snippets here is rather difficult as parser keeps on seeing URLs in my code. Let’s try with gist then]
https:// gist. github .com/em-ex/9be93e5a2dc4a88e3bc1b781a780ca82

The provided code fails with ‘undefined’ message 99% of times when it’s being called via incoming webhook from the third party platform. Yet it works fine if I execute it within backend or in preview mode with the same parameters. It seems to always work if I resend the same hook from different host using CURL… I’m not sure how the IP address of a third party API endpoint can play any role in this though - the hook DOES arrive, I see all my debug strings in logs.

Please let me know if you spot anything suspicious or need more details. Thanks!

Bump. The problem persists and is driving me insane.
Is anyone able to take a look?

Few comments:

Re line 13:

if(body.verify&&!verifyWebhook(body))

If the verifyWebhook function is a promise (and I can’t tell if it is), you have to wait for it to fulfill.

Re line 18: I think it’ll be better if you use Promise.reject(options) there and handle it in the catch() block.

Re line 22 (not that it’s so important), you have “results” there, but the previous promise returns void (shouldn’t really matter though).

Re line 46: are you sure you haven’t parsed it already on line 12?

@jonatandor35 Thank you so much for taking time to look into this!

RE: verifyWebhook, it is asynchronous. But this portion of the code (http-functions module) runs on raw promises. Do I really need to use await within promise .then/.catch chain?

Also, verification hasn’t failed once during my extensive testing.

RE: line 18, what’s the benefit of using reject there and handling it in .catch? I need to return either ok or serverError, so that third party API doesn’t bombard us with repeated attempts to resend the hook.

RE: line 22, what makes you think it returns void? handlePosterWebhook uses async/await approach and as far as I remember I don’t need to explicitly return await’ed promise.

RE: line 46, no, this is a JSON string that comes in ‘data’ field in some of the webhooks, needs to be parsed separately.

@mx1
re #1, I can’t see how it can work if you’re not waiting for it. The !verifyWebhook(body) will always be true (as it’s always undefined).
re #2, it probably won’t do any change, but you want to break the promise chain and there’s no point in continuing to the next promise (which will fail).
re #3 the handlePosterWebhook will return undefined. But you don’t really care as you don’t do anything with the results as far as I can see (so you can ignore it if you like).

Have you tried to see where the code fails (console.log’s etc…)?

@jonatandor35 So I refactored the webhook receiver function to use async/await and it made it clear that you were right about my if-condition always being true — thank you!

However, the initial problem remains unsolved: when a webhook is received, methods called by the handler ultimately fail with ‘undefined’ message.

Here’s an example from today relevant to the code snipped that I presented earlier: a product name was changed on the other platform, the webhook handler executed updateProduct routine and it errored:

This is where it gets confusing: line 235 (corresponds with line 101 in my gist) lands me on statement which shouldn’t even be executed in the first place, because there are no variants for this product and those conditions can’t be met:

During the testing period, there were other webhook handling errors showing rather strange locations in my code. Like the time when it errored on a line with just a closing parenthesis or a commented out line (I’ll try and screenshot them next time)

I don’t see where you declare the makeProductInfo function, but anyway if it’s asynchronous you have to wait for it as well.

@jonatandor35 It’s not async, it merely converts metadata from one format to another. Is there any benefit of turning it into asynchronous function?

@mx1 No. No need.

Anyway the conditions you posted don’t make sense:

if ((updatedProductData.variants.length && product.manageVariants) 
  || (!updatedProductData.variants.length && product.manageVariants))

This is logically almost equal to if(product.manageVariants) (the only difference is that in your code there will be an error in case updatedProductData doesn’t have the variant property). So what’s the point?

Try to console.log() the results of each step. For example:

console.log(updatedProductData);

Maybe it’ll help you to locate the problem.