在线支付平台设计之Order.do (上)
2009-01-07 21:13 Kevin Zhou 阅读(2983) 评论(5) 编辑 收藏 举报假如在线支付平台让我们来设计,就是说我们作为bank方,我们该怎样设计系统。首先,我想很简单的是,设计的支付平台至少包含两个:
Order.do(支付功能)
Query.do(历史交易查询功能)
这节我们只谈Order.do,下面我们开始正文;
一:Order.do工作流程
谈到支付接口,就要先看一下,支付接口Order.do的整体工作流程
这里我们假设bank位最终的接口(不是支付网关),可以直接进行划款。为了说明bank和支付网关的不同,这里我也将支付网关的工作流程简要的用图形描述一下:
二:参数约定
谈到参数设计,我们一定要考虑可从重用、多用性,使得我们设计的Order.do不会因为增加商户而要去重构接口,所以在参数设计上一定要周密。
这里谈一下设计思想:
(1) 为了能够供多个商家使用接口,参数应含有partner_no
(2) 为了能够区分每一笔交易,那么应该对每笔交易有order_no
(3) 当然支付接口不可以少money
(4) 还有交易日期order_date
(5) 为了交易时数据不被篡改,应该有一个加密之后的validate_key
(6) 附加说明:partner_no + order_no + order_date 必须唯一(或者前两项唯一)
当然还有一些其他的附加参数,这里我们\设计如下:
参数 | 长度 | 参数名称 | 是否为空 | 说明 |
partner_no | 6 | 商户代码 | not | 例如:000010 |
order_no | 50 | 订单号 | not | 例如:0001020020090101 |
money | 16 | 金额 | not | 例如:50 |
date | 14 | 订单日期 | not | 例如:20090105002300 |
currency_type | 3 | 币种 | not | 例如:RMB |
lang | 6 | 语言 | not | 例如:GB |
return_url | 255 | 交易成功跳转的url | not | 例如:http://... |
signtype | 6 | 加密类型 | not | 例如:MD5 |
signkey | 50 | 加密串 | not | 例如:加密后的key |
三:附加功能(Notify)
这里我主要谈谈Notify(通知),做过接口或者支付,都应该或多或少接触过支付接口的Notify。那么什么是Notify呢?这里用图展示一下:
从图中可以看出,商家得到客户是否支付成功,就是通过客户在bank支付成功之后,然后通过bank把支付成功后的参数加密后传递给商家,商家再进行下一步处理。那么试想一下,客户在bank端支付成功后,客户的电脑突然断电了,那么bank跳转到商家的Return路子就断了。这个时候,当然也可以处理,因为支付接口还有Query.do,商家可以根据order_no + order_date 去查询客户是否已经支付,但是这个过程还需要手工去操作,十分麻烦。
现在我们引入Notify,简单来讲,商家先给bank一个页面A,其功能就是得到客户支付后的信息,并在成功处理后Response.write(“Y”),否则Response.write(“N”)。就是客户在bank支付成功后,
然后,bank在web前端就response.redirect到商家的return_url,然后后台也通过httpwebrequest去Notify商家的页面A,然后得到商家的页面A的“Y”之后,整个支付过程就结束;反之则间隔某个时间(比如1Min)继续Notify,直到Notify得到“Y”或者在进行某(比如50)次都得到“N”后,也结束,因为这个过程不可能死循环下去~~。
四:安全附加
因为我们在设计支付接口,直接和RMB打交道,又是WEB的,能上网的地方都可以看到。所以安全性必须得很高。那么我们大概看一下,至少应该有以下几个限制:
(1) SQL注入攻击防范
(2) 参数合法性(是否含有html标签)
(3) Partner_no是否存在
(4) Validate_key是否正确
(5) 其他约定的限制(比如单次充值金额最大值限制)
五:代码范例
(1)接受参数内容
string partnerNo = SafeRequset(Request["partner_no"]); //... //public string SafeRequset(object obj) {} //SafeRequset: when obj is null return String.Empty
(2)判断商户是否存在
if(true == IsLeagalPartner(partnerNo)) { //IsLeagalPartner : judge the partnerNo is leagal... // //进行下一步的操作 }
(3)判断加密串是否合法
string bankPrivate = bankEncrypt(partnerNo, /*...*/); //加密Request内容 if(String.Compare(validateKey, bankPrivate, true) == 0) { //进行下一步的操作 }
这次先谈到这里,一次看的太多,太累,也不好理解。这也是我的学习习惯!
欢迎大家pk……