让支付宝更容易,面相对象的支付宝
支付宝接口,我拿到代码后,重新整理了一下.
具体的,将功能分为4个文件
Alipay.cs --->支付宝数据结构类
AlipayComm.cs--->公共代码静态类
AlipayResults.cs--->返回值类型类
AlipayServiceType.cs--->服务类型(比如我就是用的即时到帐)
Alipay.cs:
AlipayComm.cs:
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Security.Cryptography;
using System.Net;
namespace System.AlipaySystem
{
/// <summary>
/// AlipayComm 支付宝接口公共代码
/// </summary>
public static class AlipayComm
{
/// <summary>
/// 接口地址
/// </summary>
public const string AlipayGateWay = "https://www.alipay.com/cooperate/gateway.do?";
/// <summary>
/// 支付宝ID(支付宝公司提供)
/// </summary>
public const string AlipayName = "20880xxxxxx";
/// <summary>
/// 支付宝密码,这里填写你的密码(支付宝公司提供)
/// </summary>
public const string AlipayPassword = "mmxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
/// <summary>
/// 支付宝默认编码
/// </summary>
public const string AlipayCharset = "utf-8";
/// <summary>
/// 支付宝账户(支付宝公司提供)
/// </summary>
public const string AlipayEmail = "xxx@xxxx.com";
/// <summary>
/// 加密方式
/// </summary>
public const string AlipaySignType = "MD5";
#region CreateNew()
/// <summary>
/// 工厂模式建立一个支付类型
/// </summary>
/// <returns></returns>
public static Alipay CreateNew()
{
Alipay pay = new Alipay();
pay.Partner = AlipayName;
pay.Key = AlipayPassword;
pay.GateWay = AlipayGateWay;
pay.InputCharset = AlipayCharset;
pay.PaymentType = "2";
pay.SignType = AlipaySignType;
pay.SellerEmail = AlipayEmail;
return pay;
}
#endregion
#region CreateMd5(s,charset)
/// <summary>
/// 与ASP兼容的MD5加密算法
/// </summary>
public static string CreateMd5(string s, string _input_charset)
{
MD5 md5 = new MD5CryptoServiceProvider();
byte[] t = md5.ComputeHash(Encoding.GetEncoding(_input_charset).GetBytes(s));
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < t.Length; i++)
{
sb.Append(t[i].ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
public static string CreateMd5(string s)
{
return CreateMd5(s, AlipayCharset);
}
#endregion
#region Sort(r)
/// <summary>
/// 对参数进行排序
/// </summary>
/// <param name="r"></param>
/// <returns></returns>
public static string[] Sort(string[] r)
{
/// <summary>
/// 冒泡排序法
/// </summary>
int i, j; //交换标志
string temp;
bool exchange;
for (i = 0; i < r.Length; i++) //最多做R.Length-1趟排序
{
exchange = false; //本趟排序开始前,交换标志应为假
for (j = r.Length - 2; j >= i; j--)
{
if (System.String.CompareOrdinal(r[j + 1], r[j]) < 0) //交换条件
{
temp = r[j + 1];
r[j + 1] = r[j];
r[j] = temp;
exchange = true; //发生了交换,故将交换标志置为真
}
}
if (!exchange) //本趟排序未发生交换,提前终止算法
{
break;
}
}
return r;
}
#endregion
#region CreateHttpRequestUrl()
/// <summary>
/// 建立Http请求的Url
/// </summary>
/// <param name="gateway"></param>
/// <param name="service"></param>
/// <param name="partner"></param>
/// <param name="sign_type"></param>
/// <param name="out_trade_no"></param>
/// <param name="subject"></param>
/// <param name="body"></param>
/// <param name="payment_type"></param>
/// <param name="total_fee"></param>
/// <param name="show_url"></param>
/// <param name="seller_email"></param>
/// <param name="key"></param>
/// <param name="return_url"></param>
/// <param name="_input_charset"></param>
/// <param name="notify_url"></param>
/// <returns></returns>
public static string CreatHttpRequestUrl(
string gateway,
string service,
string partner,
string sign_type,
string out_trade_no,
string subject,
string body,
string payment_type,
string total_fee,
string show_url,
string seller_email,
string key,
string return_url,
string _input_charset,
string notify_url
)
{
/// <summary>
/// created by sunzhizhi 2006.5.21,sunzhizhi@msn.com。
/// </summary>
int i;
//构造数组;
string[] Oristr ={
"service="+service,
"partner=" + partner,
"subject=" + subject,
"body=" + body,
"out_trade_no=" + out_trade_no,
"total_fee=" + total_fee,
"show_url=" + show_url,
"payment_type=" + payment_type,
"seller_email=" + seller_email,
"notify_url=" + notify_url,
"_input_charset="+_input_charset,
"return_url=" + return_url
};
//进行排序;
string[] Sortedstr = Sort(Oristr);// BubbleSort(Oristr);
//构造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i]);
}
else
{
prestr.Append(Sortedstr[i] + "&");
}
}
prestr.Append(key);
//生成Md5摘要;
string sign = CreateMd5(prestr.ToString(), _input_charset);// GetMD5(prestr.ToString(), _input_charset);
//构造支付Url;
//char[] delimiterChars = { '=' };
StringBuilder parameter = new StringBuilder();
parameter.Append(gateway);
//重新写构造代码,原来的代码有'='无法进行解码的问题
int index1;
for (i = 0; i < Sortedstr.Length; i++)
{
index1 = Sortedstr[i].IndexOf('=');
//append key
parameter.Append(Sortedstr[i].Substring(0, index1!=-1?index1:Sortedstr[i].Length));
parameter.Append("=");
//append value
parameter.Append(index1 != -1 && index1 != Sortedstr[i].Length - 1 ? HttpUtility.UrlEncode(Sortedstr[i].Substring(index1 + 1)) : string.Empty);
parameter.Append("&");
//原来的Url解码有问题,上面已经重写
//parameter.Append(Sortedstr[i].Split(delimiterChars)[0] + "=" + HttpUtility.UrlEncode(Sortedstr[i].Split(delimiterChars)[1]) + "&");
}
parameter.Append("sign=" + sign + "&sign_type=" + sign_type);
//返回支付Url;
return parameter.ToString();
}
#endregion
#region GetRequestResult(url,timeout)
//获取远程服务器ATN结果
public static string GetRequestResult(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;
}
#endregion
#region CreateDateString()
public static string CreateDateString()
{
return CreateDateString(DateTime.Now);
}
public static string CreateDateString(DateTime time)
{
return CreateDateString(time.ToString("g"));
}
public static string CreateDateString(string dts)
{
TextBuilder text = TextBuilder.GetTextBuilder(dts);
text.Replace("-", "");
text.Replace(";", "");
text.Replace(" ", "");
dts = text.ToString();
TextBuilder.Release(text);
return dts;
}
#endregion
}
}
AlipayResult.cs:
AlipayServiceType.cs:
注意的是,Alypay.cs这个类里面的参数一定要填写完整.
我在AlipayComm.cs里面有一个CreateNew是一个工厂模式的静态实例化方法
比如可以Alipay pay=AlipayComm.CreateNew();
大家可以自己添加自己的实例化代码.
原来的支付宝,有个问题,Return_Url返回地址不能带参数,
也就是return_url="http://www.163.com/?uid=123";这句话会出现错误"ILLEGAL_SIGN";
原因是支付宝给的CreatUrl函数中:
char[] delimiterChars = { '='};
StringBuilder parameter = new StringBuilder();
parameter.Append(gateway);
for (i = 0; i < Sortedstr.Length; i++)
{
parameter.Append(Sortedstr[i].Split(delimiterChars)[0] + "=" + HttpUtility.UrlEncode(Sortedstr[i].Split(delimiterChars)[1]) + "&");
在上面的代码片段中.Split的问题.
比如http://www.163.com/?uid=123这个返回网址,他会错误的把等于号(=)左右切开.然后分别赋值.
这样的话,uid=123又变成了一个参数.....MD5校验,怎么都不回通过的.