Following on from my article: ZohoCRM: Get All eBay Active Listings, this is how to get all the orders from a client's eBay.
Why?
Our use-case is a data migration from eBay to a fresh instance of Zoho Inventory. In this task, we are simply getting a CSV with all the order IDs for a particular year output as a spreadsheet.
How?
Similar to how we retrieved the eBay active listings (see article link above), we're going to use the GetOrders call for order (sales) management.
/*
Function: fn_GetEbayOrders()
Purpose: Queries eBay for all orders for a specified year
Date Created: 2023-03-29 (Joel Lipman)
- Initial release
Date Modified: 2023-03-29 (Joel Lipman)
- Added in ability to list errors and query order line item IDs (ErrCode: 21917182)
- Modified to check that there are some orders.
More Info:
- API Explorer Test Tool: https://developer.ebay.com/DevZone/build-test/test-tool/default.aspx?index=0&env=production&api=trading
- GetOrders Documentation: https://developer.ebay.com/Devzone/XML/docs/Reference/eBay/GetOrders.html
- eBay Errors by Number: https://developer.ebay.com/devzone/xml/docs/Reference/ebay/Errors/errormessages.htm
*/
//
// declare
v_Page = 1;
v_PerPage = 100;
l_Pages = List();
//
// specify the maximum number of orders you think you have on eBay (check eBay homepage and see number of sales [ will be rounded to nearest 1000 ])
// the actual number may be less than this but this is for pagination estimates
v_MaximumOrders = 10000;
v_Year = 2022;
//
// set the filter for orders by status to return: All, Active, Cancelled, CancelPending, Completed, Inactive, InProcess
v_OrderStatus = "All";
//
// calculate from and till
v_OrdersFrom = v_Year + "-01-01T00:00:00.000Z";
v_OrdersTill = v_Year + "-12-31T23:59:59.000Z";
//
// now let's generate the page list to have all the available pages
v_TotalNumberOfPages = ceil(v_MaximumOrders / v_PerPage);
l_AddPages = leftpad(" ",v_TotalNumberOfPages).replaceAll(" ",",").toList();
for each index v_Increment in l_AddPages
{
l_Pages.add(v_Increment + 1);
}
v_TotalNumberOfPages = l_Pages.size();
//
// declare variables to store order details in a JSON or ZohoDeluge Map format
m_Response = Map();
l_JsonOrders = List();
//
// start preparing CSV file to email for export
v_ReportCSV = "Date,Order ID,Status,Amount,Currency,Notes";
l_CsvFileRows = List();
l_CsvFileRows.add(v_ReportCSV);
//
// get access token
v_AccessToken = standalone.fn_eBay_GetAccessToken();
//
v_TradingAPIVersion = 967;
v_Endpoint = "https://api.ebay.com/ws/api.dll";
//
// build header
m_Headers = Map();
m_Headers.put("X-EBAY-API-SITEID",3);
m_Headers.put("X-EBAY-API-COMPATIBILITY-LEVEL",v_TradingAPIVersion);
v_ApiCall = "GetOrders";
m_Headers.put("X-EBAY-API-CALL-NAME",v_ApiCall);
m_Headers.put("X-EBAY-API-IAF-TOKEN",v_AccessToken);
//
// build params
m_Params = Map();
m_Params.put("WarningLevel","High");
m_Params.put("ErrorLanguage","en_GB");
m_Params.put("DetailLevel","ReturnAll");
m_Params.put("OrderStatus","All");
m_Params.put("SortingOrder","Ascending");
m_Params.put("CreateTimeFrom",v_OrdersFrom);
m_Params.put("CreateTimeTo",v_OrdersTill);
//
// select which fields to return
l_OutputFields = List();
l_OutputFields.add("OrderID");
l_OutputFields.add("OrderStatus");
l_OutputFields.add("AmountPaid");
l_OutputFields.add("CreatedTime");
l_OutputFields.add("TotalNumberOfPages");
l_OutputFields.add("TotalNumberOfEntries");
m_Params.put("OutputSelector",l_OutputFields);
//
// now lets loop through a dynamic page list
for each v_Page in l_Pages
{
//
// specify which page
m_Pagination = Map();
m_Pagination.put("PageNumber",v_Page);
m_Pagination.put("EntriesPerPage",v_PerPage);
m_Params.put("Pagination",m_Pagination);
//
// convert to xml and replace root nodes
x_Params = m_Params.toXML();
x_Params = x_Params.toString().replaceFirst("<root>","<?xml version=\"1.0\" encoding=\"utf-8\"?><" + v_ApiCall + "Request xmlns=\"urn:ebay:apis:eBLBaseComponents\">");
x_Params = x_Params.toString().replaceFirst("</root>","</" + v_ApiCall + "Request>");
//
//info "Request Sent to eBay:";
//info x_Params;
//
// send the request XML as a string
x_ResponseBody = invokeurl
[
url :v_Endpoint
type :POST
parameters:x_Params
headers:m_Headers
];
//info "Response from eBay:";
//info x_ResponseBody;
//
// get pagination results from the first iteration/page
if(v_Page == 1)
{
//
// get page results
x_PaginationResult = x_ResponseBody.subString(x_ResponseBody.indexOf("<PaginationResult"),x_ResponseBody.lastIndexOf("</PaginationResult") + 19);
v_TotalNumberOfOrders = x_PaginationResult.executeXPath("/PaginationResult/TotalNumberOfEntries/text()").toLong();
//
// determine total number of pages required
v_TotalNumberOfPages = ceil(v_TotalNumberOfOrders / v_PerPage);
info "Total Order(s): " + v_TotalNumberOfOrders;
info "Total Page(s): " + v_TotalNumberOfPages;
}
//
// loop through orders in response
v_OrderNodePart = "Order";
v_OrderNodeName = v_OrderNodePart + "Array";
//
// check node is paired to closing tag
if(x_ResponseBody.contains("</" + v_OrderNodeName + ">"))
{
x_OrderNode = x_ResponseBody.subString(x_ResponseBody.indexOf("<" + v_OrderNodeName),x_ResponseBody.lastIndexOf(v_OrderNodeName) + v_OrderNodeName.length() + 1);
l_Orders = x_OrderNode.executeXPath("/" + v_OrderNodeName + "/" + v_OrderNodePart).toXmlList();
for each x_Order in l_Orders
{
//
// parse the XML
v_ThisOrderID = x_Order.executeXPath("//OrderID/text()");
v_ThisOrderStatus = x_Order.executeXPath("//OrderStatus/text()");
v_ThisOrderAmountPaid = x_Order.executeXPath("//AmountPaid/text()").toDecimal();
v_ThisOrderCurrency = x_Order.executeXPath("//AmountPaid/@currencyID").executeXPath("/currencyID/text()");
v_ThisOrderDateCreated = x_Order.executeXPath("//CreatedTime/text()");
//
// build JSON row
m_Order = Map();
m_Order.put("OrderID",v_ThisOrderID);
m_Order.put("OrderStatus",v_ThisOrderStatus);
m_Order.put("AmountPaid",v_ThisOrderAmountPaid);
m_Order.put("Currency",v_ThisOrderCurrency);
//
v_ThisOrderDateCreated = if(!isnull(v_ThisOrderDateCreated),v_ThisOrderDateCreated.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime).toString("yyyy-MM-dd HH:mm:ssZ");
m_Order.put("CreatedTime",v_ThisOrderDateCreated);
//
l_JsonOrders.add(m_Order);
//
// generate CSV row for monitoring purposes
l_CsvFileRow = List();
l_CsvFileRow.add(v_ThisOrderDateCreated);
l_CsvFileRow.add("\"" + v_ThisOrderID + "\"");
l_CsvFileRow.add("\"" + v_ThisOrderStatus + "\"");
l_CsvFileRow.add(v_ThisOrderAmountPaid);
l_CsvFileRow.add(v_ThisOrderCurrency);
l_CsvFileRow.add(" ");
//
v_CsvRow = l_CsvFileRow.toString();
l_CsvFileRows.add(v_CsvRow);
}
}
//
// report on errors of this page as well
v_ErrorNodePart = "Errors";
if(x_ResponseBody.contains("<" + v_ErrorNodePart))
{
x_ErrorNode = "<" + v_ErrorNodePart + "_Root>" + x_ResponseBody.subString(x_ResponseBody.indexOf("<" + v_ErrorNodePart),x_ResponseBody.lastIndexOf(v_ErrorNodePart + ">") + v_ErrorNodePart.length() + 1) + "</" + v_ErrorNodePart + "_Root>";
l_Errors = x_ErrorNode.executeXPath("//" + v_ErrorNodePart).toXmlList();
for each x_Error in l_Errors
{
v_ThisErrorLineItemID = x_Error.executeXPath("//ErrorParameters/Value/text()");
v_ThisErrorMessage = x_Error.executeXPath("//LongMessage/text()");
//
m_Error = Map();
m_Error.put("Error Line Item ID",v_ThisErrorLineItemID);
m_Error.put("Error Message",v_ThisErrorMessage);
l_JsonOrders.add(m_Error);
//
// generate CSV row for monitoring purposes
l_CsvFileRow = List();
l_CsvFileRow.add("????");
l_CsvFileRow.add("\"" + v_ThisErrorLineItemID + "\"");
l_CsvFileRow.add(" ");
l_CsvFileRow.add(" ");
l_CsvFileRow.add(" ");
l_CsvFileRow.add(v_ThisErrorMessage);
//
v_CsvRow = l_CsvFileRow.toString();
l_CsvFileRows.add(v_CsvRow);
}
}
//
// break if page has exceeded max
if(v_Page >= v_TotalNumberOfPages)
{
break;
}
}
//
m_Response.put("orders",l_JsonOrders);
//
// lets send the CSV and JSON by email
if(l_JsonOrders.size() > 0)
{
//
// generate a CSV list for monitoring purposes
v_CSVFilename = "ebay-orders-" + zoho.currenttime.toString("yyyy-MM-dd-HH-mm-ss") + ".csv";
l_CsvFileRows.add("-----------------------------" + v_CSVFilename);
//
// usually \n works on some systems but this one works on systems that \n doesn't
f_CSVFile = l_CsvFileRows.toString(zoho.encryption.urlDecode("%0A")).toFile(v_CSVFilename);
//
// just adding these in case
v_JsonFilename = "ebay-orders-" + zoho.currenttime.toString("yyyy-MM-dd-HH-mm-ss") + ".json";
f_JsonFile = m_Response.toString().toFile(v_JsonFilename);
//
// send via Email
v_CountRows = l_CsvFileRows.size() - 2;
v_Subject = "NextWheelsTyres: " + l_JsonOrders.size() + " eBay Orders Export for year: " + v_Year;
v_Message = "Hi there!<br /><br />Please find attached a log of <b>" + l_JsonOrders.size() + "</b> order(s) created in the year <b>"+v_Year+"</b> from eBay that was exported on <b>" + zoho.currenttime.toString("EEEE, dd-MMM-yyyy") + "</b><br /><br />This is an automated email. Please do not reply to it.<br /><br />Kind Regards,<br /><br />The Team";
sendmail
[
from :zoho.adminuserid
to :"Joel Lipman <This email address is being protected from spambots. You need JavaScript enabled to view it.>"
subject :v_Subject
message :v_Message
Attachments :file:f_CSVFile,file:f_JsonFile
]
}
//
// Output
return "Exported " + l_JsonOrders.size() + " order(s)";
- /*
- Function: fn_GetEbayOrders()
- Purpose: Queries eBay for all orders for a specified year
- Date Created: 2023-03-29 (Joel Lipman)
- - Initial release
- Date Modified: 2023-03-29 (Joel Lipman)
- - Added in ability to list errors and query order line item IDs (ErrCode: 21917182)
- - Modified to check that there are some orders.
- More Info:
- - API Explorer Test Tool: https://developer.ebay.com/DevZone/build-test/test-tool/default.aspx?index=0&env=production&api=trading
- - GetOrders Documentation: https://developer.ebay.com/Devzone/XML/docs/Reference/eBay/GetOrders.html
- - eBay Errors by Number: https://developer.ebay.com/devzone/xml/docs/Reference/ebay/Errors/errormessages.htm
- */
- //
- // declare
- v_Page = 1;
- v_PerPage = 100;
- l_Pages = List();
- //
- // specify the maximum number of orders you think you have on eBay (check eBay homepage and see number of sales [ will be rounded to nearest 1000 ])
- // the actual number may be less than this but this is for pagination estimates
- v_MaximumOrders = 10000;
- v_Year = 2022;
- //
- // set the filter for orders by status to return: All, Active, Cancelled, CancelPending, Completed, Inactive, InProcess
- v_OrderStatus = "All";
- //
- // calculate from and till
- v_OrdersFrom = v_Year + "-01-01T00:00:00.000Z";
- v_OrdersTill = v_Year + "-12-31T23:59:59.000Z";
- //
- // now let's generate the page list to have all the available pages
- v_TotalNumberOfPages = ceil(v_MaximumOrders / v_PerPage);
- l_AddPages = leftpad(" ",v_TotalNumberOfPages).replaceAll(" ",",").toList();
- for each index v_Increment in l_AddPages
- {
- l_Pages.add(v_Increment + 1);
- }
- v_TotalNumberOfPages = l_Pages.size();
- //
- // declare variables to store order details in a JSON or ZohoDeluge Map format
- m_Response = Map();
- l_JsonOrders = List();
- //
- // start preparing CSV file to email for export
- v_ReportCSV = "Date,Order ID,Status,Amount,Currency,Notes";
- l_CsvFileRows = List();
- l_CsvFileRows.add(v_ReportCSV);
- //
- // get access token
- v_AccessToken = standalone.fn_eBay_GetAccessToken();
- //
- v_TradingAPIVersion = 967;
- v_Endpoint = "https://api.ebay.com/ws/api.dll";
- //
- // build header
- m_Headers = Map();
- m_Headers.put("X-EBAY-API-SITEID",3);
- m_Headers.put("X-EBAY-API-COMPATIBILITY-LEVEL",v_TradingAPIVersion);
- v_ApiCall = "GetOrders";
- m_Headers.put("X-EBAY-API-CALL-NAME",v_ApiCall);
- m_Headers.put("X-EBAY-API-IAF-TOKEN",v_AccessToken);
- //
- // build params
- m_Params = Map();
- m_Params.put("WarningLevel","High");
- m_Params.put("ErrorLanguage","en_GB");
- m_Params.put("DetailLevel","ReturnAll");
- m_Params.put("OrderStatus","All");
- m_Params.put("SortingOrder","Ascending");
- m_Params.put("CreateTimeFrom",v_OrdersFrom);
- m_Params.put("CreateTimeTo",v_OrdersTill);
- //
- // select which fields to return
- l_OutputFields = List();
- l_OutputFields.add("OrderID");
- l_OutputFields.add("OrderStatus");
- l_OutputFields.add("AmountPaid");
- l_OutputFields.add("CreatedTime");
- l_OutputFields.add("TotalNumberOfPages");
- l_OutputFields.add("TotalNumberOfEntries");
- m_Params.put("OutputSelector",l_OutputFields);
- //
- // now lets loop through a dynamic page list
- for each v_Page in l_Pages
- {
- //
- // specify which page
- m_Pagination = Map();
- m_Pagination.put("PageNumber",v_Page);
- m_Pagination.put("EntriesPerPage",v_PerPage);
- m_Params.put("Pagination",m_Pagination);
- //
- // convert to xml and replace root nodes
- x_Params = m_Params.toXML();
- x_Params = x_Params.toString().replaceFirst("<root>","<?xml version=\"1.0\" encoding=\"utf-8\"?><" + v_ApiCall + "Request xmlns=\"urn:ebay:apis:eBLBaseComponents\">");
- x_Params = x_Params.toString().replaceFirst("</root>","</" + v_ApiCall + "Request>");
- //
- //info "Request Sent to eBay:";
- //info x_Params;
- //
- // send the request XML as a string
- x_ResponseBody = invokeUrl
- [
- url :v_Endpoint
- type :POST
- parameters:x_Params
- headers:m_Headers
- ];
- //info "Response from eBay:";
- //info x_ResponseBody;
- //
- // get pagination results from the first iteration/page
- if(v_Page == 1)
- {
- //
- // get page results
- x_PaginationResult = x_ResponseBody.subString(x_ResponseBody.indexOf("<PaginationResult"),x_ResponseBody.lastIndexOf("</PaginationResult") + 19);
- v_TotalNumberOfOrders = x_PaginationResult.executeXPath("/PaginationResult/TotalNumberOfEntries/text()").toLong();
- //
- // determine total number of pages required
- v_TotalNumberOfPages = ceil(v_TotalNumberOfOrders / v_PerPage);
- info "Total Order(s): " + v_TotalNumberOfOrders;
- info "Total Page(s): " + v_TotalNumberOfPages;
- }
- //
- // loop through orders in response
- v_OrderNodePart = "Order";
- v_OrderNodeName = v_OrderNodePart + "Array";
- //
- // check node is paired to closing tag
- if(x_ResponseBody.contains("</" + v_OrderNodeName + ">"))
- {
- x_OrderNode = x_ResponseBody.subString(x_ResponseBody.indexOf("<" + v_OrderNodeName),x_ResponseBody.lastIndexOf(v_OrderNodeName) + v_OrderNodeName.length() + 1);
- l_Orders = x_OrderNode.executeXPath("/" + v_OrderNodeName + "/" + v_OrderNodePart).toXmlList();
- for each x_Order in l_Orders
- {
- //
- // parse the XML
- v_ThisOrderID = x_Order.executeXPath("//OrderID/text()");
- v_ThisOrderStatus = x_Order.executeXPath("//OrderStatus/text()");
- v_ThisOrderAmountPaid = x_Order.executeXPath("//AmountPaid/text()").toDecimal();
- v_ThisOrderCurrency = x_Order.executeXPath("//AmountPaid/@currencyID").executeXPath("/currencyID/text()");
- v_ThisOrderDateCreated = x_Order.executeXPath("//CreatedTime/text()");
- //
- // build JSON row
- m_Order = Map();
- m_Order.put("OrderID",v_ThisOrderID);
- m_Order.put("OrderStatus",v_ThisOrderStatus);
- m_Order.put("AmountPaid",v_ThisOrderAmountPaid);
- m_Order.put("Currency",v_ThisOrderCurrency);
- //
- v_ThisOrderDateCreated = if(!isnull(v_ThisOrderDateCreated),v_ThisOrderDateCreated.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime).toString("yyyy-MM-dd HH:mm:ssZ");
- m_Order.put("CreatedTime",v_ThisOrderDateCreated);
- //
- l_JsonOrders.add(m_Order);
- //
- // generate CSV row for monitoring purposes
- l_CsvFileRow = List();
- l_CsvFileRow.add(v_ThisOrderDateCreated);
- l_CsvFileRow.add("\"" + v_ThisOrderID + "\"");
- l_CsvFileRow.add("\"" + v_ThisOrderStatus + "\"");
- l_CsvFileRow.add(v_ThisOrderAmountPaid);
- l_CsvFileRow.add(v_ThisOrderCurrency);
- l_CsvFileRow.add(" ");
- //
- v_CsvRow = l_CsvFileRow.toString();
- l_CsvFileRows.add(v_CsvRow);
- }
- }
- //
- // report on errors of this page as well
- v_ErrorNodePart = "Errors";
- if(x_ResponseBody.contains("<" + v_ErrorNodePart))
- {
- x_ErrorNode = "<" + v_ErrorNodePart + "_Root>" + x_ResponseBody.subString(x_ResponseBody.indexOf("<" + v_ErrorNodePart),x_ResponseBody.lastIndexOf(v_ErrorNodePart + ">") + v_ErrorNodePart.length() + 1) + "</" + v_ErrorNodePart + "_Root>";
- l_Errors = x_ErrorNode.executeXPath("//" + v_ErrorNodePart).toXmlList();
- for each x_Error in l_Errors
- {
- v_ThisErrorLineItemID = x_Error.executeXPath("//ErrorParameters/Value/text()");
- v_ThisErrorMessage = x_Error.executeXPath("//LongMessage/text()");
- //
- m_Error = Map();
- m_Error.put("Error Line Item ID",v_ThisErrorLineItemID);
- m_Error.put("Error Message",v_ThisErrorMessage);
- l_JsonOrders.add(m_Error);
- //
- // generate CSV row for monitoring purposes
- l_CsvFileRow = List();
- l_CsvFileRow.add("????");
- l_CsvFileRow.add("\"" + v_ThisErrorLineItemID + "\"");
- l_CsvFileRow.add(" ");
- l_CsvFileRow.add(" ");
- l_CsvFileRow.add(" ");
- l_CsvFileRow.add(v_ThisErrorMessage);
- //
- v_CsvRow = l_CsvFileRow.toString();
- l_CsvFileRows.add(v_CsvRow);
- }
- }
- //
- // break if page has exceeded max
- if(v_Page >= v_TotalNumberOfPages)
- {
- break;
- }
- }
- //
- m_Response.put("orders",l_JsonOrders);
- //
- // lets send the CSV and JSON by email
- if(l_JsonOrders.size() > 0)
- {
- //
- // generate a CSV list for monitoring purposes
- v_CSVFilename = "ebay-orders-" + zoho.currenttime.toString("yyyy-MM-dd-HH-mm-ss") + ".csv";
- l_CsvFileRows.add("-----------------------------" + v_CSVFilename);
- //
- // usually \n works on some systems but this one works on systems that \n doesn't
- f_CSVFile = l_CsvFileRows.toString(zoho.encryption.urlDecode("%0A")).toFile(v_CSVFilename);
- //
- // just adding these in case
- v_JsonFilename = "ebay-orders-" + zoho.currenttime.toString("yyyy-MM-dd-HH-mm-ss") + ".json";
- f_JsonFile = m_Response.toString().toFile(v_JsonFilename);
- //
- // send via Email
- v_CountRows = l_CsvFileRows.size() - 2;
- v_Subject = "NextWheelsTyres: " + l_JsonOrders.size() + " eBay Orders Export for year: " + v_Year;
- v_Message = "Hi there!<br /><br />Please find attached a log of <b>" + l_JsonOrders.size() + "</b> order(s) created in the year <b>"+v_Year+"</b> from eBay that was exported on <b>" + zoho.currenttime.toString("EEEE, dd-MMM-yyyy") + "</b><br /><br />This is an automated email. Please do not reply to it.<br /><br />Kind Regards,<br /><br />The Team";
- sendmail
- [
- from :zoho.adminuserid
- to :"Joel Lipman <info+This email address is being protected from spambots. You need JavaScript enabled to view it.>"
- subject :v_Subject
- message :v_Message
- Attachments :file:f_CSVFile,file:f_JsonFile
- ]
- }
- //
- // Output
- return "Exported " + l_JsonOrders.size() + " order(s)";
Error(s):
- ErrorCode (21917182) Version 1289 - Invalid orderlineids. OrderLineItemIDs 25#########-296######## could not be found. Associated Items may have been deleted or removed.: --> Get more information by querying the item in the order --> Order Array was blank using GetOrderTransactions. --> Unresolved: Ouput line item ID as order ID and error message in notes column.
- Invalid value for header "X-EBAY-API-DETAIL-LEVEL": --> I was trying to send JSON when it should be an XML request.
- One or more specified index values were invalid. Index value must range between 0 and the length of the text Line Number:173: --> Add check if <Errors> tag exists in response