Category Archives: ebay开发

【ebay开发】10/8发布管家婆v2.2

10/8号我将发布管家婆v2.2,具体的更新包括:

1)正式发布管家婆团队版,包括sql server安装指南等。

2)添加case处理模块:我们将能在管家婆中下载、查看和处理ebay case(暂不能处理paypal caes)。【已完成】

3)消息模块更新:添加功能查看消息附件(如图片),但是暂不能发送消息时带上图片。【已完成】

4)在线商品分析功能:对于一个sku,可以对比在线数库存数,防止超卖。【v2.3】

5)采购模块更新

5.1 在途采购单可以修改。

5.2 新建采购单可以不用输入供应商。【已完成】

6)订单管理更新

6.1 增加“已打印”文件夹。【已完成】

6.2 增加订单重发功能:重发后,生成新单号,订单从已发货转入待指定物流方式状态。【已完成】

6.3 合并订单和拆单功能。【已完成】

6.4 添加手动订单功能。【已完成】

6.5 批量上传跟踪号,如可以导入4px的excel,上传跟踪号。【v2.3】

6.6 选择时间范围按sku进行销售额统计。【已完成】

7)商品管理:

7.1 商品信息展示中增加”可用库存“和”在途库存“。【已完成】

7.2 添加商品状态:在售,试卖,停售,淘汰。

7.3 增加商品属性:备货天数,为系统生成“采购建议”做准备。【已完成】

8)系统管理

8.1 将ebay账号(token)等信息存入数据库中,好处是以后更新系统时,不需要拷贝SystemSettings.xml了,数据全部在ebaydata.accdb或者sql server数据库中。【已完成】

8.2 增加帮助链接:在绑定账号,添加商品sku等处添加url,跳转到帮助网页。

未完。。。

【管家婆开发】消息下载及其他

今天网友haha提了一个需求,也正中我们的痛处,那就是我们经常要重发订单,所以订单管理里面要增加一个重发订单的功能,具体的操作:

1)在目录“已发货订单”中选中一条订单

2)右击该订单,选中重发订单,订单进入“待指定物流方式”目录,同时订单显示一个图标表示该订单为重发订单。

3)生成一个新单号,这很重要,因为把订单导入4px等系统时,不允许用以前用过的单号,所以不改单号是不行的。

4)剩下的发货流程同普通订单。

今天还发现管家婆一个比较大的设计问题是消息下载的时间设置:现在下载消息的时间段同订单下载的时间段,为了加快下载速度,我们都是选择下载一天内的订单,仓库的小J每天会下载订单,但不会下载消息,等我们周一来的时候,如果不改下载订单的时间段,则下载时间为1天内的,那么很多消息就漏掉了,今天就遇到了几个愤怒的买家,这个问题是一个设计的问题,好的设计应该是能保证无论如何用户都不会漏单或者漏掉新消息

解决方法之一是在数据库中记录上次订单和消息分别下载到什么时候,那么这次下载只下载上次时间前5分钟(重叠5分钟为了防止漏单或者漏消息)到现在的订单/消息,下载完成后,更新数据库中存的那个时间,这样如果用户不久前刚刚下载,则下载就非常快。

ebay管家婆v2.0

先给大家致歉:期许的ebay管家婆v2.0到今日还没有发布,不过这段时间我快马加鞭,大部分功能已经有了,只要在完善,测似并撰写帮助文档就可以发布了!

在v2.0中,用户需要绑定paypal账号,这样做的好处是:

  • 可以检测ebay地址和paypal地址是不是一致。
  • 可以计算利润信息。

下面是v2.0的截图,敬请期待!

ebaymasterv2

ebay管家婆新春版正在紧张研发中。。。

各位亲,你可能觉得ebay管家婆有好几天没更新了,告诉大家一个好消息,就是我正在筹划ebay管家婆新春版,初步定于初八发布(2014年2月7号)。

新春版将做如下的更新:

1)优化软件整体的界面:调整界面的布局,更加美化,更加方便。

2)订单处理:

  • 下载订单可以选择下载近几天发生变化的订单(例如新生成的,买家付款的,买家留好评的),现在的方式是下载指定时间段内生成的。
  • 订单分类:待处理订单,待打印订单等
  • 订单处理:可以只标记发货而不留好评
  • 添加手动订单功能。
  • 过滤查找特定条件的订单。

3)消息管理:实现类似outlook风格的界面。

4)商品管理

  • 更完善的添加商品,查看商品界面。
  • 完善供应商管理,采购管理,入库出库管理,

5)帐目管理

  • 下载ebay的各种上架费,成交费等。

敬请期待!

第一笔收入

事情是酱紫滴:

有一个深圳的哥们,在ebay论坛看到了我的帖子,于是找我,说他有一个小需求想实现,问能不能帮忙。

考虑到长远合作的可能性,我答应帮忙,并且承诺如果实现简单免费帮他做。

结果这个小需求的确挺简单,我几个小时搞出来了,发给他试用,他觉得还行,为表达谢意给我手机充了100块话费。

俺ebay软件的第一笔收入就此诞生 :)

ebay管家婆 v1.02版本发布

各位亲,

周六一天我都宅在家里,安心开发管家婆v1.02版本,现在v1.02版本终于和大家见面了:请到下载页面下载。

1)安装包:现在提供给大家一个安装包,这样更加方便了,同时因为有了安装包,也可以申请360的审核。

2)自动升级:

现在的管家婆可以自动升级了,升级的原理是每次启动的时候,从ebaymaster.cn的服务器下载一个文件,这个文件包含当前的最新版本,和最新版本对应的升级包的网址,然后如何管家婆发现当前版本小于最新版本,就提示用户是否升级。

如果用户同意了,则下载升级包,更新原来的管家婆程序,程序就变成最新版本的了。

注意的是:在这个过程管家婆不会上传你的数据,请注意保管你的SystemSettings.xml里面的token和data/ebaydata.accdb里面的数据。

autoupgrade

3)消息模板的导入和导出:方便几个电脑之间同步数据。

注意:如果你原先已经使用了绿色版,安装了现在的安装包后,你需要把SystemSettings.xml和data/ebaydata.accdb拷贝到管家婆的新位置(一般在C:\Program Files\EbayMaster)

“良民证”

快下班的时候,公司的几个同事Communicator上找我,约我晚上去喝酒。

要是在北京上学的时候,二话不说,晚上肯定不醉不归,可是现在女儿刚刚90多天,嗷嗷待哺,我要是晚上不回去,老婆能把我从六楼扔下去。。。所以只能断然回绝了。

话说ebay论坛的那篇帖子,有个哥们回复说”大家千万不要用,QQ管家说极度危险“,我第一感觉是不太爽,第二感觉是这个哥们说的对,为啥?其他用户可能下载了,运行的时候360报说有风险,就关了,也没告诉我,我也不知道。这哥们这么一提,我就开始重视要做安装包,然后通过360/QQ空间的审核了。

360审核我是申请了,可惜不是安装包,审核没通过:

360verify

话说我上学那会,还没有360,软件拷贝到电脑上就能用,现在你要想让用户使用,就必须要有“良民证”,好比没有经过x和政府审核过的出版物就是非法出版物一样,我等既然没办法逆规则而行,只能遵守规则鸟。

良民证,可以有!

 

群发消息功能

做ebay的人都知道:沟通很重要!发完货后,过了一两个礼拜,问问买家的情况:怎么样了啊?货收到了没?有没有什么问题,喜欢不?买家收到这样的信后,即使长时间没收到货,或者货质量一般,他们一般也会感动于你的嘘寒问暖,差评的可能性就小很多!

我做ebay 2年多,一直是这样做,100%好评!可以最近有点懈怠,好久没问买家情况,得了一个差评,还有几个case :..(

跟ebay买家沟通,通过ebay网站的功能,实在效率较低,所以在管家婆中,我想把这块功能做好,做的简单方便:

  • 消息群发功能:可以同时给N个买家一起发信,问他们收到货没有。
  • 每个交易的来往信件都显示在一起,便于卖家比较对比。

下面是已经完成的功能截图:

群发消息:先按住shift键,选中所有要发消息的交易:

sendmsg01

然后 右键 选中“给买家写信“,弹出发信对话框:在这里,上面显示了所有的接收者,中间是消息模板,你可以选择一个模板(点击”管理消息模板“ 可以添加修改消息模板),选中一个模板,下面消息正文出现了模板的内容,你可以加以编辑,然后点击发送。

sendmsg02

正在发送消息:
sendmsg03

最后是 某一交易的所有往来信件 对话框:

sendmsg04

下载订单功能完成

今天完成了ebay管家婆的下载订单功能。

用户可以在管家婆左侧选择下载订单的开始时间结束时间(北京时间),然后点击”下载ebay数据“按钮,就可以下载数据了。下载数据的时候,管家婆会弹出一个进度窗口提示总共要更新多少订单和当前在下载的订单,是不是很一目了然? 🙂

另外管家婆管理的所有ebay账号的订单都会被下载,对于系统中没有的订单信息,管家婆会保存此订单信息;对于系统中已经有的订单,管家婆会更新系统中的订单信息(例如系统中的订单还是未付款状况,但是用户在上次下载数据后已经付款了,这样系统中的订单也会被更新成已付款状况)。

ebaymaster_syncorder

利用ebay api获取ebay订单(2)

在上一篇帖子里,我介绍了处理ebay订单需要了解的几个基本概念:订单号OrderID,交易号TransactionID,和唯一标识一个交易的OrderLineItemID,在这个帖子里,我们介绍:

  • 利用ebay api GetOrders函数获取卖家订单信息,包括调用这个函数时一些需要注意的事项。
  • 设计数据库表来存储订单信息。
  • 和处理订单相关的其他一些ebay api函数。

一般ebay卖家的历史订单数量很大,如果每次调用GetOrders都获取所有订单既浪费时间,也没必要, GetOrders提供几个过滤器来过滤订单,过滤器输入主要有以下几项:

  • CreateTimeFrom / CreateTimeTo: 指定只获取这段时间范围内产生的订单,注意最大的时间范围是90天。如果输入中指定了NumberOfDays,或者输入指定了Order IDs,则CreateTimeFrom/CreateTimeTo失效!
  • ModTimeFrom / ModTimeTo:指定获取在这段时间范围内发生修改的订单(创建或者状态改变,如shipped等),最多能获取最近30天状态发生改变的订单,请使用这个Filter!!
  • NumberOfDays:指定获取最近NumberOfDays天数里生成或者被修改的订单,这个参数我也没用过!
  • OrderIDArray:只获取订单号在这个数组中的订单。

GetOrders还有其他过滤器输入,在此不表,看官如有兴趣可参考ebay官方文档。上述的几个输入,是有优先次序的:

OrderIDArray > NumberOfDays > CreateTimeFrom/CreateTimeTo > ModTimeFrom/ModeTimeTo

举个例子,如果输入中同时指定了OrderIDArray和NumberOfDays,则NumberOfDays失效!

======================================

获取订单的方式:

1)系统自动下载订单:每隔一段时间(例如5分钟)调用一次GetOrders,

  • ModTimeFrom设置为上次下载结束时间的前2分钟,将ModTimeTo设置为当前时间
  • 注意ebay api的时间都是UTC时间,如果使用c#/.net的话,需要用DateTime.ToUniversalTime将本地时间转化为ebay时间(反过来通过DateTime.ToLocalTime将ebay的UTC时间转化为本地时间)。
  • 需要为GetOrders设置分页Pagination,GetOrders每页最大可以包含100条数据。
  • 通过HasMoreOrders字段看是否还有其他记录,详见下面的代码:

2)手动下载订单:

  • 同上,不过系统在数据库中记录上次下载到什么时间,当前下载从上次下载结束时间的前2分钟开始,注意上次下载结束到现在的时间间隔如果超过30天,则只能下载最近30天的数据。

我在ebay管家婆中实现的获取订单的方式是,先用DetailLevel=ReturnSummary来调用GetOrder,这样就可以返回指定时间内所有订单的订单号:

    // Given a time period specified by startDate and endDate, returns all the order ids created in that period.
// note startDate/endDate are all local date.
// CAUTION: ****The maximum date range that may be specified with the ModTimeFrom and ModTimeTo fields is 30 days.****
// If ModTimeTo-ModTimeFrom > 30 days, then select orders in range [ModTimeTo-30, ModTimeTo].
public static StringCollection GetAllOrderIds(AccountType account, DateTime startDate, DateTime endDate)
{
if (account.SellerApiContext == null)
return null;
GetOrdersCall getOrdersApiCall = new GetOrdersCall(account.SellerApiContext);
DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[] { DetailLevelCodeType.ReturnSummary };
getOrdersApiCall.DetailLevelList = new DetailLevelCodeTypeCollection(detailLevels);
getOrdersApiCall.Pagination = new eBay.Service.Core.Soap.PaginationType();
getOrdersApiCall.Pagination.EntriesPerPage = 100;
getOrdersApiCall.Pagination.PageNumber = 1;
//
// If ModTimeTo-ModTimeFrom > 30 days, then select orders in range [ModTimeTo-30, ModTimeTo].
//
TimeSpan ts = endDate - startDate;
if (ts.TotalDays > 30)
{
Logger.WriteSystemLog(String.Format("ModTimeTo-ModTimeFrom> 30 days, select range [ModTimeTo-30, ModTimeTo]"), LogLevel.Warning);
startDate = endDate.AddDays(-29);
}
getOrdersApiCall.ModTimeFrom = startDate.ToUniversalTime();
getOrdersApiCall.ModTimeTo = endDate.ToUniversalTime();
getOrdersApiCall.OutputSelector = new string[] {               
"HasMoreOrders",
"OrderArray.Order",
"OrderArray.Order.ID",
"OrderList.OrderId",
};
try
{
getOrdersApiCall.Execute();
}
catch (System.Exception ex)
{
Logger.WriteSystemLog(String.Format("GetAllOrderIds: GetOrdersCall threw exception with err msg={0}", ex.Message),
LogLevel.Error);
return null;
}
if (getOrdersApiCall.OrderList == null)
return null;
Logger.WriteSystemLog(String.Format("Retrieved {0} orders", getOrdersApiCall.OrderList.Count));
StringCollection orderIds = new StringCollection();
foreach (OrderType order in getOrdersApiCall.OrderList)
{
orderIds.Add(order.OrderID);
}
while (getOrdersApiCall.HasMoreOrders)
{
getOrdersApiCall.Pagination.PageNumber++;
getOrdersApiCall.ModTimeFrom = startDate.ToUniversalTime();
getOrdersApiCall.ModTimeTo = endDate.ToUniversalTime();
getOrdersApiCall.Execute();
Logger.WriteSystemLog(String.Format("Has more orders : retrieved {0} orders", getOrdersApiCall.OrderList.Count));
foreach (OrderType order in getOrdersApiCall.OrderList)
{
orderIds.Add(order.OrderID);
}
}
return orderIds;
}

获得了订单号后,再调用GetOrders,指定DetailLevel=ReturnAll,这样就可以获取这些订单的详细信息,然后我们分析这些信息并存储到数据库:

特别注意的是:需要检查GetOrders获取的Order的checkout status,如果checkout status不是compeleted,就说明订单付款未完成,这种Order需要忽略掉。

还需要检查订单的eBayPaymentStatus,必须是NoPaymentFailure才可以。

public static List<EbayTransactionType> GetAllOrders(AccountType account, TimeFilter timeFilter, StringCollection orderIds)
{
    List<EbayTransactionType> transList = new List<EbayTransactionType>();
    GetOrdersCall getOrdersApiCall = new GetOrdersCall(account.SellerApiContext);
    getOrdersApiCall.IncludeFinalValueFee = true;
    DetailLevelCodeType[] detailLevels = new DetailLevelCodeType[] { DetailLevelCodeType.ReturnAll };
    getOrdersApiCall.DetailLevelList = new DetailLevelCodeTypeCollection(detailLevels);
    if (orderIds != null)
        getOrdersApiCall.OrderIDList = orderIds;
    OrderTypeCollection orders = getOrdersApiCall.GetOrders(timeFilter, TradingRoleCodeType.Seller, OrderStatusCodeType.All);
    foreach (OrderType order in orders)
    {
        if (order.CheckoutStatus.Status != CompleteStatusCodeType.Complete)
continue;
if (order.CheckoutStatus.eBayPaymentStatus != PaymentStatusCodeType.NoPaymentFailure)
continue;
        foreach (TransactionType trans in order.TransactionArray)
        {
            // Process each transaction.
        }      
    }
    return transList;
}   // GetAllOrders

上面程序的一个小问题就是:如果timeFilter和orderIds都指定了,那么timeFilters失效。

为什么用OrderIDs这个过滤器而不用NumberOfDays了?因为获取了订单的号后,我们可以给用户展示一个进度条,这样的设计比较友好。

在具体分析每一个ebay交易的时候,有些问题需要注意:

  • 多种款式商品(multi-variation):一口价的list,有些可以设置成含多种款式的,比如衣服,可以有红色、蓝色等,尺寸有S/M/L/XL等,一个ebay交易,是不是multi-variation对分析订单是有影响的。

比方说有一个multi-variation的list,里面有红色、黄色两种狗狗衣服,每种颜色有S/M/L/XL不同大小,我们会在上架时给他们设置不同的SKU:

- Dog Clothes Red S (sku=100001)
- Dog Clothes Red M (sku=100002)
- Dog Clothes Red L (sku=100003)
- Dog Clothes Red XL (sku=100004)
- Dog Clothes Yellow S (sku=100005)
- ...

ebay api中定义的TransactionType含有两个成员:ItemTitle/ItemSKU,对于非multi-variation list,这两个成员就是你上架时设置的;但是对于multi-variation list,这两个成员不好用了!比方说用户买了“Dog Clothes Red L”,我们要这样才能正确获取标题和SKU:

// What is the valid way to determine if there is a variation?
if (trans.Variation != null && trans.Variation.VariationTitle != null && trans.Variation.VariationTitle.Trim() != "")
{
    // ItemTitle
    ebayTrans.ItemTitle = trans.Variation.VariationTitle;
    // ItemSKU
    ebayTrans.ItemSKU = trans.Variation.SKU;
}
else
{
    // ItemTitle
    ebayTrans.ItemTitle = trans.Item.Title;
    // ItemSKU
    ebayTrans.ItemSKU = trans.Item.SKU;
}
  • 订单是否已经付款?有些订单用户使用信用卡付款的,这些付款经过paypal处理的时候需要几天时间,在ebay管家婆中,我都视这些订单为已付款状况:【2015/3/18更新注意如果是checkout status=compelete && eBayPaymentStatus=NoPaymentFailure,则到这步的订单应该都付款了!】
ebayTrans.IsPaid = order.PaidTimeSpecified;
if (ebayTrans.IsPaid == false)
{
    // Some payment is paid using credit card, and while PayPal is processing the payment,
    // the transaction is marked as unpaid. we should view it as paid.
    if (order.OrderStatusSpecified && order.OrderStatus == OrderStatusCodeType.Completed)
        ebayTrans.IsPaid = true;
}
if (ebayTrans.IsPaid == false)
{
    if (order.CheckoutStatus.StatusSpecified && order.CheckoutStatus.Status == CompleteStatusCodeType.Complete)
        ebayTrans.IsPaid = true;
}
  • 获取评价信息:这样我们可以了解买家是否留好评:【2015/3/18更新:ebay限制每天调用GetFeedback的次数,因此按我原来的方式是不行的,不能一个订单一个订单的获取feedback,应该批量下载feedback处理和存储】
GetFeedbackCall getFeedbackApiCall = new GetFeedbackCall(account.SellerApiContext);
getFeedbackApiCall.DetailLevelList = new DetailLevelCodeTypeCollection(detailLevels);
getFeedbackApiCall.OrderLineItemID = trans.OrderLineItemID;
FeedbackDetailTypeCollection feedbacks = getFeedbackApiCall.GetFeedback();
foreach (FeedbackDetailType feedback in feedbacks)
{
    if (feedback.CommentingUser == account.ebayAccount)
        ebayTrans.IsSellerLeftFeedback = true;
    if (feedback.CommentingUser == ebayTrans.BuyerId)
        ebayTrans.IsBuyerLeftFeedback = true;
}
  • 获取订单物流跟踪号:
 if (trans.ShippingDetails != null)
{
    if (trans.ShippingDetails.ShipmentTrackingDetails.Count == 1)
    {
        ShipmentTrackingDetailsType shipmentDetails = trans.ShippingDetails.ShipmentTrackingDetails[0];
        ebayTrans.ShippingTrackingNo = shipmentDetails.ShipmentTrackingNumber;
    }
}
  • 获取发货时间:
// IsShipped
ebayTrans.IsShipped = order.ShippedTimeSpecified;
if (order.ShippedTimeSpecified)
ebayTrans.ShippedDate = order.ShippedTime;

另外注意一点:关于调用ebay api获取的时间都是格林威治时间,中国是+8区,所以如果获取的时间是2013/04/11 02:10:00,则北京时间是2012/04/11 10:10:00,c#中可以通过DateTime.ToLocalTime来把一个格林威治时间转换为本地时间。