Webhooks subscription throwing error

New Member
12 0 0

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?

0 Likes
Shopify Staff
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

0 Likes
New Member
12 0 0

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?

0 Likes
New Member
12 0 0

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?

0 Likes
Shopify Staff
Shopify Staff
472 35 90

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.

 

 

Developer Experience @ Shopify
0 Likes
New Member
12 0 0

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?

0 Likes
New Member
12 0 0

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 

0 Likes
Highlighted
Shopify Staff
Shopify Staff
472 35 90

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.  

Developer Experience @ Shopify
0 Likes
New Member
12 0 0

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...

0 Likes
New Member
12 0 0

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?
0 Likes