消息服务是开放平台为提高应用调用API效率而推出的一种主动推送服务( From淘宝 ),推送内容包括(淘宝交易、商品、退款等信息)。基于消息推送服务,应用只需要在接收到开放平台推送的消息时调用API即可,大大提高API调用效率和降低API使用费用。同时开放平台还提供消息回流服务( To淘宝 ),应用可将信息回流到淘宝,做商品数源服务等。
此处结合飞猪平台,只讨论消息主动推送服务( From淘宝 ),具体详情请参考开放平台
注意:如果该消息没有权限,则说明应用未开通相关API调用权限,通过点击“申请权限”,进入申请相应的权限包。
场景举例:订阅消息 taobao_trade_TradeChanged 当订单状态发生变更的时候,开放平台主动推送消息给应用。应用接收消息后 若只关心订单状态,则只需要将消息中的状态同步到本地即可; 若关心订单详情,则可以调用订单详情查询接口查询具体信息
调用taobao.tmc.user.permit接口给商家开通消息,需要选择开通的消息名称,如 taobao_trade_TradeChanged
接收消息的实现方式有两种:SDK方式,API方式。推荐采用SDK方式
目前支持JAVA与.NET语言,其它语言建议采用API接收消息。通过SDK接收消息只需要关注业务的处理,不需要操心消息重发、确认、长连接的重连等操作,SDK会自动处理好一切。
Java示例
TmcClient client = new TmcClient("app_key", "app_secret", "default"); // 若用户没有分组,则默认归属default分组 client.setMessageHandler(new MessageHandler() { public void onMessage(Message message, MessageStatus status) { try { System.out.println(message.getContent()); System.out.println(message.getTopic()); } catch (Exception e) { e.printStackTrace(); status.fail(); // 消息处理失败回滚,服务端需要重发 // 重试注意:不是所有的异常都需要系统重试。 // 对于字段不全、主键冲突问题,导致写DB异常,不可重试,否则消息会一直重发 // 对于,由于网络问题,权限问题导致的失败,可重试。 // 重试时间 5分钟不等,不要滥用,否则会引起雪崩 } } }); client.connect("ws://mc.api.taobao.com"); // 消息环境地址
C#示例
TmcClient client = new TmcClient("appkey", "appsecret", "default"); // 若用户没有分组,则默认归属default分组 client.OnMessage += (s, e) => { try { Console.WriteLine(e.Message.Topic); Console.WriteLine(e.Message.Content); // 默认不抛出异常则认为消息处理成功 } catch (Exception exp) { Console.WriteLine(exp.StackTrace); e.Fail(); // 消息处理失败回滚,服务端需要重发 // 重试注意:不是所有的异常都需要系统重试。 //对于字段不全、主键冲突问题,导致写DB异常,不可重试,否则消息会一直重发 // 对于,由于网络问题,权限问题导致的失败,可重试。 // 重试时间 5分钟不等,不要滥用,否则会引起雪崩 } }; client.Connect("ws://mc.api.taobao.com/"); // 消息环境地址
说明:采用main方法运行上面的代码测试时,请在client.connect()后面加上等待代码块,以便观察消息的实时接收情况。否则main线程结束后,TMC长连接也会断开。如果是在web服务器上运行上面的代码,则不用在client.connect()后面加任何等待代码,也不需要在外面包一层while(true)循环,因为web服务器上的主线程在服务器不关闭的情况下都是不会结束的,TMC的长连接会一直保持。
API方式是提供给处理多线程和长连接不方便的语言使用的,比如PHP,Python。这些语言官方暂时没有提供SDK。
Java示例
TaobaoClient client = new DefaultTaobaoClient("http://gw.api.taobao.com/router/rest", "app_key", "app_secret", "json"); do { long quantity = 100L; TmcMessagesConsumeResponse rsp = null; do { TmcMessagesConsumeRequest req = new TmcMessagesConsumeRequest(); req.setQuantity(quantity); req.setGroupName("default"); rsp = client.execute(req); if (rsp.isSuccess() && rsp.getMessages() != null) { for (TmcMessage msg : rsp.getMessages()) { // handle message System.out.println(msg.getContent()); System.out.println(msg.getTopic()); // confirm message TmcMessagesConfirmRequest cReq = new TmcMessagesConfirmRequest(); cReq.setGroupName("default"); cReq.setsMessageIds(String.valueOf(msg.getId())); TmcMessagesConfirmResponse cRsp = client.execute(cReq); System.out.println(cRsp.getBody()); } } System.out.println(rsp.getBody()); } while (rsp != null && rsp.isSuccess() && rsp.getMessages() != null && rsp.getMessages().size() == quantity); Thread.sleep(1000L); } while (true);
C#示例
ITopClient client = new DefaultTopClient("http://gw.api.taobao.com/router/rest", "app_key", "app_secret", "json"); do { long quantity = 100L; TmcMessagesConsumeResponse rsp = null; do { TmcMessagesConsumeRequest req = new TmcMessagesConsumeRequest(); req.GroupName = "default"; req.Quantity = quantity; rsp = client.Execute(req); if (!rsp.IsError && rsp.Messages != null) { foreach (TmcMessage msg in Messages) { // handle message Console.WriteLine(msg.Topic); Console.WriteLine(msg.Content); // confirm message TmcMessagesConfirmRequest cReq = new TmcMessagesConfirmRequest(); cReq.GroupName = "default"; cReq.SMessageIds = msg.Id.ToString(); TmcMessagesConfirmResponse cRsp = client.Execute(cReq); Console.WriteLine(cRsp.Body); } } Console.WriteLine(rsp.Body); } while (rsp != null && !rsp.IsError && rsp.Messages != null && rsp.Messages.Count == quantity); Thread.Sleep(new TimeSpan(0, 0, 1)); } while (true);
注:通过API拉取消息的平均RT在网络好的情况下能达到10毫秒左右,每次消费得到的消息为空时,务必暂停至少1秒才去执行下一次循环拉取消息,否则会产生很多无谓的请求,白白浪费服务端的资源,以及应用自身的API流量包。
如果开通消息的商家多或消息量大的话,可以使用多台机器组成集群来接收消息,或者对商家进行分组隔离独立接收消息。SDK和API都可以通过多连接接收消息。
消息服务支持多连接有两种方式:
分组API:
商家接收到消息之后,根据消息内容,结合自身的业务,完成相应的业务处理。