支付宝及时到帐接口使用详解
这两天写支付宝接口, 这个话题不新了, 因为很多人都 做过了, 在这里我说说我的看法吧, 先说一下实现
其实支付宝公司已经给我们做的很好了, 只要少量的改动就OK了,只是有的程序员不太明天他们的动作流程而以,我就以及时到帐为例子来说了,呵呵
在这之前就大家先下载一下c#版的及时到帐代码 这里是下载地址http://dev.alipay.com/devclub/mvnforum/viewthread_thread,4;jsessionid=595DB7442AAA5CD2FC849E7C2FBE51D7
先看一下程序的结构吧
支付宝有一个类文件叫 AliPay 是一些加密算法之类的东西,包括构造URL
要吧看一下这个类的全部内容
而我们一般不用管这个类,只要保证能调用 的到就行了,不用管他
我们要做的很少,他是怎么工作的呢,
这是开发文档里的工作图
其实我们要处理的只有三个Aspx的文件,
先看第一个吧 Default.aspx
这是一个请求的界面
代码里的key和 partner的获取方法
现在我们只要按代码里的信息填写一样就可以了,
然后远行网页
点提交
就会进入
下面的操作就是在支付平台的完成了, 跟咱的程序没有关系了
现在我们应该想,那付完钱之后呢?
我们有两个界面来处理这个问题一个是
Alipay_Return.aspx
这个是当交易成功后要调用 的界面 在这里只要改动一下就行了, 其实我们要做的只是改一下这里,只要在这里更新一下你的数据库就行了,
大家现在会问我为什么会把他们注释了呢?
我测试过,,这个界面呢是只到成功的时候 调用 一次以后就再不会调用 了,
所以这样有一个不好的地方 ,就是有些客户他们对转帐操作的很老手,当交易成功之后不等调用这个界面就关闭了浏览器,这个时候会出现什么问题呢?
那支付宝就再也不会调用这个界面 了,只能等下次交易,钱是打上了,我们也收到了,但是就是没有给客户充上钱,这个时候客户就会打电话到公司,怎么回事啊, 钱打过去了, 可是我这边还没有上帐,我们上支付宝一看有啊,但就是没有上帐 ,怎么办,最后只能手动给客户上了,但又怕他程序再自动上一把,呵呵
所以在这里不我建议使用这个页面,如果你只是修改自己的订单状态的话当然是可以的
修改余额就不要在这里写了,而是写在这个Alipay_Notify.aspx页面里,这个界面是当交易状态 发生变化时就会调用 ,在没有收到成功的消息前就会一直调用,
时效是24小时,这样的话我们就不用管他是不是转到了成功页面了,只要把这个页面挂在网上等通知就行了,
当交易成功的时候上帐 就OK了
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using Gateway;
using SystemModel;
/// <summary>
/// 创建该页面文件时,请留心该页面文件中无任何HTML代码及空格。
/// 该页面称作“通知页”,是异步被支付宝服务器所调用。
/// 当支付宝的订单状态改变时,支付宝服务器则会自动调用此页面,因此请做好自身网站订单信息与支付宝上的订单的同步工作
/// </summary>
public partial class Alipay_Notify : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
//string alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?";//此路径是在上面链接地址无法起作用时替换使用。
string partner = "写自己的"; //partner合作伙伴id(必须填写)
string key = "写自己的"; //partner 的对应交易安全校验码(必须填写)
string _input_charset = "utf-8";//编码类型,完全根据客户自身的项目的编码格式而定,千万不要填错。否则极其容易造成MD5加密错误。
alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "¬ify_id=" + Request.Form["notify_id"];
//获取支付宝ATN返回结果,true是正确的订单信息,false 是无效的
string responseTxt = AliPay.Get_Http(alipayNotifyURL, 120000);
//*******加密签名程序开始*******
int i;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll = Request.Form;
// Get names of all forms into a string array.
String[] requestarr = coll.AllKeys;
//进行排序;
string[] Sortedstr = AliPay.BubbleSort(requestarr);
//构造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]]);
}
else
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]] + "&");
}
}
}
prestr.Append(key);
string mysign = AliPay.GetMD5(prestr.ToString(), _input_charset);
//*******加密签名程序结束*******
string sign = Request.Form["sign"];
if (mysign == sign && responseTxt == "true") //验证支付发过来的消息,签名是否正确,只要成功进如这个判断里,则表示该页面已被支付宝服务器成功调用
//但判断内出现自身编写的程序相关错误导致通知给支付宝并不是发送success的消息或没有更新客户自身的数据库的情况,请自身程序编写好应对措施,否则查明原因时困难之极
{
if (Request.Form["trade_status"] == "WAIT_BUYER_PAY")// 判断支付状态_等待买家付款(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["total_fee"];//金额 如果你申请了商家购物卷功能,在返回信息里面请不要做金额的判断,否则会校验通过不了。
string TOEXCELL = "MD5结果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
StreamWriter f = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
f.Write(TOEXCELL + "订单号:" + strOrderNO.ToString().Trim() + " 金额:" + strPrice.ToString().Trim());
f.Close();
Alipaym objalipay = new Alipaym();
objalipay.APID = strOrderNO;
objalipay.addTime = DateTime.Now;
objalipay.total_fee = Convert.ToDecimal(strPrice);
objalipay.trade_status = "等待买家付款";
objalipay.Text1 = DateTime.Now.ToString();
objalipay.Text2 = "";
objalipay.Text3 = "";
objalipay.Text4 = "";
objalipay.Text5 = "";
OfficeFinanceServices.Update(objalipay);
}
else if (Request.Form["trade_status"] == "TRADE_FINISHED" || Request.Form["trade_status"] == "TRADE_SUCCESS")// 判断支付状态_交易成功结束(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
string strOrderNO = Request.Form["out_trade_no"];//订单号
string strPrice = Request.Form["total_fee"];//金额
//生成对象
OfficeFinanceServices objOfficeFinanceServices = new OfficeFinanceServices();
//订单信息
string[] login = strOrderNO.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
////查询当前的余额
decimal objdm = objOfficeFinanceServices.OfficeFinanceSelect(Convert.ToInt32(login[0].ToString().Trim()), true);
OfficeFinance objofficeFinance = new OfficeFinance();
objofficeFinance.ofId = Convert.ToInt32(login[0].ToString().Trim());
objofficeFinance.ofOrid = "cz";
objofficeFinance.ofTime = DateTime.Now;
objofficeFinance.ofType = 1;
objofficeFinance.ofAmount = Convert.ToDecimal(strPrice.ToString().Trim());
objofficeFinance.ofRemainAmount = Convert.ToDecimal(strPrice.ToString().Trim()) + objdm;
objofficeFinance.ofIsCurrentValue = 1;
objofficeFinance.ofUserId = -10;
objofficeFinance.ofNote1 = "支付宝上帐:" + strPrice.ToString().Trim() + "元";
objofficeFinance.ofNote2 = "商户:" + login[1].ToString().Trim() + " 通过支付宝上帐金额:" + strPrice + "元";
if (objOfficeFinanceServices.addOfficeFinanceOne(objofficeFinance))
{
Response.Write("success");
Alipaym objalipay = new Alipaym();
objalipay.APID = strOrderNO;
objalipay.addTime = DateTime.Now;
objalipay.total_fee = Convert.ToDecimal(strPrice);
objalipay.trade_status = "交易成功";
objalipay.Text1 = DateTime.Now.ToString();
objalipay.Text2 = "";
objalipay.Text3 = "";
objalipay.Text4 = "";
objalipay.Text5 = "";
OfficeFinanceServices.Update(objalipay);
}
else
{
Response.Write("fail");
}
}
else
{
//更新自己数据库的订单语句,请自己填写一下
}
//Response.Write("success"); //返回给支付宝消息,成功,请不要改写这个success
//success与fail及其他字符的区别在于,支付宝的服务器若遇到success时,则不再发送请求通知(即不再调用该页面,让该页面再次运行起来),
//若不是success,则支付宝默认没有收到成功的信息,则会反复不停地调用该页面直到失效,有效调用时间是24小时以内。
////写文本,纪录支付宝返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库)
string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
fs.Write(TOEXCELLR);
fs.Close();
}
else
{
Response.Write("fail");
//写文本,纪录支付宝返回消息,比对md5计算结果(如网站不支持写txt文件,可改成写数据库)
string TOEXCELLR = "MD5结果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
fs.Write(TOEXCELLR);
fs.Close();
}
}
}
最好是记录一下日志文件,这样一但出了问题还可以有个参考的地方
我的代码写的有点乱大家可以适当的改一下,呵呵
如有转载请注明出处谢谢合作!!!
做一番一生引以为豪的事业;找一个一生荣辱与共的妻子;在有生之年报答帮过我的人;并有能力帮助需要帮助的人;
QQ:361983679 Email:sufei.1013@163.com MSN:sufei.1013@163.com