asp.net B2B網(wǎng)站對接支付寶接口
更新時間:2010年06月11日 15:43:04 作者:
首先,網(wǎng)上購物系統(tǒng)必須與支付寶公司簽訂合作協(xié)議,以確保從本購物網(wǎng)站上傳到
大型網(wǎng)上購物系統(tǒng)除了能讓會員選擇貨到付款結(jié)賬方式外,還應(yīng)該提供一些更方便快捷的網(wǎng)上支付方式。如果網(wǎng)上商店沒有足夠的實力提供會員直接在網(wǎng)站中建立現(xiàn)金賬戶的功能,就可以將訂單信息轉(zhuǎn)接到支付寶,讓會員從支付寶付款。當(dāng)然就算會員可以在網(wǎng)站上建立自己的現(xiàn)金賬戶,提供支付寶支付功能也不失為另一種方便快捷的支付方式,這可以給客戶提供更多可選的支付方式。
首先,網(wǎng)上購物系統(tǒng)必須與支付寶公司簽訂合作協(xié)議,以確保從本購物網(wǎng)站上傳到
支付寶網(wǎng)站上的訂單信息能被正確接收。
當(dāng)會員于購物網(wǎng)站上買下一系列商品并選擇支付寶付款方式后,購物系統(tǒng)即將會員購物的訂單信息轉(zhuǎn)發(fā)到支付寶,網(wǎng)站頁面也會轉(zhuǎn)到支付寶的付款頁面。此時,支付寶頁面會發(fā)送一個驗證信息到本網(wǎng)站以確認(rèn)支付寶正確收到訂單信息。
會員于支付寶網(wǎng)站付款完成后,網(wǎng)站頁面會重新跳回本購物網(wǎng)站,同時支付寶會將已付款的訂單信息發(fā)回本網(wǎng)站以便對本購物網(wǎng)站的數(shù)據(jù)庫進(jìn)行必要的修改操作。另外本網(wǎng)站還需要向支付寶網(wǎng)站發(fā)送一個返回信息,告知支付寶本系統(tǒng)已正確收到付款完畢的訂單信息并且已經(jīng)完成對數(shù)據(jù)的處理操作。

向支付寶網(wǎng)站傳送訂單信息時主要參數(shù)的含義:
gateway :支付接口
service:識別是何接口實現(xiàn)何功能的表示
seller_email:商家簽約時的支付寶賬號,即收款的支付寶賬號
key:安全校驗碼,與partner是一組
partner:商戶ID,合作伙伴ID
sign_type:加密類型
_input_charset:編碼類型
show_url:展示地址,即在支付寶頁面時商品名稱旁邊的“詳情”的鏈接地址
out_trade_no:會員訂單編號,訂單編號必須在本系統(tǒng)中保持唯一
subject:商品名稱,也可稱為訂單名稱,該接口并不是單一的只能買一樣?xùn)|西,可把一次支付當(dāng)作一次下訂單
body:商品描述,即備注
total_fee:商品價格,也可稱為訂單的總金額
源碼分析(C#):
首先必須建立一個通知頁面(Notify.aspx)和一個返回頁面(Return.aspx)以接受并驗證從支付寶返回的信息并對數(shù)據(jù)庫中相應(yīng)的訂單信息做修改處理操作。
Notify.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using Gateway;
/// <summary>
/// 創(chuàng)建該頁面文件時,請留心該頁面文件中無任何HTML代碼及空格。
/// 該頁面稱作“通知頁”,是異步被支付寶服務(wù)器所調(diào)用。
/// 當(dāng)支付寶的訂單狀態(tài)改變時,支付寶服務(wù)器則會自動調(diào)用此頁面,因此請做好自身網(wǎng)站訂單信息與支付寶上的訂單的同步工作
/// </summary>
public partial class Alipay_Notify : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
//string alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?";//此路徑是在上面鏈接地址無法起作用時替換使用。
string partner = ""; //partner合作伙伴id(必須填寫)
string key = ""; //partner 的對應(yīng)交易安全校驗碼(必須填寫)
string _input_charset = "utf-8";//編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "¬ify_id=" + Request.Form["notify_id"];
//獲取支付寶ATN返回結(jié)果,true是正確的訂單信息,false 是無效的
string responseTxt = AliPay.Get_Http(alipayNotifyURL, 120000);
//*******加密簽名程序開始*******
int i;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll = Request.Form;
// Get names of all forms into a string array.
String[] requestarr = coll.AllKeys;
//進(jìn)行排序;
string[] Sortedstr = AliPay.BubbleSort(requestarr);
//構(gòu)造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]]);
}
else
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]] + "&");
}
}
}
prestr.Append(key);
string mysign = AliPay.GetMD5(prestr.ToString(), _input_charset);
//*******加密簽名程序結(jié)束*******
string sign = Request.Form["sign"];
if (mysign == sign && responseTxt == "true") //驗證支付發(fā)過來的消息,簽名是否正確,只要成功進(jìn)如這個判斷里,則表示該頁面已被支付寶服務(wù)器成功調(diào)用
//但判斷內(nèi)出現(xiàn)自身編寫的程序相關(guān)錯誤導(dǎo)致通知給支付寶并不是發(fā)送success的消息或沒有更新客戶自身的數(shù)據(jù)庫的情況,請自身程序編寫好應(yīng)對措施,否則查明原因時困難之極
{
if (Request.Form["trade_status"] == "WAIT_BUYER_PAY")// 判斷支付狀態(tài)_等待買家付款(文檔中有枚舉表可以參考)
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.Form["out_trade_no"];//訂單號
string strPrice = Request.Form["total_fee"];//金額 如果你申請了商家購物卷功能,在返回信息里面請不要做金額的判斷,否則會校驗通過不了。
}
else if (Request.Form["trade_status"] == "TRADE_FINISHED" || Request.Form["trade_status"] == "TRADE_SUCCESS")// 判斷支付狀態(tài)_交易成功結(jié)束(文檔中有枚舉表可以參考)
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.Form["out_trade_no"];//訂單號
string strPrice = Request.Form["total_fee"];//金額
}
else
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
}
Response.Write(
"success"); //返回給支付寶消息,成功,請不要改寫這個success
//success與fail及其他字符的區(qū)別在于,支付寶的服務(wù)器若遇到success時,則不再發(fā)送請求通知(即不再調(diào)用該頁面,讓該頁面再次運行起來),
//若不是success,則支付寶默認(rèn)沒有收到成功的信息,則會反復(fù)不停地調(diào)用該頁面直到失效,有效調(diào)用時間是24小時以內(nèi)。
//最好寫TXT文件,以記錄下是否異步返回記錄。
////寫文本,紀(jì)錄支付寶返回消息,比對md5計算結(jié)果(如網(wǎng)站不支持寫txt文件,可改成寫數(shù)據(jù)庫)
//string TOEXCELLR = "MD5結(jié)果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
//StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
//fs.Write(TOEXCELLR);
//fs.Close();
}
else
{
Response.Write("fail");
//最好寫TXT文件,以記錄下是否異步返回記錄。
//寫文本,紀(jì)錄支付寶返回消息,比對md5計算結(jié)果(如網(wǎng)站不支持寫txt文件,可改成寫數(shù)據(jù)庫)
string TOEXCELLR = "MD5結(jié)果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
fs.Write(TOEXCELLR);
fs.Close();
}
}
}
Return.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using Gateway;
/// <summary>
/// 創(chuàng)建該頁面文件時,請留心該頁面文件是可以對其進(jìn)行美工處理的,原因在于支付完成以后,當(dāng)前窗口會從支付寶的頁面跳轉(zhuǎn)回這個頁面。
/// 該頁面稱作“返回頁”,是同步被支付寶服務(wù)器所調(diào)用,可當(dāng)作是支付完成后的提示信息頁,如“您的某某某訂單,多少金額已支付成功”。
/// </summary>
public partial class Alipay_Return : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
//string alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?";//此路徑是在上面鏈接地址無法起作用時替換使用。
string key = ""; //partner 的對應(yīng)交易安全校驗碼(必須填寫)
string partner = ""; //partner合作伙伴id(必須填寫)
string _input_charset = "utf-8";//編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "¬ify_id=" + Request.QueryString["notify_id"];
//獲取支付寶ATN返回結(jié)果,true是正確的訂單信息,false 是無效的
string responseTxt = AliPay.Get_Http(alipayNotifyURL, 120000);
//*******加密簽名程序開始//*******
int i;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll = Request.QueryString;
// Get names of all forms into a string array.
String[] requestarr = coll.AllKeys;
//進(jìn)行排序;
string[] Sortedstr = AliPay.BubbleSort(requestarr);
//構(gòu)造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i] + "=" + Request.QueryString[Sortedstr[i]]);
}
else
{
prestr.Append(Sortedstr[i] + "=" + Request.QueryString[Sortedstr[i]] + "&");
}
}
}
prestr.Append(key);
//生成Md5摘要;
string mysign = AliPay.GetMD5(prestr.ToString(), _input_charset);
//*******加密簽名程序結(jié)束*******
string sign = Request.QueryString["sign"];
// Response.Write(prestr.ToString()); //調(diào)試用,支付寶服務(wù)器返回時的完整路徑。
if (mysign == sign && responseTxt == "true") //驗證支付發(fā)過來的消息,簽名是否正確
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.QueryString["out_trade_no"];//訂單號
string strPrice = Request.QueryString["total_fee"];//金額
string strTradeStatus = Request.QueryString["TRADE_STATUS"];//訂單狀態(tài)
Response.Write(
"訂單號:" + strOrderNO + "<br>金額:" + strPrice); //成功,可美化該頁面,提示信息
}
else
{
Response.Write("------------------------------------------");
Response.Write("<br>Result:responseTxt=" + responseTxt);
Response.Write("<br>Result:mysign=" + mysign);
Response.Write("<br>Result:sign=" + sign);
Response.Write("支付失敗"); //支付失敗,提示信息
}
}
}
除此之外在Notify.aspx頁面和Return.aspx頁面公用的一些方法,可以提取出來放在一個公共的類里面(Alipay.cs)
Alipay.cs
using System.Web;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System;
/// <summary>
/// New Interface for AliPay
/// </summary>
namespace Gateway
{
public class AliPay
{
/// <summary>
/// 與ASP兼容的MD5加密算法
/// </summary>
public static string GetMD5(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();
}
/// <summary>
/// 冒泡排序法
/// 按照字母序列從a到z的順序排列
/// </summary>
public static string[] BubbleSort(string[] r)
{
int i, j; //交換標(biāo)志
string temp;
bool exchange;
for (i = 0; i < r.Length; i++) //最多做R.Length-1趟排序
{
exchange = false; //本趟排序開始前,交換標(biāo)志應(yīng)為假
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; //發(fā)生了交換,故將交換標(biāo)志置為真
}
}
if (!exchange) //本趟排序未發(fā)生交換,提前終止算法
{
break;
}
}
return r;
}
/// <summary>
/// 生成URL鏈接或加密結(jié)果
/// </summary>
/// <param name="para">參數(shù)加密數(shù)組</param>
/// <param name="_input_charset">編碼格式</param>
/// <param name="sign_type">加密類型</param>
/// <param name="key">安全校驗碼</param>
/// <returns>字符串URL或加密結(jié)果</returns>
public static string CreatUrl(
//string gateway,//GET方式傳遞參數(shù)時請去掉注釋
string[] para,
string _input_charset,
string sign_type,
string key
)
{
int i;
//進(jìn)行排序;
string[] Sortedstr = BubbleSort(para);
//構(gòu)造待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 = GetMD5(prestr.ToString(), _input_charset);
//以下是POST方式傳遞參數(shù)
return sign;
//以下是GET方式傳遞參數(shù)
//構(gòu)造支付Url;
// char[] delimiterChars = { '='};
// StringBuilder parameter = new StringBuilder();
// parameter.Append(gateway);
// for (i = 0; i < Sortedstr.Length; i++)
// {//UTF-8格式的編碼轉(zhuǎn)換
// 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();
}
//獲取遠(yuǎn)程服務(wù)器ATN結(jié)果,驗證是否是支付寶服務(wù)器發(fā)來的請求
public static 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;
}
}
}
以上三個文件建之后,就可以在需要的地方對支付寶接口進(jìn)行調(diào)用以完成支付寶支付的功能了(Default.aspx.cs)
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Gateway;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void BtnAlipay_Click(object sender, EventArgs e)
{
//業(yè)務(wù)參數(shù)賦值;
string gateway = "https://www.alipay.com/cooperate/gateway.do?"; //支付接口
string service = "create_direct_pay_by_user"; //服務(wù)名稱,這個是識別是何接口實現(xiàn)何功能的標(biāo)識,請勿修改
string seller_email = ""; //商家簽約時的支付寶帳號,即收款的支付寶帳號
string sign_type = "MD5"; //加密類型,簽名方式“不用改”
string key = ""; //安全校驗碼,與partner是一組,獲取方式是:用簽約時支付寶帳號登陸支付寶網(wǎng)站www.alipay.com,在商家服務(wù)我的商家里即可查到。
string partner = ""; //商戶ID,合作身份者ID,合作伙伴ID
string _input_charset = "utf-8"; //編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
string show_url = "http://www.alipay.com/"; //展示地址,即在支付頁面時,商品名稱旁邊的“詳情”的鏈接地址。
string out_trade_no = TxtOrderno.Text.Trim(); //客戶自己的訂單號,訂單號必須在自身訂單系統(tǒng)中保持唯一性
string subject = TxtSubject.Text.Trim(); //商品名稱,也可稱為訂單名稱,該接口并不是單一的只能買一樣?xùn)|西,可把一次支付當(dāng)作一次下訂單
string body = TxtBody.Text.Trim(); //商品描述,即備注
string total_fee = TxtTotal_fee.Text.Trim(); //商品價格,也可稱為訂單的總金額
//服務(wù)器通知url(Alipay_Notify.aspx文件所在路經(jīng)),必須是完整的路徑地址
string notify_url = "http://localhost:8978/direct_vs2005_utf/Alipay_Notify.aspx";
//服務(wù)器返回url(Alipay_Return.aspx文件所在路經(jīng)),必須是完整的路徑地址
string return_url = "http://localhost:8978/direct_vs2005_utf/Alipay_Return.aspx";
//構(gòu)造數(shù)組;
//以下數(shù)組即是參與加密的參數(shù),若參數(shù)的值不允許為空,若該參數(shù)為空,則不要成為該數(shù)組的元素
string[] para ={
"service="+service,
"partner=" + partner,
"seller_email=" + seller_email,
"out_trade_no=" + out_trade_no,
"subject=" + subject,
"body=" + body,
"total_fee=" + total_fee,
"show_url=" + show_url,
"payment_type=1",
"notify_url=" + notify_url,
"return_url=" + return_url,
"_input_charset="+_input_charset
};
//支付URL生成
string aliay_url = AliPay.CreatUrl(
//gateway,//GET方式傳遞參數(shù)時請去掉注釋
para,
_input_charset,
sign_type,
key
);
//以下是GET方式傳遞參數(shù)
//Response.Redirect(aliay_url);
//以下是POST方式傳遞參數(shù)
Response.Write("<form name='alipaysubmit' method='post' action='https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8'>");
Response.Write("<input type='hidden' name='service' value=" + service + ">");
Response.Write("<input type='hidden' name='partner' value=" + partner + ">");
Response.Write("<input type='hidden' name='seller_email' value=" + seller_email + ">");
Response.Write("<input type='hidden' name='out_trade_no' value=" + out_trade_no + ">");
Response.Write("<input type='hidden' name='subject' value=" + subject + ">");
Response.Write("<input type='hidden' name='body' value=" + body + ">");
Response.Write("<input type='hidden' name='total_fee' value=" + total_fee + ">");
Response.Write("<input type='hidden' name='show_url' value=" + show_url + ">");
Response.Write("<input type='hidden' name='return_url' value=" + return_url + ">");
Response.Write("<input type='hidden' name='notify_url' value=" + notify_url + ">");
Response.Write("<input type='hidden' name='payment_type' value=1>");
Response.Write("<input type='hidden' name='sign' value=" + aliay_url + ">");
Response.Write("<input type='hidden' name='sign_type' value=" + sign_type + ">");
Response.Write("</form>");
Response.Write("<script>");
Response.Write("document.alipaysubmit.submit()");
Response.Write("</script>");
}
}
轉(zhuǎn)接到支付寶的付款功能在調(diào)試過程中,必須真實的從網(wǎng)站夠買商品并跳轉(zhuǎn)到支付寶網(wǎng)
付款??梢詫⑺I商品的單價設(shè)為0.01元,從支付寶付款成功并重新跳回本網(wǎng)站后,檢查訂單信息是否正確,以及對傳回的數(shù)據(jù)所做的處理操作是否正確??傊弥Ц秾毟犊畹墓δ茉谡{(diào)試過程中必須進(jìn)行實際的支付操作才能發(fā)現(xiàn)錯誤。
作者:ChenLuLouis
首先,網(wǎng)上購物系統(tǒng)必須與支付寶公司簽訂合作協(xié)議,以確保從本購物網(wǎng)站上傳到
支付寶網(wǎng)站上的訂單信息能被正確接收。
當(dāng)會員于購物網(wǎng)站上買下一系列商品并選擇支付寶付款方式后,購物系統(tǒng)即將會員購物的訂單信息轉(zhuǎn)發(fā)到支付寶,網(wǎng)站頁面也會轉(zhuǎn)到支付寶的付款頁面。此時,支付寶頁面會發(fā)送一個驗證信息到本網(wǎng)站以確認(rèn)支付寶正確收到訂單信息。
會員于支付寶網(wǎng)站付款完成后,網(wǎng)站頁面會重新跳回本購物網(wǎng)站,同時支付寶會將已付款的訂單信息發(fā)回本網(wǎng)站以便對本購物網(wǎng)站的數(shù)據(jù)庫進(jìn)行必要的修改操作。另外本網(wǎng)站還需要向支付寶網(wǎng)站發(fā)送一個返回信息,告知支付寶本系統(tǒng)已正確收到付款完畢的訂單信息并且已經(jīng)完成對數(shù)據(jù)的處理操作。

向支付寶網(wǎng)站傳送訂單信息時主要參數(shù)的含義:
gateway :支付接口
service:識別是何接口實現(xiàn)何功能的表示
seller_email:商家簽約時的支付寶賬號,即收款的支付寶賬號
key:安全校驗碼,與partner是一組
partner:商戶ID,合作伙伴ID
sign_type:加密類型
_input_charset:編碼類型
show_url:展示地址,即在支付寶頁面時商品名稱旁邊的“詳情”的鏈接地址
out_trade_no:會員訂單編號,訂單編號必須在本系統(tǒng)中保持唯一
subject:商品名稱,也可稱為訂單名稱,該接口并不是單一的只能買一樣?xùn)|西,可把一次支付當(dāng)作一次下訂單
body:商品描述,即備注
total_fee:商品價格,也可稱為訂單的總金額
源碼分析(C#):
首先必須建立一個通知頁面(Notify.aspx)和一個返回頁面(Return.aspx)以接受并驗證從支付寶返回的信息并對數(shù)據(jù)庫中相應(yīng)的訂單信息做修改處理操作。
Notify.aspx.cs
復(fù)制代碼 代碼如下:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using Gateway;
/// <summary>
/// 創(chuàng)建該頁面文件時,請留心該頁面文件中無任何HTML代碼及空格。
/// 該頁面稱作“通知頁”,是異步被支付寶服務(wù)器所調(diào)用。
/// 當(dāng)支付寶的訂單狀態(tài)改變時,支付寶服務(wù)器則會自動調(diào)用此頁面,因此請做好自身網(wǎng)站訂單信息與支付寶上的訂單的同步工作
/// </summary>
public partial class Alipay_Notify : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
//string alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?";//此路徑是在上面鏈接地址無法起作用時替換使用。
string partner = ""; //partner合作伙伴id(必須填寫)
string key = ""; //partner 的對應(yīng)交易安全校驗碼(必須填寫)
string _input_charset = "utf-8";//編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "¬ify_id=" + Request.Form["notify_id"];
//獲取支付寶ATN返回結(jié)果,true是正確的訂單信息,false 是無效的
string responseTxt = AliPay.Get_Http(alipayNotifyURL, 120000);
//*******加密簽名程序開始*******
int i;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll = Request.Form;
// Get names of all forms into a string array.
String[] requestarr = coll.AllKeys;
//進(jìn)行排序;
string[] Sortedstr = AliPay.BubbleSort(requestarr);
//構(gòu)造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]]);
}
else
{
prestr.Append(Sortedstr[i] + "=" + Request.Form[Sortedstr[i]] + "&");
}
}
}
prestr.Append(key);
string mysign = AliPay.GetMD5(prestr.ToString(), _input_charset);
//*******加密簽名程序結(jié)束*******
string sign = Request.Form["sign"];
if (mysign == sign && responseTxt == "true") //驗證支付發(fā)過來的消息,簽名是否正確,只要成功進(jìn)如這個判斷里,則表示該頁面已被支付寶服務(wù)器成功調(diào)用
//但判斷內(nèi)出現(xiàn)自身編寫的程序相關(guān)錯誤導(dǎo)致通知給支付寶并不是發(fā)送success的消息或沒有更新客戶自身的數(shù)據(jù)庫的情況,請自身程序編寫好應(yīng)對措施,否則查明原因時困難之極
{
if (Request.Form["trade_status"] == "WAIT_BUYER_PAY")// 判斷支付狀態(tài)_等待買家付款(文檔中有枚舉表可以參考)
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.Form["out_trade_no"];//訂單號
string strPrice = Request.Form["total_fee"];//金額 如果你申請了商家購物卷功能,在返回信息里面請不要做金額的判斷,否則會校驗通過不了。
}
else if (Request.Form["trade_status"] == "TRADE_FINISHED" || Request.Form["trade_status"] == "TRADE_SUCCESS")// 判斷支付狀態(tài)_交易成功結(jié)束(文檔中有枚舉表可以參考)
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.Form["out_trade_no"];//訂單號
string strPrice = Request.Form["total_fee"];//金額
}
else
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
}
Response.Write(
"success"); //返回給支付寶消息,成功,請不要改寫這個success
//success與fail及其他字符的區(qū)別在于,支付寶的服務(wù)器若遇到success時,則不再發(fā)送請求通知(即不再調(diào)用該頁面,讓該頁面再次運行起來),
//若不是success,則支付寶默認(rèn)沒有收到成功的信息,則會反復(fù)不停地調(diào)用該頁面直到失效,有效調(diào)用時間是24小時以內(nèi)。
//最好寫TXT文件,以記錄下是否異步返回記錄。
////寫文本,紀(jì)錄支付寶返回消息,比對md5計算結(jié)果(如網(wǎng)站不支持寫txt文件,可改成寫數(shù)據(jù)庫)
//string TOEXCELLR = "MD5結(jié)果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
//StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
//fs.Write(TOEXCELLR);
//fs.Close();
}
else
{
Response.Write("fail");
//最好寫TXT文件,以記錄下是否異步返回記錄。
//寫文本,紀(jì)錄支付寶返回消息,比對md5計算結(jié)果(如網(wǎng)站不支持寫txt文件,可改成寫數(shù)據(jù)庫)
string TOEXCELLR = "MD5結(jié)果:mysign=" + mysign + ",sign=" + sign + ",responseTxt=" + responseTxt;
StreamWriter fs = new StreamWriter(Server.MapPath("Notify_DATA/" + DateTime.Now.ToString().Replace(":", "")) + ".txt", false, System.Text.Encoding.Default);
fs.Write(TOEXCELLR);
fs.Close();
}
}
}
Return.aspx.cs
復(fù)制代碼 代碼如下:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Collections.Specialized;
using System.IO;
using Gateway;
/// <summary>
/// 創(chuàng)建該頁面文件時,請留心該頁面文件是可以對其進(jìn)行美工處理的,原因在于支付完成以后,當(dāng)前窗口會從支付寶的頁面跳轉(zhuǎn)回這個頁面。
/// 該頁面稱作“返回頁”,是同步被支付寶服務(wù)器所調(diào)用,可當(dāng)作是支付完成后的提示信息頁,如“您的某某某訂單,多少金額已支付成功”。
/// </summary>
public partial class Alipay_Return : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string alipayNotifyURL = "https://www.alipay.com/cooperate/gateway.do?service=notify_verify";
//string alipayNotifyURL = "http://notify.alipay.com/trade/notify_query.do?";//此路徑是在上面鏈接地址無法起作用時替換使用。
string key = ""; //partner 的對應(yīng)交易安全校驗碼(必須填寫)
string partner = ""; //partner合作伙伴id(必須填寫)
string _input_charset = "utf-8";//編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
alipayNotifyURL = alipayNotifyURL + "&partner=" + partner + "¬ify_id=" + Request.QueryString["notify_id"];
//獲取支付寶ATN返回結(jié)果,true是正確的訂單信息,false 是無效的
string responseTxt = AliPay.Get_Http(alipayNotifyURL, 120000);
//*******加密簽名程序開始//*******
int i;
NameValueCollection coll;
//Load Form variables into NameValueCollection variable.
coll = Request.QueryString;
// Get names of all forms into a string array.
String[] requestarr = coll.AllKeys;
//進(jìn)行排序;
string[] Sortedstr = AliPay.BubbleSort(requestarr);
//構(gòu)造待md5摘要字符串 ;
StringBuilder prestr = new StringBuilder();
for (i = 0; i < Sortedstr.Length; i++)
{
if (Request.Form[Sortedstr[i]] != "" && Sortedstr[i] != "sign" && Sortedstr[i] != "sign_type")
{
if (i == Sortedstr.Length - 1)
{
prestr.Append(Sortedstr[i] + "=" + Request.QueryString[Sortedstr[i]]);
}
else
{
prestr.Append(Sortedstr[i] + "=" + Request.QueryString[Sortedstr[i]] + "&");
}
}
}
prestr.Append(key);
//生成Md5摘要;
string mysign = AliPay.GetMD5(prestr.ToString(), _input_charset);
//*******加密簽名程序結(jié)束*******
string sign = Request.QueryString["sign"];
// Response.Write(prestr.ToString()); //調(diào)試用,支付寶服務(wù)器返回時的完整路徑。
if (mysign == sign && responseTxt == "true") //驗證支付發(fā)過來的消息,簽名是否正確
{
//更新自己數(shù)據(jù)庫的訂單語句,請自己填寫一下
string strOrderNO = Request.QueryString["out_trade_no"];//訂單號
string strPrice = Request.QueryString["total_fee"];//金額
string strTradeStatus = Request.QueryString["TRADE_STATUS"];//訂單狀態(tài)
Response.Write(
"訂單號:" + strOrderNO + "<br>金額:" + strPrice); //成功,可美化該頁面,提示信息
}
else
{
Response.Write("------------------------------------------");
Response.Write("<br>Result:responseTxt=" + responseTxt);
Response.Write("<br>Result:mysign=" + mysign);
Response.Write("<br>Result:sign=" + sign);
Response.Write("支付失敗"); //支付失敗,提示信息
}
}
}
除此之外在Notify.aspx頁面和Return.aspx頁面公用的一些方法,可以提取出來放在一個公共的類里面(Alipay.cs)
Alipay.cs
復(fù)制代碼 代碼如下:
using System.Web;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Net;
using System;
/// <summary>
/// New Interface for AliPay
/// </summary>
namespace Gateway
{
public class AliPay
{
/// <summary>
/// 與ASP兼容的MD5加密算法
/// </summary>
public static string GetMD5(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();
}
/// <summary>
/// 冒泡排序法
/// 按照字母序列從a到z的順序排列
/// </summary>
public static string[] BubbleSort(string[] r)
{
int i, j; //交換標(biāo)志
string temp;
bool exchange;
for (i = 0; i < r.Length; i++) //最多做R.Length-1趟排序
{
exchange = false; //本趟排序開始前,交換標(biāo)志應(yīng)為假
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; //發(fā)生了交換,故將交換標(biāo)志置為真
}
}
if (!exchange) //本趟排序未發(fā)生交換,提前終止算法
{
break;
}
}
return r;
}
/// <summary>
/// 生成URL鏈接或加密結(jié)果
/// </summary>
/// <param name="para">參數(shù)加密數(shù)組</param>
/// <param name="_input_charset">編碼格式</param>
/// <param name="sign_type">加密類型</param>
/// <param name="key">安全校驗碼</param>
/// <returns>字符串URL或加密結(jié)果</returns>
public static string CreatUrl(
//string gateway,//GET方式傳遞參數(shù)時請去掉注釋
string[] para,
string _input_charset,
string sign_type,
string key
)
{
int i;
//進(jìn)行排序;
string[] Sortedstr = BubbleSort(para);
//構(gòu)造待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 = GetMD5(prestr.ToString(), _input_charset);
//以下是POST方式傳遞參數(shù)
return sign;
//以下是GET方式傳遞參數(shù)
//構(gòu)造支付Url;
// char[] delimiterChars = { '='};
// StringBuilder parameter = new StringBuilder();
// parameter.Append(gateway);
// for (i = 0; i < Sortedstr.Length; i++)
// {//UTF-8格式的編碼轉(zhuǎn)換
// 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();
}
//獲取遠(yuǎn)程服務(wù)器ATN結(jié)果,驗證是否是支付寶服務(wù)器發(fā)來的請求
public static 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;
}
}
}
以上三個文件建之后,就可以在需要的地方對支付寶接口進(jìn)行調(diào)用以完成支付寶支付的功能了(Default.aspx.cs)
復(fù)制代碼 代碼如下:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Gateway;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void BtnAlipay_Click(object sender, EventArgs e)
{
//業(yè)務(wù)參數(shù)賦值;
string gateway = "https://www.alipay.com/cooperate/gateway.do?"; //支付接口
string service = "create_direct_pay_by_user"; //服務(wù)名稱,這個是識別是何接口實現(xiàn)何功能的標(biāo)識,請勿修改
string seller_email = ""; //商家簽約時的支付寶帳號,即收款的支付寶帳號
string sign_type = "MD5"; //加密類型,簽名方式“不用改”
string key = ""; //安全校驗碼,與partner是一組,獲取方式是:用簽約時支付寶帳號登陸支付寶網(wǎng)站www.alipay.com,在商家服務(wù)我的商家里即可查到。
string partner = ""; //商戶ID,合作身份者ID,合作伙伴ID
string _input_charset = "utf-8"; //編碼類型,完全根據(jù)客戶自身的項目的編碼格式而定,千萬不要填錯。否則極其容易造成MD5加密錯誤。
string show_url = "http://www.alipay.com/"; //展示地址,即在支付頁面時,商品名稱旁邊的“詳情”的鏈接地址。
string out_trade_no = TxtOrderno.Text.Trim(); //客戶自己的訂單號,訂單號必須在自身訂單系統(tǒng)中保持唯一性
string subject = TxtSubject.Text.Trim(); //商品名稱,也可稱為訂單名稱,該接口并不是單一的只能買一樣?xùn)|西,可把一次支付當(dāng)作一次下訂單
string body = TxtBody.Text.Trim(); //商品描述,即備注
string total_fee = TxtTotal_fee.Text.Trim(); //商品價格,也可稱為訂單的總金額
//服務(wù)器通知url(Alipay_Notify.aspx文件所在路經(jīng)),必須是完整的路徑地址
string notify_url = "http://localhost:8978/direct_vs2005_utf/Alipay_Notify.aspx";
//服務(wù)器返回url(Alipay_Return.aspx文件所在路經(jīng)),必須是完整的路徑地址
string return_url = "http://localhost:8978/direct_vs2005_utf/Alipay_Return.aspx";
//構(gòu)造數(shù)組;
//以下數(shù)組即是參與加密的參數(shù),若參數(shù)的值不允許為空,若該參數(shù)為空,則不要成為該數(shù)組的元素
string[] para ={
"service="+service,
"partner=" + partner,
"seller_email=" + seller_email,
"out_trade_no=" + out_trade_no,
"subject=" + subject,
"body=" + body,
"total_fee=" + total_fee,
"show_url=" + show_url,
"payment_type=1",
"notify_url=" + notify_url,
"return_url=" + return_url,
"_input_charset="+_input_charset
};
//支付URL生成
string aliay_url = AliPay.CreatUrl(
//gateway,//GET方式傳遞參數(shù)時請去掉注釋
para,
_input_charset,
sign_type,
key
);
//以下是GET方式傳遞參數(shù)
//Response.Redirect(aliay_url);
//以下是POST方式傳遞參數(shù)
Response.Write("<form name='alipaysubmit' method='post' action='https://www.alipay.com/cooperate/gateway.do?_input_charset=utf-8'>");
Response.Write("<input type='hidden' name='service' value=" + service + ">");
Response.Write("<input type='hidden' name='partner' value=" + partner + ">");
Response.Write("<input type='hidden' name='seller_email' value=" + seller_email + ">");
Response.Write("<input type='hidden' name='out_trade_no' value=" + out_trade_no + ">");
Response.Write("<input type='hidden' name='subject' value=" + subject + ">");
Response.Write("<input type='hidden' name='body' value=" + body + ">");
Response.Write("<input type='hidden' name='total_fee' value=" + total_fee + ">");
Response.Write("<input type='hidden' name='show_url' value=" + show_url + ">");
Response.Write("<input type='hidden' name='return_url' value=" + return_url + ">");
Response.Write("<input type='hidden' name='notify_url' value=" + notify_url + ">");
Response.Write("<input type='hidden' name='payment_type' value=1>");
Response.Write("<input type='hidden' name='sign' value=" + aliay_url + ">");
Response.Write("<input type='hidden' name='sign_type' value=" + sign_type + ">");
Response.Write("</form>");
Response.Write("<script>");
Response.Write("document.alipaysubmit.submit()");
Response.Write("</script>");
}
}
轉(zhuǎn)接到支付寶的付款功能在調(diào)試過程中,必須真實的從網(wǎng)站夠買商品并跳轉(zhuǎn)到支付寶網(wǎng)
付款??梢詫⑺I商品的單價設(shè)為0.01元,從支付寶付款成功并重新跳回本網(wǎng)站后,檢查訂單信息是否正確,以及對傳回的數(shù)據(jù)所做的處理操作是否正確??傊弥Ц秾毟犊畹墓δ茉谡{(diào)試過程中必須進(jìn)行實際的支付操作才能發(fā)現(xiàn)錯誤。
作者:ChenLuLouis
您可能感興趣的文章:
相關(guān)文章
對Entity?Framework?Core進(jìn)行單元測試
這篇文章介紹了對Entity?Framework?Core進(jìn)行單元測試的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-03-03System.Timers.Timer定時執(zhí)行程序示例代碼
如果是某個邏輯功能的定時,可以將code放到邏輯功能的類的靜態(tài)構(gòu)造函數(shù)中,在該邏輯類第一次執(zhí)行時,靜態(tài)構(gòu)造函數(shù)會被調(diào)用,則定時自然啟動2013-06-06asp.net中TextBox只能輸入數(shù)字的最簡潔的兩種方法
這篇文章介紹了asp.net中TextBox只能輸入數(shù)字的最簡潔的兩種方法,有需要的朋友可以參考一下2013-11-11ASP.NET Mvc開發(fā)之查詢數(shù)據(jù)
這篇文章主要介紹了ASP.NET Mvc開發(fā)之查詢數(shù)據(jù)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02ASP.NET MVC DropDownList數(shù)據(jù)綁定及使用詳解
DropDownList 控件用于創(chuàng)建下拉列表。DropDownList 控件中的每個可選項都是由 ListItem 元素定義的!該控件支持?jǐn)?shù)據(jù)綁定2012-12-12asp.net mvc CodeFirst模式數(shù)據(jù)庫遷移步驟詳解
這篇文章主要為大家詳細(xì)介紹了asp.net mvc CodeFirst模式數(shù)據(jù)庫遷移步驟,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10ASP.NET Ref和Out關(guān)鍵字區(qū)別分析
類型介紹 在幾乎所有的OOP語言中,都存在2種類型的值。2009-02-02.net 獲取瀏覽器Cookie(包括HttpOnly)實例分享
這篇文章介紹了.net 獲取瀏覽器Cookie(包括HttpOnly)實例,有需要的朋友可以參考一下2013-10-10