Development discussions around Shopify APIs
Hi,
I am new to Shopify development and React (although I have developed for NodeJS Express before).
Following the steps in the 'Build a Shopify App with Node and React tutorial' (https://shopify.dev/tutorials/build-a-shopify-app-with-node-and-react/build-your-user-interface-with...), I have hit a snag.
At the point of setting the Shopify App Bridge, the instructions say to add a <Provider config={config}> tag. Having defined config previously as: { apiKey: API_KEY, shopOrigin: Cookies.get("shopOrigin"), forceRedirect: true }
The problem is, as I can see in the example code provided in the tutorial, API_KEY is not defined, and predictably I get the appropriate error when testing the app from the Store admin. Even if I define API_KEY as the SHOPIFY_API_KEY from process.env, I encounter a new error: apiKey must be provided.
I'm officially at a loss. Any help would be appreciated.
Hi @tobrien,
The API_KEY value here is expected to be set as an environment variable within your app. One way of doing that is to set the value as a webpack plugin (at compile time) in your next.config.js file like so:
const apiKey = JSON.stringify(process.env.SHOPIFY_API_KEY); module.exports = withCSS({ webpack: config => { const env = { API_KEY: apiKey }; config.plugins.push(new webpack.DefinePlugin(env)); return config; } });
You can find some more information on DefinePlugin in the webpack docs.
Hope this helps!
Paulo
Hi @paulomarg
Thank you for your response. I did forget to mention I have included this in my next.config.js:
require("dotenv").config() const withCSS = require('@zeit/next-css') const webpack = require('webpack') const apiKey = JSON.stringify(process.env.SHOPIFY_API_KEY) module.exports = withCSS({ webpack: (config) => { const env = { API_KEY: apiKey } config.plugins.push(new webpack.DefinePlugin(env)) return config } })Am I missing something obvious (like a typo)? Is it something to do with how I am starting the application or the structure of my project?
Hi again!
This looks OK to me, the demo project is set up so API_KEY should be set at that point. It could indeed be some other issue as you said.
The first thing I'd suggest is to make sure that your API key is set in your .env file, and to check that the value is being set at this point when you recompile your project.
For anyone else that encounters this, a restart of ngrok seemed to do the trick. Although I'm sure I had done that before posting, this also resolved the issue when I subsequently encountered the error.
Of course first check that next.config.js is set up properly as described.
I have the same issue 'AppBridgeError: APP::ERROR::INVALID_CONFIG: apiKey must be provided'.
I cannot solve this, by restarting ngrok, nodejs-server.
Any solutions?
Hi @samsuzuki,
Can you please provide a bit more detail on the error you're seeing, like when does it happen, and the code that triggers it?
Also, just to check all the boxes, make sure your API key is set in your .env file and is being properly loaded when your server starts.
Thank you!
@paulomarg Thank you for your reply. Sorry for my lack of information.
I'm new as a React/ Node.js developer( usually I am a iOS app developer).
And I was doing this tutorial . It works fine halfway.
But, at this part(#Add Shopify Bridge), my code does not work fine. Before 'Add Shopify Bridge' section, my code works fine.
When I open below URL(my ngrok with OAuth) after writing "Add Shopify Bridge" code with restarting web-server and ngrok, this error message appear.
https://24e3f0c517ea.ngrok.io/auth?shop=xn-ccka2ewcwdtfo276cihcb50i.myshopify.com
Error Message:
Unhandled Runtime ErrorAppBridgeError: APP::ERROR::INVALID_CONFIG: apiKey must be provided
Browser(Google Chrome) console error message:
My development enviroment
"@shopify/app-bridge-react": "^1.26.2","@shopify/koa-shopify-auth": "^3.1.65","@shopify/polaris": "^5.2.0","@zeit/next-css": "^1.0.1","dotenv": "^8.2.0","isomorphic-fetch": "^2.2.1","js-cookie": "^2.2.1","koa": "^2.13.0","koa-session": "^6.0.0","next": "^9.5.2","react": "^16.13.1","react-dom": "^16.13.1"
My code is below.
/.env
SHOPIFY_API_KEY='xxxxxxxx'
SHOPIFY_API_SECRET_KEY='xxxxxxx'
/server.js
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 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({ secure: true, sameSite: 'none' }, server));
server.keys = [SHOPIFY_API_SECRET_KEY];
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products'],
afterAuth(ctx) {
const { shop, accessToken} = ctx.session;
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
ctx.redirect('/');
},
}),
);
server.use(verifyRequest());
server.use(async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
return
});
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
/page/_app.js
import App from 'next/app';
import Head from 'next/head';
import { AppProvider } from '@shopify/polaris';
import { Provider } from '@shopify/app-bridge-react';
import '@shopify/polaris/dist/styles.css';
import translations from '@shopify/polaris/locales/en.json'
import Cookies from 'js-cookie';
class MyApp extends App {
render() {
const { Component, pageProps } = this.props;
const config = { apiKey: API_KEY, shopOrigin: Cookies.get("shopOrigin"), forceRedirect: true };
return (
<React.Fragment>
<Head>
<title>Sample App</title>
<meta charSet="utf-8" />
</Head>
<Provider config={config}>
<AppProvider i18n={translations}>
<Component { ...pageProps} />
</AppProvider>
</Provider>
</React.Fragment>
);
}
}
export default MyApp;
/page/index.js
import { EmptyState, Layout, Page, TextStyle } from '@shopify/polaris';
import { TitleBar } from '@shopify/app-bridge-react';
const img = 'https://cdn.shopify.com/s/files/1/0757/9955/files/empty-state.svg';
const Index = () => (
<Page>
<TitleBar
title="Sample App"
primaryAction={{
content: 'Select products',
}}
/>
<Layout>
<EmptyState
heading="Discount your products temporarily"
action={{
content: 'Select products',
onAction: () => console.log('clicked!'),
}}
image={img}
>
<p>Select products to change their price temporarily.</p>
</EmptyState>
</Layout>
</Page>
);
export default Index;
Other code: same as codes before 'Add Shopify Bridge' section
Thank you for your support.
@paulomarg Also, "/next.config.js" is here.
require("dotenv").config();
const withCSS = require('@zeit/next-css');
const webpack = require('webpack');
const apiKey = JSON.stringify(process.env.SHOPFIY_API_KEY);
module.exports = withCSS({
webpack: (config) => {
const env = { API_KEY: apiKey};
config.plugins.push(new webpack.DefinePlugin(env));
return config;
},
});
Thank you.
@paulomarg I solved! Sorry for bothering you.
The reason of the error is here.
const apiKey = JSON.stringify(process.env.SHOPFIY_API_KEY);
" SHOPFIY" is typo.
Hello @paulomarg,
I am having this same problem. I am currently getting the API_KEY not defined error when trying to access my .io site.
The following is my server.js file,
1 require('isomorphic-fetch');
2 const dotenv = require('dotenv');
3 const Koa = require('koa');
4 const next = require('next');
5 const { default: createShopifyAuth } = require('@shopify/koa-shopify-auth');
6 const { verifyRequest } = require('@shopify/koa-shopify-auth');
7 const session = require('koa-session');
8
9 dotenv.config();
10 const port = parseInt(process.env.PORT, 10) || 3000;
11 const dev = process.env.NODE_ENV !== 'production';
12 const app = next({ dev });
13 const handle = app.getRequestHandler();
14
15 const { SHOPIFY_API_SECRET_KEY, SHOPIFY_API_KEY } = process.env;
16
17 app.prepare().then(() => {
18 const server = new Koa();
19 server.use(session({ secure: true, sameSite: 'none' }, server));
20 server.keys = [SHOPIFY_API_SECRET_KEY];
21
22 server.use(
23 createShopifyAuth({
24 apiKey: SHOPIFY_API_KEY,
25 secret: SHOPIFY_API_SECRET_KEY,
26 scopes: ['read_products'],
27 afterAuth(ctx) {
28 const { shop, accessToken } = ctx.session;
29 ctx.cookies.set('shopOrigin', shop, { httpOnly:false, secure: true, sameSite: 'none'});
30 ctx.redirect('/');
31 },
32 }),
33 );
34
35 server.use(verifyRequest());
36 server.use(async (ctx) => {
37 await handle(ctx.req, ctx.res);
38 ctx.respond = false;
39 ctx.res.statusCode = 200;
40 return
41 });
42
43 server.listen(port, () => {
44 console.log(`> Ready on http://localhost:${port}`);
45 });
46 });
my pages/_app.js file,
1 import App from 'next/app';
2 import Head from 'next/head';
3 import { AppProvider } from '@shopify/polaris';
4 import { Provider } from '@shopify/app-bridge-react';
5 import '@shopify/polaris/dist/styles.css';
6 import translations from '@shopify/polaris/locales/en.json';
7 import Cookies from 'js-cookie';
8
9
10 class MyApp extends App {
11 render() {
12 const { Component, pageProps } = this.props;
13 const config = { apiKey: API_KEY, shopOrigin: Cookies.get("shopOrigin"), forceRedirect: true };
14 return (
15 <React.Fragment>
16 <Head>
17 <title>Sample App</title>
18 <meta charSet="utf-8" />
19 </Head>
20 <Provider config={config}>
21 <AppProvider i18n={translations}>
22 <Component {...pageProps} />
23 </AppProvider>
24 </Provider>
25 </React.Fragment>
26 );
27 }
28 }
29
30 export default MyApp;
31
~
and my next.config.js file,
1 require("dotenv").config();
2 const withCSS = require('@zeit/next-css');
3 const webpack = require('webpack');
4
5 const apiKey = JSON.stringify(process.env.SHOPIFY_API_KEY);
6
7 module.exports = withCSS({
8 webpack: (config) => {
9 const env = { API_KEY: apiKey };
10 config.plugins.push(new webpack.DefinePlugin(env));
11 return config;
12 },
13 });
~
~
I am following the same tutorial. Before this error, the app was working perfectly. I'm unsure how to proceed. My .env file also includes my secret api key, and api key. While looking for an error in my code, I redid this step in the tutorial multiple times, so I'm assuming that it is one of these lines that are the issue. I've also taken tobrian's advice and restarted ngrok, but this did not solve my issue.
If you have any suggestions please let me know.
Thank you!
Ashlyn
Hi @ash0kz,
Your code seems to be right to me. One thing to keep in mind is that whenever you make changes to server.js and next.config.js, you need to actually stop and restart your server with NPM (step 5 of the App Bridge tutorial section), otherwise the changes won't take effect. Did you make sure to restart it after adding the lines?
To be sure that this code is being run, you can call console.log(apiKey); in next.config.js where you do
const env = { API_KEY: apiKey };
, and your API key should be printed in your terminal when you restart the server.
Hope this helps!
" SHOPFIY" is typo
Dear all,
Piggybacking on this thread as it is the same tutorial, same error, slight twist on the installation... repl.it installing direct from github (vs. a local git clone, npm install + ngrok).
The steps are as follows:
Once everything was configured & up and running, the tutorial application goes through the installation, "payment", and register the callback, all nicely as expected. Adding a product also seems to trigger the callback as expected.
But once the tutorial app is installed on a store, when Shopify tries to display the app dashboard itself ("Discount your products temporarily"), the app page content itself hangs.
Chrome introspect shows the error "AppBridgeError apiKey must be provided". With a bit of poking around, it seems that API_KEY is not picked up (nor shopOrigin) in _app.js ....
I'm not sure if it is a repl.it or a React issue... client or server side (but probably not a Shopify one).
Any ideas? ....
Thx.
W
ps: I did get it running on a local + ngrok... that said, the repl.it approach is much nicer for eventually collaborating and expanding on the original tutorial....
i got the definetly same issue, when i tried to use heroku server rather than ngrok. If i use ngrok everything works fine.
User | RANK |
---|---|
8 | |
7 | |
3 | |
3 | |
3 |
Connect your PayPal account to allow your customers to checkout using the PayPal gateway a...
ByYour online store speed can enhance your store’s discoverability, boost conversion rates a...
ByShopping is at our fingertips with mobile devices. Is your theme optimized to be user-frie...
By