Topics covering webhook creation & management, event handling, Pub/Sub, and Eventbridge, in Shopify apps.
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?
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.
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?
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?
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
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?
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
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
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...
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 (
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.
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.
OK, I found the problem. Registering the webhook using
Thanks for the solution - that was driving me crazy. Kind of obvious after the fact.
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?
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
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
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..
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.