86447004 2009-03-16
【51CTO独家特稿】51CTO推出的"SaaS时代的软件开发"系列专题受到了广大开发人员的关注。在了解了SaaS的基本概念、商业模式和开发方式等知识后,你也许想亲自动手开发一个SaaS应用,却又不知该如何开始。51CTO开发频道特别邀请了阿里软件的工程师李战老师撰写此文,从阿里软件的商业模式开始,逐步深入,手把手教您开发一个基于阿里SaaS平台的Hello World程序。
阿里软件的商业模式
阿里软件有一个旺旺软件平台,将自己开发的在线软件接入,就可以让阿里巴巴的电子商务客户使用。阿里巴巴是全球最大的电子商务网络公司,拥有超过1亿的注册用户数。如果能将自己开发的软件推销给这个庞大的客户群,将会获得巨大的回报。而阿里软件的旺旺平台就是这样一个集软件开发、接入、销售和服务一体的在线软件运营平台。
在阿里旺旺软件平台上,只要你的软件做得好,吸引了大量用户来订购,哪怕你的软件每月只收一元钱,每月都能获得相当数量的销售收入。这正是阿里旺旺软件平台最吸引人的独特商业模式!
然而,要想在阿里旺旺软件平台上赚钱,先得搞清旺旺平台是怎样运作的。下图展示了阿里旺旺软件平台的基本商业模式:
阿里旺旺软件平台的基本商业模式
阿里旺旺软件平台实际上是阿里巴巴旗下所有用户的软件桌面。任何一个阿里巴巴的用户,包括B2B、淘宝、支付宝、雅虎、阿里妈妈和口碑网的用户,都可以随时进入到旺旺软件的桌面来,使用各种在线软件。当然,在阿里巴巴旗下的各个网站中,也有众多的快捷启动方式,直接将用户引至相关的软件应用中。
另一方面,阿里旺旺软件平台也是ISV(独立软件提供商)的软件营销平台,任何一个软件开发商都可以将自己的软件放到这个营销平台上。当有用户订购并使用你的软件后,每月都能软件使用费,而且是直接打入你的支付宝帐号。
阿里软件平台的开发和接入
阿里旺旺软件平台的开发和接入流程大致如下:
阿里旺旺软件平台的开发和接入流程
要在阿里旺旺软件平台进行开发,首先要注册成为阿里软件的ISV(独立软件提供商)。先进入http://www.alisoft.com/,然后找到其中的“开发者加盟”页面。如果你已经有阿里巴巴中国站或淘宝网的帐号,可以直接登录进入。如果没有,需要注册一个帐号并登陆。登录之后,你将有一个工作平台。第一次进入工作平台的时候,需要填写两三项最基本的内容,此后即可开始使用工作平台。
在ISV工作平台,你可以注册一个新的软件,开始阿里旺旺软件平台的软件营销之旅。目前,阿里旺旺软件平台支持B/S和C/S两类软件。B/S类软件可以给用户更多的方式来进入你的软件,从阿里巴巴的所有网站或旺旺客户端都行。而C/S类软件则只能从旺旺客户端进入,因为旺旺客户端是安装在客户电脑中的即时通讯软件,只有旺旺客户端才能接入C/S软件。
Hello World 起步
我们来注册一个名叫HelloWorld的软件,输入相关的软件基本信息之后,在ISV工作平台的软件列表中,将有一个HelloWorld的软件项目。其中,我们会得到两个代码,一个是APP ID(应用程序标识),另一个是CERT CODE(授权码)。这两个东西会在随后与平台的WEB API调用中经常用到。
当然,一个B/S结构的SaaS软件,一定有一个URL入口。因此,在注册完HelloWorld软件后,还需要补充编辑更多的软件信息,包括测试入口和使用入口的URL。这里,我们将HelloWorld程序的入口指定为http://helloworld.leadzen.cn/。当最终用户从阿里软件网站或旺旺客户端,以及阿里巴巴其他网站进入我们的HelloWorld时,就会将浏览器引导到我们设置的URL,当然后面会跟上一大堆调用参数。
我们的HelloWorld程序是在自己的服务器上运行的,并非运行在阿里软件的服务器上。因此,我们可以简单地这样理解,阿里旺旺软件平台是阿里巴巴用户使用软件的一个集中的启动入口,但软件一旦运行起来,就是主要是在ISV自己的服务上运行了。尽管将来阿里软件会提供有*.aliapp.com域名的应用程序宿主环境,但这也是属于与平台不同的服务器。
阿里旺旺软件平台与ISV应用服务器之间的交互关系如下图所示:
阿里平台与ISV服务器之间的交互关系
当最终用户在阿里旺旺软件平台上使用我们的HelloWorld软件时,我们的helloworld.leadzen.cn服务器会收到类似于下面的调用请求:
http://helloworld.leadzen.cn/?user_id=12176230&app_id=22875&app_instance_id=USERFB4B11067FC25455E32AC4F039B2CD38&token=
A2842BC81AE060C067017336B894F1B6E9AA7A8ED137A91903D1&target=
在这个请求中会带上一系列参数,各个参数的解释如下:
◆user_id 用于识别阿里巴巴用户的标识信息
◆app_id 要使用的应用程序标识,也就是注册软件时的APP_ID
◆app_instance_id 应用程序实例标识,一个实例服务于一个人或一个公司
◆token 身份认证令牌,只有10秒生存期并一次有效
当我们的服务器收到这样的请求之后,首先应该识别访问用户的身份是否合法,然后才能为其提供相关的服务。要验证用户的身份,这就需要调用阿里旺旺软件平台提供的validateUser服务。
目前,阿里旺旺软件平台采用的是REST风格的API调用格式。说白了就是从ISV的服务器发起一个HTTP请求到阿里旺旺软件平台,并得到以XML表示的返回结果。阿里旺旺软件平台提供了专门的API调用地址,开发测试的调用地址为:
http://sipdev.alisoft.com/sip/rest
当软件开发测试完成并上线使用之后,必须使用正式的API调用地址:
http://sipdev.alisoft.com/sip/rest
例如,开发测试中的validateUser服务调用形式可能如下:
http://sipdev.alisoft.com/sip/rest?sip_appkey=22875 &sip_apiname=alisoft.validateUser &sip_timestamp=2008-10-28 20:00:00 &sip_sign=23ed99f1a0a1eac5f3787d522afde1c4 &userId=12176230 &appId=22875 &appInstanceId=USERFB4B11067FC25455E32AC4F039B2CD38 &token= A2842BC81AE060C067017336B894F1B6E9AA7A8ED137A91903D1 |
其中的参数分为系统级参数和应用级参数,以sip_开头的是系统级参数,而其他的是应用级参数。
系统级参数说明如下:
◆sip_appkey ISV应用的唯一编号,即APP_ID
◆sip_apiname 服务名,这里是alisoft.validateUser,其他服务有各自的名称
◆sip_timestamp 发出请求时间戳(yyyy-mm-dd hh:mm:ss.xxx),支持毫秒
◆sip_sign 请求数据的签名,系统级参数和应用参数按顺序拼接后签名
应用级参数说明如下:
◆userId 用户ID,也是客户端传过来的那个user_id
◆appId 应用标识,即APP_ID
◆appInstanceId 应用实例ID,也是客户端传过来的app_instance_id
◆token 身份验证令牌,也是客户端传过来的token
其中的sip_sign参数,是一个签名数据。为了防止非法的调用或调用数据被中途篡改,旺旺平台要求每一个WEB API调用必须进行签名。签名过程中会用到注册新软件时得到的CERT_CODE,这是每个ISV必须保密的重要数据,旺旺平台据此来识别ISV的真实身份。
ISV每个应用的CERT_CODE是放在待签名数据的最前面。接下来是本次调用的所用到的参数按名称的字母顺排列,依次将参数名及参数值填充到待签名数据中。待签名的数据是用UTF8编码的字节串。准备好待签名数据之后,要进行一次标准的MD5散列运算,得到签名结果。签名的结果要求是用十六进制字节码表示的字符串。
当调用旺旺平台的各个参数准备好之后,即可创建一个HTTP请求到阿里旺旺软件平台的服务器。而调用参数可以直接拼接在 http://sipdev.alisoft.com/sip/rest 这一URL的最后,也可以作为POST数据来传递。
而阿里旺旺软件平台会在收到调用请求后,对调用参数的签名进行比对,以确认ISV的身份。同事,还要核对token是否超期或失效,当然还要检查timestamp是否在合理的范围之内。
调用完成后,旺旺平台会返回响应的HTTP报文。在这个报文的头部信息中,有一个sip_status项目,是用来表示调用状态的。而HTTP报文的内容,是以XML形式返回的结果。因此我们还需要从XML中解析出结果的内容。例如,validateUser返回的结果可能是下列形式:
?xml version="1.0" encoding="utf-8" ? String1/String |
不同WEB API接口所返回的数据格式是不同的,具体可以参阅阿里旺旺软件平台的在线文档。地址:http://isp.alisoft.com/apidoc/api/apiIndex.html
HelloWorld源代码
我们的HelloWorld程序实现了一个识别和验证阿里巴巴用户,并在页面上输出不同的结果。下面是HelloWorld的源程序。
Default.aspx
%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" % !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" html xmlns="http://www.w3.org/1999/xhtml" head runat="server" title阿里旺旺软件平台HelloWorld示例/title /head body asp:Label ID="helloText" runat="server"/asp:Label /body /html |
Default.aspx.cs
using System; using System.Web; using System.Security.Cryptography; using System.Text; using System.Net; using System.Xml; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //准备调用参数: string userId = Request.Params["user_id"]; string appId = Request.Params["app_id"]; string appInstanceId = Request.Params["app_instance_id"]; string token = Request.Params["token"]; string sip_appkey = appId; string sip_apiname = "alisoft.validateUser"; string sip_timestamp = DateTime.Now.ToString(); string data = "9c4fb3400ed711de80b8836e34b2dea8"; //CERT_CODE(注册软件时获得的) //在CERT_CODE之后,按参数名字母顺序将参数名及其值拼接起来,用以对所有参数签名: data += "appId" + appId; data += "appInstanceId" + appInstanceId; data += "sip_apiname" + sip_apiname; data += "sip_appkey" + sip_appkey; data += "sip_timestamp" + sip_timestamp; data += "token" + token; data += "userId" + userId; //用MD5算法对调用参数进行签名: MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider(); string sip_sign = BitConverter.ToString(MD5.ComputeHash(Encoding.UTF8.GetBytes(data))); sip_sign = sip_sign.Replace("-", ""); //一定要去除结果中的“-”! //拼装调用参数: string api_params = "sip_appkey=" + sip_appkey + "&sip_apiname=" + sip_apiname + "&sip_timestamp=" + sip_timestamp + "&sip_sign=" + sip_sign + "&userId=" + userId + "&appId=" + appId + "&appInstanceId=" + appInstanceId + "&token=" + token; //发出对阿里旺旺软件平台的WEB调用: WebRequest request = WebRequest.Create("http://sipdev.alisoft.com/sip/rest?" + api_params); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; WebResponse response = request.GetResponse(); //根据返回结果进行相应处理 if (response.Headers.Get("sip_status") == "9999") //调用平台成功 { XmlDocument xml = new XmlDocument(); xml.Load(response.GetResponseStream()); switch (int.Parse(xml.SelectSingleNode("String").InnerText)) { case 0: say("HelloWorld,欢迎合法使用者!"); break; case 1: say(sip_sign + "HelloWorld,欢迎合法订购者!"); break; case -1: say("尚未订购或被授权使用本软件!"); break; case -2: say("非法使用,拒绝提供软件服务!"); break; default: say("调用参数可能出现错误!"); break; }; } else say("调用阿里旺旺软件平台失败!"); } private void say(string text) { helloText.Text = text; //helloText是一个ASP.NET的Label控件 } } |
本程序是用Visual Studio 2008编写,并在ASP.NET 2.0环境下测试通过。如果你在测试本程序时遇到“服务器提交了协议冲突. Section=ResponseHeader Detail=CR 后面必须是 LF”的错误,请在你的web.config中的 configuration 中加入以下内容:
system.net settings httpWebRequest useUnsafeHeaderParsing="true"/ /settings /system.net |