微信支付笔记
? ? 一、開發(fā)前的準(zhǔn)備:
? ? ? ? 開發(fā)前需要配置支付授權(quán)目錄,支付相關(guān)的頁面全部要在這個(gè)指定的目錄中,不能在子目錄中。測(cè)試授權(quán)目錄和測(cè)試白名單可以不用管。
?? ?二、微信支付開發(fā)前需要這幾個(gè)參數(shù):
? ? ? ?1、AppID?? ?在微信公眾號(hào)管理后臺(tái)(https://mp.weixin.qq.com/)的開發(fā)者中心獲取
? ? ? ?2、微信支付商戶號(hào)??在微信公眾號(hào)管理后臺(tái)(https://mp.weixin.qq.com/)的 微信支付 菜單下可以看到
? ? ? ?3、商戶密匙???微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置
?
? ? 三、微信公眾號(hào)支付的邏輯是這樣的:
? ? ? ? ?1. 我們自己的系統(tǒng)生成待支付訂單信息 [訂單號(hào)、金額、商品名稱、說明等信息]
? ? ? ? ?2. 將系統(tǒng)的訂單信息使用統(tǒng)一下單的數(shù)據(jù)格式提交到微信服務(wù)器 ,微信服務(wù)器會(huì)返回一個(gè)預(yù)支付交易會(huì)話標(biāo)識(shí)?prepay_id
? ? ? ? ? ? ??統(tǒng)一下單的API文檔:?https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
? ? ? ? ?3. 使用公眾號(hào)APPID和第二部返回的預(yù)支付交易會(huì)話標(biāo)識(shí)?prepay_id,加上時(shí)間戳?timeStamp、?隨機(jī)字符串nonceStr ,簽名?paySign 生成js參數(shù),在HTML頁面里完成支付
?網(wǎng)頁端調(diào)起支付API文檔: ??https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
? ? ? ? ?4. 微信服務(wù)器異步通知我們服務(wù)器上的回調(diào)地址,完成支付
?
? ? 從第三部分的HTML頁面講起,我們看到官方文檔中微信的網(wǎng)頁支付的代碼是這樣的:
function onBridgeReady() {WeixinJSBridge.invoke('getBrandWCPayRequest', {"appId":"wx2421b1c4370ec43b",//公眾號(hào)名稱,由商戶傳入 "timeStamp":" 1395712654",//時(shí)間戳,自1970年以來的秒數(shù) "nonceStr":"e61463f8efa94090b1f366cccfbbb444",//隨機(jī)串 "package":"prepay_id=u802345jgfjsdfgsdg888", "signType":"MD5", //微信簽名方式: "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名 }, function(res) { if (res.err_msg == "get_brand_wcpay_request:ok") {} }); } if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(); } ?
? ? 注意:這個(gè)JS需要在微信瀏覽器里面直接調(diào)用,無需引用其他js文件,其他瀏覽器是不行的.
? ? 第一次看到這個(gè)js腳本的時(shí)候比較奇怪,這里怎么沒有支付的金額、商品名稱、訂單號(hào)呢,后來才知道訂單的信息是需要提前提交給微信服務(wù)器的,這個(gè)提交的過程就叫統(tǒng)一下單。
? ? 支付頁面的Javascript代碼很簡(jiǎn)單,只有這幾個(gè)參數(shù)需要我們自己根據(jù)實(shí)際情況進(jìn)行替換:
"appId":"wx2421b1c4370ec43b", //公眾號(hào)名稱,由商戶傳入 | 這個(gè)參數(shù)已知 "timeStamp":" 1395712654", //時(shí)間戳,自1970年以來的秒數(shù) | 寫個(gè)函數(shù)生成下即可,簡(jiǎn)單 "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //隨機(jī)串 | 寫個(gè)函數(shù)生成下 "package":"prepay_id=u802345jgfjsdfgsdg888", //prepay_id 就是前面提到的支付交易會(huì)話標(biāo)識(shí),具體怎么生成在后面講"signType":"MD5", //微信簽名方式:固定的,填寫MD5即可
//微信簽名 簽名生成方法可見API文檔 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3,我在文章后面會(huì)給出代碼
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"
? ? 我們先搞定最簡(jiǎn)單的部分:隨機(jī)字符串和時(shí)間戳的生成C#實(shí)現(xiàn)
/// <summary>/// 隨機(jī)串 /// </summary> public static string getNoncestr(){Random random = new Random();return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S");}/// <summary>/// 時(shí)間截,自1970年以來的秒數(shù)/// </summary> public static string getTimestamp(){TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);return Convert.ToInt64(ts.TotalSeconds).ToString();}View Code
?
? ?現(xiàn)在只有prepay_id和paySign目前不知道怎么產(chǎn)生的,另外幾個(gè)參數(shù)都搞定了。
? ?prepay_id需要通過統(tǒng)一下單接口https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1獲取到,我們看這個(gè)接口要傳的參數(shù)有不少,新建一個(gè)UnifiedOrder類:
/// <summary>/// 微信統(tǒng)一接口請(qǐng)求實(shí)體對(duì)象/// </summary> [Serializable]public class UnifiedOrder{/// <summary>/// 公共號(hào)ID(微信分配的公眾賬號(hào) ID)/// </summary>public string appid = "";/// <summary>/// 商戶號(hào)(微信支付分配的商戶號(hào))/// </summary>public string mch_id = "";/// <summary>/// 微信支付分配的終端設(shè)備號(hào)/// </summary>public string device_info = "";/// <summary>/// 隨機(jī)字符串,不長于 32 位/// </summary>public string nonce_str = "";/// <summary>/// 簽名/// </summary>public string sign = "";/// <summary>/// 商品描述/// </summary>public string body = "";/// <summary>/// 附加數(shù)據(jù),原樣返回/// </summary>public string attach = "";/// <summary>/// 商戶系統(tǒng)內(nèi)部的訂單號(hào),32個(gè)字符內(nèi)、可包含字母,確保在商戶系統(tǒng)唯一,詳細(xì)說明/// </summary>public string out_trade_no = "";/// <summary>/// 訂單總金額,單位為分,不能帶小數(shù)點(diǎn)/// </summary>public int total_fee = 0;/// <summary>/// 終端IP/// </summary>public string spbill_create_ip = "";/// <summary>/// 訂 單 生 成 時(shí) 間 , 格 式 為yyyyMMddHHmmss,如 2009 年12 月 25 日 9 點(diǎn) 10 分 10 秒表示為 20091225091010。時(shí)區(qū)為 GMT+8 beijing。該時(shí)間取自商戶服務(wù)器/// </summary>public string time_start = "";/// <summary>/// 交易結(jié)束時(shí)間/// </summary>public string time_expire = "";/// <summary>/// 商品標(biāo)記 商品標(biāo)記,該字段不能隨便填,不使用請(qǐng)?zhí)羁?#xff0c;使用說明詳見第 5 節(jié)/// </summary>public string goods_tag = "";/// <summary>/// 接收微信支付成功通知/// </summary>public string notify_url = "";/// <summary>/// JSAPI、NATIVE、APP/// </summary>public string trade_type = "";/// <summary>/// 用戶標(biāo)識(shí) trade_type 為 JSAPI時(shí),此參數(shù)必傳/// </summary>public string openid = "";/// <summary>/// 只在 trade_type 為 NATIVE時(shí)需要填寫。/// </summary>public string product_id = "";}View Code
? ?用參數(shù)填充這個(gè)對(duì)象
//統(tǒng)一下單UnifiedOrder order = new UnifiedOrder();order.appid = "1111111111111111"; //公眾賬號(hào)ID,請(qǐng)?zhí)鎿Q成公眾號(hào)實(shí)際的appidorder.mch_id = "111111111111111"; //調(diào)用接口提交的商戶號(hào),請(qǐng)?zhí)鎿Q成真實(shí)的商戶號(hào) order.device_info = "WEB"; //終端設(shè)備號(hào)(門店號(hào)或收銀設(shè)備ID),注意:PC網(wǎng)頁或公眾號(hào)內(nèi)支付請(qǐng)傳"WEB" 固定值order.nonce_str = TenpayUtil.getNoncestr(); //隨機(jī)字符串,不長于32位,見前面的隨機(jī)字符串函數(shù) TenpayUtil代碼后面給出order.body = "xxxxxxx設(shè)備充值"; //商品或支付單簡(jiǎn)要描述order.attach = "這是一個(gè)支付測(cè)試訂單"; //附加數(shù)據(jù)order.out_trade_no = "11111111111111111111111"; //商戶系統(tǒng)內(nèi)部的訂單號(hào),32個(gè)字符內(nèi)、可包含字母,請(qǐng)?zhí)鎿Q成真實(shí)的訂單號(hào)order.total_fee = 0.01 * 100; //int類型,訂單總金額,單位為分,請(qǐng)?zhí)顚憣?shí)際訂單金額order.spbill_create_ip = Page.Request.UserHostAddress; //用戶端ip 11.11.11.11 格式order.notify_url = "http://baidu.com/notify_url.aspx"; //接收微信支付異步通知回調(diào)地址,請(qǐng)?zhí)鎿Q成真實(shí)的回調(diào)地址,回調(diào)頁面文章后面會(huì)給出例子 order.openid = "111111111111111111111111111111"; //trade_type=JSAPI,此參數(shù)必傳,請(qǐng)?zhí)鎿Q成用戶在商戶appid下的唯一標(biāo)識(shí),用戶的openid怎么獲取請(qǐng)參考微信開發(fā)的API文檔 order.trade_type = "JSAPI"; //交易類型 JSAPI--公眾號(hào)支付、NATIVE--原生掃碼支付、APP--app支付
? ? ? 將這些信息提交給微信服務(wù)器就能獲取到臨時(shí)支付交易會(huì)話標(biāo)識(shí)?prepay_id了,下面代碼里的paySignKey是商戶密匙。
//得到 prepay_id 微信生成的預(yù)支付回話標(biāo)識(shí),用于后續(xù)接口調(diào)用中使用,該值有效期為2小時(shí)string prepay_id = tenpay.getPrepay_id(order, paySignKey); //tenapy代碼文章末尾給出string timeStamp = TenpayUtil.getTimestamp(); //時(shí)間戳 string nonceStr = TenpayUtil.getNoncestr(); //隨機(jī)字符串
? ? ?簽名參數(shù)paySign的獲取:
// 4.根據(jù)得到的prepay_id計(jì)算paySign 簽名SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();sParams.Add("appId", "1111111111111111111"); //請(qǐng)?zhí)鎿Q成真實(shí)的APPIDsParams.Add("timeStamp", timeStamp);sParams.Add("nonceStr", nonceStr);sParams.Add("package", "prepay_id=" + prepay_id);sParams.Add("signType", "MD5"); string paySign = tenpay.getsign(sParams, paySignKey); //得到 paySign 簽名 paySingKey 是商戶密匙 ? ? ? 這樣paySign和prepay_id參數(shù)都成功獲取到了,將這些參數(shù)替換掉HTML頁面的js參數(shù)就可以彈出微信支付窗口:
? ? ? ? ? ? ? ? ? ? ? ? ??
?
需要用到的一些代碼:
TenpayUtil
public class TenpayUtil{/// <summary>/// 統(tǒng)一支付接口/// </summary>const string UnifiedPayUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";/// <summary>/// 網(wǎng)頁授權(quán)接口/// </summary>const string access_tokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";/// <summary>/// 微信訂單查詢接口/// </summary>const string OrderQueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";/// <summary>/// 隨機(jī)串/// </summary>public static string getNoncestr(){Random random = new Random();return MD5Util.GetMD5(random.Next(1000).ToString(), "utf-8").ToLower().Replace("s", "S");}/// <summary>/// 時(shí)間截,自1970年以來的秒數(shù)/// </summary>public static string getTimestamp(){TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);return Convert.ToInt64(ts.TotalSeconds).ToString();}/// <summary>/// 網(wǎng)頁授權(quán)接口/// </summary>public static string getAccess_tokenUrl(){return access_tokenUrl;}/// <summary>/// 獲取微信簽名/// 將集合M內(nèi)非空參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序/// 格式(即key1=value1&key2=value2…)拼接成字符串stringA/// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3/// </summary>/// <param name="sParams">集合M</param>/// <param name="key">key設(shè)置路徑:微信商戶平臺(tái)(pay.weixin.qq.com)-->賬戶設(shè)置-->API安全-->密鑰設(shè)置</param>/// <returns></returns>public string getsign(SortedDictionary<string, string> sParams, string key){int i = 0;string sign = string.Empty;StringBuilder sb = new StringBuilder();foreach (KeyValuePair<string, string> temp in sParams){if (temp.Value == "" || temp.Value == null || temp.Key.ToLower() == "sign"){continue;}i++;sb.Append(temp.Key.Trim() + "=" + temp.Value.Trim() + "&");}sb.Append("key=" + key.Trim() + "");string signkey = sb.ToString();sign = MD5Util.GetMD5(signkey, "utf-8");return sign;}/// <summary>/// Post數(shù)據(jù)到指定接口并返回?cái)?shù)據(jù)/// </summary>/// <param name="url">地址</param>/// <param name="postData">要提交的數(shù)據(jù)</param>/// <returns></returns>public string PostXmlToUrl(string url, string postData){string returnmsg = "";Bird.Net.Http.HttpHelper httpHelper = new Bird.Net.Http.HttpHelper();httpHelper.Encoding = Encoding.UTF8;returnmsg = httpHelper.GetHtml(url, postData, true);/*using (System.Net.WebClient wc = new System.Net.WebClient()){returnmsg = wc.UploadString(url, "POST", postData);}*/return returnmsg;}public string order_request_data = "";public string order_post_data = "";/// <summary>/// 統(tǒng)一下單獲取prepay_id/// </summary>/// <param name="order">統(tǒng)一下單</param>/// <param name="key">商戶密匙</param>/// <returns>prepay_id</returns>public string getPrepay_id(UnifiedOrder order, string key){string prepay_id = "";order_post_data = getUnifiedOrderXml(order, key);order_request_data = PostXmlToUrl(UnifiedPayUrl, order_post_data);SortedDictionary<string, string> requestXML = GetInfoFromXml(order_request_data);foreach (KeyValuePair<string, string> k in requestXML){if (k.Key == "prepay_id"){prepay_id = k.Value;break;}}return prepay_id;}/// <summary>/// 獲取微信訂單明細(xì)/// </summary>public OrderDetail getOrderDetail(QueryOrder queryorder, string key){string post_data = getQueryOrderXml(queryorder, key);string request_data = PostXmlToUrl(OrderQueryUrl, post_data);OrderDetail orderdetail = new OrderDetail();SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data);foreach (KeyValuePair<string, string> k in requestXML){switch (k.Key){case "retuen_code":orderdetail.result_code = k.Value;break;case "return_msg":orderdetail.return_msg = k.Value;break;case "appid":orderdetail.appid = k.Value;break;case "mch_id":orderdetail.mch_id = k.Value;break;case "nonce_str":orderdetail.nonce_str = k.Value;break;case "sign":orderdetail.sign = k.Value;break;case "result_code":orderdetail.result_code = k.Value;break;case "err_code":orderdetail.err_code = k.Value;break;case "err_code_des":orderdetail.err_code_des = k.Value;break;case "trade_state":orderdetail.trade_state = k.Value;break;case "device_info":orderdetail.device_info = k.Value;break;case "openid":orderdetail.openid = k.Value;break;case "is_subscribe":orderdetail.is_subscribe = k.Value;break;case "trade_type":orderdetail.trade_type = k.Value;break;case "bank_type":orderdetail.bank_type = k.Value;break;case "total_fee":orderdetail.total_fee = k.Value;break;case "coupon_fee":orderdetail.coupon_fee = k.Value;break;case "fee_type":orderdetail.fee_type = k.Value;break;case "transaction_id":orderdetail.transaction_id = k.Value;break;case "out_trade_no":orderdetail.out_trade_no = k.Value;break;case "attach":orderdetail.attach = k.Value;break;case "time_end":orderdetail.time_end = k.Value;break;default:break;}}return orderdetail;}/// <summary>/// 把XML數(shù)據(jù)轉(zhuǎn)換為SortedDictionary[string, string]集合/// </summary>/// <param name="strxml">XML數(shù)據(jù)</param>/// <returns>集合</returns>public SortedDictionary<string, string> GetInfoFromXml(string xmlstring){SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();try{XmlDocument doc = new XmlDocument();doc.LoadXml(xmlstring);XmlElement root = doc.DocumentElement;int len = root.ChildNodes.Count;for (int i = 0; i < len; i++){string name = root.ChildNodes[i].Name;if (!sParams.ContainsKey(name)){sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim());}}}catch { }return sParams;}/// <summary>/// 微信統(tǒng)一下單接口xml參數(shù)整理/// </summary>/// <param name="order">微信支付參數(shù)實(shí)例</param>/// <param name="key">商戶密鑰</param>/// <returns></returns>protected string getUnifiedOrderXml(UnifiedOrder order, string key){string return_string = string.Empty;SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();sParams.Add("appid", order.appid);sParams.Add("attach", order.attach);sParams.Add("body", order.body);sParams.Add("device_info", order.device_info);sParams.Add("mch_id", order.mch_id);sParams.Add("nonce_str", order.nonce_str);sParams.Add("notify_url", order.notify_url);sParams.Add("openid", order.openid);sParams.Add("out_trade_no", order.out_trade_no);sParams.Add("spbill_create_ip", order.spbill_create_ip);sParams.Add("total_fee", order.total_fee.ToString());sParams.Add("trade_type", order.trade_type);order.sign = getsign(sParams, key);sParams.Add("sign", order.sign);//拼接成XML請(qǐng)求數(shù)據(jù)StringBuilder sbPay = new StringBuilder();foreach (KeyValuePair<string, string> k in sParams){if (k.Key == "attach" || k.Key == "body" || k.Key == "sign"){sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");}else{sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">");}}return_string = string.Format("<xml>{0}</xml>", sbPay.ToString());return return_string;}/// <summary>/// 微信訂單查詢接口XML參數(shù)整理/// </summary>/// <param name="queryorder">微信訂單查詢參數(shù)實(shí)例</param>/// <param name="key">密鑰</param>/// <returns></returns>protected string getQueryOrderXml(QueryOrder queryorder, string key){string return_string = string.Empty;SortedDictionary<string, string> sParams = new SortedDictionary<string, string>();sParams.Add("appid", queryorder.appid);sParams.Add("mch_id", queryorder.mch_id);sParams.Add("transaction_id", queryorder.transaction_id);sParams.Add("out_trade_no", queryorder.out_trade_no);sParams.Add("nonce_str", queryorder.nonce_str);queryorder.sign = getsign(sParams, key);sParams.Add("sign", queryorder.sign);//拼接成XML請(qǐng)求數(shù)據(jù)StringBuilder sbPay = new StringBuilder();foreach (KeyValuePair<string, string> k in sParams){if (k.Key == "attach" || k.Key == "body" || k.Key == "sign"){sbPay.Append("<" + k.Key + "><![CDATA[" + k.Value + "]]></" + k.Key + ">");}else{sbPay.Append("<" + k.Key + ">" + k.Value + "</" + k.Key + ">");}}return_string = string.Format("<xml>{0}</xml>", sbPay.ToString().TrimEnd(','));return return_string;}}View Code
MD5Util
public class MD5Util{public MD5Util() { }/** 獲取大寫的MD5簽名結(jié)果 */public static string GetMD5(string encypStr, string charset){string retStr;MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();//創(chuàng)建md5對(duì)象byte[] inputBye;byte[] outputBye;try{inputBye = Encoding.UTF8.GetBytes(encypStr);}catch (Exception ex){inputBye = Encoding.UTF8.GetBytes(encypStr);}outputBye = m5.ComputeHash(inputBye);retStr = System.BitConverter.ToString(outputBye);retStr = retStr.Replace("-", "").ToUpper();return retStr;}}View Code
OrderDetail
/// <summary>/// 微信訂單明細(xì)實(shí)體對(duì)象/// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1/// </summary> [Serializable]public class OrderDetail{/// <summary>/// 返回狀態(tài)碼,SUCCESS/FAIL 此字段是通信標(biāo)識(shí),非交易標(biāo)識(shí),交易是否成功需要查看trade_state來判斷/// </summary>public string return_code = "";/// <summary>/// 返回信息返回信息,如非空,為錯(cuò)誤原因 簽名失敗 參數(shù)格式校驗(yàn)錯(cuò)誤/// </summary>public string return_msg = "";/// <summary>/// 公共號(hào)ID(微信分配的公眾賬號(hào) ID)/// </summary>public string appid = "";/// <summary>/// 商戶號(hào)(微信支付分配的商戶號(hào))/// </summary>public string mch_id = "";/// <summary>/// 隨機(jī)字符串,不長于32位/// </summary>public string nonce_str = "";/// <summary>/// 簽名詳見簽名算法 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3/// </summary>public string sign = "";/// <summary>/// 業(yè)務(wù)結(jié)果,SUCCESS/FAIL /// 此字段是通信標(biāo)識(shí),非交易標(biāo)識(shí),交易是否成功需要查看result_code來判斷/// </summary>public string result_code = "";/// <summary>/// 錯(cuò)誤代碼 詳細(xì)參見第6節(jié)錯(cuò)誤列表/// </summary>public string err_code = "";/// <summary>/// 錯(cuò)誤代碼描述/// </summary>public string err_code_des = "";/// <summary>/// 交易狀態(tài)///SUCCESS—支付成功///REFUND—轉(zhuǎn)入退款///NOTPAY—未支付///CLOSED—已關(guān)閉///REVOKED—已撤銷///USERPAYING--用戶支付中///NOPAY--未支付(輸入密碼或確認(rèn)支付超時(shí)) PAYERROR--支付失敗(其他原因,如銀行返回失敗)/// </summary>public string trade_state = "";/// <summary>/// 終端設(shè)備號(hào)(門店號(hào)或收銀設(shè)備ID),注意:PC網(wǎng)頁或公眾號(hào)內(nèi)支付請(qǐng)傳"WEB"/// </summary>public string device_info = "";/// <summary>/// 用戶在商戶appid下的唯一標(biāo)識(shí)/// </summary>public string openid = "";/// <summary>/// 用戶是否關(guān)注公眾賬號(hào),Y-關(guān)注,N-未關(guān)注,僅在公眾賬號(hào)類型支付有效/// </summary>public string is_subscribe = "";/// <summary>/// 交易類型,取值如下:JSAPI,NATIVE,APP,詳細(xì)說明見參數(shù)規(guī)定/// </summary>public string trade_type = "";/// <summary>/// 銀行類型,采用字符串類型的銀行標(biāo)識(shí)/// </summary>public string bank_type = "";/// <summary>/// 訂單總金額,單位為分/// </summary>public string total_fee = "";/// <summary>/// 現(xiàn)金券支付金額<=訂單總金額,訂單總金額-現(xiàn)金券金額為現(xiàn)金支付金額 /// </summary>public string coupon_fee = "";/// <summary>/// 貨幣類型,符合ISO 4217標(biāo)準(zhǔn)的三位字母代碼,默認(rèn)人民幣:CNY/// </summary>public string fee_type = "";/// <summary>/// 微信支付訂單號(hào)/// </summary>public string transaction_id = "";/// <summary>/// 商戶系統(tǒng)的訂單號(hào),與請(qǐng)求一致。/// </summary>public string out_trade_no = "";/// <summary>/// 商家數(shù)據(jù)包,原樣返回/// </summary>public string attach = "";/// <summary>/// 支付完成時(shí)間,格式為yyyyMMddhhmmss,如2009年12月27日9點(diǎn)10分10秒表示為20091227091010。/// 時(shí)區(qū)為GMT+8 beijing。該時(shí)間取自微信支付服務(wù)器/// </summary>public string time_end = "";}View Code
UnifiedOrder
/// <summary>/// 微信統(tǒng)一接口請(qǐng)求實(shí)體對(duì)象/// </summary> [Serializable]public class UnifiedOrder{/// <summary>/// 公共號(hào)ID(微信分配的公眾賬號(hào) ID)/// </summary>public string appid = "";/// <summary>/// 商戶號(hào)(微信支付分配的商戶號(hào))/// </summary>public string mch_id = "";/// <summary>/// 微信支付分配的終端設(shè)備號(hào)/// </summary>public string device_info = "";/// <summary>/// 隨機(jī)字符串,不長于 32 位/// </summary>public string nonce_str = "";/// <summary>/// 簽名/// </summary>public string sign = "";/// <summary>/// 商品描述/// </summary>public string body = "";/// <summary>/// 附加數(shù)據(jù),原樣返回/// </summary>public string attach = "";/// <summary>/// 商戶系統(tǒng)內(nèi)部的訂單號(hào),32個(gè)字符內(nèi)、可包含字母,確保在商戶系統(tǒng)唯一,詳細(xì)說明/// </summary>public string out_trade_no = "";/// <summary>/// 訂單總金額,單位為分,不能帶小數(shù)點(diǎn)/// </summary>public int total_fee = 0;/// <summary>/// 終端IP/// </summary>public string spbill_create_ip = "";/// <summary>/// 訂 單 生 成 時(shí) 間 , 格 式 為yyyyMMddHHmmss,如 2009 年12 月 25 日 9 點(diǎn) 10 分 10 秒表示為 20091225091010。時(shí)區(qū)為 GMT+8 beijing。該時(shí)間取自商戶服務(wù)器/// </summary>public string time_start = "";/// <summary>/// 交易結(jié)束時(shí)間/// </summary>public string time_expire = "";/// <summary>/// 商品標(biāo)記 商品標(biāo)記,該字段不能隨便填,不使用請(qǐng)?zhí)羁?#xff0c;使用說明詳見第 5 節(jié)/// </summary>public string goods_tag = "";/// <summary>/// 接收微信支付成功通知/// </summary>public string notify_url = "";/// <summary>/// JSAPI、NATIVE、APP/// </summary>public string trade_type = "";/// <summary>/// 用戶標(biāo)識(shí) trade_type 為 JSAPI時(shí),此參數(shù)必傳/// </summary>public string openid = "";/// <summary>/// 只在 trade_type 為 NATIVE時(shí)需要填寫。/// </summary>public string product_id = "";}View Code
回調(diào)頁面測(cè)試:
public partial class tools_WeChat_Pay_notify_url : System.Web.UI.Page {protected void Page_Load(object sender, EventArgs e){//接收從微信后臺(tái)POST過來的數(shù)據(jù)System.IO.Stream s = Request.InputStream;int count = 0;byte[] buffer = new byte[1024];StringBuilder builder = new StringBuilder();while ((count = s.Read(buffer, 0, 1024)) > 0){builder.Append(Encoding.UTF8.GetString(buffer, 0, count));}s.Flush();s.Close();s.Dispose();TenpayUtil payUtil = new TenpayUtil();SortedDictionary<string, string> requestXML = payUtil.GetInfoFromXml(builder.ToString());const string paySignKey = "111111111111111111111111111111111111";string sing = payUtil.getsign(requestXML, paySignKey);if (requestXML.ContainsKey("return_code")){//Response.Write(requestXML["return_code"]); }//成功返回Response.Write("<xml>");Response.Write("<return_code><![CDATA[SUCCESS]]></return_code>");Response.Write("<return_msg><![CDATA[OK]]></return_msg>");Response.Write("</xml>");}/// <summary>/// 從XML數(shù)據(jù)中獲取值/// </summary>/// <param name="requestXML">XML數(shù)據(jù)</param>/// <param name="key">Key</param>/// <returns>Value</returns>public string getVal(SortedDictionary<string, string> data, string key){if (data.ContainsKey(key)){return data[key];}return "";} }View Code
?
轉(zhuǎn)載于:https://www.cnblogs.com/relax/p/4935636.html
總結(jié)
- 上一篇: 这个视频的无字幕无水印版在哪里可以找到?
- 下一篇: hbase RPCServer源码分析