结账地址填写完整后,配送区域只显示 No shipping methods available。这句话只代表当前 Quote 没收集到可用 rate,并没有说明是地址、承运商配置、商品数据还是第三方接口失败。

先固定一个可重复的测试 Quote

SELECT entity_id, store_id, is_active, items_count,
       items_qty, subtotal, grand_total
FROM quote
WHERE entity_id=456;

SELECT address_id, address_type, country_id, region_id,
       region, postcode, city, shipping_method
FROM quote_address
WHERE quote_id=456;

postcode、region_id 和 country_id 缺失会让某些承运商直接返回 false。不要只看前端表单文字,检查保存进 Quote 的真实值。

配置作用域对照

配置检查内容
Enabled 目标 Website/Store 是否启用
Ship to Applicable Countries 地址国家是否允许
Minimum/Maximum Order Amount 是否按含税或未税金额判断
Specific Error Message 是否隐藏了真实原因
Handling Fee 格式是否导致 rate 计算异常
bin/magento config:show carriers/flatrate/active
bin/magento config:show carriers/flatrate/sallowspecific
bin/magento config:show carriers/flatrate/specificcountry
bin/magento config:show general/country/allow

CLI 默认读取的 scope 可能不是问题店铺。多网站站点要同时核对后台 Use Default/Use Website 的继承状态。

商品是否具备运费计算所需信息

SELECT item_id, sku, product_type, qty, weight,
       is_virtual, free_shipping
FROM quote_item
WHERE quote_id=456
ORDER BY item_id;

全虚拟购物车本来就不需要配送;实体商品重量为 0 时,第三方实时运费可能拒绝;可配置、Bundle 商品要避免父子重量重复或全部丢失。库存不可售也可能让结账流程提前阻止收集。

第三方承运商请求应记录什么

  • 请求发生时间、目标 endpoint 和非敏感响应码;
  • 目的国家、邮编、包裹总重量和币种;
  • 连接超时、认证失败或无可用服务的原始响应;
  • 不要在日志中记录 API 密钥和完整客户地址。
grep -RniE 'shipping|carrier|rate|timeout' var/log | tail -n 100
curl -sk -o /dev/null -w '%{http_code} %{time_connect} %{time_total}
'  'https://carrier-api.example.com/health'

用四组地址做边界测试

同城正常邮编、允许国家的偏远邮编、不允许国家、缺少 Region 的地址各测试一次。若只有一个邮编失败,问题多半在服务范围或远程 API;所有地址都失败,再查配置 scope 与模块异常。

恢复后确认用户选择的 shipping_method 已写入 quote_address,订单创建后 shipping_description 与金额一致。仅让列表出现一个 rate,还不能证明下单时同一个 rate 能被再次验证。