You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用eBay SDK添加商品兼容性时出现LookupAttribute相关报错

eBay API 添加配件兼容性信息报错排查

问题描述

我有一款用于库存管理并发布eBay拍卖商品的C# WinForms应用程序。尝试修改商品listings添加配件兼容性信息时,出现以下报错:

"No <Item.LookupAttributeArray.LookupAttribute> exists or <Item.LookupAttributeArray.LookupAttribute> is specified as an empty tag"

eBay API参考文档相关说明:

ConditionID(新增):ConditionID在沙箱环境的部分分类中受支持,自2010年5月起,在生产环境的大多数分类中生效。当GetCategoryFeatures显示商品主分类的ConditionEnabled为Enabled或Required时,应使用ConditionID替代AttributeSetArray、LookupAttributeArray或ItemSpecifics来指定商品状态。

相关代码

MainForm 代码

public partial class MainForm : Form
{
    public List<string[]> CsvData { get; set; } = [];
    public string? SerialNumber { get; set; }
    public string? File { get; set; }

    public MainForm()
    {
        InitializeComponent();
    }

    private void MainForm_Load(object sender, EventArgs e)
    {
        Logger.Logger.LogInfo("Starting Up...");
    }

    private void TbSerial_TextChanged(object sender, EventArgs e)
    {
        SerialNumber = tbSerial.Text;
    }

    private void btnCSV_Click(object sender, EventArgs e)
    {
        var dialog = new OpenFileDialog();
        dialog.ShowDialog();
        File = dialog.FileName;

        CreateDataTable();
    }

    private void CreateDataTable()
    {
        var dataTable = new DataTable();
        dataTable.Columns.Add("Year");
        dataTable.Columns.Add("Make");
        dataTable.Columns.Add("Line");
        dataTable.Columns.Add("Model");

        if (File != null)
        {
            var streamReader = new StreamReader(File);
            while (!streamReader.EndOfStream)
            {
                var totalData = streamReader.ReadLine()?.Split(',');
                if (totalData is not { Length: > 0 }) continue;

                CsvData.Add(totalData);

                dataTable.Rows.Add(totalData[0], totalData[1], totalData[2], totalData[3]);
            }
        }

        dataGridView1.DataSource = dataTable;
    }

    private void BtnEbayUpdate_Click(object sender, EventArgs e)
    {
        if (CsvData.Count <= 0)
            Logger.Logger.LogError("You must upload a fitment file first!!");

        if (string.IsNullOrEmpty(SerialNumber))
            Logger.Logger.LogError("You must input a serial number!!");

        var itemCompatibilityTypeCollection = new ItemCompatibilityTypeCollection();

        for (var i = 0; i < CsvData.Count; i++)
        {
            var line = CsvData[i];
            if (i == 0) { continue; }
            var year = line[0];
            var make = line[1];
            var model = line[3];

            var fitmentYear = new NameValueListType
            {
                Name = "Year",
                Value = [year]
            };
            var fitmentMake = new NameValueListType
            {
                Name = "Make",
                Value = [make]
            };
            var fitmentModel = new NameValueListType
            {
                Name = "Model",
                Value = [model]
            };

            NameValueListTypeCollection fitmentData =
            [
                fitmentYear,
                fitmentMake,
                fitmentModel
            ];

            var itemCompatibilityType = new ItemCompatibilityType
            {
                NameValueList = fitmentData
            };

            itemCompatibilityTypeCollection.Add(itemCompatibilityType);
        }

        var db = new GWDB.GWDB();
        var invRecord = db.Inventories
            .Where(s => s.SerialNumber == SerialNumber && s.Status == "Auction")
            .Select(x => x)
            .FirstOrDefault();
        if (invRecord == null) return;

        var eBayId = invRecord.eBayID;
        var auction = eBay.eBay.GetItemRequest(eBayId);
        if (auction.Item == null) return;

        auction.Item.ItemCompatibilityList = new ItemCompatibilityListType
        {
            Compatibility = itemCompatibilityTypeCollection
        };

        auction.Item.ConditionID = 4000;

        var response = eBay.eBay.ReviseItem(auction.Item);
        if (response.Ack != AckCodeType.Success) return;

        Logger.Logger.LogInfo(@$"Auction {eBayId} has been updated with fitment info.");
    }
}

eBay 工具类代码

public class eBay
{
    public static eBayAPIInterfaceService eBayServiceCall(string callName)
    {
        var endpoint = "https://api.ebay.com/wsapi";
        const string siteId = "100";
        var appId = AppSettingsHelper.AppID;     // use your app ID
        var devId = AppSettingsHelper.DevID;     // use your dev ID
        var certId = AppSettingsHelper.CertID;   // use your cert ID
        const string version = "965";
        // Build the request URL
        var requestURL = endpoint
                         + "?callname=" + callName
                         + "&siteid=" + siteId
                         + "&appid=" + appId
                         + "&version=" + version
                         + "&routing=default";

        var service = new eBayAPIInterfaceService();
        // Assign the request URL to the service locator.
        service.Url = requestURL;
        // Set credentials
        service.RequesterCredentials = new CustomSecurityHeaderType
        {
            eBayAuthToken = AppSettingsHelper.Token, // use your token
            Credentials = new UserIdPasswordType
            {
                AppId = appId,
                DevId = devId,
                AuthCert = certId
            }
        };
        return service;
    }

    /// <summary>
    /// Verify whether item is ready to be added to eBay.
    /// </summary>
    public static string AddEbayItem(ItemType item)
    {
        var service = eBayServiceCall("VerifyAddItem");

        var request = new VerifyAddItemRequestType
        {
            Version = "949",
            ErrorLanguage = "en_US",
            WarningLevel = WarningLevelCodeType.High,
            Item = item
        };

        try
        {
            var response = service.VerifyAddItem(request);
            if (response != null)
            {
                switch (response.Ack)
                {
                    case AckCodeType.Warning:
                        {
                            for (var i = 0; i < response.Errors.Count; i++)
                            {
                                Logger.Logger.LogWarning(response.Errors[i].LongMessage);
                                i++;
                            }
                            break;
                        }
                    case AckCodeType.Failure:
                        {
                            for (var i = 0; i < response.Errors.Count; i++)
                            {
                                Logger.Logger.LogError(response.Errors[i].LongMessage);
                                i++;
                            }
                            break;
                        }
                    case AckCodeType.Success:
                        {
                            Logger.Logger.LogInfo((response.Message));
                            break;
                        }
                    case AckCodeType.PartialFailure:
                        break;
                    case AckCodeType.CustomCode:
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }

                // If item is verified, the item will be added.
                if (response.ItemID != "0") return null;
            }

            var ebayID = AddItemRequest(item);
            return ebayID;
        }
        catch (Exception ex)
        {
            Logger.Logger.LogError(@"Exception:");
            Logger.Logger.LogError($@"{ex.Message}");
            return null;
        }
    }

    /// <summary>
    /// Add item to eBay. Once verified.
    /// </summary>
    /// <param name="item">Accepts ItemType object from VerifyAddItem method.</param>
    public static string AddItemRequest(ItemType item)
    {
        try
        {
            var service = eBayServiceCall("AddItem");

            var request = new AddItemRequestType
            {
                Version = "949",
                ErrorLanguage = "en_US",
                WarningLevel = WarningLevelCodeType.High,
                Item = item
            };

            var response = service.AddItem(request);

            Logger.Logger.LogInfo($@"ItemID: {response.ItemID}");

#if DEBUG
            //Process.Start($@"http://ebay.com/itm/{response.ItemID}");
#else
            //Process.Start($@"http://ebay.com/itm/{response.ItemID}");
#endif
            return response.ItemID;
        }
        catch (Exception ex)
        {
            Logger.Logger.LogError(@"Exception:");
            Logger.Logger.LogError($@"{ex.Message}");
            return null;
        }
    }

    /// <summary>
    /// Retrieve item details.
    /// </summary>
    /// <param name="ItemID">eBay Item ID</param>
    public static GetItemResponseType GetItemRequest(string ItemID)
    {
        var service = eBayServiceCall("GetItem");
        var request = new GetItemRequestType
        {
            Version = "949",
            ItemID = ItemID
        };
        var response = service.GetItem(request);
        return response;
    }

    public static ReviseItemResponseType ReviseItem(ItemType item)
    {
        var service = eBayServiceCall("ReviseItem");
        var request = new ReviseItemRequestType
        {
            Version = "949",
            Item = item
        };
        var response = service.ReviseItem(request);
        return response;
    }

    public static bool EndEbayItem(string itemID)
    {
        try
        {
            var status = false;

            var service = eBayServiceCall("EndItem");

            var request = new EndItemRequestType
            {
                Version = "949",
                ErrorLanguage = "en_US",
                WarningLevel = WarningLevelCodeType.High,
                EndingReason = EndReasonCodeType.NotAvailable,
                ItemID = itemID
            };

            var response = service.EndItem(request);
            if (response.Ack == AckCodeType.Success)
                status = true;

            Logger.Logger.LogInfo($@"Auction ID {itemID} ended: {response.Ack}");
            return status;
        }
        catch (Exception ex)
        {
            Logger.Logger.LogError(@"Exception:");
            Logger.Logger.LogError($@"{ex.Message}");
            return false;
        }
    }
}

问题原因与修复方案

核心原因

调用ReviseItem时,从GetItem返回的Item对象中保留了旧的LookupAttributeArray空值或无效数据,而当前商品分类要求用ConditionID替代该字段,导致API校验失败;同时API请求版本不统一(工具类用965,修改请求用949),也可能引发字段处理逻辑冲突。

修复步骤

  1. 清空旧属性数组
    在设置ConditionID和兼容性信息后,显式清空Item对象中的LookupAttributeArray和AttributeSetArray字段,避免旧数据干扰:
auction.Item.ItemCompatibilityList = new ItemCompatibilityListType
{
    Compatibility = itemCompatibilityTypeCollection
};

auction.Item.ConditionID = 4000;
// 显式清空旧的属性数组,解决API校验报错
auction.Item.LookupAttributeArray = null;
auction.Item.AttributeSetArray = null;

var response = eBay.eBay.ReviseItem(auction.Item);
  1. 统一API版本号
    修改ReviseItem方法中的版本号,和eBayServiceCall保持一致:
public static ReviseItemResponseType ReviseItem(ItemType item)
{
    var service = eBayServiceCall("ReviseItem");
    var request = new ReviseItemRequestType
    {
        Version = "965", // 改为与工具类一致的版本号
        Item = item
    };
    var response = service.ReviseItem(request);
    return response;
}
  1. 额外检查项
  • 调用GetCategoryFeatures接口确认当前商品分类的ConditionEnabled状态,确保ConditionID的使用符合分类要求;
  • 验证CSV数据读取逻辑,确保兼容性信息(Year/Make/Model)无空值,避免生成无效的NameValueList。

内容的提问来源于stack exchange,提问作者Drew Jackson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:07:01