如何在会话中访问令牌(Shopify 访问令牌)
How to access a token in session (Shopify Access Token)
我主要从事前端工作,所以我对 NodeJS 不是很熟悉。
我正在开发一个 Shopify 自定义应用程序,这个应用程序的目的是在下订单时它会收到 webhook 请求,并根据该请求将一些数据发送到其他 API(计费应用程序)
我用 shopify app cli 构建了 shopify 应用程序,我的 server.js 文件是这样的;
import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import graphQLProxy, { ApiVersion } from "@shopify/koa-shopify-graphql-proxy";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
import session from "koa-session";
const { receiveWebhook } = require("@shopify/koa-shopify-webhooks");
import * as handlers from "./handlers/index";
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();
const { SHOPIFY_API_SECRET, SHOPIFY_API_KEY, SCOPES } = process.env;
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.use(
session(
{
sameSite: "none",
secure: true,
},
server
)
);
server.keys = [SHOPIFY_API_SECRET];
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET,
scopes: [SCOPES],
async afterAuth(ctx) {
//Auth token and shop available in session
//Redirect to shop upon auth
const { shop, accessToken } = ctx.session;
// This accessToken is what I need on other scope
ctx.cookies.set("shopOrigin", shop, {
httpOnly: false,
secure: true,
sameSite: "none",
});
// Register Webhook
handlers.registerWebhooks(
shop,
accessToken,
"ORDERS_PAID",
"/webhooks/orders/paid",
ApiVersion.October20
);
console.log(accessToken);
ctx.redirect("/");
},
})
);
const webhook = receiveWebhook({ secret: SHOPIFY_API_SECRET });
router.post("/webhooks/orders/paid", webhook, (ctx) => {
let user_id = ctx.state.webhook.payload.customer.id;
console.log("received webhook, user_id: ", user_id);
//console.log("ctx", ctx);
// I need that accessToken here to get some more info from Admin API with GraphQL
let accessToken = "???"
handlers
.graphqlRequest(
accessToken,
"https://my-store.myshopify.com/admin/api/2020-10/graphql.json",
`{
customer(id: "gid://shopify/Customer/${user_id}") {
email
metafields(first: 5) {
edges {
node {
key
value
}
}
}
}
}`
)
.then((res) => {
console.log("res => ", res);
})
.catch((err) => {
console.log("err => ", err);
});
});
server.use(
graphQLProxy({
version: ApiVersion.October20,
})
);
router.get("(.*)", verifyRequest(), async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
});
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
createShopifyAuth()
方法使用我的应用程序密钥和应用程序 api 密钥获取 accessToken,我可以在 afterAuth()
方法中使用它,但我还需要在 router.post()
中使用该令牌从 Shopify Admin API.
获取更多信息的方法
根据 Shopify 文档(或我的理解),该密钥在会话中可用,但我如何访问该会话数据?或者我可以在 router.push()
?
中使用该令牌做什么?
会话仅为从管理面板登录应用程序的用户创建。在线创建访问令牌的方法也是如此。
如果您从 webhook 请求(a.k.a 不需要您重新登录应用程序的请求)请求访问令牌,您将无法访问该会话,您将无法能够获取访问令牌。此外,会话有时会过期。
为了在 webhook 请求中使用访问令牌,您需要创建一个 offline
无限期有效的访问令牌。 createShopifyAuth
有一个创建离线访问令牌的选项,您只需将 accessMode: 'offline'
添加到您的请求中(更多关于此 here)
示例:
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
accessMode: 'offline',
scopes: ['read_products', 'read_orders'],
创建离线访问令牌后,您需要将其保存在数据库中(或其他方式)并从 webhook 路由请求它,以便发出您的 graphql 请求。
仅此而已。
我主要从事前端工作,所以我对 NodeJS 不是很熟悉。 我正在开发一个 Shopify 自定义应用程序,这个应用程序的目的是在下订单时它会收到 webhook 请求,并根据该请求将一些数据发送到其他 API(计费应用程序)
我用 shopify app cli 构建了 shopify 应用程序,我的 server.js 文件是这样的;
import "@babel/polyfill";
import dotenv from "dotenv";
import "isomorphic-fetch";
import createShopifyAuth, { verifyRequest } from "@shopify/koa-shopify-auth";
import graphQLProxy, { ApiVersion } from "@shopify/koa-shopify-graphql-proxy";
import Koa from "koa";
import next from "next";
import Router from "koa-router";
import session from "koa-session";
const { receiveWebhook } = require("@shopify/koa-shopify-webhooks");
import * as handlers from "./handlers/index";
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();
const { SHOPIFY_API_SECRET, SHOPIFY_API_KEY, SCOPES } = process.env;
app.prepare().then(() => {
const server = new Koa();
const router = new Router();
server.use(
session(
{
sameSite: "none",
secure: true,
},
server
)
);
server.keys = [SHOPIFY_API_SECRET];
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET,
scopes: [SCOPES],
async afterAuth(ctx) {
//Auth token and shop available in session
//Redirect to shop upon auth
const { shop, accessToken } = ctx.session;
// This accessToken is what I need on other scope
ctx.cookies.set("shopOrigin", shop, {
httpOnly: false,
secure: true,
sameSite: "none",
});
// Register Webhook
handlers.registerWebhooks(
shop,
accessToken,
"ORDERS_PAID",
"/webhooks/orders/paid",
ApiVersion.October20
);
console.log(accessToken);
ctx.redirect("/");
},
})
);
const webhook = receiveWebhook({ secret: SHOPIFY_API_SECRET });
router.post("/webhooks/orders/paid", webhook, (ctx) => {
let user_id = ctx.state.webhook.payload.customer.id;
console.log("received webhook, user_id: ", user_id);
//console.log("ctx", ctx);
// I need that accessToken here to get some more info from Admin API with GraphQL
let accessToken = "???"
handlers
.graphqlRequest(
accessToken,
"https://my-store.myshopify.com/admin/api/2020-10/graphql.json",
`{
customer(id: "gid://shopify/Customer/${user_id}") {
email
metafields(first: 5) {
edges {
node {
key
value
}
}
}
}
}`
)
.then((res) => {
console.log("res => ", res);
})
.catch((err) => {
console.log("err => ", err);
});
});
server.use(
graphQLProxy({
version: ApiVersion.October20,
})
);
router.get("(.*)", verifyRequest(), async (ctx) => {
await handle(ctx.req, ctx.res);
ctx.respond = false;
ctx.res.statusCode = 200;
});
server.use(router.allowedMethods());
server.use(router.routes());
server.listen(port, () => {
console.log(`> Ready on http://localhost:${port}`);
});
});
createShopifyAuth()
方法使用我的应用程序密钥和应用程序 api 密钥获取 accessToken,我可以在 afterAuth()
方法中使用它,但我还需要在 router.post()
中使用该令牌从 Shopify Admin API.
根据 Shopify 文档(或我的理解),该密钥在会话中可用,但我如何访问该会话数据?或者我可以在 router.push()
?
会话仅为从管理面板登录应用程序的用户创建。在线创建访问令牌的方法也是如此。
如果您从 webhook 请求(a.k.a 不需要您重新登录应用程序的请求)请求访问令牌,您将无法访问该会话,您将无法能够获取访问令牌。此外,会话有时会过期。
为了在 webhook 请求中使用访问令牌,您需要创建一个 offline
无限期有效的访问令牌。 createShopifyAuth
有一个创建离线访问令牌的选项,您只需将 accessMode: 'offline'
添加到您的请求中(更多关于此 here)
示例:
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
accessMode: 'offline',
scopes: ['read_products', 'read_orders'],
创建离线访问令牌后,您需要将其保存在数据库中(或其他方式)并从 webhook 路由请求它,以便发出您的 graphql 请求。
仅此而已。