我有一个基于 Node.js 构建的自定义网站,我希望能够通过 GET 请求获取我的所有产品。 shopify buy-button 不允许我一次将所有产品带入页面(它有分页),这使我无法正确过滤所有产品(我在网站上有自定义过滤器) 。
因此,根据我在 Shopify 论坛中读到的一篇文章,我希望执行以下操作:
<div class="wps-buy-button" id='[product-id]-[var-id]' data-id='[product-id]' data-var='[var-id]'></div>
这将允许我过滤所有不同的 Shopify 产品。 但是,现在困难的部分是获取
product-id
和 var-id
字段。人们可能会认为只需转到 Products => All Products => Export 就足够了,但他们没有在其中列出产品 ID 和 var-id 。
我尝试使用 Shopify-Buy npm 模块,它看起来像下面的代码,但得到了一个丑陋的、无法使用的响应:
所以我的问题是,如何使用 API 或其他方式获得所有不同 Shopify 产品的响应,而无需 必须使用 PHP,或支付 shopify 插件 才能获得产品 - ids 和 var-ids (我使用的是 Shopify lite 计划,因为我只是将其插入到我现有的平台中)。
代码:
import Client from 'shopify-buy';
const client = Client.buildClient({
domain: 'your-shop-name.myshopify.com',
storefrontAccessToken: 'your-storefront-access-token'
});
// Fetch all products in your shop
client.product.fetchAll().then((products) => {
// Do something with the products
console.log(products);
});
回复:
[ GraphModel {
id: [Getter],
handle: [Getter],
description: [Getter],
descriptionHtml: [Getter],
updatedAt: [Getter],
title: [Getter],
image: [Getter],
products: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: false,
hasPreviousPage: false,
variableValues: { first: 20, productsFirst: 20 } },
type: { name: 'CollectionConnection',
kind: 'OBJECT',
fieldBaseTypes: { edges: 'CollectionEdge', pageInfo: 'PageInfo' },
implementsNode: false } ]
[ GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: false,
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: { [Boolean: true] value: true },
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
GraphModel {
id: [Getter],
availableForSale: [Getter],
createdAt: [Getter],
updatedAt: [Getter],
descriptionHtml: [Getter],
description: [Getter],
handle: [Getter],
productType: [Getter],
title: [Getter],
vendor: [Getter],
publishedAt: [Getter],
onlineStoreUrl: [Getter],
options: [Getter],
images: [Getter],
variants: [Getter],
refetchQuery: [Getter],
type: [Getter],
nextPageQueryAndPath: [Function],
hasNextPage: true,
hasPreviousPage: { [Boolean: true] value: true },
variableValues: { first: 20, productsFirst: 20 } },
type: { name: 'ProductConnection',
kind: 'OBJECT',
fieldBaseTypes: { edges: 'ProductEdge', pageInfo: 'PageInfo' },
implementsNode: false } ]
要获取 Shopify 产品 ID 和产品变体 ID,您可以使用 Shopify REST API。既然您已经拥有 NodeJS 应用程序,您就可以使用 Shopify API Node.js 模块。只需获取所有产品,将获取的数据传递到前端,然后使用问题中提到的脚本来呈现 Shopify 购买按钮。
获取所有产品的示例代码
const Shopify = require('shopify-api-node');
const shopify = new Shopify({
shopName: 'store-url.myshopify.com',
apiKey: 'xxxxxxxxxxxxxxxx',
password: 'xxxxxxxxxxxxxx',
autoLimit: true
});
shopify.product.count()
.then(async (count) => {
if (count > 0) {
const pages = Math.ceil(count / 250);
let products = [];
for (i = 0; i < pages; i++) {
// use Promise.all instead of waiting for each response
const result = await shopify.product.list({
limit: 250,
page: i + 1,
fields: 'id, variants'
});
products = products.concat(result);
}
// products array should have all the products. Includes id and variants
console.log(products);
}
})
.catch(err => {
console.log(err);
});
为了获得更好的性能,请考虑将产品保存在数据库中并定期更新信息。
此解决方案可在 2023 年与
shopify-api-node
配合使用:
let products: IPaginatedResult<IProduct> = []
let page_info: string | undefined = undefined
// Get all products
// page_info is the next page ID to fetch
// https://shopify.dev/docs/api/usage/pagination-rest
do {
const newProducts = await shopify.product.list({
limit: 250, // max is 250
page_info
})
products = [...products, ...newProducts]
page_info = newProducts.nextPageParameters?.page_info
} while (page_info)
return products