摘要: 不知不觉又到虎年了,回想自己的09年,走得很艰辛。"岁月催人老"这句歌词时常回荡在耳边,让人感到无比的凄凉。岁月无情,生活节奏像彩色泡泡不断变换,不断的消失,让人无所适从。或许真的老了,让人无斗志、无激情、更沉伦。 十年河东,十年依旧!曾以为自己能改变世界,现在却在不断的改变自己想法。 回顾自己走过的09年,有些窝囊,有些充实。6月份离开自己工作过将近5年的地方,发现自己5年中没有一个成熟的产品,...阅读全文
posted @ 2010-02-09 01:02 windsea123 阅读(1454) 评论(9) 编辑
摘要: 08年,公司没什么项目做,本人主要从事软件框架编写。个人认为,做管理软件不需要什么高深的算法和技术,做的都是些Copy->Paste的工作,在程序保证质量的情况下,代码写得优雅一点就可以了!在上次写的<程序员,回头是岸>的文章中,看了很多回复,反思了一下,希望我的情绪不会影响到大家对程序的执着!就如一些兄弟回复一样,我五年的工作经历到现在一事无成,是我个人问题。确实,我从没有去怪...阅读全文
posted @ 2009-01-13 21:49 windsea123 阅读(4782) 评论(29) 编辑

    不知不觉又到虎年了,回想自己的09年,走得很艰辛。"岁月催人老"这句歌词时常回荡在耳边,让人感到无比的凄凉。岁月无情,生活节奏像彩色泡泡不断变换,不断的消失,让人无所适从。或许真的老了,让人无斗志、无激情、更沉伦。

    十年河东,十年依旧!曾以为自己能改变世界,现在却在不断的改变自己想法。

    回顾自己走过的09年,有些窝囊,有些充实。6月份离开自己工作过将近5年的地方,发现自己5年中没有一个成熟的产品,没有一个客户,没有任何一点自己的想法。回想起走过的5年,才觉得离开是多么值得庆幸。半年来,确实学了很多技术上的东西,从原来的winform转向webform,做了几个小网站(http://www.gzthw.com/)及http://www.gzfz.org/信息门户,积累了不同平台的软件架构。接触到了不同的管理模式,感觉自己经历过了软件公司的两个极端,让原本激情的心,一下跌倒深渊,从此发现创业不是那么容易。首先说原来的公司,那时候的老板确实让人佩服,和政府的关系相当的好,每年都有个几十万的申报项目,可惜的是老板只有市场策略。由于产品的不完善和中国的信息化落后,最终没有打开市场,公司没有预期的好,到现在只能靠政府支持维持运作。同现在的公司比较,虽然同样是私人企业,差别挺大,现公司规章制度几乎都是老板定,在树立企业文化是完全不顾及人文关怀。在大老板与小老板之间,工作时间是最不合理的,安排一个任务,不作计划,凭空想像的把任务交给你来完成。如果你没在规定时间没完成你自己还会觉得亏欠他很多,所以得加班加点来做。福利就更别提出,每付出一分钱他就在先看他的流动资金还有多少?我种做法个人觉得用在客户上合适一点,员工都要生存。公司在工资上,有时候还得讨价还价,每一个人都是不一样的基本工资。其实这种方式好吗?大家处在一起会不把自己的工资说出来么,基本工资没什么保密的啊!公司的激励制度就是让大家互相猜疑。能力强,做得好,态度端正的人就应该得到相应的回报。提成有时候也是看得见摸不着的东西,销售合同打八折,减去一些回扣来算提成,有些单不拿也可,郁闷的是客户付了个预付款,如果要等客户付完款才算提成,那黄花菜也凉了。总结今年下半年,工作经常加班到晚上。完成将近10万元的单,工资低,没年终奖,没提成,凄凉,心空,财空。 从此得出以下结论:

     一、要么有钱,有钱就有地位,什么事情都能呼风唤雨。原来老板说的话--"能用钱解决的问题就不是问题",居然被《蜗居》炒得这么透明。

     二、要么不吃不喝,不眠不休,努力工作,相信有一天会成功。

     三、请相信这个社会"强者恒强",相信自己,你跟着强人,你才会变得更强。请不要相信什么现在我们还弱,明年我们会成为NO.1,三年后我们会上市。

posted @ 2010-02-09 01:02 windsea123 阅读(1454) 评论(9) 编辑
大家想必都有这种困惑——拿到支付宝的接口代码后,尽管里面的程序有注释,接口代码包中也附有开发说明,但还是不知道该如何入手。这不难想象是什么原因,因为自己并不了解这个接口的工作原理是什么?
那么这篇文章就是要向大家全面展示关于支付宝接口的所有东西,以便大家能快速上手把接口接入自己的项目中,也能帮助那些已经对支付宝接口有所了解的程序开发者们更了解支付宝的一些通用规则、特殊用途等。
正题开始——
一、 结构
a) 一般由两部分组成,接入部分与通知返回部分。接入部分即为传递参数等信息组合成超级链接,并用该链接来进行跳转。通知返回部分则是支付宝服务器对该笔订单处理完毕后,通知与返回该笔订单的详细信息到商户服务器,商
户服务器接收到后,并对其进行数据处理。
b) 以实物标准双接口ASP代码中的程序为例。
i. 接入部分的页面文件包含:配置页alipay_Config.asp、方法详细页alipay/Alipay_Payto.asp、程序入口页index.asp以及MD5加密方法类页alipayto/Alipay_md5.asp。
ii. 通知返回部分的页面文件包含:方法详细页alipay/Alipay_Payto.asp、MD5加密方法类页alipayto/Alipay_md5.asp、支付完成后(支付宝处理完毕后)自动跳转回的自定义页面return_Alipay_Notify.asp、两方服务器间相互交互(肉眼无法见到的)通知页Alipay_Notif
y.asp。
这里大家可以一目了然,MD5加密方法类与方法详细页不论是哪部分都有被调用,因此这两个文件可视为核心代码部分,若想理解接口的工作原理则要从该部分入手。
c) 以实物标准双接口的ASP.NET C#语言代码程序为例:
i. 接入部分的页面文件包含:无需更改的ALIPAY的类文件App_Code/AliPay.cs及入口页面文件Default.aspx
ii. 通知返回部分的页面文件包含:两方服务器间相互交互(肉眼无法见到的)通知页Alipay_Notify.aspx、支付完成后(支付宝处理完毕后)自动跳转回的自定义页面Alipay_Return.aspx、
无需更改的ALIPAY的类文件App_Code/AliPay.cs
这个架构是否更容易理解了?没错,核心部分的运算过程就在AliPay.cs这个文件中。
二、 工作原理
大家对结构部分已经有所了解,那么我们就开始分析具体的这个接口是如何运作的。
a) 接入部分原理
i. 第一步——选定参数信息:
结合技术文档以及接口代码DEMO,选定传递给支付宝服务器的参数,以实物标准双接口为例。如必传项service、partner、seller_email、sign、sign_type、out_trade
_no、price、subject、quantity、payment_type以及最少一组的物流信息参数三个logistics_type、logistics_fee、logistics_payment
等,选填项body、discount、show_url等。
以ASP.NET C#语言代码程序为例:
string service = "trade_create_by_buyer";
string seller_email = "aaaa@126.com";
string sign_type = "MD5";
string key = "********************************";
string partner = "2088************";
string _input_charset = "utf-8";
string show_url = "http://www.alipay.com/%22;
string out_trade_no = TxtOrderno.Text.Trim();
string subject = TxtSubject.Text.Trim();
string body = TxtBody.Text.Trim();
string price = TxtPrice.Text.Trim();
string quantity = TxtQua.Text.Trim();
string logistics_type = "POST";
string logistics_fee = TxtPost.Text.Trim();
string logistics_payment = "BUYER_PAY";
string notify_url = "http://www.xxx.com/swnet05utf8/Alipay_Notify.aspx%22;
string return_url = "http://www.xxx.com/swnet05utf8/Alipay_Return.aspx%22;
ii. 第二步——排序:
把这些参数的变量名(即技术文档里给出的变量名,以这种方式组合:service=”trade_create_by_buyer”作为一串字符串)按从a到z的顺序依次排序。以ASP.NET C#语言代码程序为例,该功能在ALIPAY.CS类中;以ASP代码中的程序为例,该功能在alipayto/Alipay_Payto.asp文件中。
iii. 第三步——加密:
目前一般的加密方式是MD5,不论是哪种加密方式,要加密的信息是要传给支付宝的信息,且存在于技术文档中,而非自定义的变量名。对以上排序好的所有参数(不包括网关参数即:string gateway = "https://www.alipay.com/cooperate/gateway.do?";)以循环的方式,用‘&’字符拼接成一长串字符串(这里需要注意,所有的参数都是&字符来拼接的,拼接后直接再拼接安全校验码Key,在程序中大家可看到,这个key是直接加到该字符串后面而没有用&字符),之后进行加密。得出的加密字符串集存储于sign这个参数中。
iv. 第四步——拼接字符串成URL链接
我们已经拿到了各个参数、参数所属的值以及加密得出的加密字符串,那么手上现在的所有参数信息的格式,应当都是一组一组的service=”trade_create_by_buyer”这种格式的字符串,拼接的话,则依靠循环的方式遍历所有的这种字符串,因为这次的拼接是要成URL链接,所以之前排除在外的网关gaetway和加密类型参数sig
n_type也都会被拼接进来,那么,连接的字符则用大家所熟知的字符’&’,就这样得出一个完整的URL链接地址,如:
https://www.alipay.com/cooperate/gateway.do?seller_email=test%40126.com&discount=0&logistics_fee=0.01&notify_url=http%3A%2F%2Flocalhost%3A8088%2Fjsp_shi_gbk%2Falipay_notify.jsp&payment_type=1&service=trade_create_by_buyer&partner=2088002123456782&_input_charset=utf-8&logistics_type=EMS&price=0.01&out_trade_no=20081115162330&subject=AAA20081115162330&logistics_payment=SELLER_PAY&quantity=1&body=%E6%94%AF%E4%BB%98%E5%AE%9D%E6%B5%8B%E8%AF%95&return_url=http%3A%2F%2Flocalhost%3A8088%2Fjsp_shi_gbk%2Falipay_return.jsp&sign=a7ffc1c8ba85df972bb472adc3d199ba&sign_type=MD5
该链接来自支付宝官方的技术文档“标准实物双接口技术文档”
v. 第五步——自动跳转
第四步中已经运算得出的URL链接字符串,我们则要让其活起来,那么活起来的方式就是——用程序调用它,也就是所谓的页面自动跳转。这样就能跳到支付宝的官方收银台页面。
可以说,现在已经成功的把支付宝接口融合进了大家自己的网站中,且能够使用支付宝来进行付款了。
b) 通知返回部分原理
i. 专业术语
通知返回是两个页面,即传递给支付宝时的notify_url参数所对应的页面文件(asp.net的是Alipay_Notify.aspx、asp的是Alipay_Notify.asp)称之为通知页,传递
给支付宝时的return_url参数所对应的页面文件(asp.net的是Alipay_Return.aspx、asp的是return_Alipay_Notify.asp)称之为返回页。
ii. 通知返回原理
1. 第一步——验证是否是支付宝服务器发来的请求:
a) 以asp程序代码为例:
alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?"
alipayNotifyURL = alipayNotifyURL &"partner=" & partner & "&notify_id=" & request("notify_id")
Set Retrieval = Server.CreateObject("Msxml2.ServerXMLHTTP.3.0")
Retrieval.setOption 2, 13056
Retrieval.open "GET", alipayNotifyURL, False, "", ""
Retrieval.send()
ResponseTxt = Retrieval.ResponseText
Set Retrieval = Nothing
得到的便是ResponseTxt的值,这是下面的步骤要用到的。
b) 以asp.net C#程序代码为例:
//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
public String Get_Http(String a_strUrl, int timeout)
{
string strResult;
try
{
HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(a_strUrl);
myReq.Timeout = timeout;
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
Stream myStream = HttpWResp.GetResponseStream();
StreamReader sr = new StreamReader(myStream, Encoding.Default);
StringBuilder strBuilder = new StringBuilder();
while (-1 != sr.Peek())
{
strBuilder.Append(sr.ReadLine());
}

strResult = strBuilder.ToString();
}
catch (Exception exp)
{

strResult = "错误:" + exp.Message;
}

return strResult;
}
调用部分:
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
string partner = "2088************";

alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "&notify_id=" + Request.Form["notify_id"];

//获取支付宝ATN返回结果,true是正确的订单信息,false 是无效的
string responseTxt = Get_Http(alipayNotifyURL, 120000);
得到的便是ResponseTxt的值,这是下面的步骤要用到的。
2. 第二步——排序:
该部分的排序的原理与“接入部分”的原理“排序步骤”一样,值得注意的是,这里的参数是支付宝通知返回时,传回来的订单信息的各种参数以及值。
3. 第三步——加密:
该部分的加密原理与“接入部分”的原理“加密步骤”一样,依然值得注意的部分是加密的参数信息,这些参数信息是来源于上面一步骤排序好后的参数拼接起来的字符串来加密的。
4. 第四步——判断:
上面我们有得到加密的结果(命名为mysign吧)、检验是否是支付宝发来的消息的正确性ResponseTxt、以及通过POST或GET的方式得到的sign参数的值,那么这个判断的含义便是通知返回里最重要
的部分了,因为它是来检验下面的程序是否执行我们的数据处理的。如何判断呢?各语言程序代码中,都是把加密得出的结果mysign与从支付宝那或得到的sign的值进行比较,并且还要让reponseTxt这个的
值要等于true,这样才达到验证成功。值得注意的是,大家都有遇到过这种事,支付部分即接入部分的确是做好了,但为什么无法与支付宝的交易信息同步,出现的问题就在这个判断上没有成功,下面的第五部分则会详细说
明。
5. 第五步——自身网站的数据处理
终于判断成功了,程序已经执行到了这里。各语言程序代码的这块地方的注释都写着“更新自己数据库的订单语句”或是“这里可以指定你需要显示的内容”。如字面上的意思,这块地方就是要我们大家来对这笔交易信息进行数
据处理,即编写程序。这个说法大概专业了点,简单易懂的讲法便是,支付宝的交易成功的信息和其他的一切交易状态,自己的网站也能够对这笔订单同步起来,即支付宝里这笔订单的交易状态是“买家已付款等待卖家发货”,
那么自己网站里显示的这笔状态也因如此,那么就应当在这里面写下诸如:
if (Request.Form["trade_status"] == "WAIT_SELLER_SEND_GOODS")// 判断支付状态_买家付款成功,等待卖家发货(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["price"];//金额
string sql = "update order_table set order_status = ‘买家已付款,等待卖家发货’ where order_no = " + strOrderNO;
Update(sql);
}
等数据库处理代码。
iii. 存在的区别
1. 大家仔细阅读代码不难发现,在通知页中程序运行时,获取参数的方法是用POST方式,而返回页中程序运行时,获取参数的方法是用GET方式。由此可知一些基本的信息——返回页传递回来的参数信息是储存在URL链接
里的,而通知页的参数信息是不在URL链接里,也能从中推断出二者在功能上的差异。
2. 大家可看到通知页面比返回页中多一个环节,那就是Response.Write("success");
作用上不同的详细说明,大家可以看下面的第四部分。
三、 参数
首先大家有个疑问,技术文档中的输入参数列表中给出了诸多参数,而手上拿到的代码里只写了一部分参数来进行传递信息,这究竟是为什么?那么我们先带着这个疑问往下看。
以下讨论的参数不涵盖网关gateway、加密参数sign、加密类型sign_type,因为这些都是必须的。
以实物标准双接口为例,可把参数看做几个功能部分组成
a) 不可缺少的参数
i. service服务参数,这个是用来区别这个接口是用的什么接口,所以绝对不能修改。
ii. partner合作身份者ID、key安全校验码或称私钥这一组参数是签约合同生效后才能拿的到,partner是来鉴别是哪个商家与支付宝签约,而这个Key它如同钥匙般相当重要。
iii. seller_email收款人支付宝账号,支付宝中有手机类型、电子邮件类型的支付宝账号是都可以用这个参数的。
iv. subject在支付宝的收银台里是直接与商品名称关联在一起的,但是说的更准确些的话,这个参数是这笔交易的名称,因为这笔交易不一定只买一件商品。它的作用不仅是在收银台里可以清晰的显示出来,而且在支付宝的
账户的交易明细的列表里,它也是排在第一列,由此可推测出,它有财务对账、作为交易查询的筛选条件等诸多作用。非常重要。
v. out_trade_no技术文档中给出的是商户交易号(确保在商户系统中唯一),顾名思义这个就是我们大家自己网站的订单系统里的唯一订单号,而非支付宝的。这里需要强调的,这个订单号必须得是唯一的,如何唯一
法?自己网站里订单系统的订单号是绝对唯一的吧,支付宝要求的唯一就是这个,为什么非要唯一?支付宝会根据订单号来判定这笔订单对于这个商家的所有交易中是否是唯一的。
vi. price金额、quantity数量,这里设置有两种方式一种商品的单价金额,多个数量(即大于等于1)。另种是数量为1,金额代表总额,甚至是包含了运费。为什么大部分的客户要这么做?原因很简单,第一,购物
车里的东西不一定是单纯的一件或者多件相同的商品,那么为商品设置金额时就有困难了,因此这里用总额是最好的,而数量就默认为1。第二,运费的设置很多客户是与各家快递公司签约、每件物品的快递费用也不尽相同,为
了省去麻烦,在程序计算的时候干脆把运费也加进去。因此我们只需要记住一件事,这个price的金额就是所谓的总额了。
vii. payment_type支付类型,没什么可说的直接写成1,无需改动。
viii. 物流信息logistics_type、logistics_fee、logistics_payment这是一组物流信息,实物标准双接口中必须得至少有一组物流信息,也就是指这三个参数了,最多可有三组,哪三
组呢?logistics_type_1、logistics_fee_1、logistics_payment_1(第二组);logistics_type_2、logistics_fee_2、logist
ics_payment_2(第三组)。后两组为可选项。一般前面有说Price已经是总额了且包含了运费,那么这里物流运费就直接设置成0即可,即logistics_fee=”0”,其他两个的信息可参考技术文档来填写,因为要从技术文档中的枚举列表里来选择,所以绝不可乱填写。
b) 可增加的有用参数
i. 物流信息最多三组,最少一组,这已经在前部分有所提及,这里就不再细说。
ii. _input_charset,当是UTF-8的编码格式时必须得用到且不允许为空的,即_input_charset=”utf-8”
iii. notify_url、return_url,return_url代表支付完毕后可以自动从支付宝的官方页面跳转回来,notify_url这个是防止调单的首选最佳工具。
iv. body,在支付宝收银台中的商品描述里显示,如果subject是订单名称的话,那么这个body则最准确的称之为订单描述,其实个人认为它作为备注之类的更为恰当。很多人都很郁闷支付宝为何不能像其他公司的接
口有个自定义的参数来存放客户想要的东西,其实body也具有类似的这种功能,它不仅容纳的信息是所有参数里最大的,而且还是以字符串的形式储存,个人认为它其实也是非常重要的不可缺少的参数之一呢。
v. discount折扣,顾名思义如果小于0,则是用原金额Price*quantity+(discount),实际金额便比原总额小了。现在有些商户有支付宝的优惠卷,而优惠卷的用途也是在这个参数中体现,具体
做法与前面无异。
vi. show_url商品展示地址,这个链接的作用是在支付宝收银台的商品链接旁边有个下划线“详情”的链接,而点链接弹出的一个新页面便是这个商品展示地址的页面。
vii. 收货信息receive_name、receive_address、receive_zip、receive_phone、receive_mobile,这些信息若也设置为传递给支付宝的参数之一的话,那么在
支付宝收银台点选下一步的时候,本该出现的填写收货信息页面不见踪影,而直接跳到了收货信息页面的下一个页面去了。很多商户在自己的网站的购物流程中都有一个填写收货信息的选项卡,为了省去到支付宝收银台中还要填
写一次收货信息的麻烦,那么这些收货信息的参数就派上用场了。值得注意的是,收货人姓名和地址是必填项,不然还是会出现收货信息填写页。
viii. buyer_email买家支付宝账号,这个设置好后呈现的效果便是,原本是空的支付宝账号的输入框此时已经有个支付宝账号在里面放置。
c) 剩下的参数无需理会
整个实物标准双接口的参数介绍完毕,那么其他接口的参数还要介绍吗?大家从上面分析得出的东西对比技术文档的参数列表是否看出什么来了?
1、 参数列表的最后一列叫“可空”,N代表不允许为空,Y代表允许为空,结合上面的不可缺少参数与增加的有用参数来进行比较,不难发现,不可缺少的参数全是为N的。
2、 有些为Y的参数有一组,例如buyer_email、buyer_id,凡是遇到这种的一般都是二可选一也可都不选,或是二必选一。举例说明:二必选一的是seller_email、seller_id,二选一的
是buyer_email、buyer_id。
所有的接口的参数如此分析就能判断出哪些是重要参数哪些可不要,结合技术文档与程序接口来研究就能一目了然。
四、 通知返回
a) 返回页
传递给支付宝时的return_url参数所对应的页面文件。
具备的属性:1、支付接口中买家的购买流程已经走到支付宝里且支付宝提示支付成功时,页面会自动跳转回自身网站的这个页面里来。
2、同步的,无时差
3、获得参数的方法是用get方式获取。
4、不论跳转回来程序判断是真还是假(if(sign = mysign and responseTxt = true))只跳转回来一次,不重复。
5、这个并不是支付宝服务器调用了该页面,而是通过与组合拼接各参数形成的URL链接原理等同,拼接出来的URL链接,之后程序上做自动跳转。
6、基于5的原因,该页面的程序调试可不必在服务器上而是本机上调试、运行。
b) 通知页
传递给支付宝时的notify_url参数所对应的页面文件
具备的属性:1、这个通知页就是被支付宝调用才能启动的。
2、服务器间的互动,不像返回页肉眼可以看到,这个是看不到的。
3、获得参数的方法是用POST方式获取。
4、支付宝中的该笔交易存在,且该笔交易状态发生了变更,就会被调用。
5、被调用程序判断(if(sign = mysign and responseTxt = true)),若我们自己在该判断中有做程序编写,成功则不再被调用,不成功则会反复被调用。
6、异步的,第一次收到订单信息(以下都称之为“通知”)是与返回页近乎等同或等同的同步时间,在判断不成功的情况下,会收到第二次第三次等次数的通知,时间间隔从最先的一两分钟,到后面的几个小时。失效时间是4
8小时。
7、基于6的原因,该页面的程序调试必须在服务器上调试、运行。
8、程序编写时必须采用程序执行成功,才写页面response.Write(“success”);,不成功则写页面response.Write(“fail”); 支付宝根据success来判定是否要重新再次发送通知。
9、该页面的Html页面中必须是空白、无任何Html标签、无任何空格。
以C# ASP.NET实物标准双接口代码为例:
if (mysign == sign && responseTxt == "true")
{
if (Request.Form["trade_status"] == "WAIT_BUYER_PAY")// 判断支付状态_等待买家付款(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
}
else if (Request.Form["trade_status"] == "WAIT_SELLER_SEND_GOODS")// 判断支付状态_买家付款成功,等待卖家发货(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["price"];//金额
string sql = "update order_table set order_status = '买家已付款,等待卖家发货' where order_no = @out_trade_no";
Update(sql,para);
}
else if (Request.Form["trade_status"] == "WAIT_BUYER_CONFIRM_GOODS")// 判断支付状态_卖家已发货等待买家确认(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["price"];//金额
string sql = "update order_table set order_status = '卖家已发货,等待买家确认收货' where order_no = @out_trade_no";
Update(sql, para);
}
else if (Request.Form["trade_status"] == "TRADE_FINISHED")// 判断支付状态_交易成功结束(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["price"];//金额
string sql = "update order_table set order_status = '交易成功' where order_no = @out_trade_no";
Update(sql, para);
}
else
{
//更新自己数据库的订单语句,请自己填写一下
}

Response.Write("success");
}
else
{
Response.Write("fail");
}
c) 在支付宝的众多接口中,不是所有的接口都拥有通知页与返回页的。有的接口只有返回页;有的接口有通知页且用XML格式的内容显示在当前页面中;有的没有通知页也没有返回页仅仅只以XML格式的内容显示在当前页面中
。所以,我们要根据各接口的技术文档与程序实例来做相应的数据处理。
d) 大家这里存在一个疑问,一般大家的做法都是把数据库更新些在返回页中,但是很多情况下出现了订单不同步即掉单现象。这是为什么?返回页是当前页面自动跳转的,这虽然跳转的反应速度不错,但人的手动关闭该页面操作绝
对可以使之在没有跳转回来之前就关掉了该页面,此时原本该数据库更新的程序并没有被启动,这样直接导致了掉单,所以一般大商户,尤其是网络游戏行业的即时到帐充值的技术做法是:返回页中有订单处理程序,通知页中也
有,当返回页中的订单没做过处理时,通知页中的数据处理程序便启动;这样即可近乎100%解决掉单问题(还有种掉单原因是大家自己的服务器出现问题,比如MS3XML.DLL问题,这个问题至今没有什么可以解决的办法,只能重装或是更换服务器,也有的服务器因为中毒才导致的。)。
五、 调试
接入部分做好了,通知返回部分也做好了,那么开始调试吧。
调试也分成两大部分来做。
a) 部分网站用了框架模式frame,但这个并不适用支付宝的接口程序,因此绝对不能把支付宝的接口页面置于整个网站的框架之下。
b) 确定好要用POST还是GET方式来传递参数,二者不能混用。由于有些网站中不一定只有一个接口入口,所以整个网站都必须保持一致性,不能这个接口用POST,那个接口用GET,这样直接导致后续出现一系列连查找
原因都极其困难的现象。
c) 接入部分的调试工作,则是输入支付宝要求的格式的值,如subject、body的值不允许有非法字符、金额格式必须是小数点后两位数或是正整数且不是金额格式(即$123.00),以及非常重要的一个原则,传递的参数要么不传递这个参数(即传递的众多参数中,这个参数完全不存在),要么这个参数不允许为空。很多人在调试时支付出现一系列“调试错误”有很大的一部分原因就是参
数的设置存在问题。
d) 编码格式一定要确认再确认,在支付时直接出现“调试错误,SIGN不对”只有两种原因,一是C部分已提到的参数的设置问题,另一个便是这个编码格式的问题。编码格式是非常重要的,绝对不能这个地方用GBK,另个地
方用utf-8。
e) 通过接口走一次真实的操作,若是支付接口,则走一笔真实的交易,金额则是0.01元,不要觉得很麻烦,也不要把这个工作交个经理或者你的老板来做,因为它直接关系到你后续的操作步骤与调试的顺畅程度。
f) 返回部分在本机电脑上就可以调试完毕,之前有提到不要把支付测试工作交给自己以外的其他人,这里就可以得到充分的说明,不论是哪种语言都拥有自己风格的单步监控程序代码的能力,返回部分就要一步一步监控程序的执行
,确保1、是否执行到了“mysign == sign && responseTxt == "true"”,这个IF语句的判断;2、是否进入了这个语句里而不是else里;3、数据库更新程序是否执行成功,而不是卡着不动了;4、数据库更新完毕后,程序是否走完。基本出现问题的地方就在第一步,所以不要
觉得奇怪为什么掉单?
g) 通知页的调试,这个调试就比较麻烦了,首先这个支付宝接口已经完成且放在了服务器上,别人可以通过互联网来进行支付;其次,要把通知页中的“写日志”程序启动起来,日志内容主要记录trade_status、tr
ade_no、out_trade_no、price、sign、mysign、responseTxt等。一般出现的原因依旧是“mysign == sign && responseTxt == "true"”这个判断上不被通过。
六、 其他
a) 有些接口,例如支付的接口,是支持POST或者GET方式传递参数的。
i. POST传递方式:
这里需要注意的地方是:<form action=” aliay_url” …>中action的值是网关+编码格式参数,即https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8,GBK的编码格式可以为:https://www.alipay.com/cooperate/gateway.do?。
ii. GET传递方式:
是用&字符来连接起来的一长串URL链接字符串,通过自动跳转不是<form action=” aliay_url” …>的方式来存放,而是用Response.Redirect(aliay_url)方式来进行跳转。

http://dev.alipay.com/devclub/mvnforum/viewthread_thread,161
posted @ 2009-08-11 22:10 windsea123 阅读(295) 评论(0) 编辑

FCKeditor相关资料简介:

官方网站http://www.fckeditor.net/
官方文档
http://wiki.fckeditor.net/
下载地址
http://www.fckeditor.net/download/default.html
官方演示
http://www.fckeditor.net/demo/default.html
下载
FCKeditor2.6.4zip是其最新的Javascript文件和图片等;
FCKeditor.NET.zip是一个ASP.NET控件DLL文件。

启用VS新建一个C#WEB Site工程,取名FCKPro

FCKeditor安装:

所谓安装就是一个简单的拷贝过程。把下载的FCKeditor2.6.4.zip文件包直接解压缩到FCKPro的根目录下,这样根目录下就得到一个FCKeditor文件夹,里面富含所有FCKeditor的核心文件。

然后把下载的FCKeditor.Net.zip随便解压缩到你硬盘的一个空目录,里面是FCKeditor.Net的源代码,你可以对它进行再度开发,我们只是直接使用其目录下的"bin"Debug目录中的FredCK.FCKeditorV2.dll文件。

VS中添加对FredCK.FCKeditorV2.dll的引用:

1.FCKPro工程浏览器上右键,选择添加引用(Add Reference…),找到浏览(Browse)标签,然后定位到你解压好的FredCK.FCKeditorV2.dll,确认就可以了。这时,FCKPro工程目录下就多了一个bin文件夹,里面包含FredCK.FCKeditorV2.dll文件。当然,你也可以完全人工方式的来做,把FredCK.FCKeditorV2.dll直接拷贝到FCKPro"bin"下面,VS在编译时会自动把它编译进去的。

2.为了方便RAD开发,我们把FCKeditor控件也添加到VS的工具箱(Toolbox)上来,展开工具箱的常用标签组(General),右键选择组件(Choose Items…),在对话框上直接找到浏览按钮,定位FredCK.FCKeditorV2.dll,然后确认就可以了。这时工具箱呈现出控件的样子,这样会省去很多在开发时使用FCKeditor控件时要添加的声明代码。

至此,你已经完成了FCKeditor的安装,并可以在你的项目中使用FCKeditor了,当然后面还有很多需要配置的东西。

FCKeditor详细的设置:

进入FCKeditor文件夹,编辑 fckconfig.js 文件。

1此步骤是必须的,也是最重要的一步。

修改

var _FileBrowserLanguage = 'asp' ; // asp | aspx | cfm | lasso | perl | php | py

var _QuickUploadLanguage = 'asp' ; // asp | aspx | cfm | lasso | php

改为

var _FileBrowserLanguage = 'aspx' ; // asp | aspx | cfm | lasso | perl | php | py

var _QuickUploadLanguage = 'aspx' ; // asp | aspx | cfm | lasso | php

2、配置语言包。有英文、繁体中文等,这里我们使用简体中文。

修改

FCKConfig.DefaultLanguage = 'en' ;

FCKConfig.DefaultLanguage = 'zh-cn' ;

3、配置皮肤。有defaultoffice2003silver风格等,这里我们可以使用默认。

FCKConfig.SkinPath = FCKConfig.BasePath + 'skins/default/' ;

4、在编辑器域内可以使用Tab键。(1为是,0为否)

FCKConfig.TabSpaces = 0 ; 改为FCKConfig.TabSpaces = 1 ;

5、加上几种我们常用的字体的方法,例如:

修改

FCKConfig.FontNames = 'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ;

FCKConfig.FontNames = '宋体;黑体;隶书;楷体_GB2312;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana'

6、编辑器域内默认的显示字体为12px,想要修改可以通过修改样式表来达到要求,打开/editor/css/fck_editorarea.css,修改font-size属性即可。如font-size: 14px;

7、关于安全性。

如果你的编辑器用在网站前台的话,那就不得不考虑安全了,在前台千万不要使用Defaulttoolbar,要么自定义一下功能,要么就用系统已经定义好的Basic,也就是基本的toolbar

修改

FCKConfig.ToolbarSets["Basic"] = [

     ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About']

FCKConfig.ToolbarSets["Basic"] = [

['Bold','Italic','-','OrderedList','UnorderedList','-',/*'Link',*/'Unlink','-','Style','FontSize','TextColor','BGColor','-','Smiley','SpecialChar','Replace','Preview']

] ;

这是我改过的Basic,把图像功能去掉,把添加链接功能去掉,因为图像和链接和flash和图像按钮添加功能都能让前台页直接访问和上传文件,要是这儿不改直接给你上传个木马还不马上玩完?

当然也可以配置一下WebConfig,也能让它确保安全,接下来我们将讲到。

FCKPro工程项目的设置:

1、配置WebConfig,在<appSettings>节点添加,如下所示:

<appSettings>

     <add key="FCKeditor:BasePath" value="/项目名称/fckeditor/"/>

   //Win2003下,Files目录一定要有IIS_WPG用户的写权限,否则可能无法上传

     <add key="FCKeditor:UserFilesPath" value="/项目名称/Files/" />

</appSettings>

说明:BasePathfckeditor所在路径,fckeditor由于我们直接放网站目录下这样写就可以,如果您的网站多放几层适当调整即可。UserFilesPath是所有上传的文件的所在目录。我们新建了一个Files文件夹放在了项目中做为上传文件的所在目录,这里为了方便,但由于考虑到安全性,我们建议Files要单独做wwwroot目录下的一个站点比较好,和我们的站点FCKEditor平行。不要把它放FCKEditor里,为什么呢?因为Files是要让客户有写的权限的,如果放FCKEditor下很危险。Files目录要有写的权限。你根据自己网站需求设置那个帐号,本文为方便设置User实际中你可能用ASP.NET帐号更合理。

2、在FCKpro工程项目中编写一个最简单的页面

<%@ Page Language="C#"   AutoEventWireup="true"    CodeFile="Default.aspx.cs" Inherits="_Default" validateRequest="false" %>

<%@ Register Assembly="FredCK.FCKeditorV2" Namespace="FredCK.FCKeditorV2" TagPrefix="FCKeditorV2" %>

// 这里要主要两个参数

// 默认为<%@ Page Language="C#"   AutoEventWireup="true"    CodeFile="Default.aspx.cs" Inherits="_Default" %>

// 我们要添加一个参数 validateRequest=false,否则提交带html代码的内容会报错

// 从客户端(...)中检测到有潜在危险的 Request.Form 值。

<!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>无标题页</title>

</head>

<body>

     <form id="form1" runat="server">

     <div>

         <FCKeditorV2:FCKeditor ID="FCKeditor1" runat="server">

         </FCKeditorV2:FCKeditor>

         &nbsp;</div>

     </form>

</body>

</html>

如何获取其内容呢?读取FCKeditor1控件的Value属性值即可。

FCKEditor 2.6的问题:

1.FCKeditor出现"this connector is disabled Please check the"editor/filemanager/connectors/aspx/config.aspx"错误的解决办法

打开editor/filemanager/connectors/aspx/config.ascx修改CheckAuthentication()方法,返回true


2.在上传文件窗口点击浏览服务器,会出现the server didn't send back a proper xml.....错误提示,因为后期版本的FCKEditor要求不同类型的文件分别传到不同的目录,包括file,image,falsh,media等目录,一定要先建立起来。

FCKeditor精简版的制作方法

 进入FCKeditor文件夹,把所有“_”开头的文件和文件夹删掉,这些都是一些范例,只保留editor文件夹、fckconfig.jsfckeditor.jsfckstyles.xmlfcktemplates.xml就可以了;

  进入editor文件夹,删掉“_source”文件夹,里面放的同样是源文件;

  退回上一级目录进入filemanager文件夹,有browserupload两个文件夹。进入browser"default"connectors,只保留aspx文件夹,其余的删掉;mcpuk目录亦可删除;upload也一样,只保留aspx文件夹;

  退到editor再进入images文件夹,smiley里面放的是表情图标,有msnfun两个系列,如果你想用自己的表情图标,可以把它们都删除;如果你想用这里的表情图标那就不要删了;

  lang里面放的是语言包,如果只是用简体中文,那么只保留fcklanguagemanager.jszh-cn.js两个文件就行了,建议也保留en.js(英文)、zh.js(繁体中文)两个文件,fcklanguagemanager.js是语言配置文件,有了它才能和fckconfig.js里的设置成对,对应上相应的语言文件,一定要保留!

  再退出lang文件夹,进入skins文件夹,如果你想使用FCKeditor默认的奶黄色,那就把除了default文件夹外的另两个文件夹直接删除,如果想用别的,那就看你自己的喜好了。

至此,文件精简完毕,由原来的2.55M变成现在的797K了。接着修改设置。

一、自定义 FCKeditor 的 BasePathBasePath 即FCKeditor在网站中的相对路径,默认值是 /fckeditor/,最好在Web.config appSettings中对其进行配置:
<add key="FCKeditor:BasePath" value="/FCKeditor_2.6.3/"/>

这样做有诸多优点:

开发环境与生产环境不同,开发环境一般是http://localhost/xxx.com/这种情况下FCKeditor就得放在一个虚拟目录http://localhost/fckeditor/中,若涉及多个网站的开发,而各网站的FCKeditor有差别时,这样显然不是最优;

而且因为物理目录结构与逻辑目录结构不同,也会有发生错误的隐患;

而如果采用Web.config的配置,就可以在开发环境采用不同的配置,FCKeditor的物理路径与生产环境保持一致;
当升级FCKeditor时,只需要将新版本的FCKeditor放在相应版本号的目录里,修改一下配置即可。这样可以解决因为静态资源的客户端缓存问题,不同用户出现不同的错误的问题;
可以直观地看到自己的FCKeditor的版本号。

二、配置文件上传的目录

FCKeditor的文件上传(如图片上传)目录可以通过Web.config appSettings进行配置,如:

<add key="FCKeditor:UserFilesPath" value="/UploadFile/FCKeditor/"/>

也可以在/FCKeditorBasePath/editor/filemanager/connectors/aspx/config.ascx 中进行配置,但我建议 FCKeditor 目录中的内容能不改就不改(fckconfig.js除外),这样日后升级可以放心地替换即可。

三、自定义文件上传的子目录的格式

我们知道,一个文件夹下面不能存放过多的文件(据称Windows下面的目录下2000为阈值),否则对该目录的访问会严重影响I/O性能。而FCKeditor的文件存储是在单一的一个目录进行的。我对FCKeditor进行了扩展,可以在Web.config appSettings对存储目录的格式自定义,如:

<add key="FCKeditor:FolderPattern" value="%y/%m-%d/"/>

以今天的日期为例:这样产生的文件上传子目录格式为:2008/10-21/。
年月日格式的目录可以随意组合,如:

<add key="FCKeditor:FolderPattern" value="%y/%m/%d/"/>

这样产生的文件上传子目录变成了2008/10/21/

参考:

%y    代表 当前时间的年份
%m    代表 当前时间的月份
%d    代表 当前时间的日

四、自定义文件上传的文件名格式

FCKeditor对文件名的处理规则是:如果当前目录下没有重名文件,则上传后的文件名与用户PC上的文件名一致;若存在n个重名文件,则加入用户PC上的文件名是Example.xxx,上传后的文件名变为:Example(n).xxx

我的项目里要求对用户上传的文件名变成Guid的格式,所以我对FCKeditor也做了扩展,在Web.config appSettings可以对上传后文件的格式自定义,如:

<add key="FCKeditor:FilenamePattern" value="%guid.%extl"/>

这样的文件名如:a299e63a-7d2d-493d-bbb9-99162ef5b6b8.gif

参考:

%guid    代表 一个新的guid字符串
%fnl    代表 源文件名的小写
%fnu    代表 源文件名的大写
%extl    代表 源文件扩展名的小写
%extu    代表 源文件扩展名的大写

五、对上传图片进行缩放处理

用到FCKeditor图片上传功能的场景中,很多是内容的发表。内容中往往不需要几千像素大小的图片,比如我的项目中,文章区域最宽也就560像素,所以我做了一个扩展,在Web.config appSettings中可以对图片的最大宽度进行自定义:

<add key="FCKeditor:MaxWidthOfUploadedImg" value="560"/>

有了这段配置,上传后的图片的宽度都控制在了560像素及以内

六、自定义上传后图片URL中的域名
为了加快页面的渲染,我们可以把图片等静态资源放在一个独立的域名当中。但FCKeditor默认的图片上传后URL是相对路径, 如:/fck/2008-03-01/1.jpg:

我增加了这个扩展,在Web.config appSettings可以配置上传后图片URL的域名,如:

<add key="FCKeditor:UploadedFilesDomain" value="http://www.hong100.cn/"/>
图片地址就变成绝对地址了,形式如: :http:www.aa.com/fck/2008-03-01/1.jpg


七、解决上传文件名含有中文的文件时提示 "invalid file type" 的问题

这个问题只需要在Web.config中增加一段配置即可解决:

<location path="FCKeditor_2.6.3/editor/filemanager/connectors/aspx/upload.aspx">
    <system.web>
        <globalization requestEncoding="utf-8" responseEncoding="gb2312"/>
    </system.web>
</location>

注意:

responseEncoding是网站的默认编码
FCKeditor_2.6.3是FCKeditor的BasePath

八、FCKeditor的安全

在FCKeditor的2.3.2版本里,曾有一个漏洞,可以通过 /editor/filemanager/browser/default/connectors/aspx/connector.aspx 往服务器上传任意文件,我的网站就曾经中招。

2.6.3虽然暂未发现类似的问题,但一般情况下用不到的文件最好还是删除比较好:

FCKeditor BasePath 根目录中除了保留:
/editor
/fckconfig.js
/fckpackager.xml
/fckstyles.xml
/fcktemplates.xml
/license.txt外,全部删除
/editor/filemanager/中除了保留:
/connectors/aspx/config.ascx
/connectors/aspx/upload.aspx外,全部删除
删除
/editor/_source/
/editor/filemanager/connectors/aspx/config.ascx 的 CheckAuthentication() 方法中,增加验证用户是否登录的逻辑

posted @ 2009-08-10 21:22 windsea123 阅读(283) 评论(1) 编辑


 

只能输入数字:"^[0-9]*$"。
只能输入n位的数字:"^\d{n}$"。
只能输入至少n位的数字:"^\d{n,}$"。
只能输入m~n位的数字:。"^\d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"。
只能输入有1~3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"。
只能输入非零的正整数:"^\+?[1-9][0-9]*$"。
只能输入非零的负整数:"^\-[1-9][]0-9"*$。
只能输入长度为3的字符:"^.{3}$"。
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"。
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"。
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"。
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"。
只能输入由数字、26个英文字母或者下划线组成的字符串:"^\w+$"。
验证用户密码:"^[a-zA-Z]\w{5,17}$"正确格式为:以字母开头,长度在6~18之间,只能包含字符、数字和下划线。
验证是否含有^%&',;=?$\"等字符:"[^%&',;=?$\x22]+"。
只能输入汉字:"^[\u4e00-\u9fa5]{0,}$"
验证Email地址:"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。
验证InternetURL:"^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$"。
验证电话号码:"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为:"XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。
验证身份证号(15位或18位数字):"^\d{15}|\d{18}$"。
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"1"~"12"。
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"和"1"~"31"。
利用正则表达式限制网页表单里的文本框输入内容:

用正则表达式限制只能输入中文:onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"

用正则表达式限制只能输入全角字符: onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"

用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1

s="http://www.9499.net/page1.htm"
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2")
alert(s)

匹配双字节字符(包括汉字在内):[^\x00-\xff]

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;}

匹配空行的正则表达式:\n[\s| ]*\r

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/

匹配首尾空格的正则表达式:(^\s*)|(\s*$)

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, "");
}

利用正则表达式分解和转换IP地址:

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:

function IP2V(ip)
{
re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:

var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
符号解释:

字符
描述

\
将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。

^
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。

$
匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。

*
匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。

+
匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。

?
匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。

{n}
n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。

{n,}
n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。

{n,m}
m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

?
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。

.
匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。

(pattern)
匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。

(?:pattern)
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。

(?=pattern)
正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

(?!pattern)
负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

x|y
匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。

[xyz]
字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。

[^xyz]
负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。

[a-z]
字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。

[^a-z]
负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。

\b
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B
匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\cx
匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。

\d
匹配一个数字字符。等价于 [0-9]。

\D
匹配一个非数字字符。等价于 [^0-9]。

\f
匹配一个换页符。等价于 \x0c 和 \cL。

\n
匹配一个换行符。等价于 \x0a 和 \cJ。

\r
匹配一个回车符。等价于 \x0d 和 \cM。

\s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

\t
匹配一个制表符。等价于 \x09 和 \cI。

\v
匹配一个垂直制表符。等价于 \x0b 和 \cK。

\w
匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。

\W
匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。

\xn
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.

\num
匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。

\n
标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。

\nm
标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。

\nml
如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。

\un
匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

posted @ 2009-05-27 15:41 windsea123 阅读(41) 评论(0) 编辑

在做信息管理系统时,很多中式报表都是多维的,要实现报表数据显示,通常要用到多维表头。然而,非常遗憾的是,Winform中DataGrid、DataGridView本身不提供多维表头设计,要实现多维报表只好利用第三方的控件。通过对DataGridView的扩展,利用标题行进行重绘,可实现多维表头的友好界面。下面是对多维表头的探讨和实现。

1、常用多表头制作方法

     a.第三方控件实现多维表头:FlexGrid--展示效果很好,就是数据量大加载时显示速度较慢。

     b.报表方式实现多维表头:CrystalReport、Grid++Report--通过预览方式实现数据显示

     c、DataGridView实现多维表头

2、DataGridView多维表头实现原理

     通过重绘标题栏进行多栏实现,通过RowSpan和ColSpan来进行合并,类似Html的Table实现方式。

3、调用方法 

Code

4、界面显示

      这段代码是两年前写的,由于当时时间和编程水平有限,很多代码段没有加注释,代码的可读性极差,只是为了达到效果,具体合并的实现方法自己也已模糊。

posted @ 2009-03-31 16:33 windsea123 阅读(2787) 评论(3) 编辑
posted @ 2009-03-27 10:20 windsea123 阅读(160) 评论(0) 编辑
摘要: 在网上看了很多程序(QQ、Azureus、Ants、PPStream)都实现了p2p,以前觉得技术很高深。通过这段时间的学习才发现,单纯的实现p2p在局域网通讯很容易,但是要实现外网穿透(NAT)感觉很困难。最近看了Azureus和emule源码,分别是JAVA和C++版,本人对这两门语言都不熟悉,看起来很吃力。最后只好根据VC++实现的P2PDemo程序进行了改版,根据设计思路用c#写了一个De...阅读全文
posted @ 2009-03-26 21:19 windsea123 阅读(4931) 评论(26) 编辑
摘要: 08年,公司没什么项目做,本人主要从事软件框架编写。个人认为,做管理软件不需要什么高深的算法和技术,做的都是些Copy->Paste的工作,在程序保证质量的情况下,代码写得优雅一点就可以了!在上次写的<程序员,回头是岸>的文章中,看了很多回复,反思了一下,希望我的情绪不会影响到大家对程序的执着!就如一些兄弟回复一样,我五年的工作经历到现在一事无成,是我个人问题。确实,我从没有去怪...阅读全文
posted @ 2009-01-13 21:49 windsea123 阅读(4782) 评论(29) 编辑
摘要: 之所以写这样的标题,不是因为自己对自己没信心,也不是为了诋毁这个职业!很久以前认为只要坚持定会走向成功,强烈的认为能用程序改变世界、改变生活,到头来却是世界改变了我! 很多人认为坚持一定能成功!这是犯了经验错误。我在一家公司写了将近五年的管理系统(公司称ERP),先后做过代码编写、实施、架构编写。由于ERP实施很难,当时公司做的也是第一个项目,当时我刚毕业没什么代码、实施、管理经验,最终项目没能落...阅读全文
posted @ 2009-01-08 22:19 windsea123 阅读(3639) 评论(88) 编辑
摘要: 最近接触了一些关于SOA的相关理论,很是遗憾,没看出什么名堂来。最近为什么网络上比较流行SOA呢?个人认为这东西太悬乎了,凡是有什么好的软件思想或是方法都称之SOA,难怪架构师和软件企业那么热忠的去追捧它,似乎SOA万能,好多软件厂商都鼓吹自己的软件是面向SOA的,用SOA的热门词汇来攻关市场。几年前,一个简单的业务流程管理软件当作ERP,然后换成iERP,直至现在ERP变得很烂很臭,最终让企业谈...阅读全文
posted @ 2008-11-08 12:14 windsea123 阅读(1674) 评论(4) 编辑