支付宝接口 2

来源:互联网 发布:淘宝上的情蛊有效吗 编辑:程序博客网 时间:2024/03/29 18:01

 由于现在来博客园少了,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页面和其他的页面不在一个线程,不属于用一个Session2、支付宝会一直发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