如何通过Shopify API获取全部1300个变体?分页遇状态0错误
Shopify API分页获取变体失败(状态0错误)修复方案
问题背景
需要从Shopify API获取全部1300个变体插入自定义表,但默认请求仅返回50条,实现分页时出现状态0错误,无法继续拉取后续数据。
代码问题排查
原代码存在以下几个关键问题导致分页失败:
- 请求对象复用污染:循环中复用同一个
HttpRequestMessage实例,可能残留上一次请求的参数,引发请求异常 - 鉴权Token无效:
Shopify记录未执行初始化操作(如FindFirst()),导致Shopify.Token为空,请求鉴权失败 - Link Header解析逻辑错误:遍历Link Header时重复使用变量名
LinkPart,导致分页URL提取逻辑混乱;且未兼容Shopify Link Header中引号的不同格式 - 错误信息缺失:请求失败时仅输出状态码,状态0通常表示请求未发送成功,无法定位具体原因
- 代码冗余:插入记录的逻辑在分支中完全重复,可简化
修复后的完整代码
procedure InsertVariants() var Client: HttpClient; Request: HttpRequestMessage; Response: HttpResponseMessage; Content: HttpContent; JsonResponse: Text; JsonObject: JsonObject; JsonArray: JsonArray; JsonToken: JsonToken; VariantObject: JsonObject; TempToken: JsonToken; ShopifyVariantRecord: Record "Shopify Variants Mercalab"; VariantIdInteger: BigInteger; ProductIdInteger: BigInteger; PriceDecimal: Decimal; CompareAtPriceDecimal: Decimal; Sku: Text; ShopifyVariantesOriginal: Record "Shpfy Variant"; NextPageUrl: Text; BaseUrl: Text; Shopify : Record "Shpfy Company"; LastErr: HttpError; begin ShopifyVariantRecord.DeleteAll(); BaseUrl := 'https://shoptest.myshopify.com/admin/api/2024-04/variants.json'; NextPageUrl := BaseUrl; // 初始化Shopify公司记录,确保获取有效Token if not Shopify.FindFirst() then begin Message('未找到有效的Shopify公司记录'); exit; end; repeat // 每次循环创建新的请求对象,避免参数污染 Clear(Request); Request.SetRequestUri(NextPageUrl); Request.Method := 'GET'; Client.DefaultRequestHeaders.Clear(); Client.DefaultRequestHeaders.Add('X-Shopify-Access-Token', Shopify.Token); if Client.Send(Request, Response) then begin Content := Response.Content(); Content.ReadAs(JsonResponse); JsonObject.ReadFrom(JsonResponse); if JsonObject.Get('variants', JsonToken) then begin JsonArray := JsonToken.AsArray(); foreach JsonToken in JsonArray do begin if JsonToken.IsObject() then begin VariantObject := JsonToken.AsObject(); // 解析Variant ID if VariantObject.Get('id', TempToken) then begin EVALUATE(VariantIdInteger, TempToken.AsValue().AsText()); VariantIdInteger := Max(VariantIdInteger, 0); end else VariantIdInteger := 0; // 解析Product ID if VariantObject.Get('product_id', TempToken) then begin EVALUATE(ProductIdInteger, TempToken.AsValue().AsText()); ProductIdInteger := Max(ProductIdInteger, 0); end else ProductIdInteger := 0; // 解析Price if VariantObject.Get('price', TempToken) then begin EVALUATE(PriceDecimal, TempToken.AsValue().AsText()); PriceDecimal := Max(PriceDecimal, 0); end else PriceDecimal := 0; // 解析Compare At Price CompareAtPriceDecimal := 0; if VariantObject.Get('compare_at_price', TempToken) then begin if not TempToken.AsValue().IsNull() then begin EVALUATE(CompareAtPriceDecimal, TempToken.AsValue().AsText()); CompareAtPriceDecimal := Max(CompareAtPriceDecimal, 0); end; end; // 解析SKU Sku := ''; if VariantObject.Get('sku', TempToken) then Sku := TempToken.AsValue().AsText(); // 插入记录(简化重复逻辑) ShopifyVariantRecord.Init(); ShopifyVariantRecord.id := VariantIdInteger; ShopifyVariantRecord.product_id := ProductIdInteger; ShopifyVariantRecord.price := PriceDecimal; ShopifyVariantRecord.compare_at_price := CompareAtPriceDecimal; ShopifyVariantRecord.sku := Sku; // 匹配原变体记录 ShopifyVariantesOriginal.SetRange(SKU, Sku); if ShopifyVariantesOriginal.FindFirst() then begin ShopifyVariantRecord.Coincide := (VariantIdInteger = ShopifyVariantesOriginal.Id); ShopifyVariantRecord."Id variante BC" := ShopifyVariantesOriginal.Id; end else begin ShopifyVariantRecord.Coincide := false; ShopifyVariantRecord."Id variante BC" := 0; end; ShopifyVariantRecord.Insert(); end; end; NextPageUrl := GetNextPageUrl(Response); end else begin Message('响应中未找到变体数据'); NextPageUrl := ''; end; end else begin LastErr := Client.LastError(); Message('请求Shopify API失败: 状态码%1,错误信息:%2', Format(Response.HttpStatusCode), LastErr.Message); NextPageUrl := ''; end; until NextPageUrl = ''; Message('已保存%1条Shopify变体数据', ShopifyVariantRecord.Count()); end; procedure GetNextPageUrl(Response: HttpResponseMessage): Text var LinkHeaders: List of [Text]; LinkSegments: List of [Text]; Segment: Text; StartPos: Integer; EndPos: Integer; begin if not Response.Headers.Contains('Link') then exit(''); Response.Headers.GetValues('Link', LinkHeaders); foreach LinkHeaders do begin LinkSegments := LinkHeaders.Split(','); foreach Segment in LinkSegments do begin // 匹配rel="next"或rel='next'的格式 if Segment.Contains('rel="next"') or Segment.Contains('rel=''next''') then begin StartPos := Segment.IndexOf('<') + 1; EndPos := Segment.IndexOf('>'); if StartPos > 0 and EndPos > StartPos then exit(Segment.Substring(StartPos, EndPos - StartPos)); end; end; end; exit(''); end;
关键修复说明
- 请求对象重置:每次循环调用
Clear(Request)创建新的请求实例,避免旧参数残留 - Token有效性保障:添加
Shopify.FindFirst()确保获取有效的鉴权Token,这是状态0错误的常见原因 - Link Header解析优化:修正变量名冲突,兼容单双引号的rel格式,提升分页URL提取的稳定性
- 错误信息增强:捕获
Client.LastError()获取详细错误描述,便于定位问题 - 代码简化:合并插入记录的重复逻辑,增加解析失败的默认值处理,提升代码健壮性
内容的提问来源于stack exchange,提问作者JulioSistemas
相关产品推荐
相关产品推荐

