tenpay.dll: MD5Util.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Cryptography; namespace tenpay { public class MD5Util { public MD5Util() { // // TODO: 在此處添加構(gòu)造函數(shù)邏輯 // } /** 獲取大寫的MD5簽名結(jié)果 */ public static string GetMD5(string encypStr, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //創(chuàng)建md5對(duì)象 byte[] inputBye; byte[] outputBye; //使用GB2312編碼方式把字符串轉(zhuǎn)化為字節(jié)數(shù)組. try { inputBye = Encoding.GetEncoding(charset).GetBytes(encypStr); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(encypStr); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", "").ToUpper(); return retStr; } } } OrderDetail.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace tenpay { /// <summary> /// 微信訂單明細(xì)實(shí)體對(duì)象 /// </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ī)字符串,不長(zhǎng)于32位 /// </summary> public string nonce_str = ""; /// <summary> /// 簽名 /// </summary> public string sign = ""; /// <summary> /// 業(yè)務(wù)結(jié)果,SUCCESS/FAIL /// </summary> public string result_code = ""; /// <summary> /// 錯(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) /// </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、MICROPAY、APP /// </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 = ""; } } QueryOrder.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace tenpay { /// <summary> /// 微信訂單查詢接口請(qǐng)求實(shí)體對(duì)象 /// </summary> [Serializable] public class QueryOrder { /// <summary> /// 公共號(hào)ID(微信分配的公眾賬號(hào) ID) /// </summary> public string appid = ""; /// <summary> /// 商戶號(hào)(微信支付分配的商戶號(hào)) /// </summary> public string mch_id = ""; /// <summary> /// 微信訂單號(hào),優(yōu)先使用 /// </summary> public string transaction_id = ""; /// <summary> /// 商戶系統(tǒng)內(nèi)部訂單號(hào) /// </summary> public string out_trade_no = ""; /// <summary> /// 隨機(jī)字符串,不長(zhǎng)于 32 位 /// </summary> public string nonce_str = ""; /// <summary> /// 簽名,參與簽名參數(shù):appid,mch_id,transaction_id,out_trade_no,nonce_str,key /// </summary> public string sign = ""; } } UnifiedOrder.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace tenpay { /// <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ī)字符串,不長(zhǎng)于 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í)羁?,使用說明詳見第 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 = ""; } } TenpayUtil.cs using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; namespace tenpay { 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(), "GBK").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> /// 獲取微信簽名 /// </summary> /// <param name="sParams"></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> public string PostXmlToUrl(string url, string postData) { string returnmsg = ""; using (System.Net.WebClient wc = new System.Net.WebClient()) { returnmsg = wc.UploadString(url, "POST", postData); } return returnmsg; } /// <summary> /// 獲取prepay_id /// </summary> public string getPrepay_id(UnifiedOrder order, string key) { string prepay_id = ""; string post_data = getUnifiedOrderXml(order, key); string request_data = PostXmlToUrl(UnifiedPayUrl, post_data); SortedDictionary<string, string> requestXML = GetInfoFromXml(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"></param> /// <returns></returns> protected 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()); byte[] byteArray = Encoding.UTF8.GetBytes(return_string); return_string = Encoding.GetEncoding("GBK").GetString(byteArray); 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; } } } 看官網(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" ) {} // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但并不保證它絕對(duì)可靠。
}
);
}
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();
}
主要是prepay_id和paySign的獲取。類庫tenpay.dll的作用就是獲取這兩個(gè)東西的。 大致流程:獲取公眾號(hào)的code——》獲取預(yù)定單號(hào)的openid——》獲取prepay_id。 1.根據(jù)自己的業(yè)務(wù)邏輯生成內(nèi)部訂單 protected void btnPay_Click(object sender, EventArgs e) { if (Fetch.GetUserCookie() == null) { Response.Redirect("/App/Login.aspx?url=/App/indexPay.aspx"); return; } int salePrice = Utility.StrToInt(OrderAmount, 0); OnLineOrder onlineOrder = new OnLineOrder(); onlineOrder.ShareID = 13; onlineOrder.OrderID = PayHelper.GetOrderIDByPrefix("WX"); #region 訂單處理 if (Fetch.GetUserCookie() == null) { onlineOrder.OperUserID = 0; } else { onlineOrder.OperUserID = Fetch.GetUserCookie().UserID; } onlineOrder.Accounts = Fetch.GetUserCookie().Accounts; onlineOrder.CardTotal = 1; onlineOrder.CardTypeID = salePrice / 10; //< 30 ? 1 : salePrice < 60 ? 2 : salePrice < 120 ? 3 : 4; onlineOrder.OrderAmount = salePrice; onlineOrder.IPAddress = GameRequest.GetUserIP(); //生成訂單 Message umsg = treasureFacade.RequestOrder(onlineOrder); if (!umsg.Success) { RenderAlertInfo(true, umsg.Content, 2); return; } #endregion //發(fā)起微信支付 Response.Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公眾號(hào)appid&redirect_uri=http://你的網(wǎng)站/App/Pay/PayOrder.aspx?showwxpaytitle=1&response_type=code&scope=snsapi_base&state=" + OrderAmount + "_" + onlineOrder.OrderID + "#wechat_redirect"); } 2.進(jìn)入公眾號(hào)配置網(wǎng)頁授權(quán)獲取用戶基本信息 這樣配置后就可以調(diào)用微信的接口獲取到公眾號(hào)的code Response.Redirect("https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公眾號(hào)appid&redirect_uri=http://你的網(wǎng)站/App/Pay/PayOrder.aspx?showwxpaytitle=1&response_type=code&scope=snsapi_base&state=" + OrderAmount + "_" + onlineOrder.OrderID + "#wechat_redirect"); 訪問https://open.weixin.qq.com/connect/oauth2/authorize接口,成功后會(huì)跳轉(zhuǎn)到設(shè)置的redirect_uri頁面,其中會(huì)包含code參數(shù),接下來就到redirect_uri頁面(我這里就是PayOrder.aspx了)簡(jiǎn)單的獲取code參數(shù):
View Code
上面一句 protected string code = GameRequest.GetQueryString("code"); 就獲取到了傳過來的code參數(shù)。 然后調(diào)用網(wǎng)頁授權(quán)接口https://api.weixin.qq.com/sns/oauth2/access_token 獲取openid 這個(gè)接口返回的數(shù)據(jù)是json類型的,使用JavaScriptSerializer類和結(jié)構(gòu)體把openid取出: public struct authorization { public string access_token { get; set; } //屬性的名字,必須與json格式字符串中的"key"值一樣。 public string expires_in { get; set; } public string refresh_token { get; set; } public string openid { get; set; } public string scope { get; set; } } TenpayUtil tenpay = new TenpayUtil(); string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString(); string AppSecret = ConfigurationManager.AppSettings["AppSecret"].ToString(); string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString(); appId = ConfigurationManager.AppSettings["AppId"].ToString(); string post_data = "appid=" + appId + "&secret=" + AppSecret + "&code=" + code + "&grant_type=authorization_code"; string requestData = tenpay.PostXmlToUrl(TenpayUtil.getAccess_tokenUrl(), post_data); JavaScriptSerializer js = new JavaScriptSerializer(); //實(shí)例化一個(gè)能夠序列化數(shù)據(jù)的類 authorization auth = js.Deserialize<authorization>(requestData); //將json數(shù)據(jù)轉(zhuǎn)化為對(duì)象類型并賦值給auth AppId和AppSecret是公眾號(hào)里面給的,mch_id是通過微信支付申請(qǐng)后微信發(fā)郵件給的,paySignKey是自己設(shè)置的證書密陰 TenpayUtil.getAccess_tokenUrl()="https://api.weixin.qq.com/sns/oauth2/access_token" 這樣轉(zhuǎn)化后就可以得到openid order.openid = auth.openid; 終于到重頭戲獲取prepay_id了 UnifiedOrder order = new UnifiedOrder(); order.appid = appId; order.attach = "vinson"; order.body = OrderAmount + "拍幣"; order.device_info = ""; order.mch_id = mch_id; order.nonce_str = TenpayUtil.getNoncestr(); order.notify_url = "http://你的網(wǎng)站/App/Shop/pay.aspx"; order.openid = auth.openid; order.out_trade_no = OrderID; order.trade_type = "JSAPI"; order.spbill_create_ip = Page.Request.UserHostAddress; order.total_fee = int.Parse(OrderAmount) * 100; //order.total_fee = 1; prepay_id = tenpay.getPrepay_id(order, paySignKey); 對(duì)象類型UnifiedOrder方便把多個(gè)參數(shù)融合一個(gè)對(duì)象中,看看tenpay.getPrepay_id(order, paySignKey)方法: /// <summary> /// 獲取prepay_id /// </summary> public string getPrepay_id(UnifiedOrder order, string key) { string prepay_id = ""; string post_data = getUnifiedOrderXml(order, key); string request_data = PostXmlToUrl(UnifiedPayUrl, post_data); SortedDictionary<string, string> requestXML = GetInfoFromXml(request_data); foreach (KeyValuePair<string, string> k in requestXML) { if (k.Key == "prepay_id") { prepay_id = k.Value; break; } } return prepay_id; } 接口UnifiedPayUrl="https://api.mch.weixin.qq.com/pay/unifiedorder" 這個(gè)接口的參數(shù)是xml格式的,返回來的數(shù)據(jù)也是xml格式的 /// <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()); byte[] byteArray = Encoding.UTF8.GetBytes(return_string); return_string = Encoding.GetEncoding("GBK").GetString(byteArray); return return_string; } 所有參數(shù)準(zhǔn)備完畢,就剩下最后的微信簽名paySign了: prepay_id = tenpay.getPrepay_id(order, paySignKey); timeStamp = TenpayUtil.getTimestamp(); nonceStr = TenpayUtil.getNoncestr(); SortedDictionary<string, string> sParams = new SortedDictionary<string, string>(); sParams.Add("appId", appId); sParams.Add("timeStamp", timeStamp); sParams.Add("nonceStr", nonceStr); sParams.Add("package", "prepay_id=" + prepay_id); sParams.Add("signType", "MD5"); paySign = tenpay.getsign(sParams, paySignKey); 這里要注意了:appId這些參數(shù)的大小寫一定要和js那邊的參數(shù)大小寫一致!稍微有所不同都會(huì)提示“商戶簽名錯(cuò)誤”。 <script type="text/javascript"> var appId = "<%=appId %>"; var timeStamp = "<%=timeStamp %>"; var nonceStr = "<%=nonceStr %>"; var prepay_id = "<%=prepay_id %>"; var paySign = "<%=paySign %>"; var OrderID="<%=OrderID %>"; //alert("appId:" + appId + ",timeStamp:" + timeStamp + ",nonceStr:" + nonceStr + ",prepay_id:" + prepay_id + ",paySign:" + paySign); //return; function onBridgeReady() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": appId, //公眾號(hào)名稱,由商戶傳入 "timeStamp": timeStamp, //時(shí)間戳,自1970年以來的秒數(shù) "nonceStr": nonceStr, //隨機(jī)串 "package": "prepay_id=" + prepay_id, "signType": "MD5", //微信簽名方式: "paySign": paySign //微信簽名 }, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { $(function () { $.ajax({ contentType: "application/json", url: "/WS/vinson.asmx/payWeiXin", data: "{OrderID:'" + OrderID + "'}", type: "POST", dataType: "json", success: function (json) { json = eval("(" + json.d + ")"); if (json.success == "success") { $("#tip").text("支付成功,正在跳轉(zhuǎn)......"); window.location = "http://你的網(wǎng)站/App/Shop/successful.aspx"; } else { $("#tip").text(json.msg); alert(json.msg); window.location = "http://你的網(wǎng)站/App/indexPay.aspx"; } }, error: function (err, ex) { alert(err.responseText); } }); }) } // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:res.err_msg將在用戶支付成功后返回 ok,但并不保證它絕對(duì)可靠。 else { alert("交易取消"); window.location="http://www.你的網(wǎng)站.cn/App/indexPay.aspx"; } } ); } 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(); } </script> 要發(fā)起微信支付,還要到公眾號(hào)設(shè)置支付授權(quán)目錄: 一切準(zhǔn)備就緒,就可以真正的發(fā)起微信支付了: vinson
|
|