由于项目需要用到在线冲值功能所以需要调用支付宝接口。说真的支付宝接口提供的dome真是有点烂…那代码对于可扩展性就更加不用说。所以自己花时间搞了一个不过真是把我搞到头晕,花了很长时间才扩展完成并调试调用(幸好自己有调试环境)。相信这功能对大家有用共享出来。
为了方便扩展制定支付宝回调接口
public interface IReturnHandler
{
/// 〈summary〉
/// 处理Returl_url回调请求
/// 〈/summary〉
/// 〈param name="properties"〉支付宝相关参数〈/param〉
/// 〈param name="customs"〉自定义参数〈/param〉
void Return(System.Collections.Specialized.NameValueCollection properties, IList〈string〉 customs);
/// 〈summary〉
/// 处理Notify_url回调请求
/// 〈/summary〉
/// 〈param name="properties"〉支付宝相关参数〈/param〉
/// 〈param name="customs"〉自定义参数〈/param〉
void Notify(System.Collections.Specialized.NameValueCollection properties, IList〈string〉 customs);
/// 〈summary〉
/// 支付宝处理错误回调请求
/// 〈/summary〉
/// 〈param name="properties"〉支付宝相关参数〈/param〉
/// 〈param name="customs"〉自定义参数〈/param〉
/// 〈param name="responsetext"〉结果内容〈/param〉
void OnError(System.Collections.Specialized.NameValueCollection properties, IList〈string〉 customs,string responsetext);
/// 〈summary〉
/// 合作商ID
/// 〈/summary〉
string Partner
{
get;
}
/// 〈summary〉
/// 加密Key
/// 〈/summary〉
string Key
{
get;
}
/// 〈summary〉
/// 卖家邮件地址
/// 〈/summary〉
string Seller_Email
{
get;
}
}
重新实现AliPay类
/// 〈summary〉
/// 支付宝虚拟货币支付
/// 〈/summary〉
public class AliPay
{
/// 〈summary〉
/// 构造虚拟货币支付对象
/// 〈/summary〉
/// 〈param name="subject"〉商品名称〈/param〉
/// 〈param name="body"〉商品描述〈/param〉
/// 〈param name="total_fee"〉总金额〈/param〉
public AliPay(string subject, string body, decimal total_fee
,string returnurl)
{
Gateway = Untity.Service_Ulr;
Service = "create_direct_pay_by_user";
Sing_Type = Untity.Sing_Type;
Payment_Type = "1";
Subject = subject;
Body = body;
Total_Fee = total_fee;
Return_Url = returnurl;
Notify_Url = returnurl;
}
public string Notify_Url
{
get;
set;
}
public string Buyer_Id
{
get;
set;
}
public void Execute〈T〉(params string[] customparams) where T:IReturnHandler,new()
{
System.DateTime currentTime = new System.DateTime();
currentTime = System.DateTime.Now;
string out_trade_no = currentTime.ToString("g");
Out_Trade_No = out_trade_no.Replace("-", "");
Out_Trade_No = Out_Trade_No.Replace(":", "");
Out_Trade_No = Out_Trade_No.Replace(" ", "");
//返回支付Url;
System.Web.HttpContext.Current.Response.Redirect(parameter.ToString());
}
}
Alipay的代码就贴部分出来,具体代码下载源码可以得到。
Execute方法是用调用支付宝接口,T泛型参数主要描述支付宝回调后用那个IReturnHandler的实现者来处理;customparams就是用户自定义的参数可以是多个,注意参数内容过多生成Returl_url过长会导致支付宝处理错误。
接收支付宝回调的HttpHandler
由于把回调处理类型和自定义参数放在Return_utl里,所以必须要实现一个HttpHandler来进行相关请求接收。
public class ReturnHandler:System.Web.IHttpHandler
{
#region IHttpHandler 成员
public bool IsReusable
{
get { return false; }
}
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;
}
public void ProcessRequest(System.Web.HttpContext context)
{
string requesturl = context.Server.UrlDecode(context.Request.Path);
string alipayNotifyURL = Untity.Service_Ulr;
string urltype=System.IO.Path.GetFileName(requesturl).Substring(0, 1).ToLower();
MatchCollection matchs = Regex.Matches(requesturl, @"_([0-9a-zA-Z\%=]+)");
string TypeName = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(matchs[0].Groups[1].Value));
IReturnHandler handler = (IReturnHandler)Activator.CreateInstance(Type.GetType(TypeName));
IList〈string〉 paramsdata = new List〈string〉();
for (int k = 1; k 〈 matchs.Count; k++)
{
paramsdata.Add(matchs[k].Groups[1].Value);
}
string partner = handler.Partner;
string key = handler.Key;
NameValueCollection payResultData;
if (urltype == "r")
{
payResultData = context.Request.QueryString;
}
else
{
payResultData = context.Request.Form;
}
alipayNotifyURL = alipayNotifyURL + "service=notify_verify" + "&partner=" + partner + "?ify_id=" + payResultData["notify_id"];
string responseTxt = Get_Http(alipayNotifyURL, 120000);
int i;
String[] requestarr = payResultData.AllKeys;
//进行排序;
string[] Sortedstr = Untity.BubbleSort(requestarr);
//构造待md5摘要字符串;
string prestr = "";
for (i = 0; i 〈 Sortedstr.Length; i++)
{
if (context.Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr = prestr + Sortedstr[i] + "=" + payResultData[Sortedstr[i]];
}
else
{
prestr = prestr + Sortedstr[i] + "=" + payResultData[Sortedstr[i]] + "&";
}
}
}
prestr = prestr + key;
string mysign =Untity.GetMD5(prestr);
string sign = payResultData["sign"];
if (responseTxt == "true" && mysign == sign) //验证支付发过来的消息,签名是否正确
{
string status = payResultData["trade_status"];
if (status == "TRADE_FINISHED")// WAIT_SELLER_SEND_GOODS 判断支付状态(文档中有枚举表可以参考)
{
//更新自己数据库的订单语句,请自己填写一下
if (urltype == "r")
{
handler.Return(payResultData, paramsdata);
}
else
{
handler.Notify(payResultData, paramsdata);
}
}
}
else
{
handler.OnError(payResultData, paramsdata, responseTxt);
}
}
#endregion
}
到这里封装完成。