Pulling orders from your ChannelAdvisor account is easy!
Retrieve the orders that have not already been exported by your developer key. Here's the flow (you can see the details in the C# sample below or the attached project files
):
1. Define your order criteria, for example Payment Cleared, and Unshipped.
2. Set the orderCriteria's ExportState to NotExported.
3. Set PageNumberFilter to 1
3. Call GetOrderList and process the first page of Orders returned.
4. Once you've imported the orders for the page, call SetOrdersExportStatus to mark them as Exported.
5. Increment PageNumberFilter and go back to step 3. Repeat until 0 orders are returned in the response.
NOTE: Orders marked as exported will not appear in future GetOrderList calls.
NOTE: The Export state is tracked by your developer key. This means that you will not be affected by another developer's application that is pulling orders from your account (assuming they have security rights to read the same account data as you). If you have two different applications exporting orders, you can request a second developer key so your two applications don't collide.
The sample below is a C# windows application.
Follow these steps to get it working (this is not meant to be an intro to working with web services in .NET): Project files are here
.
1. Create a C# windows app. Mine is called sampleExport.
2. Add a web service reference pointing to https://api.channeladvisor.com/ChannelAdvisorAPI/v6/OrderService.asmx?WSDL
. .NET will create a web service proxy. Note that pointing the web reference to the url without ?WSDL at the end will cause the proxy builder tool to fail. My proxy's namespace is sampleExport.com.channeladvisor.api. You will need to change any references to that namespace in the code to match the namespace for your proxy. If you accepted the default when you added the web reference, it will most likely be <YourAppName>.com.channeladvisor.api
3. Put your credentials in the variables developerKey, password, and accountID.
4. Orders that are pulled down are just written to the disk, currently to C:\Orders\, and files are named <ClientOrderIdentifier>.xml. Feel free to change these.
5. Once the complete page of orders is written out, setOrdersExported is called, passing the list of ClientOrderIdentifiers.
6. By setting these as exported, the sample won't retrieve these orders again.
7. Writing the orders to disk could be used as a rudimentary queuing system. You could use a second application to do something else with them once they exist as files, or you can change the code here to do something more useful, like load them directly into a database.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using sampleExport.com.channeladvisor.api; // this is the .NET generated proxy for ChannelAdvisor web services
namespace sampleExport
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string developerKey = string.Empty;
string password = string.Empty;
string accountID = string.Empty;
developerKey = "DevKey";
password= "SomePassword";
accountID = "AccountKey";
OrderCriteria criteria = new OrderCriteria();
criteria.StatusUpdateFilterBeginTimeGMT = DateTime.UtcNow.AddDays(-30);
criteria.StatusUpdateFilterEndTimeGMT = DateTime.UtcNow;
// this would be like a Ready-To-Ship Report
criteria.PaymentStatusFilter = "Cleared";
criteria.ShippingStatusFilter = "Unshipped";
criteria.ExportState = "NotExported";
criteria.DetailLevel = "Complete";
criteria.PageSize = 20;
OrderService orderService = new OrderService();
orderService.APICredentialsValue = new APICredentials();
orderService.APICredentialsValue.DeveloperKey = developerKey;
orderService.APICredentialsValue.Password = password;
try
{
criteria.PageNumberFilter = 1;
while(true)
{
APIResultOfArrayOfOrderResponseItem orderResponse = orderService.GetOrderList(accountID, criteria);
if (orderResponse.Status == ResultStatus.Failure)
{
throw new Exception(orderResponse.Message);
}
if (orderResponse.ResultData.Length == 0)
break; // we ran out of pages that have data in them
List<string> clientOrderIdentifiers = new List<string>();
XmlSerializer serializer = new XmlSerializer(typeof(OrderResponseDetailComplete));
XmlTextWriter writer = null;
foreach(OrderResponseItem order in orderResponse.ResultData)
{
OrderResponseDetailComplete completeOrder = order as OrderResponseDetailComplete;
//put the order on the disk as its own file
using (writer = new XmlTextWriter(string.Format(@"C:\orders\{0}.xml", completeOrder.ClientOrderIdentifier), System.Text.Encoding.UTF8))
{
serializer.Serialize(writer, completeOrder);
}
//keep the ClientOrderIdentifier so we can send a batch to mark the orders as exported, filtering the orders from future queries
clientOrderIdentifiers.Add(completeOrder.ClientOrderIdentifier);
}
//submit our batch of processed orders
APIResultOfArrayOfBoolean exportStatusResponse = orderService.SetOrdersExportStatus(accountID, clientOrderIdentifiers.ToArray(), true);
if (exportStatusResponse.Status == ResultStatus.Failure)
{
throw new Exception(exportStatusResponse.Message);
}
//make sure each order was succesfully updated
for (int responseCount = 0; responseCount < exportStatusResponse.ResultData.Length; ++responseCount)
{
if (exportStatusResponse.ResultData[responseCount] == false)
{
//order was not successfully marked as exported
MessageBox.Show("Order was not successfully marked as exported:" + orderResponse.ResultData[responseCount].ClientOrderIdentifier);
}
}
++criteria.PageNumberFilter;
}
}
catch (Exception ex)
{ // big catch for the entire function
MessageBox.Show(ex.ToString());
}
}
}
}
The GetOrderList request XML produced by the code above is equivalent to the following:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://api.channeladvisor.com/webservices/" xmlns:ord="http://api.channeladvisor.com/datacontracts/orders"> <soapenv:Header> <web:APICredentials> <web:DeveloperKey>DevKey</web:DeveloperKey> <web:Password>SomePassword</web:Password> </web:APICredentials> </soapenv:Header> <soapenv:Body> <web:GetOrderList> <web:accountID>AccountKey</web:accountID> <web:orderCriteria> <ord:StatusUpdateFilterBeginTimeGMT>2012-01-29T16:01:14.243</ord:StatusUpdateFilterBeginTimeGMT> <ord:StatusUpdateFilterEndTimeGMT>2012-02-28T16:01:14.243</ord:StatusUpdateFilterEndTimeGMT> <ord:DetailLevel>Complete</ord:DetailLevel> <ord:ExportState>NotExported</ord:ExportState> <ord:PaymentStatusFilter>Cleared</ord:PaymentStatusFilter> <ord:ShippingStatusFilter>Unshipped</ord:ShippingStatusFilter> <ord:PageNumberFilter>1</ord:PageNumberFilter> <ord:PageSize>20</ord:PageSize> </web:orderCriteria> </web:GetOrderList> </soapenv:Body> </soapenv:Envelope>
Right, you will not get updates if you mark it as exported, so you should mark orders exported when you aren't interested in any changes made in the ChannelAdvisor order. We have designed the Export feature to support a query of ChangedSinceLastExport, but that has not been created yet.
When this method is supposed to be ready?
Please also explain how StatusUpdateFilter works? If I turn ExportStatus On, then will i be able to get changes in statuses?
Actually it gets same orders again and again, But I don't want to get orders which and their statuses are unchanged.
The query for orders changed since the last export was never implemented and is not currently on the roadmap.
The status update filter is a window of time that you can define. If the checkout, payment, or shipping status of an order was changed during that time period, the order will be returned in the response. The common use case is to set the start date to the last time you queried for orders and set the end date to the present time.
Export status is simply a filtering mechanism that you can control. The idea is that you mark an order as exported once you no longer want GetOrderList to retrieve it and set the export state filter to NotExported in your GetOrderList requests. If you wish to retrieve exported orders, simply set the export state filter to Exported.
We use caching to improve the performance of GetOrderList, and as a result you can easily retrieve stale data by retrieving an order, updating it, and then retrieving it again while the cache is still alive. The list of orders that matches an exact set of filter criteria is cached for thirty minutes, and order details are cached for fifteen minutes.
How do I apply this example into my old ASP code?
You'll need to understand how to access SOAP web services from asp. Try googling it for articles. I found this which looks pretty good: http://www.devarticles.com/c/a/ASP/An-Introduction-To-XML-SOAP-Using-ASP-and-VB6/![]()
Once you get a reference to the web service in vb6, you should be able to follow along in the text at the top of the page and the code insert.
When using GetOrderList to pull orders from channel advisor into a 3rd party system, Can we use other custom attributes that we create or can we use standard Channel Advisor fields such as MPN & Manufacturer. I don't see them on the results but Im not by any means an expert on this. Thanks
The fields you mention are all inventory-related and are not necessarily pertinent to orders, but you can use the SKU from an order line item to retrieve that item's inventory data using the Inventory Service "get" methods if you need the MPN, attributes, or any other details of the item in your processing.
Is there any way setting the shipped flag to shipped when exporting the order?
No. You can submit shipment notifications for your orders using SubmitOrderShipmentList.
How can i get the total Tax Cost for the number of LineItems from the same order#?
In the above example why does the page number have to be incremented? If the first page of exported orders have their status set to exported surely when a repeat call is made the next set of orders are now the new page 1.
We use caching to significantly improve the performance of GetOrderList. The list of orders that results from a particular set of criteria (sans PageNumber) will be persisted for thirty minutes, during which time you can iterate through the pages using subsequent GetOrderList calls without worrying about the overall result set changing. If you change any criteria other than PageNumber, you will get a fresh set of pages.
way the code example in http://developer.channeladvisor.com/display/cadn/Application+Example+-+GetOrderList+by+ExportState
is not in line with the WSDL that page refers to. For example the code creates an OrderService object which contains an APICredentialsValue Property. There's nothing called OrderService defined in that WSDL. There's an abstract OrderServiceSoap, an abstract orderServiceSoapChannel, and an actual OrderServiceSoapClient, but none of them have a property called anything like APICredentialsValue.
There are a couple of different ways to reference a WSDL in .Net, and they use different naming schemes in the proxy classes they generate.
I think you're deliberately missing the point, Marshall. I've now tried v5, v5, v6 and v7 WSDL. None of them define the objects or structures you use in the sample code. Where do I go to for WSDL that matches your code, or where do I go for sample code that matches the WSDL? Either would be great.
Excuse me. v4, v5, v6 and v7
The sample code above assumes a web reference to the Order Service WSDL. You can download the entire sample solution using the link near the top of the page and see for yourself that the sample code is valid for the type of reference that is used in the project.
If you were to use a service reference, you would create and populate an APICredentials object and then use it as the first parameter to each method call. The method signatures in your proxy classes should make it fairly straightforward to see what is needed.
What happens if someone reopens the checkout (for example to split the order) after an order has been tagged as "Exported"? This is quite common and it appears that our downstream system would simply miss the change to the order in this case.
Ian Slinger