支付宝支付
程序员文章站
2022-04-11 15:27:31
...
对支付宝支付的二次封装,支持pc端和wap端支付
类图
pay(pc):
var orderNo = ""; //订单号
var subject = ""; //订单名称
var fee = 0.ToString("0.##"); //付款金额
var notifyUrl = "host/Alipay/NotifyUrl.aspx";
var returnUrl = "host/Alipay/ReturnUrl.aspx";
var show_url = "host";
var alipay = new Alipay.Submit();
alipay.Pay(orderNo, subject, fee, body, notify_url, return_url, show_url);
pay(wap):
var orderNo = ""; //订单号
var title = "在线捐赠(WAP):" + ""; //订单名称
var fee = 0.ToString("0.##"); //付款金额
var notifyUrl = "host/Alipay/NotifyUrl.aspx";
var returnUrl = "host/Alipay/ReturnUrl.aspx";
var show_url = "host";
var alipay = new Alipay.Submit();
alipay.Submit.Pay(orderNo, subject, fee, body, notify_url, return_url, show_url);
return(pc):
public partial class NotifyUrl : Alipay.NotifyPage
{
protected override void OnNotifyConfirm()
{
//todo:业务逻辑处理
}
}
return(wap):
public partial class NotifyUrl : Alipay.Wap.NotifyPage
{
protected override void OnNotifyConfirm()
{
//todo:业务逻辑处理
}
}
PC端的Submit.cs
using System.Text;
using System.IO;
using System.Net;
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
namespace Alipay
{
/// <summary>
/// 支付宝各接口请求提交类
/// 构造支付宝各接口表单HTML文本,获取远程HTTP数据
/// </summary>
public class Submit
{
public Submit()
{
}
/// <summary>
/// 实例化
/// </summary>
/// <param name="partner">合作者身份ID</param>
/// <param name="key">交易安全校验码</param>
/// <param name="sellerMail">卖方(收款方)支付宝账户</param>
public Submit(string partner, string key, string sellerMail)
{
Config.Partner = partner;
Config.Key = key;
Config.SellerEmail = sellerMail;
}
/// <summary>
/// 提交支付请求,get
/// </summary>
/// <param name="orderNo">商户订单号</param>
/// <param name="fee">付款金额</param>
/// <param name="title">订单名称</param>
/// <param name="desc">订单描述</param>
/// <param name="notifyUrl">服务器异步通知页面路径</param>
/// <param name="returnUrl">页面跳转同步通知页面路径</param>
/// <param name="showUrl">商品展示地址</param>
public void Pay(string orderNo, string fee, string title, string desc, string notifyUrl,
string returnUrl, string showUrl)
{
var para = new SortedDictionary<string, string>
{
{"partner", Config.Partner},
{"_input_charset", Config._Charset.ToLower()},
{"service", Config._PayMode},
{"payment_type", Config._PayType},
{"notify_url", notifyUrl},
{"return_url", returnUrl},
{"seller_email", Config.SellerEmail},
{"out_trade_no", orderNo},
{"subject", title},
{"total_fee", fee},
{"body", desc},
{"show_url", showUrl},
{"anti_phishing_key", _GetDateTimeString()}
};
var dicPara = BuildRequestPara(para);
var sbHtml = new StringBuilder();
sbHtml.AppendFormat(
"<form id='alipaysubmit' name='alipaysubmit' action='{0}_input_charset={1}' method='get'>",
Config._GateWay, Config._Charset);
foreach (var temp in dicPara)
{
sbHtml.AppendFormat("<input type='hidden' name='{0}' value='{1}'/>", temp.Key, temp.Value);
}
//submit按钮控件请不要含有name属性
sbHtml.Append("<input type='submit' value='支付' style='display:none;'></form>");
sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>");
HttpContext.Current.Response.Write(sbHtml.ToString());
}
/// <summary>
/// 提交支付请求,post
/// </summary>
/// <param name="notifyUrl">服务器异步通知页面路径</param>
/// <param name="returnUrl">页面跳转同步通知页面路径</param>
/// <param name="sellerEmail">卖家支付宝帐户</param>
/// <param name="orderNo">商户订单号</param>
/// <param name="subject">订单名称</param>
/// <param name="fee">付款金额</param>
/// <param name="title">订单描述</param>
/// <param name="showUrl">商品展示地址</param>
public void PostPay(string notifyUrl, string returnUrl, string sellerEmail, string orderNo, string subject
, string fee, string title, string showUrl)
{
var para = new SortedDictionary<string, string>
{
{"partner", Config.Partner},
{"_input_charset", Config._Charset.ToLower()},
{"service", Config._PayMode},
{"payment_type", Config._PayType},
{"notify_url", notifyUrl},
{"return_url", returnUrl},
{"seller_email", sellerEmail},
{"out_trade_no", orderNo},
{"subject", subject},
{"total_fee", fee},
{"body", title},
{"show_url", showUrl},
{"anti_phishing_key", _GetDateTimeString()}
};
var encoding = Encoding.GetEncoding(Config._Charset);
var strRequestData = BuildRequestParaToString(para, encoding);
var bytesRequestData = encoding.GetBytes(strRequestData);
var strUrl = string.Format("{0}_input_charset={1}", Config._GateWay, Config._Charset);
string strResult;
try
{
var myReq = (HttpWebRequest)WebRequest.Create(strUrl);
myReq.Method = "post";
myReq.ContentType = "application/x-www-form-urlencoded";
myReq.ContentLength = bytesRequestData.Length;
var requestStream = myReq.GetRequestStream();
requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);
requestStream.Close();
var HttpWResp = (HttpWebResponse)myReq.GetResponse();
var myStream = HttpWResp.GetResponseStream();
var reader = new StreamReader(myStream, encoding);
var responseData = new StringBuilder();
string line;
while ((line = reader.ReadLine()) != null)
{
responseData.Append(line);
}
myStream.Close();
strResult = responseData.ToString();
}
catch (Exception ex)
{
strResult = "报错:" + ex.Message;
}
HttpContext.Current.Response.Write(strResult);
}
/// <summary>
/// 生成请求时的签名
/// </summary>
internal string BuildRequestMysign(Dictionary<string, string> sPara)
{
return MD5.Sign(Core.CreateLinkString(sPara), Config.Key, Config._Charset);
}
/// <summary>
/// 生成要请求给支付宝的参数数组
/// </summary>
internal Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)
{
var sPara = Core.FilterPara(sParaTemp);
var mysign = BuildRequestMysign(sPara);
sPara.Add("sign", mysign);
sPara.Add("sign_type", Config._SignType);
return sPara;
}
/// <summary>
/// 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数
/// 注意:远程解析XML出错,与IIS服务器配置有关
/// </summary>
/// <returns>时间戳字符串</returns>
private string _GetDateTimeString()
{
var url = string.Format("{0}service=query_timestamp&partner={1}", Config._GateWay, Config.Partner);
var Reader = new XmlTextReader(url);
var xmlDoc = new XmlDocument();
xmlDoc.Load(Reader);
return xmlDoc.SelectSingleNode("/alipay/response/timestamp/encrypt_key").InnerText;
}
/// <summary>
/// 生成要请求给支付宝的参数数组
/// </summary>
internal string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code)
{
return Core.CreateLinkStringUrlencode(BuildRequestPara(sParaTemp), code);
}
/*
/// <summary>
/// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能
/// </summary>
/// <param name="sParaTemp">请求参数数组</param>
/// <param name="strMethod">提交方式。两个值可选:post、get</param>
/// <param name="fileName">文件绝对路径</param>
/// <param name="data">文件数据</param>
/// <param name="contentType">文件内容类型</param>
/// <param name="lengthFile">文件长度</param>
/// <returns>支付宝处理结果</returns>
internal static string BuildRequest(SortedDictionary<string, string> sParaTemp, string strMethod, string fileName, byte[] data, string contentType, int lengthFile)
{
//待请求参数数组
Dictionary<string, string> dicPara = new Dictionary<string, string>();
dicPara = BuildRequestPara(sParaTemp);
//构造请求地址
string strUrl = Config._GateWay + "_input_charset=" + Config._Charset;
//设置HttpWebRequest基本信息
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(strUrl);
//设置请求方式:get、post
request.Method = strMethod;
//设置boundaryValue
string boundaryValue = DateTime.Now.Ticks.ToString("x");
string boundary = "--" + boundaryValue;
request.ContentType = "\r\nmultipart/form-data; boundary=" + boundaryValue;
//设置KeepAlive
request.KeepAlive = true;
//设置请求数据,拼接成字符串
StringBuilder sbHtml = new StringBuilder();
foreach (KeyValuePair<string, string> key in dicPara)
{
sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"" + key.Key + "\"\r\n\r\n" + key.Value + "\r\n");
}
sbHtml.Append(boundary + "\r\nContent-Disposition: form-data; name=\"withhold_file\"; filename=\"");
sbHtml.Append(fileName);
sbHtml.Append("\"\r\nContent-Type: " + contentType + "\r\n\r\n");
string postHeader = sbHtml.ToString();
//将请求数据字符串类型根据编码格式转换成字节流
Encoding code = Encoding.GetEncoding(Config._Charset);
byte[] postHeaderBytes = code.GetBytes(postHeader);
byte[] boundayBytes = Encoding.ASCII.GetBytes("\r\n" + boundary + "--\r\n");
//设置长度
long length = postHeaderBytes.Length + lengthFile + boundayBytes.Length;
request.ContentLength = length;
//请求远程HTTP
Stream requestStream = request.GetRequestStream();
Stream myStream;
try
{
//发送数据请求服务器
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
requestStream.Write(data, 0, lengthFile);
requestStream.Write(boundayBytes, 0, boundayBytes.Length);
HttpWebResponse HttpWResp = (HttpWebResponse)request.GetResponse();
myStream = HttpWResp.GetResponseStream();
}
catch (WebException e)
{
return e.ToString();
}
finally
{
if (requestStream != null)
{
requestStream.Close();
}
}
//读取支付宝返回处理结果
StreamReader reader = new StreamReader(myStream, code);
StringBuilder responseData = new StringBuilder();
String line;
while ((line = reader.ReadLine()) != null)
{
responseData.Append(line);
}
myStream.Close();
return responseData.ToString();
}
*/
}
}
wap端的Submit.cs
using System.Text;
using System.IO;
using System.Net;
using System;
using System.Collections.Generic;
using System.Web;
using System.Xml;
namespace Alipay.Wap
{
/// <summary>
/// 支付宝各接口请求提交类
/// 构造支付宝各接口表单HTML文本,获取远程HTTP数据
/// </summary>
public class Submit
{
public Submit()
{
}
/// <summary>
/// 实例化
/// </summary>
/// <param name="partner">合作者身份ID</param>
/// <param name="key">交易安全校验码</param>
/// <param name="sellerMail">卖方(收款方)支付宝账户</param>
public Submit(string partner, string key, string sellerMail)
{
Config.Partner = partner;
Config.Key = key;
Config.SellerEmail = sellerMail;
}
/// <summary>
/// 提交支付请求,get
/// </summary>
/// <param name="orderNo">商户订单号</param>
/// <param name="fee">付款金额</param>
/// <param name="title">订单名称</param>
/// <param name="desc">订单描述</param>
/// <param name="notifyUrl">服务器异步通知页面路径</param>
/// <param name="returnUrl">页面跳转同步通知页面路径</param>
/// <param name="showUrl">商品展示地址</param>
public void Pay(string orderNo, string fee, string title, string desc, string notifyUrl,
string returnUrl, string showUrl)
{
var req_id = DateTime.Now.ToString("yyyyMMddHHmmssfff"); //请求号,须保证每次请求都是唯一
const string format = "xml";
const string v = "2.0";
if (string.IsNullOrEmpty(fee)) fee = "0";
if (string.IsNullOrEmpty(title)) title = "在线捐赠(WAP)";
if (string.IsNullOrEmpty(orderNo)) orderNo = req_id;
var req_dataToken =
string.Format(
"<direct_trade_create_req><notify_url>{0}</notify_url><call_back_url>{1}</call_back_url><seller_account_name>{2}</seller_account_name><out_trade_no>{3}</out_trade_no><subject>{4}</subject><total_fee>{5}</total_fee><merchant_url>{6}</merchant_url></direct_trade_create_req>",
notifyUrl, returnUrl, Config.SellerEmail, orderNo, title, fee, showUrl);
//创建支付宝交易订单,并获取授权码token,alipay.wap.trade.create.direct
var sParaTempToken = new SortedDictionary<string, string>();
sParaTempToken.Add("partner", Config.Partner);
sParaTempToken.Add("_input_charset", Config._Charset.ToLower());
sParaTempToken.Add("sec_id", Config._SignType.ToUpper());
sParaTempToken.Add("service", "alipay.wap.trade.create.direct");
sParaTempToken.Add("format", format);
sParaTempToken.Add("v", v);
sParaTempToken.Add("req_id", req_id);
sParaTempToken.Add("req_data", req_dataToken);
var sHtmlTextToken = BuildRequest(Config._GateWayWap, sParaTempToken);
var code = Encoding.GetEncoding(Config._Charset);
sHtmlTextToken = HttpUtility.UrlDecode(sHtmlTextToken, code);
var dicHtmlTextToken = ParseResponse(sHtmlTextToken);
var request_token = dicHtmlTextToken["request_token"];
//根据授权码token调用交易接口alipay.wap.auth.authAndExecute
var req_data = string.Format("<auth_and_execute_req><request_token>{0}</request_token></auth_and_execute_req>", request_token);
var sParaTemp = new SortedDictionary<string, string>
{
{"partner", Config.Partner},
{"_input_charset", Config._Charset.ToLower()},
{"sec_id", Config._SignType.ToUpper()},
{"service", "alipay.wap.auth.authAndExecute"},
{"format", format},
{"v", v},
{"req_data", req_data}
};
var sHtmlText = BuildRequest(Config._GateWayWap, sParaTemp, "get", "确认");
HttpContext.Current.Response.Write(sHtmlText);
}
/// <summary>
/// 建立请求,以表单HTML形式构造(默认)
/// </summary>
/// <param name="GATEWAY_NEW">支付宝网关地址</param>
/// <param name="sParaTemp">请求参数数组</param>
/// <param name="strMethod">提交方式。两个值可选:post、get</param>
/// <param name="strButtonValue">确认按钮显示文字</param>
/// <returns>提交表单HTML文本</returns>
private string BuildRequest(string GATEWAY_NEW, SortedDictionary<string, string> sParaTemp, string strMethod, string strButtonValue)
{
var dicPara = BuildRequestPara(sParaTemp);
var sbHtml = new StringBuilder();
sbHtml.Append("<form id='alipaysubmit' name='alipaysubmit' action='" + GATEWAY_NEW + "_input_charset=" + Config._Charset + "' method='" + strMethod.ToLower().Trim() + "'>");
foreach (var temp in dicPara)
{
sbHtml.Append("<input type='hidden' name='" + temp.Key + "' value='" + temp.Value + "'/>");
}
//submit按钮控件请不要含有name属性
sbHtml.Append("<input type='submit' value='" + strButtonValue + "' style='display:none;'></form>");
sbHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>");
return sbHtml.ToString();
}
/// <summary>
/// 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
/// </summary>
/// <param name="gateWayWap">支付宝网关地址</param>
/// <param name="sParaTemp">请求参数数组</param>
/// <returns>支付宝处理结果</returns>
private string BuildRequest(string gateWayWap, SortedDictionary<string, string> sParaTemp)
{
var code = Encoding.GetEncoding(Config._Charset);
var strRequestData = BuildRequestParaToString(sParaTemp,code);
var bytesRequestData = code.GetBytes(strRequestData);
var strUrl = string.Format("{0}_input_charset={1}", gateWayWap, Config._Charset);
string strResult;
try
{
var myReq = (HttpWebRequest)WebRequest.Create(strUrl);
myReq.Method = "post";
myReq.ContentType = "application/x-www-form-urlencoded";
myReq.ContentLength = bytesRequestData.Length;
var requestStream = myReq.GetRequestStream();
requestStream.Write(bytesRequestData, 0, bytesRequestData.Length);
requestStream.Close();
var HttpWResp = (HttpWebResponse)myReq.GetResponse();
var myStream = HttpWResp.GetResponseStream();
var reader = new StreamReader(myStream, code);
var responseData = new StringBuilder();
string line;
while ((line = reader.ReadLine()) != null)
{
responseData.Append(line);
}
myStream.Close();
strResult = responseData.ToString();
}
catch (Exception exp)
{
strResult = "报错:"+exp.Message;
}
return strResult;
}
/// <summary>
/// 生成要请求给支付宝的参数数组
/// </summary>
private string BuildRequestParaToString(SortedDictionary<string, string> sParaTemp, Encoding code)
{
return Core.CreateLinkStringUrlencode(BuildRequestPara(sParaTemp), code);
}
/// <summary>
/// 生成要请求给支付宝的参数数组
/// </summary>
private Dictionary<string, string> BuildRequestPara(SortedDictionary<string, string> sParaTemp)
{
var sPara = Core.FilterPara(sParaTemp);
var mysign = MD5.Sign(Core.CreateLinkString(sPara), Config.Key, Config._Charset);
sPara.Add("sign", mysign);
if (sPara["service"] != "alipay.wap.trade.create.direct" && sPara["service"] != "alipay.wap.auth.authAndExecute")
{
sPara.Add("sign_type", Config._SignType);
}
return sPara;
}
/// <summary>
/// 解析远程模拟提交后返回的信息
/// </summary>
/// <param name="strText">要解析的字符串</param>
/// <returns>解析结果</returns>
private Dictionary<string, string> ParseResponse(string strText)
{
var strSplitText = strText.Split('&');
var dicText = new Dictionary<string, string>();
foreach (string text in strSplitText)
{
var nPos = text.IndexOf('=');
dicText.Add(text.Substring(0, nPos), text.Substring(nPos + 1, text.Length - nPos - 1));
}
if (dicText["res_data"] != null)
{
//token从res_data中解析出来(也就是说res_data中已经包含token的内容)
var xmlDoc = new XmlDocument();
try
{
xmlDoc.LoadXml(dicText["res_data"]);
var strRequest_token = xmlDoc.SelectSingleNode("/direct_trade_create_res/request_token").InnerText;
dicText.Add("request_token", strRequest_token);
}
catch (Exception exp)
{
dicText.Add("request_token", exp.ToString());
}
}
return dicText;
}
}
}
Config.cs
using System.Configuration;
namespace Alipay
{
/// <summary>
/// 账户配置
/// 1.登录支付宝网站(www.alipay.com)
/// 2.点击“商家服务”(https://b.alipay.com/order/myOrder.htm)
/// 3.点击“查询合作者身份(PID)”、“查询安全校验码(Key)”
/// </summary>
public class Config
{
/// <summary>
/// 合作者身份ID
/// </summary>
public static string Partner{ internal get; set; }
/// <summary>
/// 交易安全校验码
/// </summary>
public static string Key { internal get; set; }
/// <summary>
/// 卖方(收款方)支付宝账户
/// </summary>
public static string SellerEmail { internal get; set; }
/// <summary>
/// 字符编码格式:utf-8
/// </summary>
internal static string _Charset { get { return "utf-8"; } }
/// <summary>
/// 签名方式:MD5
/// </summary>
internal static string _SignType { get { return "MD5"; } }
/// <summary>
/// 支付宝网关地址pc
/// </summary>
internal static string _GateWay { get { return "https://mapi.alipay.com/gateway.do?"; } }
/// <summary>
/// 支付宝网关地址wap
/// </summary>
internal static string _GateWayWap { get { return "http://wappaygw.alipay.com/service/rest.htm?"; } }
/// <summary>
/// 支付宝消息验证地址
/// </summary>
internal static string _VeryfyUrl { get { return "https://mapi.alipay.com/gateway.do?service=notify_verify&"; } }
/// <summary>
/// 交易方式:即时到账交易pc
/// </summary>
internal static string _PayMode { get { return "create_direct_pay_by_user"; } }
/// <summary>
/// 支付类型:1
/// </summary>
internal static string _PayType { get { return "1"; } }
/// <summary>
/// 日志路径:/log/Alipay
/// </summary>
internal static string _LogPath { get { return "/log/Alipay"; } }
/// <summary>
/// 商户的私钥,如果签名方式设置为“0001”时,请设置该参数
/// </summary>
internal static string _PrivateKey { get { return ""; } }
/// <summary>
/// 商户的公钥,如果签名方式设置为“0001”时,请设置该参数
/// </summary>
internal static string _PublicKey { get { return ""; } }
static Config()
{
if (string.IsNullOrEmpty(Partner))
Partner = ConfigurationManager.AppSettings["Alipay.Partner"];
if (string.IsNullOrEmpty(Key))
Key = ConfigurationManager.AppSettings["Alipay.Key"];
if (string.IsNullOrEmpty(SellerEmail))
SellerEmail = ConfigurationManager.AppSettings["Alipay.SellerEmail"];
}
}
}
Core.cs
using System.Linq;
using System.Web;
using System.Text;
using System.IO;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Alipay
{
internal class Core
{
/// <summary>
/// 除去数组中的空值和签名参数并以字母a到z的顺序排序
/// </summary>
internal static Dictionary<string, string> FilterPara(SortedDictionary<string, string> dicArrayPre)
{
return
dicArrayPre.Where(
temp =>
temp.Key.ToLower() != "sign" && temp.Key.ToLower() != "sign_type" &&
!string.IsNullOrEmpty(temp.Value)).ToDictionary(temp => temp.Key, temp => temp.Value);
}
/// <summary>
/// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
/// </summary>
internal static string CreateLinkString(Dictionary<string, string> dicArray)
{
var prestr = new StringBuilder();
foreach (var temp in dicArray)
{
prestr.Append(temp.Key + "=" + temp.Value + "&");
}
prestr.Remove(prestr.Length - 1, 1);
return prestr.ToString();
}
/// <summary>
/// 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值做urlencode
/// </summary>
internal static string CreateLinkStringUrlencode(Dictionary<string, string> dicArray, Encoding code)
{
var prestr = new StringBuilder();
foreach (var temp in dicArray)
{
prestr.AppendFormat("{0}={1}&", temp.Key, HttpUtility.UrlEncode(temp.Value, code));
}
prestr.Remove(prestr.Length - 1, 1);
return prestr.ToString();
}
/// <summary>
/// 写日志
/// </summary>
internal static void LogResult(string text)
{
var strPath = HttpContext.Current.Server.MapPath(Config._LogPath);
var dateFloderName = DateTime.Now.ToString("yyyyMM");
strPath = string.Format("{0}/{1}", strPath, dateFloderName);
if (!Directory.Exists(strPath))
{
Directory.CreateDirectory(strPath);
}
strPath = strPath + "\\" + DateTime.Now.ToString("yyyyMMddHHmmssffff", DateTimeFormatInfo.InvariantInfo) + ".txt";
var fs = new StreamWriter(strPath, true, Encoding.Default);
fs.Write(text);
fs.Close();
}
/// <summary>
/// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组
/// </summary>
internal static SortedDictionary<string, string> GetRequestPost()
{
int i;
var sArray = new SortedDictionary<string, string>();
var coll = HttpContext.Current.Request.Form;
var requestItem = coll.AllKeys;
for (i = 0; i < requestItem.Length; i++)
sArray.Add(requestItem[i], HttpContext.Current.Request.Form[requestItem[i]]);
return sArray;
}
/*
/// <summary>
/// 获取文件的md5摘要
/// </summary>
/// <param name="sFile">文件流</param>
/// <returns>MD5摘要结果</returns>
internal static string GetAbstractToMD5(Stream sFile)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(sFile);
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
/// <summary>
/// 获取文件的md5摘要
/// </summary>
/// <param name="dataFile">文件流</param>
/// <returns>MD5摘要结果</returns>
internal static string GetAbstractToMD5(byte[] dataFile)
{
System.Security.Cryptography.MD5 md5 = new MD5CryptoServiceProvider();
byte[] result = md5.ComputeHash(dataFile);
StringBuilder sb = new StringBuilder(32);
for (int i = 0; i < result.Length; i++)
{
sb.Append(result[i].ToString("x").PadLeft(2, '0'));
}
return sb.ToString();
}
*/
}
}
MD5.cs
using System.Text;
using System.Security.Cryptography;
namespace Alipay
{
internal sealed class MD5
{
/// <summary>
/// 签名字符串
/// </summary>
/// <param name="str">需要签名的字符串</param>
/// <param name="key">**</param>
/// <param name="charset">编码格式</param>
/// <returns>签名结果</returns>
internal static string Sign(string str, string key, string charset)
{
var sb = new StringBuilder(32);
str += key;
var md5 = new MD5CryptoServiceProvider();
var t = md5.ComputeHash(Encoding.GetEncoding(charset).GetBytes(str));
for (var i = 0; i < t.Length; i++)
sb.Append(t[i].ToString("x").PadLeft(2, '0'));
return sb.ToString();
}
/// <summary>
/// 验证签名
/// </summary>
/// <param name="prestr">需要签名的字符串</param>
/// <param name="sign">签名结果</param>
/// <param name="key">**</param>
/// <param name="charset">编码格式</param>
/// <returns>验证结果</returns>
internal static bool Verify(string prestr, string sign, string key, string charset)
{
var mysign = Sign(prestr, key, charset);
return mysign == sign;
}
}
}
Notify.cs
Notify.cs
using System.Text;
using System.IO;
using System.Net;
using System;
using System.Collections.Generic;
namespace Alipay
{
/// <summary>
/// 处理支付宝各接口通知返回
/// </summary>
internal class Notify
{
/// <summary>
/// 验证消息是否是支付宝发出的合法消息
/// </summary>
/// <param name="inputPara">通知返回参数数组</param>
/// <param name="notifyId">通知验证ID</param>
/// <param name="sign">支付宝生成的签名结果</param>
/// <returns>验证结果</returns>
internal bool Verify(SortedDictionary<string, string> inputPara, string notifyId, string sign)
{
var isSign = GetSignVeryfy(inputPara, sign);
var responseTxt = "true";
if (!string.IsNullOrEmpty(notifyId)) { responseTxt = GetResponseTxt(notifyId); }
//判断responsetTxt是否为true,isSign是否为true
//responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
//isSign不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
return responseTxt == "true" && isSign;
}
/// <summary>
/// 获取返回时的签名验证结果
/// </summary>
/// <param name="inputPara">通知返回参数数组</param>
/// <param name="sign">对比的签名结果</param>
/// <returns>签名验证结果</returns>
private bool GetSignVeryfy(SortedDictionary<string, string> inputPara, string sign)
{
var sPara = Core.FilterPara(inputPara); //过滤空值、sign与sign_type参数
var preSignStr = Core.CreateLinkString(sPara); //获取待签名字符串
return MD5.Verify(preSignStr, sign, Config.Key, Config._Charset);
}
/// <summary>
/// 获取是否是支付宝服务器发来的请求的验证结果
/// </summary>
/// <param name="notifyId">通知验证ID</param>
/// <returns>验证结果</returns>
private string GetResponseTxt(string notifyId)
{
var veryfyUrl = string.Format("{0}partner={1}¬ify_id={2}", Config._VeryfyUrl, Config.Partner, notifyId);
//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求
try
{
var myReq = (HttpWebRequest)WebRequest.Create(veryfyUrl);
myReq.Timeout = 120000;
var HttpWResp = (HttpWebResponse)myReq.GetResponse();
var myStream = HttpWResp.GetResponseStream();
var sr = new StreamReader(myStream, Encoding.Default);
var strBuilder = new StringBuilder();
while (-1 != sr.Peek())
{
strBuilder.Append(sr.ReadLine());
}
return strBuilder.ToString();
}
catch (Exception exp)
{
return string.Format("错误:{0}", exp.Message);
}
}
}
}
PC端的NotifyPage.cs
PC端的NotifyPage.cs
using System;
using System.Collections.Generic;
using System.Linq;
namespace Alipay
{
/// <summary>
/// pc网页支付接口接入页
/// </summary>
public abstract class NotifyPage : System.Web.UI.Page
{
/// <summary>
/// 商户订单号
/// </summary>
protected string OrderNo { get; private set; }
/// <summary>
/// 支付宝交易号
/// </summary>
protected string TradeNo { get; private set; }
/// <summary>
/// 交易状态
/// </summary>
protected string TradeStatus { get; private set; }
/// <summary>
/// 业务逻辑处理
/// </summary>
protected abstract void OnNotifyConfirm();
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) return;
var sPara = GetRequestPost();
Core.LogResult(Request.Url.ToString());
if (sPara.Count > 0) //判断是否有带返回参数
{
var formString = Request.Form.Keys.Cast<string>()
.Aggregate("", (current, key) =>
current + string.Format("{0} = {1}\r\n", key.PadLeft(30, ' '),
Request.Form[key]));
Core.LogResult(formString);
var aliNotify = new Notify();
var verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
if (verifyResult)//验证成功
{
OrderNo = Request.Form["out_trade_no"];
TradeNo = Request.Form["trade_no"];
TradeStatus = Request.Form["trade_status"];
//该种交易状态只在一种情况下出现——开通了高级即时到账,买家付款成功后。
if (TradeStatus == "TRADE_FINISHED" || TradeStatus == "TRADE_SUCCESS")
{
OnNotifyConfirm(); //业务逻辑处理
Core.LogResult(string.Format("业务逻辑处理,OrderNo:{0},TradeNo:{1},TradeStatus:{2}", OrderNo, TradeNo, TradeStatus));
}
Response.Write("success");
}
else
{
using System;
using System.Linq;
using System.Xml;
namespace Alipay.Wap
{
/// <summary>
/// 手机网页支付接口接入页
/// </summary>
public abstract class NotifyPage : System.Web.UI.Page
{
/// <summary>
/// 商户订单号
/// </summary>
protected string OrderNo { get; private set; }
/// <summary>
/// 支付宝交易号
/// </summary>
protected string TradeNo { get; private set; }
/// <summary>
/// 交易状态
/// </summary>
protected string TradeStatus { get; private set; }
/// <summary>
/// 业务逻辑处理
/// </summary>
protected abstract void OnNotifyConfirm();
protected bool PaySucceed = false;
protected string PayMsg = "";
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) return;
var sPara = Core.GetRequestPost();
Core.LogResult(Request.Url.ToString());
if (sPara.Count > 0) //判断是否有带返回参数
{
var formString = Request.Form.Keys.Cast<string>()
.Aggregate("", (current, key) =>
current + string.Format("{0} = {1}\r\n", key.PadLeft(30, ' '),
Request.Form[key]));
Core.LogResult(formString);
var aliNotify = new Alipay.Notify();
var verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);
if (verifyResult) //验证成功
{
try
{
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(sPara["notify_data"]);
OrderNo = xmlDoc.SelectSingleNode("/notify/out_trade_no").InnerText; //商户订单号
TradeNo = xmlDoc.SelectSingleNode("/notify/trade_no").InnerText; //支付宝交易号
TradeStatus = xmlDoc.SelectSingleNode("/notify/trade_status").InnerText; //交易状态
//该种交易状态只在两种情况下出现
//1、开通了普通即时到账,买家付款成功后。
//2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后
if (TradeStatus == "TRADE_FINISHED" || TradeStatus == "TRADE_SUCCESS")
{
try
{
OnNotifyConfirm();
Core.LogResult(string.Format("业务逻辑处理,OrderNo:{0},TradeNo:{1},TradeStatus:{2}", OrderNo, TradeNo, TradeStatus));
Response.Write("success");
}
catch
{
}
}
else
{
Response.Write(TradeStatus);
}
}
catch (Exception exc)
{
Response.Write(exc.ToString());
}
}
else //验证失败
{
Response.Write("fail");
}
}
else
{
Response.Write("无返回参数");
}
}
}
}
Response.Write("fail"); } } else { Response.Write("无返回参数"); } } /// <summary> /// 获取支付宝POST过来通知消息,并以“参数名=参数值”的形式组成数组 /// </summary> private SortedDictionary<string, string> GetRequestPost() { int i; var sArray = new SortedDictionary<string, string>(); var coll = Request.Form; var requestItem = coll.AllKeys; for (i = 0; i < requestItem.Length; i++) sArray.Add(requestItem[i], Request.Form[requestItem[i]]); return sArray; } }}
wap端的NotifyPage.cs
上一篇: 不领证不克夫
下一篇: 躺在床上回顾一下2014