Solved

Shopify graphql admin api and webhook script ERROR ==> please help me

Edith_Jenkins1
Tourist
6 0 0

Hi, everyone.

 

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');

dotenv.config();

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

const { receiveWebhook, registerWebhook } = require('@shopify/koa-shopify-webhooks');

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, SHOPIFY_APP_URL } = process.env;

const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');

app.prepare().then(() => {
  const server = new Koa();
  const router = new Router();
  server.use(session({ secure: true, sameSite: 'none' }, server));

  server.keys = [SHOPIFY_API_SECRET_KEY];

  server.use(
    createShopifyAuth({
      apiKey: SHOPIFY_API_KEY,
      secret: SHOPIFY_API_SECRET_KEY,
      scopes: ['write_products', 'write_orders'],
      async afterAuth(ctx) {
        const { shop, accessToken, scope } = ctx.session;
        ctx.cookies.set('shopOrigin', shop, {
          httpOnly: false,
          secure: true,
          sameSite: 'none'
        });

        const registerProductsUpdate = await registerWebhook({
          address: `${SHOPIFY_APP_URL.replace(/https:\/\//, "")}/webhooks/products/update`,
          topic: 'PRODUCTS_UPDATE',
          accessToken: accessToken,
          shop: shop,
          ApiVersion: ApiVersion.October20
        });
        if (registerProductsUpdate.success) {
          console.log('Successfully registered webhook PRODUCTS_UPDATE !');
        } else {
          console.log('Failed to register webhook PRODUCTS_UPDATE ', registerProductsUpdate.result);
        }




        const registerOrderCreate = await registerWebhook({
          address: `${SHOPIFY_APP_URL.replace(/https:\/\//, "")}/webhooks/orders/create`,
          topic: 'ORDERS_CREATE',
          accessToken: accessToken,
          shop: shop,
          ApiVersion: ApiVersion.October20
        });
        if (registerOrderCreate.success) {
          console.log('Successfully registered webhook ORDERS_CREATE !');
        } else {
          console.log('Failed to register webhook ORDERS_CREATE ', registerOrderCreate.result);
        }

        ctx.redirect(`/?shop=${shop}`);

      },
    }),
  );

  const webhook = receiveWebhook({ secret: SHOPIFY_API_SECRET_KEY });

  router.post('/webhooks/products/update', webhook, (ctx) => {
    try {
      console.log(`Webhook processed, returned status code 200`);
    } catch (error) {
      console.log(`Failed to process webhook: ${error}`);
    }
  });
  router.post('/webhooks/orders/create', webhook, (ctx) => {
    try {
      console.log(`Webhook processed, returned status code 200`);
    } catch (error) {
      console.log(`Failed to process webhook: ${error}`);
    }
  });




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

  const handleRequest = async (ctx) => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  };

  router.get("(/_next/static/.*)", handleRequest); // Static content is clear
  router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
  router.get("(.*)", verifyRequest(), handleRequest); // Everything else must have sessions

  server
    .use(router.allowedMethods())
    .use(router.routes());

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

 

 

But I got the error 

 

FetchError: invalid json response body at https://*****.myshopify.com/admin/api/undefined/graphql.json reason: Unexpected end of JSON input

 

I can't register any webhook.

Please help me asap

 

Accepted Solution (1)
itsjustme
Tourist
4 1 1

This is an accepted solution.

I've figured it out. For me the issue was when registering webhooks, after updating to @Shopify/koa-shopify-auth package to 4.1.3 from version 3, the "https://" prefix is removed from the HOST environment variable when it was previously included.

Just double check all your options when you register a webhook. Here's what a successful webhook registration looks like for anyone struggling with this issue.

let registerOrdersPaidWebhook = async () => {
  // Register Order Paid Webhook
   const registerOrdersPaidWebhook = await registerWebhook({
       address: `https://${HOST_NAME}/webhooks/orders/paid`,
       topic: "ORDERS_PAID",
       accessToken,
       shop,
       apiVersion: ApiVersion.April21,
    });

    if (registerOrdersPaidWebhook.success) {
       console.log("Successfully registered ORDERS_PAID webhook!");
    } else {
       console.log("Failed to register ORDERS_PAID webhook", registerOrdersPaidWebhook.result);
    }
 };

 

View solution in original post

Replies 5 (5)

Kevin_A
Shopify Staff
318 42 61

Hey @Edith_Jenkins1 

It doesn't look like you are defining an API version there. That could possibly be the problem. 

Kevin_A | Solutions Engineer @ 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 Shopify.dev or the Shopify Web Design and Development Blog

Edith_Jenkins1
Tourist
6 0 0

As you see, I define api version 

ApiVersion: ApiVersion.October20 

 

Kevin_A
Shopify Staff
318 42 61

Hey @Edith_Jenkins1 

Ah yes I missed that. Can you log the x-request-id response header if possible and send me that? 

Kevin_A | Solutions Engineer @ 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 Shopify.dev or the Shopify Web Design and Development Blog

itsjustme
Tourist
4 1 1

Hey @Kevin_A I'm having this same issue.

A code block that creates an app subscription mutation on install that's been working for months just starting throwing this error after upgrading the @shopify/koa-shopify-auth package to 4.1.3 and moving to session storage. I'm getting the same invalid json error as @Edith_Jenkins1 

FetchError: invalid json response body at https://<shop>.myshopify.com/admin/api/undefined/graphql.json reason: Unexpected end of JSON input

I don't know why the URL with "admin/api/UNDEFINED/graphql.json" is being returned in the error. I specify the April 2021 admin api (and I've tried 2020-10, 2021-01 with the same results). Here's the fetch request I'm making:

// This code throws the invalid json error 
// Note: query parameter is required to make the mutation
const mutation = JSON.stringify({
    query: `mutation {
      appSubscriptionCreate(
        test: true
        name: "name..."
        returnUrl: "${returnUrl}"
        lineItems: [
          {
            plan: {
              appUsagePricingDetails: {
                cappedAmount: { amount: 1500, currencyCode: USD }
                terms: "terms..."
              }
            }
          },
          {
            plan: {
              appRecurringPricingDetails: {
                price: { amount: 0.00, currencyCode: USD }
              }
            }
          }
        ]
      )
      {
        userErrors {
          field
          message
        }
        confirmationUrl
        appSubscription {
          id
          status
          lineItems {
            id
            plan {
              pricingDetails {
                __typename
              }
            }
          }
        }
      }
    }`
  });

 const response = await fetch(
        `https://${shop}/admin/api/2021-04/graphql.json`,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "X-Shopify-Access-Token": accessToken,
          },
          body: mutation,
        }
      );

 I can make POST requests to the same url with the same api version, but using a query instead of a mutation and I get back the correct info. For example:

// This code works with no errors  
const query = `query {
    webhookSubscriptions(first:10) {
      edges {
        node {
          topic
          updatedAt
        }
      }
    }
  }`;

  const response = await fetch(
    `https://${shop}/admin/api/2021-04/graphql.json`,
    {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "X-Shopify-Access-Token": accessToken,
      },
      body: JSON.stringify({ query }),
    }
  );

  const responseJson = await response.json();

 This query returns the webhook data as expected. I'm not sure what's causing the invalid json error, but I can't install my app to test anything anymore because of it. 

Happy to provide any extra info you need to get this solved ASAP. 

 

itsjustme
Tourist
4 1 1

This is an accepted solution.

I've figured it out. For me the issue was when registering webhooks, after updating to @Shopify/koa-shopify-auth package to 4.1.3 from version 3, the "https://" prefix is removed from the HOST environment variable when it was previously included.

Just double check all your options when you register a webhook. Here's what a successful webhook registration looks like for anyone struggling with this issue.

let registerOrdersPaidWebhook = async () => {
  // Register Order Paid Webhook
   const registerOrdersPaidWebhook = await registerWebhook({
       address: `https://${HOST_NAME}/webhooks/orders/paid`,
       topic: "ORDERS_PAID",
       accessToken,
       shop,
       apiVersion: ApiVersion.April21,
    });

    if (registerOrdersPaidWebhook.success) {
       console.log("Successfully registered ORDERS_PAID webhook!");
    } else {
       console.log("Failed to register ORDERS_PAID webhook", registerOrdersPaidWebhook.result);
    }
 };