Webhooks subscription throwing error

zoultrex
Tourist
18 0 2

I'm following the tutorial here: https://developers.shopify.com/tutorials/build-a-shopify-app-with-node-and-react/listen-for-store-ev...

Maybe I missed some part of the tutorial, but I'm getting the following error:

Failed to register createOrderWebhook webhook { data:
   { webhookSubscriptionCreate: { userErrors: [Array], webhookSubscription: null } },
  extensions:
   { cost:
      { requestedQueryCost: 10,
        actualQueryCost: 10,
        throttleStatus: [Object] } } }

Why such an error would happen? Also, how do I grab the userErrors: [Array] to inspect whats inside?

Replies 18 (18)

jennifergray
Shopify Staff
1 0 0

Hi @zoultrex ,

 

To get a better idea of where your error is coming from, you can inspect what's inside the usersError array with a console.log which would look something like this:

console.log(registration.result.data.webhookSubscriptionCreate.userErrors);

This should provide you with an error message to help you out with debugging.

Jennifer

To learn more visit the Shopify Help Center or the Community Blog.

zoultrex
Tourist
18 0 2

Thanks Jennifer, it was because I was not using https on my registerWebhook call...
But now I'm having a new error:

userErrors [ { field: [ 'webhookSubscription', 'callbackUrl' ],
    message: 'Address for this topic has already been taken' } ]

That error makes sense because I have tried this many times before and maybe the subscription have gone through without me realizing...
But the weird thing is that I'm not receiving any test messages.

I'm  using the shop admin notification page (https://[shop].myshopify.com/admin/settings/notifications) to send the test hooks but no event comes through, but ngrok is accusing traffic change and printing this response when I click send test notification: 

POST /                                                         302 Found  

Does it means theres a message coming through but the server is not handling it?

zoultrex
Tourist
18 0 2

BTW here is my server code, which I made based on the main app building tutorial (https://developers.shopify.com/tutorials/build-a-shopify-app-with-node-and-react/listen-for-store-ev...)

require('isomorphic-fetch');
const dotenv = require('dotenv');
const Koa = require('koa');
const next = require('next');
const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
const { verifyRequest } = require('@shopify/koa-shopify-auth');
const session = require('koa-session');
//webhooks
const Router = require('koa-router')
const {receiveWebhook, registerWebhook} = require('@shopify/koa-shopify-webhooks');


dotenv.config();
const { default: graphQLProxy } = require('@shopify/koa-shopify-graphql-proxy');
const { ApiVersion } = require('@shopify/koa-shopify-graphql-proxy');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();

const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;

app.prepare().then(() => {
    const server = new Koa();
    server.use(session(server));
    server.keys = [SHOPIFY_API_SECRET_KEY];
    //webhooks
    const router = new Router();
    server.use(
        createShopifyAuth({
            apiKey: SHOPIFY_API_KEY,
            secret: SHOPIFY_API_SECRET_KEY,
            scopes: ['read_products', 'write_products', 'read_orders', 'write_orders'],
            async afterAuth(ctx) {
                //console.log(`-- ctx.method: ${ctx.method} \n-- ctx.url: ${ctx.url} --`);
                const { shop, accessToken } = ctx.session;
                ctx.cookies.set('shopOrigin', shop, { httpOnly: false });
                //webhooks
                
                const wh_orders_create = await registerWebhook({
                    address: 'https://<shop>.myshopify.com/webhooks/orders/create',
                    topic: 'ORDERS_CREATE',
                    accessToken,
                    shop,
                });
                if (wh_orders_create.success) {
                    console.log('Successfully registered createOrderWebhook webhook!');
                } else {
                    console.log(
                    'Failed to register createOrderWebhook webhook',
                    wh_orders_create.result,
                    );
                    console.log(
                        'userErrors',
                        wh_orders_create.result.data.webhookSubscriptionCreate.userErrors
                        );
                }

                const wh_products_create = await registerWebhook({
                    address: 'https://<shop>.myshopify.com/webhooks/products/create',
                    topic: 'PRODUCTS_CREATE',
                    accessToken,
                    shop,
                });
                if (wh_products_create.success) {
                    console.log('Successfully registered createOrderWebhook webhook!');
                } else {
                    console.log(
                    'Failed to register createOrderWebhook webhook',
                    wh_products_create.result,
                    );
                    console.log(
                        'userErrors',
                        wh_products_create.result.data.webhookSubscriptionCreate.userErrors
                        );
                }

                ctx.redirect('/');
            },
        }),
    );
      

    server.use(verifyRequest());
    server.use(async (ctx) => {
        await handle(ctx.req, ctx.res);
        ctx.respond = false;
        ctx.res.statusCode = 200;
        return
    });

    server.use(
        // receive webhooks
        receiveWebhook({
          path: '/webhooks/orders/create',
          secret: SHOPIFY_API_SECRET_KEY,
          onReceived(ctx) {
            console.log('received webhook: ', ctx.state.webhook);
          },
        }),
      );

      server.use(
        // receive webhooks
        receiveWebhook({
          path: '/webhooks/products/create',
          secret: SHOPIFY_API_SECRET_KEY,
          onReceived(ctx) {
            console.log('received webhook: ', ctx.state.webhook);
          },
        }),
      );

     server.use(graphQLProxy({version: ApiVersion.July19}));

    server.listen(port, () => {
        console.log(`> Ready on http://localhost:${port}`);
    });
});

Should I perhaps be trying another approach?

Ryan
Shopify Staff
499 42 120

The webhook notification test in the admin doesn't work to send webhooks to addresses configured by an application.  You would need to create a new one in the admin that is targeting the same address as your app in order to test like that, these webhooks are independent of ones registered by applications.  A way to test the app's webhook would be to create an order on the shop.

 

Another thing to check when you hit the "topic is already in use", is you can use the webhooks endpoint in order to see webhooks already registered to your app to ensure you have the correct address.

 

 

Ryan | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

zoultrex
Tourist
18 0 2

Hi Ryan, thanks for the reply! So... I have done some testing.

Creating a transaction on the shop did not send any webhooks, in fact, using the shop transaction had the exact same reaction on my server as using the test button on the admin notification setting, ngrok printed (POST / ______ 302 Found), I wonder if theres something else for me to check.

Also, I checked the link you sent about the webhooks endpoint but I have no idea where to start, I mean, I see that this is part of a URL to send a request to (/admin/api/2019-07/webhooks.json) but I don't know how and where to build that request. What would be the rest of that URL? What API exactly should I use?


https://help.shopify.com/en/api/getting-started/webhooks#configure-webhook

The URL above also has some info on how to test a webhook, but I wanna actually build an app that receives them, so the example in that page did not make much sense to me considering what I'm trying to achieve, am I missing something there?

Last but not least, actually quite relevant, I just remembered to mention that in my admin settings I did setup a URL to receive the same topic (orders_create) and it happens that I used my server URL there on the admin notification setting.
I guess that means that I have 2 subscriptions (one from the app itself running on my server, and another from the admin notification settings), both directed to my server, but none of them are being printed by the app.

I know the setup from the admin works because I have tested them on zappier integrated with google sheets and I was able to see the data fill the rows.

Isn't there something wrong with my server code?

zoultrex
Tourist
18 0 2

Another thing that makes me think there's something wrong on my code, or on my setup, is the fact that if I follow the example from this server code:
https://github.com/Shopify/shopify-demo-app-node-react/blob/listen-for-store-events-with-webhooks-st...
basically changing the webhook receive code from the Koa server to the koa-router as in the link above, when I make a purchase (or a test using the admin link), ngrok prints: POST / 405 Method Not Allowed 

Ryan
Shopify Staff
499 42 120

While I'm not very familiar with the tutorial or it's end state code, your server code does seem to be the most likely place for the problem based on everything discussed so far.  I would recommend stepping over the tutorial parts again, and trying to compare your code to the source on github to troubleshoot where your problem is.  

Ryan | Shopify 
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Mark it as an Accepted Solution
 - To learn more visit the Shopify Help Center or the Shopify Blog

zoultrex
Tourist
18 0 2

Hey Ryan

I have now used the exact same code from the github link you sent and the problem persists, ngrok is showing 405 method not allowed when a webhook is sent to my local server.

I just have no idea what this means and there is no explanation on the error codes doc from shopify.

I wonder if I should close this issue, since the registration seems to be ok now, and open another regarding the 405 error...

zoultrex
Tourist
18 0 2

Solved it, although did not fully understand why I needed to take this extra step.

It only worked when I started all over again and before registering the webhook for the first time I went back to the shop admin settings and uninstalled the app manually. Then after running the server for the first time using the link in the tutorial (

https://ADDRESS.ngrok.io/auth?shop=SHOPNAME.myshopify.com) it successfully registered the webhook and successfully received a webhook for the sample transaction.

So I can guess why uninstalling the app manually and installing again using the auth link above solved the registration problem, but does anyone care to explain why the webhooks were resulting in a 405 error before and they are fine now?
ozzyonfire
Shopify Partner
47 2 17

I am having the exact same problem as you are. 

 

Followed the tutorial... successfully registered webhooks. But ngrok keeps giving me a 405 method not allowed on my webhook routes. 

 

Uninstalling and reinstalling the app had no effect - still 405. 

 

I'm not as familiar with koa-router, I normally just use express... I can see the line:

server.use(router.allowedMethods());

But we're not setting that anywhere, does it just infer the allowed methods based on what routes have been configured by the router?

Or does this have to do with a configuration of ngrok?

Thanks in advance.

CRandyHill
Excursionist
17 0 5

I'm having same problem, exact same server.js as example, everything works properly including registering the webhook, yet when I create a product ngrok is displaying:

 

POST /webhooks/products/create                                 403 Forbidden                    

POST //webhooks/products/create                                405 Method Not Allowed           

 

Removing and reinstalling isn't fixing it. I'm also occasionally seeing the following errors in my node app. 

 

Error: write EPIPE

      at afterWriteDispatched (internal/stream_base_commons.js:149:25)

      at writeGeneric (internal/stream_base_commons.js:140:3)

      at Socket._writeGeneric (net.js:776:11)

      at Socket._write (net.js:788:8)

      at doWrite (_stream_writable.js:435:12)

      at clearBuffer (_stream_writable.js:574:7)

      at Socket.Writable.uncork (_stream_writable.js:329:7)

      at connectionCorkNT (_http_outgoing.js:656:8)

      at processTicksAndRejections (internal/process/task_queues.js:81:21)

 

Also I'm running on MacOS Catalina, so I turned off the macos firewall, but didn't help.

CRandyHill
Excursionist
17 0 5

OK, I found the problem. Registering the webhook using

 

const registration = await registerWebhook({
address:`${HOST}/webhooks/products/create`,
topic: 'PRODUCTS_CREATE',
accessToken,
shop,
apiVersion: ApiVersion.October19
});
 
 
while 
 
router.post('//webhooks/products/create', webhook, (ctx) => {
console.log('received webhook: ', ctx.state.webhook);
});
 
 
I knew that this code obviously works for everyone else, so I traced my mistake to misdeclaring host as:
 
rjdiepenbrock
Visitor
2 0 0

Thanks for the solution - that was driving me crazy. Kind of obvious after the fact. 

jaimish11
Visitor
1 0 0

I'm having the same problem as well. I'm using the exact same file from the tutorial and my HOST is declared correctly. However, I'm still receiving the 405 forbidden method error on NGROK. I'm trying to receive a product creation webhook from the Shopify admin. I'm able to successfully register the webhook, but cannot receive it. Any other tips you might have?

zoultrex
Tourist
18 0 2

I came back to this project and now I used straight the code from github but its returning 405 when a webhook is fired. Ot works ok to register the webhook, but not to receive, neither from  the admin panel or when using a test shop to fire the events.

It seels to me that clearly the example on the github in this link does not work out of the box for receiving webhooks.
I`m gonna review this entire thing and see if I can post back a solution to when you start by the github example 

mrfochon
Excursionist
24 1 4

another "solution" for me was to remove the " " around the Host name in the process.env file.

and use the link https://XXXXXXXXXX.ngrok.io/auth?shop=XXXXXXXXXX.myshopify.com 

the webhook got registered properly;

event - compiled successfully
> Ready on http://localhost:3000
event - build page: /next/dist/pages/_error
wait  - compiling...
event - compiled successfully
Successfully registered webhook!
event - build page: /
wait  - compiling...
event - compiled successfully

but then the webhook is not visible in Setting - Notification and Ngrok has errors:

POST /                                                          405 Method Not Allowed   
POST /                                                          405 Method Not Allowed   
POST /                                                          405 Method Not Allowed   
GET  /_next/static/webpack/5b407d169f58e7464866.hot-update.json 200 OK                   
GET  /_next/webpack-hmr                                         200 OK                   
GET  /_next/webpack-hmr                                         200 OK                   
POST /graphql                                                   406 Not Acceptable   

and he UI has a network error:

Network error: Unexpected end of JSON input
mrfochon
Excursionist
24 1 4

got the solution from @Echizen  and it was what I was strongly looking after, the API version.

fixed the issue by changing the API version in the server.js file.

original mentions  server.use(graphQLProxy({ version: ApiVersion.April19 }));

changed to  server.use(graphQLProxy({ version: ApiVersion.April20 }));

if you are trying this and it s 2021, you should adapt the value as well..

suggestion, would be cool to have the API version as a .env setting..

PSKuma
Visitor
1 0 0

Hello,

Still I am getting "method not allowed" error when clicked on form submit button. 

APP URL looks like this "https://1ef575c88b6d.ngrok.io/"

This was the error.

POST https://1ef575c88b6d.ngrok.io/?hmac=12261275528af04d6f9b318a0b75cb9eff0f859557553709665f957b5e16f2f8... 405