最近须要为网站加入支付宝的充值接口,而目前关于支付宝接口开发的资料比较杂乱,这里就我这次开发所用到的资料进行汇总整理,但愿可以帮助须要的朋友。php
支付宝的接口有多种类型,因此首先你要肯定签约的合同类型,肯定使用的是哪一个接口,不至于走错了道道。java
此步骤中,能够参考文档:支付宝接口操做教程sql
若是是即时到帐的开发,请先下载并仔细阅读:标准快速付款接口文档数据库
文档中比较详细的介绍了逻辑流程,时序图以及枚举定义等,最好在看示例代码以前通读之安全
支付宝示例程序的调试须要商户号和相应的密钥,不然没法进行程序的调试,具体获取方法请查看官方帮助,再也不赘述服务器
asp 即时到帐接口代码实例:点此下载 (31.62 KB)
php_GBK 即时到帐接口代码实例:点此下载 (22.02 KB)
php_UTF-8 即时到帐接口代码实例:点此下载 (22.02 KB)
net_05_GBK(post方式) 即时到帐接口代码实例:点此下载 (12.03 KB)
net_05_UTF-8(post方式) 即时到帐接口代码实例: 点此下载 (10.72 KB)
java_GBK(get方式) 即时到帐接口代码实例:点此下载 (136.54 KB)
java_UTF-8 (get方式)即时到帐接口代码实例:点此下载 (112.67 KB) 网络
下面内容转自http://dev.alipay.com/devclub/mvnforum/viewthread_thread,161_offset,0架构
你们想必都有这种困惑——拿到支付宝的接口代码后,尽管里面的程序有注释,接口代码包中也附有开发说明,但仍是不知道该如何入手。这不难想象是什么缘由,由于本身并不了解这个接口的工做原理是什么?
那么这篇文章就是要向你们全面展现关于支付宝接口的全部东西,以便你们能快速上手把接口接入本身的项目中,也能帮助那些已经对支付宝接口有所了解的程序开发者们更了解支付宝的一些通用规则、特殊用途等。
正题开始——
1、 结构
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这个文件中。框架
2、 工做原理
你们对结构部分已经有所了解,那么咱们就开始分析具体的这个接口是如何运做的。
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#语言代码程序为例:asp.netstring 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/";
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";
string return_url = "http://www.xxx.com/swnet05utf8/Alipay_Return.aspx";
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连接地址,如:
该连接来自支付宝官方的技术文档“标准实物双接口技术文档”
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 & "¬ify_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 + "¬ify_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");
做用上不一样的详细说明,你们能够看下面的第四部分。
3、 参数
首先你们有个疑问,技术文档中的输入参数列表中给出了诸多参数,而手上拿到的代码里只写了一部分参数来进行传递信息,这到底是为何?那么咱们先带着这个疑问往下看。
如下讨论的参数不涵盖网关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_一、logistics_fee_一、logistics_paymen
t_1(第二组);logistics_type_二、logistics_fee_二、logistics_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) 剩下的参数无需理会
整个实物标准双接口的参数介绍完毕,那么其余接口的参数还要介绍吗?你们从上面分析得出的东西对比技术文档的参数列表是否看出什么来了?
一、 参数列表的最后一列叫“可空”,N表明不容许为空,Y表明容许为空,结合上面的不可缺乏参数与增长的有用参数来进行比较,不难发现,不可缺乏的参数全是为N的。
二、 有些为Y的参数有一组,例如buyer_email、buyer_id,凡是遇到这种的通常都是二可选一也可都不选,或是二必选一。举例说明:二必选一的是seller_email、seller_id,二选一的
是buyer_email、buyer_id。
全部的接口的参数如此分析就能判断出哪些是重要参数哪些可不要,结合技术文档与程序接口来研究就能一目了然。
4、 通知返回
a) 返回页
传递给支付宝时的return_url参数所对应的页面文件。
具有的属性:
一、支付接口中买家的购买流程已经走到支付宝里且支付宝提示支付成功时,页面会自动跳转回自身网站的这个页面里来。
二、同步的,无时差
三、得到参数的方法是用get方式获取。
四、不论跳转回来程序判断是真仍是假(if(sign = mysign and responseTxt = true))只跳转回来一次,不重复。
五、这个并非支付宝服务器调用了该页面,而是经过与组合拼接各参数造成的URL连接原理等同,拼接出来的URL连接,以后程序上作自动跳转。
六、基于5的缘由,该页面的程序调试可没必要在服务器上而是本机上调试、运行。
b) 通知页
传递给支付宝时的notify_url参数所对应的页面文件
具有的属性:
一、这个通知页就是被支付宝调用才能启动的。
二、服务器间的互动,不像返回页肉眼能够看到,这个是看不到的。
三、得到参数的方法是用POST方式获取。
四、支付宝中的该笔交易存在,且该笔交易状态发生了变动,就会被调用。
五、被调用程序判断(if(sign = mysign and responseTxt = true)),若咱们本身在该判断中有作程序编写,成功则再也不被调用,不成功则会反复被调用。
六、异步的,第一次收到订单信息(如下都称之为“通知”)是与返回页近乎等同或等同的同步时间,在判断不成功的状况下,会收到第二次第三次等次数的通知,时间间隔从最早的一两分钟,到后面的几个小时。失效时间是4
8小时。
七、基于6的缘由,该页面的程序调试必须在服务器上调试、运行。
八、程序编写时必须采用程序执行成功,才写页面response.Write(“success”);,不成功则写页面response.Write(“fail”); 支付宝根据success来断定是否要从新再次发送通知。
九、该页面的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.