Hi all,
I've been following the Node and React Shopify app tutorial, and have managed to get basically everything working. I can access the GraphQL API no problem, and have written a few of my own queries and mutations. However, some of the data I need is only available through the Shopify REST API.
I've read through the Shopify OAuth guide and I'm able to retrieve a valid access_token. I'm using that to send a GET request to retrieve a list of collections, but I get a 401 Unauthorized response. I've tried using Postman to test the exact request, and it works fine.
Is there anything special I need to do? Is it possible that some of the GraphQL code from the demo is interfering? I've posted my code below, in case it's helpful.
fetch("https://my-fake-demo-store.myshopify.com/admin/api/2019-04/custom_collections.json", { mode: 'no-cors', method: 'GET', headers: { "X-Shopify-Access-Token": accessToken, "Content-type": "application/json", }, }).then(response => { console.log(response) return response; }).then(json => { console.log(json) });
Solved! Go to the solution
@Alex sure thing, I just added the X-Request-Id with a value of "thresher_collections_rest_api_test" to my header. Thanks for your response!
@Alex apologies, wasn't 100% sure what you were asking. I attached an image showing the response I get back from the above fetch request. The response.headers seem to be empty. Does my code above look correct, or am I missing something?
So after doing some more digging, it looks like I can't query the REST API because the requests are coming directly from my app frontend instead of backend. Does that make sense?
Are there examples of how to connect to the REST API via Node JS server + React app?
Edit: it appears that is the case. I'm able to access the REST API from my server.js file with the following code:
fetch("https://" + shop + "/admin/api/2019-04/custom_collections.json", { headers: { "X-Shopify-Access-Token": accessToken, }, }) .then(response => response.json()) .then(json => console.log(json))
I'm not sure how to set this up so I can call the API from my React front end though.
This is an accepted solution.
I managed to figure this out, and wanted to share an update in case anyone runs into the same issue. My problem was that my API calls were coming from the frontend instead of the backend and they were being rejected. My solution was to create my own backend routes and call them from my frontend.
1. Add koa-router to server.js
const Router = require('koa-router'); const router = new Router();
2. Add custom backend routes to make API calls to Shopify:
router.get('/api/:object', async (ctx) => { try { const results = await fetch("https://" + ctx.cookies.get('shopOrigin') + "/admin/api/2019-04/" + ctx.params.object + ".json", { headers: { "X-Shopify-Access-Token": ctx.cookies.get('accessToken'), }, }) .then(response => response.json()) .then(json => { return json; }); ctx.body = { status: 'success', data: results }; } catch (err) { console.log(err) } })
3. Call backend routes from React frontend:
getCollections = () => { var fetchUrl = "/api/custom_collections"; var method = "GET"; fetch(fetchUrl, { method: method }) .then(response => response.json()) .then(json => console.log(json)) }
I'm not sure if this is the most effective solution, so feel free to chime in if you have suggestions to improve this.
Hi Thresher, tried your solution, still getting 401. Where did you add the custom backend route in server.js? I have no backend experience, and I'm really confused...
app.prepare().then(()=>{ const server = new Koa(); server.use(session(server)); server.keys = [SHOPIFY_API_SECRET_KEY]; server.use( createShopifyAuth({ apiKey: SHOPIFY_API_KEY, secret: SHOPIFY_API_SECRET_KEY, scopes: ['read_products', 'read_orders', 'write_products'], afterAuth(ctx) { const { shop, accessToken } = ctx.session; ctx.cookies.set('shopOrigin', shop, { httpOnly: false }); ctx.redirect('/'); }, }), ); server.use(graphQLProxy({version: ApiVersion.April19})); server.use(verifyRequest()); server.use(async (ctx) => { await handle(ctx.req, ctx.res); ctx.respond = false; ctx.res.statusCode = 200; return }); router.get('/api/:object', async (ctx) => { try { const results = await fetch("https://" + ctx.cookies.get('shopOrigin') + "/admin/api/2019-04/" + ctx.params.object + ".json", { headers: { "X-Shopify-Access-Token": ctx.cookies.get('accessToken'), }, }) .then(response => response.json()) .then(json => { return json; }); ctx.body = { status: 'success', data: results }; } catch (err) { console.log(err) } }) server.listen(port, () => { console.log(`> Ready on http://localhost:${port}`); });
@Ireneludi make sure that you include the code from step 1 at the top of server.js. You're missing a line below where you set the shopOrigin cookie:
ctx.cookies.set('accessToken', accessToken);
Let me know if that works!
@Thresher got this error GET https://bd73afd9.ngrok.io/api/orders 404 (Not Found)
and my frontend fetch function is like
const fetchUrl = '/api/orders'; const method = "GET"; fetch(fetchUrl, {method: method,}) .then(response=>response.json()).then(json => console.log(json))
then I tried to change the fetchUrl
const fetchUrl = 'https://getordertest.myshopify.com/api/orders.json'; const method = "GET"; fetch(fetchUrl, {method: method,}) .then(response=>response.json()).then(json => console.log(json))
and I got : Access to fetch at 'https://getordertest.myshopify.com/api/orders.json' from origin 'https://bd73afd9.ngrok.io' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
And I add {mode: 'no-cors'}
and I just got an opaque response...
User | Count |
---|---|
14 | |
12 | |
10 | |
8 | |
7 |