C# MVC 微信支付教程系列之掃碼支付代碼實例
今天,我們來一起探討一下這個微信掃碼支付。何為掃碼支付呢?這里面,掃的碼就是二維碼了,就是我們經(jīng)常掃一掃的那種二維碼圖片,例如,我們自己添加好友的時候,可以通過輸入對方的微信號,也可以掃一掃對方的二維碼。掃碼支付,作為,微信支付里面,不可或缺的一個功能,對商品的支付提供了極為方便的體驗,用途也非常的多。
例如我們在地鐵、公交站常見的那些自動售貨機(不錯,就是那種投硬幣,就可以自動出貨的那種機器)中都用到。微信(支付寶)的掃碼支付的出現(xiàn),大大的減少了這方面的風險,近些年來,二維碼的應用越來越廣,甚至有些地方,直接用來自動售票(就是把起始點設定好,票價設定好,直接把二維碼貼出來,讓乘客自動掃相關的二維碼,完成購票,上車的時候,只需要提供自己的支付憑證給乘車員驗證即可),這樣,不僅綠色環(huán)保了,還大大的提高了售票的速度(去過大車站購票的人應該深有體驗,排隊買個票,好歹半個小時以上,心里也是萬頭草泥馬在奔騰的)。
咱就不扯遠了,說回咱么今天要做的微信支付之掃碼支付。微信官方的文檔,這個掃碼支付(NativePay)分為兩種,一種是“生成掃描支付模式”,另外一種是“生成直接支付url,支付url有效期為2小時”,至于這里面,兩種掃碼模式,怎么靈活利用呢,官方也沒有一個明確的說明。個人理解為,第一種(生成掃描支付模式),適用于固定二維碼的,就是永久使用的那種。
例如一些商家的公眾號的二維碼,是永久的,什么時候掃,都是關注這個公眾號的,但是,這種的話,我記得微信是有限量的,貌似是一個公眾號,限量10w,個人觀點,覺得這個限量,是足夠我們使用的。第二種(生成直接支付url,支付url有效期為2小時),這種的話,因為有有效期這種時間限制,超過了2個小時,該二維碼就失效,但是對生成的二維碼數(shù)量沒有限制,所以,這種個人觀點覺得適用于那種臨時根據(jù)實際情況生成的二維碼,例如:公眾平臺登陸的時候二次驗證的二維碼,自定義生成,僅為一次性繳費使用的二維碼,等等)。接下來,我們就開始講講實際例子,首先將的就是第一種模式。
掃碼支付之模式一(生成掃描支付模式):
首先,我們新建一個“MVC”的項目(asp.net的官方的demo就是了,要asp.net的自己看demo吧,demo地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1),然后把系統(tǒng)自動生成的HomeControler和View中的Home都刪了。
然后自己新建一個HomeControler,代碼如下:
// GET: Home public ActionResult Index() { return View(); }
再添加一個View,代碼如下:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首頁</title> </head> <body> <div> </div> </body> </html>
接下來,我們先把官方的demo的一些我們會用到的東西拷貝過來,其中包括以下幾個文件夾,如下圖:
就這個lib和business兩個,把這兩個文件夾,支付復制到咱們的新項目中,并且包含在項目中,如下:
然后我們再“重新生成”以下項目,或者快捷鍵:ctrl+shift+b,這時候,會提下如下錯誤:
這時候,我們?nèi)ヌ砑右?,把lib文件夾中的LitJson.dll 添加上即可,如下圖:
到這里,我們就基本把官方的demo的環(huán)境給搭建好了,接下來,我們就要開始編寫代碼了。
首先,我的邏輯是,從前到后,就是從前端到后端。前端是顯示二維碼的地方,那么我們就先給他一個div(本文使用到的是jquery的二維碼生成插件,全名叫:jquery.qrcode.min.js,我會傳到附件上),然后在頁面加載完畢的時候,會請求后臺,讓他返回二維碼字符串,然后再通過jquery的二維碼生成插件,讓他生成二維碼并顯示在前臺,代碼如下:
前端:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首頁</title> <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" /> </head> <body> <p> 模式一:生成掃描支付模式 <br /> <div id="QRCode1"> </div> </p> <p> 模式二:生成直接支付url,支付url有效期為2小時 <br /> <div id="QRCode2"> </div> </p> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script> <script src="~/Scripts/jquery.qrcode.min.js"></script> <script type="text/javascript"> $(function () { fGetQRCode1(); }) function fGetQRCode1() { $.messager.progress({ title: "", msg: "正在生成二維碼:模式一,請稍后..." }); $.ajax({ type: "post", url: "/Home/GetQRCode1", data: { time: new Date(), productId:7788 }, success: function (json) { $.messager.progress('close');//記得關閉 if (json.result) { $('#QRCode1').qrcode(json.str); //生成二維碼 } else { $('#QRCode1').html("二維碼生成失敗"); } } }) } </script> </body> </html>
后端:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using WxPayAPI; namespace WxPay.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } /// <summary> /// 模式一 /// </summary> /// <returns></returns> [HttpPost] public ActionResult GetQRCode1() { object objResult = ""; string strProductID = Request.Form["productId"]; string strQRCodeStr = GetPrePayUrl(strProductID); if (!string.IsNullOrWhiteSpace(strProductID)) { objResult = new { result = true, str = strQRCodeStr }; } else { objResult = new { result = false }; } return Json(objResult); } /** * 生成掃描支付模式一URL * @param productId 商品ID * @return 模式一URL */ public string GetPrePayUrl(string productId) { WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID);//公眾帳號id data.SetValue("mch_id", WxPayConfig.MCHID);//商戶號 data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//時間戳 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//隨機字符串 data.SetValue("product_id", productId);//商品ID data.SetValue("sign", data.MakeSign());//簽名 string str = ToUrlParams(data.GetValues());//轉(zhuǎn)換為URL串 string url = "weixin://wxpay/bizpayurl?" + str; return url; } /** * 參數(shù)數(shù)組轉(zhuǎn)換為url格式 * @param map 參數(shù)名與參數(shù)值的映射表 * @return URL字符串 */ private string ToUrlParams(SortedDictionary<string, object> map) { string buff = ""; foreach (KeyValuePair<string, object> pair in map) { buff += pair.Key + "=" + pair.Value + "&"; } buff = buff.Trim('&'); return buff; } } }
這時候,模式一是不是感覺就完成了?那么我們現(xiàn)在試試,我們?yōu)g覽該頁面,如下:
然后用微信掃一掃功能掃一下,發(fā)現(xiàn)提示如下:
這是什么鬼,是不是,你心里面是不是想知道為啥,那我來告訴你,這是為啥,這是因為,你還沒有設置回調(diào)頁面或者回調(diào)頁面有問題,這個時候,我們再新建一個Control,命名為:NativeNotifyController.cs,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; using WxPayAPI; namespace WxPay.Controllers { public class NativeNotifyController : Controller { // GET: NativeNotify public ActionResult Index() { string strData = ProcessNotify(); Response.Write(strData); return View(); } public string ProcessNotify() { WxPayData notifyData = GetNotifyData(); //檢查openid和product_id是否返回 if (!notifyData.IsSet("openid") || !notifyData.IsSet("product_id")) { WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "回調(diào)數(shù)據(jù)異常"); return res.ToXml(); } //調(diào)統(tǒng)一下單接口,獲得下單結(jié)果 string openid = notifyData.GetValue("openid").ToString(); string product_id = notifyData.GetValue("product_id").ToString(); WxPayData unifiedOrderResult = new WxPayData(); try { unifiedOrderResult = UnifiedOrder(openid, product_id); } catch (Exception ex)//若在調(diào)統(tǒng)一下單接口時拋異常,立即返回結(jié)果給微信支付后臺 { WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "統(tǒng)一下單失敗"); return res.ToXml(); } //若下單失敗,則立即返回結(jié)果給微信支付后臺 if (!unifiedOrderResult.IsSet("appid") || !unifiedOrderResult.IsSet("mch_id") || !unifiedOrderResult.IsSet("prepay_id")) { WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "統(tǒng)一下單失敗"); return res.ToXml(); } //統(tǒng)一下單成功,則返回成功結(jié)果給微信支付后臺 WxPayData data = new WxPayData(); data.SetValue("return_code", "SUCCESS"); data.SetValue("return_msg", "OK"); data.SetValue("appid", WxPayConfig.APPID); data.SetValue("mch_id", WxPayConfig.MCHID); data.SetValue("nonce_str", WxPayApi.GenerateNonceStr()); data.SetValue("prepay_id", unifiedOrderResult.GetValue("prepay_id")); data.SetValue("result_code", "SUCCESS"); data.SetValue("err_code_des", "OK"); data.SetValue("sign", data.MakeSign()); return data.ToXml(); } /// <summary> /// 接收從微信支付后臺發(fā)送過來的數(shù)據(jù)并驗證簽名 /// </summary> /// <returns>微信支付后臺返回的數(shù)據(jù)</returns> public WxPayData GetNotifyData() { //接收從微信后臺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(); //轉(zhuǎn)換數(shù)據(jù)格式并驗證簽名 WxPayData data = new WxPayData(); try { data.FromXml(builder.ToString()); } catch (WxPayException ex) { //若簽名錯誤,則立即返回結(jié)果給微信支付后臺 WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", ex.Message); } return data; } private WxPayData UnifiedOrder(string openId, string productId) { //統(tǒng)一下單 WxPayData req = new WxPayData(); req.SetValue("body", "廣東XXXX股份有限公司"); req.SetValue("attach", "附加信息,用于后臺或者存入數(shù)據(jù)庫,做自己的判斷"); req.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo()); req.SetValue("total_fee", 1); req.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); req.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); req.SetValue("goods_tag", "商品的備忘,可以自定義"); req.SetValue("trade_type", "NATIVE"); req.SetValue("openid", openId); req.SetValue("product_id", productId); WxPayData result = WxPayApi.UnifiedOrder(req); return result; } } }
記得,也要新建一個View,就是在Index那里,右鍵添加一個View,View的代碼如下(你沒眼花,就是空的,不管他):
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> </div> </body> </html>
接著,把這個項目,發(fā)布出來,放到服務器的iis上,這里面,我把他發(fā)布在http://sm.lmx.ren/上面(必須要發(fā)布到網(wǎng)上哈,如果不懂發(fā)布的,你可以自己去學習基礎知識先了),這還沒完,還需要把到公眾平臺上,設置回調(diào)頁面,操作如下:
這樣,就大功告成了。這時候,我們再試試掃碼,發(fā)現(xiàn)已經(jīng)得到以下提示了,這樣子,就代表,我們的模式一,已經(jīng)成功完成了。如下圖:
這時候,細心的朋友就會提問了,我這都支付成功了,怎么頁面沒啥提示呀,這頁面不交互很不友好啊。嗯,沒錯,童鞋,你有前途,現(xiàn)在我就告訴你,怎么做交互,但是,為了你日后更加有前途,我只告訴你邏輯,具體怎么實現(xiàn),自己來想,多動腦。
那么邏輯是怎么的呢?常規(guī)邏輯下,我們微信掃頁面上的這個二維碼的時候,這個時候,他已經(jīng)把我們二維碼里面的參數(shù),傳到微信服務器,然后有他們開始統(tǒng)一下單(如果對邏輯不清晰,可以看看官方的文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3):他們在統(tǒng)一下單的時候,就會生成一個product_id,這個家伙的作用呢 ,就是告訴你現(xiàn)在微信服務器,已經(jīng)生成了一個單號,勞資已經(jīng)收到你的支付請求了,趕緊給老子付款,O(∩_∩)O哈哈~。。。停,停,停。這時候,思路不能繼續(xù)往下走了。
記得,前面有個叫做“統(tǒng)一下單“,那既然有這個步驟,那我們可以利用一下,就是當他統(tǒng)一下單成功的時候,我們可以在頁面更新一下狀態(tài),告訴客戶:您已成功掃描,并下單成功,請支付。是不是,我們可以提示他們這個。然后等用戶在手機上,支付成功的時候,這個時候,頁面是不是也要反饋給用戶,告訴他,小子,你的錢已經(jīng)到我的口袋了,你可以走了(你走,我沒有你這樣的寶寶)。O(∩_∩)O哈哈~,但是,你還要停,停住,停下來。我們服務公司怎么知道這個微信用戶已經(jīng)付款成功了呢?來,我們把視線回到代碼上,找到lib/Config.cs,如下圖:
然后打開config.cs,找到以下代碼:
對了,你很聰明。微信的處理邏輯就是,等用戶支付成功之后,他會給這個鏈接發(fā)送支付結(jié)果,默認是以前那個aspx的頁面,現(xiàn)在我換成mvc,所以,我們得手動新建一個control了,命名為:ResultNotifyController,然后代碼如下:
using LmxPublic.Log; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; using System.Web.Mvc; using WxPayAPI; namespace WxPay.Controllers { public class ResultNotifyController : Controller { // GET: ResultNotify public ActionResult Index() { string strData = ProcessNotify(); Response.Write(strData); return View(); } public string ProcessNotify() { WxPayData notifyData = GetNotifyData(); //檢查支付結(jié)果中transaction_id是否存在 if (!notifyData.IsSet("transaction_id")) { //若transaction_id不存在,則立即返回結(jié)果給微信支付后臺 WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "支付結(jié)果中微信訂單號不存在"); return res.ToXml(); } string transaction_id = notifyData.GetValue("transaction_id").ToString(); //查詢訂單,判斷訂單真實性 if (!QueryOrder(transaction_id)) { //若訂單查詢失敗,則立即返回結(jié)果給微信支付后臺 WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "訂單查詢失敗"); return res.ToXml(); } //查詢訂單成功 else { WxPayData res = new WxPayData(); res.SetValue("return_code", "SUCCESS"); res.SetValue("return_msg", "OK"); Log.Info(this.GetType().ToString(), "order query success : " + res.ToXml()); string strXml = res.ToXml(); FileLog.WriteLog(strXml); return res.ToXml();//如果我們走到這一步了,那就代表,用戶已經(jīng)支付成功了,所以,該干嘛干嘛了。 } } /// <summary> /// 接收從微信支付后臺發(fā)送過來的數(shù)據(jù)并驗證簽名 /// </summary> /// <returns>微信支付后臺返回的數(shù)據(jù)</returns> public WxPayData GetNotifyData() { //接收從微信后臺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(); Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString()); //轉(zhuǎn)換數(shù)據(jù)格式并驗證簽名 WxPayData data = new WxPayData(); try { data.FromXml(builder.ToString()); } catch (WxPayException ex) { //若簽名錯誤,則立即返回結(jié)果給微信支付后臺 WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", ex.Message); Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml()); return res; } return data; } //查詢訂單 private bool QueryOrder(string transaction_id) { WxPayData req = new WxPayData(); req.SetValue("transaction_id", transaction_id); WxPayData res = WxPayApi.OrderQuery(req); if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS") { return true; } else { return false; } } } }
前臺,對,也是要新建一個View,代碼如下(沒錯,也是空的)
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> </div> </body> </html>
好,模式一就到這里了,呼呼。。。沒想到啊,一個模式一,讓我從上午寫到下午,真心累。。。還有一個模式二呢。。。喝口水先,咱,接著來。
好,喝完水,接著干,下面是模式二:
模式二(生成直接支付url,支付url有效期為2小時)
由于有了上面模式一的詳細說明,模式二,我就簡單一點的來說了,如果又不懂的,到群里來問我吧。
模式二,前端,增加一些代碼,如下(完整的,包括模式一的代碼了):
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>首頁</title> <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" /> <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" /> </head> <body> <p> 模式一:生成掃描支付模式 <br /> <div id="QRCode1"> </div> </p> <p> 模式二:生成直接支付url,支付url有效期為2小時 <br /> <div id="QRCode2"> </div> </p> <script src="~/Scripts/jquery-1.10.2.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script> <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script> <script src="~/Scripts/jquery.qrcode.min.js"></script> <script type="text/javascript"> $(function () { fGetQRCode1(); }) function fGetQRCode1() { $.messager.progress({ title: "", msg: "正在生成二維碼:模式一,請稍后..." }); $.ajax({ type: "post", url: "/Home/GetQRCode1", data: { time: new Date(), productId:7788 }, success: function (json) { $.messager.progress('close');//記得關閉 if (json.result) { $('#QRCode1').qrcode(json.str); //生成二維碼 } else { $('#QRCode1').html("二維碼生成失敗"); } fGetQRCode2(); }, error: function (json) { $('#QRCode1').html("二維碼生成失敗"); fGetQRCode2(); } }) } function fGetQRCode2() { $.messager.progress({ title: "", msg: "正在生成二維碼:模式二,請稍后..." }); $.ajax({ type: "post", url: "/Home/GetQRCode2", data: { time: new Date(), productId: 7788 }, success: function (json) { $.messager.progress('close');//記得關閉 if (json.result) { $('#QRCode2').qrcode(json.str); //生成二維碼 } else { $('#QRCode2').html("二維碼生成失敗"); } }, error: function (json) { $('#QRCode2').html("二維碼生成失敗"); } }) } </script> </body> </html>
后端:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using WxPayAPI; namespace WxPay.Controllers { public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } /// <summary> /// 模式一 /// </summary> /// <returns></returns> [HttpPost] public ActionResult GetQRCode1() { object objResult = ""; string strProductID = Request.Form["productId"]; string strQRCodeStr = GetPrePayUrl(strProductID); if (!string.IsNullOrWhiteSpace(strProductID)) { objResult = new { result = true, str = strQRCodeStr }; } else { objResult = new { result = false }; } return Json(objResult); } /// <summary> /// 模式二 /// </summary> /// <returns></returns> [HttpPost] public ActionResult GetQRCode2() { object objResult = ""; string strProductID = Request.Form["productId"]; string strQRCodeStr = GetPayUrl(strProductID); if (!string.IsNullOrWhiteSpace(strProductID)) { objResult = new { result = true, str = strQRCodeStr }; } else { objResult = new { result = false }; } return Json(objResult); } /** * 生成掃描支付模式一URL * @param productId 商品ID * @return 模式一URL */ public string GetPrePayUrl(string productId) { WxPayData data = new WxPayData(); data.SetValue("appid", WxPayConfig.APPID);//公眾帳號id data.SetValue("mch_id", WxPayConfig.MCHID);//商戶號 data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//時間戳 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//隨機字符串 data.SetValue("product_id", productId);//商品ID data.SetValue("sign", data.MakeSign());//簽名 string str = ToUrlParams(data.GetValues());//轉(zhuǎn)換為URL串 string url = "weixin://wxpay/bizpayurl?" + str; return url; } /** * 參數(shù)數(shù)組轉(zhuǎn)換為url格式 * @param map 參數(shù)名與參數(shù)值的映射表 * @return URL字符串 */ private string ToUrlParams(SortedDictionary<string, object> map) { string buff = ""; foreach (KeyValuePair<string, object> pair in map) { buff += pair.Key + "=" + pair.Value + "&"; } buff = buff.Trim('&'); return buff; } /** * 生成直接支付url,支付url有效期為2小時,模式二 * @param productId 商品ID * @return 模式二URL */ public string GetPayUrl(string productId) { WxPayData data = new WxPayData(); data.SetValue("body", "廣東XXXX股份有限公司");//商品描述 data.SetValue("attach", "附加信息,用于后臺或者存入數(shù)據(jù)庫,做自己的判斷");//附加數(shù)據(jù) data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//隨機字符串 data.SetValue("total_fee", 1);//總金額 data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始時間 data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易結(jié)束時間 data.SetValue("goods_tag", "商品的備忘,可以自定義");//商品標記 data.SetValue("trade_type", "NATIVE");//交易類型 data.SetValue("product_id", productId);//商品ID WxPayData result = WxPayApi.UnifiedOrder(data);//調(diào)用統(tǒng)一下單接口 string url = result.GetValue("code_url").ToString();//獲得統(tǒng)一下單接口返回的二維碼鏈接 return url; } } }
特此更正,感謝“ abc54288”的指出,模式二也是有回調(diào)的,回調(diào)的接口設置在Config.cs,中,如下圖:
所以下面的作廢,但是如果需要手動查詢訂單情況的,還可以用下列的方法查詢。再次感謝園友:“ abc54288”。
由于模式二是沒有支付結(jié)果回調(diào)的,所以,我們要查詢支付成功與否,需要自己寫方法來查詢,官方提供的查詢支付成功與否的方法有以下,
/*** * 訂單查詢完整業(yè)務流程邏輯 * @param transaction_id 微信訂單號(優(yōu)先使用) * @param out_trade_no 商戶訂單號 * @return 訂單查詢結(jié)果(xml格式) */ public static string Run(string transaction_id, string out_trade_no) { Log.Info("OrderQuery", "OrderQuery is processing..."); WxPayData data = new WxPayData(); if(!string.IsNullOrEmpty(transaction_id))//如果微信訂單號存在,則以微信訂單號為準 { data.SetValue("transaction_id", transaction_id); } else//微信訂單號不存在,才根據(jù)商戶訂單號去查單 { data.SetValue("out_trade_no", out_trade_no); } WxPayData result = WxPayApi.OrderQuery(data);//提交訂單查詢請求給API,接收返回數(shù)據(jù) Log.Info("OrderQuery", "OrderQuery process complete, result : " + result.ToXml()); return result.ToPrintStr(); }
可以通過這個微信訂單號(transaction_id)來查詢,也可以通過商戶訂單號(out_trade_no),所以,我們要合理利用這里面的技巧,上述模式二,我用的out_trade_no 是一個隨機字符串,我們可以把這個字符串記錄好,放數(shù)據(jù)庫還是放哪里,你自己喜歡,然后寫一個ajsx長輪詢來,定時查詢這個商戶訂單號,看看有沒有支付成功,來做支付確認。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C#程序中使用LINQ to XML來查詢XML格式數(shù)據(jù)的實例
這篇文章主要介紹了C#程序中使用LINQ to XML來查詢XML格式數(shù)據(jù)的實例,LINQ to XML是.NET框架中集成的接口,可以將XML數(shù)據(jù)放到內(nèi)存中進行處理,需要的朋友可以參考下2016-03-03Silverlight文件上傳下載實現(xiàn)方法(下載保存)
這篇文章主要介紹了Silverlight文件上傳下載實現(xiàn)方法(下載保存) ,需要的朋友可以參考下2015-11-11