Shopify Apps with NodeJS problem "Error: Failed to parse session token '******' jwt expired"
Shopify Apps with NodeJS problem "Error: Failed to parse session token '******' jwt expired"
问候 我每次想对 Shopify 进行管理 REST API 调用时都会遇到问题 我遇到了这个问题“错误:无法解析会话令牌 '****' jwt 已过期”我在网上看到一些代码示例我有自己的 accessToken 和商店自定义会话存储但是每次当我尝试从前端调用我自己的路线并获取有关商店的更多详细信息时我在这里遇到这个问题是代码示例任何人都可以帮帮我?
server.js
import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "@shopify/shopify-api";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
const helmet = require("koa-helmet");
const compress = require("koa-compress");
const cors = require("koa-cors");
const logger = require("koa-logger");
const bodyParser = require("koa-bodyparser");
import axios from "axios";
import { storeCallback, loadCallback, deleteCallback } from "./custom-session";
const sequelize = require("./database/database");
const { Shopify_custom_session_storage } = require("./../models/sequelizeModels");
// import apiRouter from "./../routers/apiRouter";
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
dev,
});
const handle = app.getRequestHandler();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\/|\/$/g, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(storeCallback, loadCallback, deleteCallback)
});
sequelize.sync()
.then(() => {
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
// Getting users data from database and saving it to variable //
try {
await Shopify_custom_session_storage.findAll({
raw: true,
where:{
shop: shop
},
limit:1
});
} catch(err) {
console.log(err);
throw err;
}
// End of Getting users data from database and saving it to variable //
const response = await Shopify.Webhooks.Registry.register({
shop,
accessToken,
path: "/webhooks",
topic: "APP_UNINSTALLED",
webhookHandler: async (topic, shop, body) =>{
return Shopify_custom_session_storage.destroy({
where: {
shop: shop
}
})
.then(result => {
return true;
})
.catch(err => {
if(err) throw err;
return false;
});
}
});
if (!response.success) {
console.log(
`Failed to register APP_UNINSTALLED webhook: ${response.result}`
);
}
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`);
},
})
);
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.post("/webhooks", async (ctx) => {
try {
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
}
});
router.post("/graphql", verifyRequest({ returnHeader: true }), async (ctx, next) => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
}
);
// Our Routes //
router.get("/getProducts", verifyRequest({ returnHeader: true }), async (ctx) => {
try{
const session = await Shopify.Utils.loadCurrentSession(ctx.req, ctx.res);
const client = new Shopify.Clients.Rest(session.shop, session.accessToken);
console.log(session);
}catch(err) {
console.log(err);
throw new Error(err);
}
});
// End of Our Routes //
router.get("(/_next/static/.*)", handleRequest); // Static content is clear
router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
router.get("(.*)", async (ctx) => {
const shop = ctx.query.shop;
try {
let user = await Shopify_custom_session_storage.findAll({
raw: true,
where:{
shop: shop
},
limit:1
});
// This shop hasn't been seen yet, go through OAuth to create a session
if (user[0].shop == undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
} catch(err) {
console.log(err);
throw err;
}
});
server.use(router.allowedMethods());
server.use(router.routes());
// Setting our installed dependecies //
server.use(bodyParser());
server.use(helmet());
server.use(cors());
server.use(compress());
server.use(logger());
// End of Setting our installed dependecies //
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
})
.catch((err) => {
if(err) throw err;
return process.exit(1);
})
_app.js
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch, getSessionToken } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";
import axios from 'axios';
function userLoggedInFetch(app) {
const fetchFunction = authenticatedFetch(app);
return async (uri, options) => {
const response = await fetchFunction(uri, options);
if (
response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1"
) {
const authUrlHeader = response.headers.get(
"X-Shopify-API-Request-Failure-Reauthorize-Url"
);
const redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
return null;
}
return response;
};
}
function MyProvider(props) {
const app = useAppBridge();
const client = new ApolloClient({
fetch: userLoggedInFetch(app),
fetchOptions: {
credentials: "include",
},
});
const axios_instance = axios.create();
// Intercept all requests on this Axios instance
axios_instance.interceptors.request.use(function (config) {
return getSessionToken(app) // requires a Shopify App Bridge instance
.then((token) => {
// Append your request headers with an authenticated token
config.headers["Authorization"] = `Bearer ${token}`;
return config;
});
});
const Component = props.Component;
return (
<ApolloProvider client={client}>
<Component {...props} axios_instance={axios_instance}/>
</ApolloProvider>
);
}
class MyApp extends App {
render() {
const { Component, pageProps, host } = this.props;
return (
<AppProvider i18n={translations}>
<Provider
config={{
apiKey: API_KEY,
host: host,
forceRedirect: true,
}}
>
<MyProvider Component={Component} {...pageProps} />
</Provider>
</AppProvider>
);
}
}
MyApp.getInitialProps = async ({ ctx }) => {
return {
host: ctx.query.host,
};
};
export default MyApp;
index.js
import { Heading, Page, Button } from "@shopify/polaris";
function Index(props){
async function getProducts(){
const res = await props.axios_instance.get("/products");
return res;
}
async function handleClick() {
const result = await getProducts();
console.log(result);
}
return (
<Page>
<Heading>Shopify app with Node and React </Heading>
<Button onClick={handleClick}>Get Products</Button>
</Page>
);
}
export default Index;
我找到了“错误:无法解析会话令牌‘******’jwt 已过期”的解决方案问题是计算机时间未同步,检查计算机时间并同步它,以我的示例为例,我在 Kali Linux 上搜索如何在 Kali Linux 上同步时间并在您最终同步时间时按照该教程重新启动应用程序服务器并重试。就是这样,我为此浪费了 4 天时间。
问候 我每次想对 Shopify 进行管理 REST API 调用时都会遇到问题 我遇到了这个问题“错误:无法解析会话令牌 '****' jwt 已过期”我在网上看到一些代码示例我有自己的 accessToken 和商店自定义会话存储但是每次当我尝试从前端调用我自己的路线并获取有关商店的更多详细信息时我在这里遇到这个问题是代码示例任何人都可以帮帮我?
server.js
import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import Shopify, { ApiVersion } from "@shopify/shopify-api";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
const helmet = require("koa-helmet");
const compress = require("koa-compress");
const cors = require("koa-cors");
const logger = require("koa-logger");
const bodyParser = require("koa-bodyparser");
import axios from "axios";
import { storeCallback, loadCallback, deleteCallback } from "./custom-session";
const sequelize = require("./database/database");
const { Shopify_custom_session_storage } = require("./../models/sequelizeModels");
// import apiRouter from "./../routers/apiRouter";
dotenv.config();
const port = parseInt(process.env.PORT, 10) || 8081;
const dev = process.env.NODE_ENV !== "production";
const app = next({
dev,
});
const handle = app.getRequestHandler();
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\/|\/$/g, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(storeCallback, loadCallback, deleteCallback)
});
sequelize.sync()
.then(() => {
app.prepare().then(async () => {
const server = new Koa();
const router = new Router();
server.keys = [Shopify.Context.API_SECRET_KEY];
server.use(
createShopifyAuth({
async afterAuth(ctx) {
// Access token and shop available in ctx.state.shopify
const { shop, accessToken, scope } = ctx.state.shopify;
const host = ctx.query.host;
// Getting users data from database and saving it to variable //
try {
await Shopify_custom_session_storage.findAll({
raw: true,
where:{
shop: shop
},
limit:1
});
} catch(err) {
console.log(err);
throw err;
}
// End of Getting users data from database and saving it to variable //
const response = await Shopify.Webhooks.Registry.register({
shop,
accessToken,
path: "/webhooks",
topic: "APP_UNINSTALLED",
webhookHandler: async (topic, shop, body) =>{
return Shopify_custom_session_storage.destroy({
where: {
shop: shop
}
})
.then(result => {
return true;
})
.catch(err => {
if(err) throw err;
return false;
});
}
});
if (!response.success) {
console.log(
`Failed to register APP_UNINSTALLED webhook: ${response.result}`
);
}
// Redirect to app with shop parameter upon auth
ctx.redirect(`/?shop=${shop}&host=${host}`);
},
})
);
const handleRequest = async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
};
router.post("/webhooks", async (ctx) => {
try {
await Shopify.Webhooks.Registry.process(ctx.req, ctx.res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
}
});
router.post("/graphql", verifyRequest({ returnHeader: true }), async (ctx, next) => {
await Shopify.Utils.graphqlProxy(ctx.req, ctx.res);
}
);
// Our Routes //
router.get("/getProducts", verifyRequest({ returnHeader: true }), async (ctx) => {
try{
const session = await Shopify.Utils.loadCurrentSession(ctx.req, ctx.res);
const client = new Shopify.Clients.Rest(session.shop, session.accessToken);
console.log(session);
}catch(err) {
console.log(err);
throw new Error(err);
}
});
// End of Our Routes //
router.get("(/_next/static/.*)", handleRequest); // Static content is clear
router.get("/_next/webpack-hmr", handleRequest); // Webpack content is clear
router.get("(.*)", async (ctx) => {
const shop = ctx.query.shop;
try {
let user = await Shopify_custom_session_storage.findAll({
raw: true,
where:{
shop: shop
},
limit:1
});
// This shop hasn't been seen yet, go through OAuth to create a session
if (user[0].shop == undefined) {
ctx.redirect(`/auth?shop=${shop}`);
} else {
await handleRequest(ctx);
}
} catch(err) {
console.log(err);
throw err;
}
});
server.use(router.allowedMethods());
server.use(router.routes());
// Setting our installed dependecies //
server.use(bodyParser());
server.use(helmet());
server.use(cors());
server.use(compress());
server.use(logger());
// End of Setting our installed dependecies //
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
})
.catch((err) => {
if(err) throw err;
return process.exit(1);
})
_app.js
import ApolloClient from "apollo-boost";
import { ApolloProvider } from "react-apollo";
import App from "next/app";
import { AppProvider } from "@shopify/polaris";
import { Provider, useAppBridge } from "@shopify/app-bridge-react";
import { authenticatedFetch, getSessionToken } from "@shopify/app-bridge-utils";
import { Redirect } from "@shopify/app-bridge/actions";
import "@shopify/polaris/dist/styles.css";
import translations from "@shopify/polaris/locales/en.json";
import axios from 'axios';
function userLoggedInFetch(app) {
const fetchFunction = authenticatedFetch(app);
return async (uri, options) => {
const response = await fetchFunction(uri, options);
if (
response.headers.get("X-Shopify-API-Request-Failure-Reauthorize") === "1"
) {
const authUrlHeader = response.headers.get(
"X-Shopify-API-Request-Failure-Reauthorize-Url"
);
const redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.APP, authUrlHeader || `/auth`);
return null;
}
return response;
};
}
function MyProvider(props) {
const app = useAppBridge();
const client = new ApolloClient({
fetch: userLoggedInFetch(app),
fetchOptions: {
credentials: "include",
},
});
const axios_instance = axios.create();
// Intercept all requests on this Axios instance
axios_instance.interceptors.request.use(function (config) {
return getSessionToken(app) // requires a Shopify App Bridge instance
.then((token) => {
// Append your request headers with an authenticated token
config.headers["Authorization"] = `Bearer ${token}`;
return config;
});
});
const Component = props.Component;
return (
<ApolloProvider client={client}>
<Component {...props} axios_instance={axios_instance}/>
</ApolloProvider>
);
}
class MyApp extends App {
render() {
const { Component, pageProps, host } = this.props;
return (
<AppProvider i18n={translations}>
<Provider
config={{
apiKey: API_KEY,
host: host,
forceRedirect: true,
}}
>
<MyProvider Component={Component} {...pageProps} />
</Provider>
</AppProvider>
);
}
}
MyApp.getInitialProps = async ({ ctx }) => {
return {
host: ctx.query.host,
};
};
export default MyApp;
index.js
import { Heading, Page, Button } from "@shopify/polaris";
function Index(props){
async function getProducts(){
const res = await props.axios_instance.get("/products");
return res;
}
async function handleClick() {
const result = await getProducts();
console.log(result);
}
return (
<Page>
<Heading>Shopify app with Node and React </Heading>
<Button onClick={handleClick}>Get Products</Button>
</Page>
);
}
export default Index;
我找到了“错误:无法解析会话令牌‘******’jwt 已过期”的解决方案问题是计算机时间未同步,检查计算机时间并同步它,以我的示例为例,我在 Kali Linux 上搜索如何在 Kali Linux 上同步时间并在您最终同步时间时按照该教程重新启动应用程序服务器并重试。就是这样,我为此浪费了 4 天时间。