由于现在来博客园少了,blog也不常更新,其实有时候还在写东西,大部分懒的传。今天想更新,才发现写的东西也不知道扔哪里了,也许被误删除了,尤其有两篇自己比较满意的也找不见了。明天去公司找找,把能找到的都传上来。
把以前写的最终版本支付宝接口放上来。
库的改变:
1、 增加了一个接口,
public void CommonProcessNotify(Page page, string verifyUrl, string key, Verify verify, string encode)
这个接口触发NotifyEvent事件,此事件通过NotifyEventArgs类型暴露了支付宝Notify通知的所有参数,并且不给支付宝回发“success”或者“fail”,回发由调用者实现。这个方法提供了支付宝Notify通知的所有功能。
如果仅仅需要处理下面几个事件,可以参考:http://www.cnblogs.com/bluewater/archive/
2006/10/16
/530630.aspx
WaitBuyerPay
WaitSellerConfirmTrade
WaitSysConfirmPay
WaitSellerSendGoods
WwaitBuyerConfirmGoods
WaitSysPaySeller
TradeFinished
TradeClosed
这几个事件细化了支付宝的Notify通知,定义了最常用的几个事件,调用起来要方便些。
2、 记录了日志记录功能。
用Log4net记录了Request.Form集合,可以看到支付宝Notify发过来的整个参数,便于调试。日志默认是Error级别,并且只有在debug版本有日志输出,实际使用时应该用release版本的库(或者修改Log4net的日志级别),以免记录下许多无用的日志。
调用方式的改变:
用Notify接口模拟出了Return方式。支付宝的Return接口虽然方便调用,但是安全可靠性差,很难在实际中应用。通过下面的方式,可以用Notify模拟return,如果支付宝的Notify发送的及时还可以完全替代Return方式。
解决方法是:让提交给支付宝信息的页面一直等待,直到收到Notify通知。
AutoResetEvent ansyCard=new AutoResetEvent(false);
ansyCard.WaitOne(); //阻塞当前线程,直到Notify完成。displaycard.aspx
ansyCard.Set();//在Notify页面发解除阻塞通知,displaycard页面继续执行。Notify.aspx
思路就是上面那么简单,但实际上还有几个问题:1、支付宝服务器发Notify页面和其他的页面不在一个线程,不属于用一个Session。2、支付宝会一直发Notify,必须要保证,解锁的是设置锁的那个线程,而不能把其他的线程锁解开。
详细的实现方式可以看源代码,此方法可为解决这种类型的问题提供了一个思路。
调试:
调试支付宝必须满足两个条件:
1、 有个公网IP,如果是ADSL每次拨号也会分配一个,可以通过ipconfig命令查到此次拨号分配的IP,这样支付宝就能访问到你。
2、 必须附加到IIS,一是通过手动附加到aspnet_wp进程,二是把启动选项的服务器改称虚拟目录的地址。
满足上面两个条件就可以调试支付宝了。
源代码的使用方法:
修改web.config中的下面几项后,就可以直接运行实例程序。Temp.aspx是测试AutoResetEvent的页面。
<add key="key" value=" "/>
<add key="partner" value=""/>
<add key="sellerEmail" value=" "/>
<add key="sellerId" value=" "/>
<add key="notifyUrl" value=" "/>
关于AutoResetEvent可以看下面的文章
http://www.cnblogs.com/bluewater/archive/
2006/08/14
/476720.html
string
key
=
ConfigurationManager.AppSettings[
"
key
"
];
string
partner
=
ConfigurationManager.AppSettings[
"
partner
"
];
string
sellerEmail
=
ConfigurationManager.AppSettings[
"
sellerEmail
"
];
string
sellerId
=
ConfigurationManager.AppSettings[
"
sellerId
"
];
string
outTradeNo
=
Guid.NewGuid().ToString();
string
url
=
ConfigurationManager.AppSettings[
"
notifyUrl
"
].ToString();
string
gatewayUrl
=
"
https://www.alipay.com/cooperate/gateway.do
"
;
//
AliPay ap
=
new
AliPay();
DigitalGoods dg
=
new
DigitalGoods(
"
create_digital_goods_trade_p
"
, partner, key,
"
MD5
"
, subject, outTradeNo, (
decimal
)money,
1
, sellerEmail, sellerId);
dg.Buyer_Id
=
"
temp
"
;
dg.Notify_Url
=
url;
Session[
"
outtradeNo
"
]
=
outTradeNo;
ap.CreateDigitalTrade(gatewayUrl, dg,
this
);
string
myScript
=
@"
document.all['discard'].src='displayCard.aspx'
"
;
Page.ClientScript.RegisterStartupScript(
this
.GetType(),
"
myScript
"
, myScript,
true
);
display.aspx
protected
void
Page_Load(
object
sender, EventArgs e)

{
//Session["outtradeNo"] = Request.QueryString["a"];
AutoResetEvent ansyCard=new AutoResetEvent(false);
Application[Session["outtradeNo"].ToString() + "Event"] = ansyCard;
ansyCard.WaitOne();
if (Application[Session["outtradeNo"].ToString()] != null)

{

string s = string.Format("<script language='javascript'>alert('你的充值卡密码是:{0}')</script>", Application[Session["outtradeNo"].ToString()]);
Response.Write(s);

}
}
notify.aspx
void
ap_WaitBuyerPay(
object
sender, NotifyEventArgs e)

{
Card card = new Card();
AutoResetEvent ansyCard = (AutoResetEvent)Application[e.Out_Trade_No + "Event"];
TradeLog tradeLog = null;

try

{
tradeLog = new TradeLog(e.Buyer_Id, e.Trade_Status, e.Trade_No, e.Buyer_Id, e.Subject, (int)e.Price, 1);
SNInfo snInfo = card.GetSn((int)e.Price);
card.WriteLog(tradeLog);
Application[e.Out_Trade_No] = snInfo.Password;

ansyCard.Set();


}
catch (Exception ex)

{
//日志
//
if (tradeLog != null)

{

string t = e.Buyer_Id + e.Trade_Status + e.Trade_No + e.Buyer_Id + e.Subject + (int)e.Price + "sendgoods";
Log4net.log.Error(t, ex);
}
else

{
//
Log4net.log.Error(GetForms(Request.Form), ex);
}
ansyCard.Set();
}
}
代码:
http://www.cnblogs.com/files/bluewater/commonalipay2.rar