React项目中Shopify Storefront API单商品页403 Forbidden问题求助
React调用Shopify Storefront API获取单商品报403错误排查
我在React项目中调用Shopify Storefront API获取单商品数据时出现POST 403 (forbidden)错误,但商品列表页请求完全正常,求帮忙排查问题。
相关代码:
shopifyApi.jsx(Products.jsx引入,请求正常)
export const fetchProducts = async () => { const response = await fetch(`https://<MyShopifyStore/>.myshopify.com/api/2024-10/graphql.json`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': '' }, body: JSON.stringify({ query: ` { products(first: 5) { edges { node { id title descriptionHtml images(first: 1) { edges { node { src } } } variants(first: 1) { edges { node { priceV2 { amount } } } } } } } } `, }), }); const { data } = await response.json(); return data.products.edges; };
Products.jsx(请求及展示正常)
import { fetchProducts } from '../../../api/shopifyApi.js' const Products = () => { const [productsList, setProductsList] = useState([]); useEffect(() => { const getProducts = async () => { const productData = await fetchProducts(); setProductsList(productData) }; getProducts(); }, []); return ( <div className="product-container"> <div className='product-grid'> { productsList.map(({ node }) => ( <div className='product-card' key={node.id} > <Link to={`/product/${node.productId}`} reloadDocument > {node.images.edges.length > 0 && ( <img src={node.images.edges[0].node.src} alt={node.title} width={300} /> )} {/* <div dangerouslySetInnerHTML={{ __html: node.descriptionHtml }} /> */} <h2>{node.title}</h2> </Link> <p>£{node.variants.edges[0].node.priceV2.amount}</p> <button type='button'>ADD TO CART</button> </div> )) } </div> </div> ) } export default Products
ProductPage.jsx(请求报错403)
const ProductPage = () => { const { productId } = useParams(); const [product, setProduct] = useState(null); useEffect(() => { const fetchProduct = async () => { const response = await fetch(`https://<MyShopifyStore/>.myshopify.com/api/2024-10/graphql.json`, { method: 'POST', header: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': '' }, body: JSON.stringify({ query: ` query { product(id: "gid//shopify/Product/${productId}") { edges { node { id title descriptionHtml images(first: 1) { edges { node { src } } } } } } } ` }) }) const { data } = await response.json(); setProduct(data?.product?.edges) }; fetchProduct(); }, [productId]) if (!product) return <div>Loading...</div> return ( <div className='product-page-container'> <h1>{product.title}</h1> {product.images.edges.length > 0 && ( <img src={product.images.edges[0].node.src} alt={product.title} /> )} <div dangerouslySetInnerHTML={{ __html: product.descriptionHtml }}/> </div> ) } export default ProductPage;
错误分析及解决方案
1. 请求头拼写错误
ProductPage.jsx的fetch配置中写了header而非正确的headers(少了末尾的s),导致请求头未正确携带授权令牌和内容类型,Shopify API直接拒绝未授权请求返回403。
修正代码:
headers: { 'Content-Type': 'application/json', 'X-Shopify-Storefront-Access-Token': '' // 确保此处填入有效的Storefront令牌 },
2. GraphQL查询格式错误
- 单个
product查询返回的是节点对象,而非包含edges的结构,你的查询写法product { edges { node {...} } }不符合API规范。 gid格式错误,正确格式是gid://shopify/Product/xxx,你写的是gid//shopify/Product/xxx(少了一个冒号),导致查询ID无效。
修正后的查询:
query { product(id: "gid://shopify/Product/${productId}") { id title descriptionHtml images(first: 1) { edges { node { src } } } } }
3. 状态赋值与渲染逻辑错误
修正查询后,data.product是单个商品节点,不是edges数组,需要调整状态赋值和渲染逻辑:
// 状态赋值 setProduct(data?.product) // 渲染部分 return ( <div className='product-page-container'> <h1>{product.title}</h1> {product.images.edges.length > 0 && ( <img src={product.images.edges[0].node.src} alt={product.title} /> )} <div dangerouslySetInnerHTML={{ __html: product.descriptionHtml }}/> </div> )
4. 路由参数传递错误
Products.jsx中传递的node.productId字段不存在,列表查询返回的节点只有id(格式为gid://shopify/Product/xxx),导致ProductPage拿到的productId无效。
修正路由参数传递:
// Products.jsx中提取ID部分传递 <Link to={`/product/${node.id.split('/').pop()}`} reloadDocument >
内容的提问来源于stack exchange,提问作者ryanl
相关产品推荐
相关产品推荐

