Ошибка Walmart API POST с 400 Bad Request (лента инвентаризации) ARCA
У меня проблемы с запросом POST к API Walmart Marketplace для массового обмена данными, и я надеюсь на некоторую помощь.
Предыстория: я успешно писал подпрограммы аутентификации подписи и могу успешно выполнять команды GET, такие как get products и т. Д. Это указывает на то, что подписи аутентификации правильно отформатированы, а заголовки (по большей части) верны.
Проблема: я получаю ответ 400 Неверный запрос, содержание запроса недействительно. ответ при попытке отправить тестовый фид в Walmarts API. Я читал, что эта проблема распространена, но мне еще не удалось найти ни одного сообщения на форуме, которое бы четко объясняло реальную проблему или как ее исправить. Вот мои текущие параметры:
ARCA ARCA Отдых Клиент для Chrome
URL:
https://marketplace.walmartapis.com/v2/feeds?feedType=inventory
Заголовки:
Accept: application/xml
WM_SVC.NAME: Walmart Marketplace
WM_CONSUMER.ID: <Consumer ID>
WM_SEC.AUTH_SIGNATURE: <Good Auth Signature>
WM_QOS.CORRELATION_ID: 15649814651
WM_SEC.TIMESTAMP: <Timestamp>
WM_CONSUMER.CHANNEL.TYPE: <Channel Type>
Content-Type: multipart/form-data
Вложение файла (не сырые данные, хотя это было опробовано)
<?xml version="1.0" encoding="utf-8"?>
<InventoryFeed xmlns="http://walmart.com/">
<InventoryHeader>
<version>1.4</version>
</InventoryHeader>
<inventory>
<sku>KON04418</sku>
<quantity>
<unit>EACH</unit>
<amount>4</amount>
</quantity>
<fulfillmentLagTime>1</fulfillmentLagTime>
</inventory>
</InventoryFeed>
Когда я беру этот же XML-файл и проверяю его в Walmart API Explorer, файл принимается с кодом ответа 200 (ОК).
С помощью плагина Notepad++ XML Tools я подтвердил, что XML соответствует XSD, предоставленному Walmart. Я видел множество постов, касающихся границ, которые необходимо применить, поэтому я дополнительно попытался изменить тип контента и добавить границы, но безуспешно получить принятый запрос.
Любая помощь в получении этого запроса для возврата кода ответа 200 будет принята с благодарностью.
Наконец, как только этот запрос будет подтвержден в ARCA, я буду реализовывать его на C#. У меня уже есть весь написанный код, но есть некоторая неясность относительно того, как добавить вложение в HttpWebRequest вместо простой передачи потока необработанных данных. Если бы можно было дать какую-то ясность в отношении разницы, я был бы снова признателен.
1 ответ
Так что этот ответ не является чистым и элегантным, это скорее обходной путь, чем что-либо еще. Я говорил с несколькими людьми из инженерной команды Walmart, и мне сказали, что C# SDK должен появиться в ближайшие несколько месяцев.
После всех моих исследований выяснилось, что есть несколько хитростей в том, как вы отправляете многокомпонентную форму в Walmart, и система очень негибкая. Я видел сообщения о добавлении специально отформатированных границ в тело HTTP-запроса, но мне не повезло. Мне не удалось прикрепить тело в виде файла или потока данных к запросу.
Обойти это довольно просто, и, к сожалению, безобразно. Это займет немного настройки, но вы можете создать оболочку.jar вокруг Java SDK Walmart и вызывать ее из вашей программы.Net.
Итак.. шаги в процессе:
- Соберите соответствующие файлы.XSD и сгенерируйте из них классы C#.
- Создайте правильно отформатированный файл инвентаризации XML. Не забудьте включить пространства имен! Walmart не сможет выполнить определенные вызовы, если вы не включите соответствующие пространства имен ns2 / ns3.
Динамически генерируйте пакетный файл для вызова вашего Java-модуля. Появление процесса командной строки напрямую, казалось, почему-то капризно, поэтому я выбрал вместо этого командный файл.
string path = @Directory.GetParent(Environment.CurrentDirectory).ToString(); if (File.Exists(@"../inventory.bat")) { File.Delete(@"../inventory.bat"); } string batchCommand = @"cd " + path + Environment.NewLine + @"java -jar WalmartWrapper.jar SubmitInventoryFeed inventoryFeed.xml"; File.WriteAllText(path + @"\\inventory.bat", batchCommand); ProcessStartInfo info = new ProcessStartInfo(); info.UseShellExecute = true; info.FileName = @"inventory.bat"; info.WorkingDirectory = path; var p = Process.Start(info); p.WaitForExit();`
Отсюда, Java-модуль вступает во владение. Потребовалось немного взломать, чтобы заставить его работать больше как SDK, а не как пример программы. Вот некоторые примеры кода для работы...
Точка входа
if ("SubmitInventoryFeed".equals(args[0].trim())) { if (args.length < 2) { System.out.println("Need second argument for SubmitInventoryFeed"); return; } String filename = args[1]; Feed inventoryFeed = new Feed(); try { inventoryFeed.submitInventoryFeed(filename); } catch (Exception ex) { System.out.println("submitInventoryFeed failed: " + ex.getMessage()); } }
Вызов SDK (это голые кости submitInventoryFeed без проверки ошибок)
String path = Paths.get(".").toAbsolutePath().normalize().toString(); File itemFile = FileHandler.getFile(filename.trim()); String filePath = path + "\\" + "MarketplaceClientConfig.properties"; WalmartMarketplace wm = Utils.getClient(filePath); Response response = wm.submitFeed(MarketplaceFeedType.inventory, itemFile);
Ты можешь использовать
ResponseChecker.isResponse200(response, true)
проверить на успешность представлений- Использовать FeedAcknowledgement ack = response.readEntity(FeedAcknowledgement.class); чтобы получить фактический ответ, чтобы проверить ошибки
Я буду первым, кто скажет, что мне не терпится заменить эту работу на C# SDK, ожидающий от Walmart, но на данный момент это единственный способ, которым я смог представить. Я подробно рассмотрел код walmart, но, к сожалению, под капотом происходит некое волшебство Java, которое делает вложение файлов, поэтому на самом деле нет никакого способа получить доступ к точной процедуре и обратному инжинирингу для C#. Я думаю, что кто-то, кто действительно знал Java изнутри и снаружи, мог бы понять это, но у меня достаточно опыта Java, чтобы позволить мне собрать работоспособное, хотя и некрасивое решение.