微信支付教程系列之掃碼支付javascript
1 // GET: Home 2 public ActionResult Index() 3 { 4 return View(); 5 }
再添加一個View,代碼以下:php
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <title>首頁</title> 9 </head> 10 <body> 11 <div> 12 </div> 13 </body> 14 </html>
接下來,咱們先把官方的demo的一些咱們會用到的東西拷貝過來,其中包括如下幾個文件夾,以下圖:css
就這個lib和business兩個,把這兩個文件夾,支付複製到我們的新項目中,而且包含在項目中,以下:html
而後咱們再「從新生成」如下項目,或者快捷鍵:ctrl+shift+b,這時候,會提下以下錯誤:前端
這時候,咱們去添加引用,把lib文件夾中的LitJson.dll 添加上便可,以下圖:java
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <title>首頁</title> 9 <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" /> 10 <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" /> 11 <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" /> 12 </head> 13 <body> 14 <p> 15 模式一:生成掃描支付模式 16 <br /> 17 <div id="QRCode1"> 18 </div> 19 </p> 20 <p> 21 模式二:生成直接支付url,支付url有效期爲2小時 22 <br /> 23 <div id="QRCode2"> 24 </div> 25 </p> 26 <script src="~/Scripts/jquery-1.10.2.js"></script> 27 <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script> 28 <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script> 29 <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script> 30 <script src="~/Scripts/jquery.qrcode.min.js"></script> 31 <script type="text/javascript"> 32 $(function () { 33 fGetQRCode1(); 34 }) 35 function fGetQRCode1() { 36 $.messager.progress({ 37 title: "", 38 msg: "正在生成二維碼:模式一,請稍後..." 39 }); 40 $.ajax({ 41 type: "post", 42 url: "/Home/GetQRCode1", 43 data: { 44 time: new Date(), 45 productId:7788 46 }, 47 success: function (json) { 48 $.messager.progress('close');//記得關閉 49 if (json.result) { 50 $('#QRCode1').qrcode(json.str); //生成二維碼 51 } 52 else { 53 $('#QRCode1').html("二維碼生成失敗"); 54 } 55 } 56 }) 57 } 58 </script> 59 </body> 60 </html>
後端:jquery
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using WxPayAPI; 7 namespace WxPay.Controllers 8 { 9 public class HomeController : Controller 10 { 11 // GET: Home 12 public ActionResult Index() 13 { 14 return View(); 15 } 16 /// <summary> 17 /// 模式一 18 /// </summary> 19 /// <returns></returns> 20 [HttpPost] 21 public ActionResult GetQRCode1() 22 { 23 object objResult = ""; 24 string strProductID = Request.Form["productId"]; 25 string strQRCodeStr = GetPrePayUrl(strProductID); 26 if (!string.IsNullOrWhiteSpace(strProductID)) 27 { 28 objResult = new { result = true, str = strQRCodeStr }; 29 } 30 else 31 { 32 objResult = new { result = false }; 33 } 34 return Json(objResult); 35 } 36 /** 37 * 生成掃描支付模式一URL 38 * @param productId 商品ID 39 * @return 模式一URL 40 */ 41 public string GetPrePayUrl(string productId) 42 { 43 WxPayData data = new WxPayData(); 44 data.SetValue("appid", WxPayConfig.APPID);//公衆賬號id 45 data.SetValue("mch_id", WxPayConfig.MCHID);//商戶號 46 data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//時間戳 47 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//隨機字符串 48 data.SetValue("product_id", productId);//商品ID 49 data.SetValue("sign", data.MakeSign());//簽名 50 string str = ToUrlParams(data.GetValues());//轉換爲URL串 51 string url = "weixin://wxpay/bizpayurl?" + str; 52 return url; 53 } 54 /** 55 * 參數數組轉換爲url格式 56 * @param map 參數名與參數值的映射表 57 * @return URL字符串 58 */ 59 private string ToUrlParams(SortedDictionary<string, object> map) 60 { 61 string buff = ""; 62 foreach (KeyValuePair<string, object> pair in map) 63 { 64 buff += pair.Key + "=" + pair.Value + "&"; 65 } 66 buff = buff.Trim('&'); 67 return buff; 68 } 69 } 70 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Web; 6 using System.Web.Mvc; 7 using WxPayAPI; 8 namespace WxPay.Controllers 9 { 10 public class NativeNotifyController : Controller 11 { 12 // GET: NativeNotify 13 public ActionResult Index() 14 { 15 string strData = ProcessNotify(); 16 Response.Write(strData); 17 return View(); 18 } 19 public string ProcessNotify() 20 { 21 WxPayData notifyData = GetNotifyData(); 22 //檢查openid和product_id是否返回 23 if (!notifyData.IsSet("openid") || !notifyData.IsSet("product_id")) 24 { 25 WxPayData res = new WxPayData(); 26 res.SetValue("return_code", "FAIL"); 27 res.SetValue("return_msg", "回調數據異常"); 28 return res.ToXml(); 29 } 30 //調統一下單接口,得到下單結果 31 string openid = notifyData.GetValue("openid").ToString(); 32 string product_id = notifyData.GetValue("product_id").ToString(); 33 WxPayData unifiedOrderResult = new WxPayData(); 34 try 35 { 36 unifiedOrderResult = UnifiedOrder(openid, product_id); 37 } 38 catch (Exception ex)//若在調統一下單接口時拋異常,當即返回結果給微信支付後臺 39 { 40 WxPayData res = new WxPayData(); 41 res.SetValue("return_code", "FAIL"); 42 res.SetValue("return_msg", "統一下單失敗"); 43 return res.ToXml(); 44 } 45 //若下單失敗,則當即返回結果給微信支付後臺 46 if (!unifiedOrderResult.IsSet("appid") || !unifiedOrderResult.IsSet("mch_id") || !unifiedOrderResult.IsSet("prepay_id")) 47 { 48 WxPayData res = new WxPayData(); 49 res.SetValue("return_code", "FAIL"); 50 res.SetValue("return_msg", "統一下單失敗"); 51 return res.ToXml(); 52 } 53 //統一下單成功,則返回成功結果給微信支付後臺 54 WxPayData data = new WxPayData(); 55 data.SetValue("return_code", "SUCCESS"); 56 data.SetValue("return_msg", "OK"); 57 data.SetValue("appid", WxPayConfig.APPID); 58 data.SetValue("mch_id", WxPayConfig.MCHID); 59 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr()); 60 data.SetValue("prepay_id", unifiedOrderResult.GetValue("prepay_id")); 61 data.SetValue("result_code", "SUCCESS"); 62 data.SetValue("err_code_des", "OK"); 63 data.SetValue("sign", data.MakeSign()); 64 return data.ToXml(); 65 } 66 /// <summary> 67 /// 接收從微信支付後臺發送過來的數據並驗證簽名 68 /// </summary> 69 /// <returns>微信支付後臺返回的數據</returns> 70 public WxPayData GetNotifyData() 71 { 72 //接收從微信後臺POST過來的數據 73 System.IO.Stream s = Request.InputStream; 74 int count = 0; 75 byte[] buffer = new byte[1024]; 76 StringBuilder builder = new StringBuilder(); 77 while ((count = s.Read(buffer, 0, 1024)) > 0) 78 { 79 builder.Append(Encoding.UTF8.GetString(buffer, 0, count)); 80 } 81 s.Flush(); 82 s.Close(); 83 s.Dispose(); 84 //轉換數據格式並驗證簽名 85 WxPayData data = new WxPayData(); 86 try 87 { 88 data.FromXml(builder.ToString()); 89 } 90 catch (WxPayException ex) 91 { 92 //若簽名錯誤,則當即返回結果給微信支付後臺 93 WxPayData res = new WxPayData(); 94 res.SetValue("return_code", "FAIL"); 95 res.SetValue("return_msg", ex.Message); 96 } 97 return data; 98 } 99 private WxPayData UnifiedOrder(string openId, string productId) 100 { 101 //統一下單 102 WxPayData req = new WxPayData(); 103 req.SetValue("body", "廣東XXXX股份有限公司"); 104 req.SetValue("attach", "附加信息,用於後臺或者存入數據庫,作本身的判斷"); 105 req.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo()); 106 req.SetValue("total_fee", 1); 107 req.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss")); 108 req.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss")); 109 req.SetValue("goods_tag", "商品的備忘,能夠自定義"); 110 req.SetValue("trade_type", "NATIVE"); 111 req.SetValue("openid", openId); 112 req.SetValue("product_id", productId); 113 WxPayData result = WxPayApi.UnifiedOrder(req); 114 return result; 115 } 116 } 117 }
記得,也要新建一個View,就是在Index那裏,右鍵添加一個View,View的代碼以下(你沒眼花,就是空的,無論他):ajax
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <title>Index</title> 9 </head> 10 <body> 11 <div> 12 </div> 13 </body> 14 </html>
接着,把這個項目,發佈出來,放到服務器的iis上,這裏面,我把他發佈在http://sm.lmx.ren/上面(必需要發佈到網上哈,若是不懂發佈的,你能夠本身去學習基礎知識先了),這還沒完,還須要把到公衆平臺上,設置回調頁面,操做以下:數據庫
1 using LmxPublic.Log; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Web; 7 using System.Web.Mvc; 8 using WxPayAPI; 9 namespace WxPay.Controllers 10 { 11 public class ResultNotifyController : Controller 12 { 13 // GET: ResultNotify 14 public ActionResult Index() 15 { 16 string strData = ProcessNotify(); 17 Response.Write(strData); 18 return View(); 19 } 20 public string ProcessNotify() 21 { 22 WxPayData notifyData = GetNotifyData(); 23 //檢查支付結果中transaction_id是否存在 24 if (!notifyData.IsSet("transaction_id")) 25 { 26 //若transaction_id不存在,則當即返回結果給微信支付後臺 27 WxPayData res = new WxPayData(); 28 res.SetValue("return_code", "FAIL"); 29 res.SetValue("return_msg", "支付結果中微信訂單號不存在"); 30 return res.ToXml(); 31 } 32 string transaction_id = notifyData.GetValue("transaction_id").ToString(); 33 //查詢訂單,判斷訂單真實性 34 if (!QueryOrder(transaction_id)) 35 { 36 //若訂單查詢失敗,則當即返回結果給微信支付後臺 37 WxPayData res = new WxPayData(); 38 res.SetValue("return_code", "FAIL"); 39 res.SetValue("return_msg", "訂單查詢失敗"); 40 return res.ToXml(); 41 } 42 //查詢訂單成功 43 else 44 { 45 WxPayData res = new WxPayData(); 46 res.SetValue("return_code", "SUCCESS"); 47 res.SetValue("return_msg", "OK"); 48 Log.Info(this.GetType().ToString(), "order query success : " + res.ToXml()); 49 string strXml = res.ToXml(); 50 FileLog.WriteLog(strXml); 51 return res.ToXml();//若是咱們走到這一步了,那就表明,用戶已經支付成功了,因此,該幹嗎幹嗎了。 52 } 53 } 54 /// <summary> 55 /// 接收從微信支付後臺發送過來的數據並驗證簽名 56 /// </summary> 57 /// <returns>微信支付後臺返回的數據</returns> 58 public WxPayData GetNotifyData() 59 { 60 //接收從微信後臺POST過來的數據 61 System.IO.Stream s = Request.InputStream; 62 int count = 0; 63 byte[] buffer = new byte[1024]; 64 StringBuilder builder = new StringBuilder(); 65 while ((count = s.Read(buffer, 0, 1024)) > 0) 66 { 67 builder.Append(Encoding.UTF8.GetString(buffer, 0, count)); 68 } 69 s.Flush(); 70 s.Close(); 71 s.Dispose(); 72 Log.Info(this.GetType().ToString(), "Receive data from WeChat : " + builder.ToString()); 73 //轉換數據格式並驗證簽名 74 WxPayData data = new WxPayData(); 75 try 76 { 77 data.FromXml(builder.ToString()); 78 } 79 catch (WxPayException ex) 80 { 81 //若簽名錯誤,則當即返回結果給微信支付後臺 82 WxPayData res = new WxPayData(); 83 res.SetValue("return_code", "FAIL"); 84 res.SetValue("return_msg", ex.Message); 85 Log.Error(this.GetType().ToString(), "Sign check error : " + res.ToXml()); 86 return res; 87 } 88 89 return data; 90 } 91 //查詢訂單 92 private bool QueryOrder(string transaction_id) 93 { 94 WxPayData req = new WxPayData(); 95 req.SetValue("transaction_id", transaction_id); 96 WxPayData res = WxPayApi.OrderQuery(req); 97 if (res.GetValue("return_code").ToString() == "SUCCESS" && 98 res.GetValue("result_code").ToString() == "SUCCESS") 99 { 100 return true; 101 } 102 else 103 { 104 return false; 105 } 106 } 107 } 108 }
前臺,對,也是要新建一個View,代碼以下(沒錯,也是空的)json
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <title>Index</title> 9 </head> 10 <body> 11 <div> 12 </div> 13 </body> 14 </html>
模式二(生成直接支付url,支付url有效期爲2小時)
1 @{ 2 Layout = null; 3 } 4 <!DOCTYPE html> 5 <html> 6 <head> 7 <meta name="viewport" content="width=device-width" /> 8 <title>首頁</title> 9 <link href="~/Scripts/jquery-easyui-1.4.5/themes/bootstrap/easyui.css" rel="stylesheet" /> 10 <link href="~/Scripts/jquery-easyui-1.4.5/themes/mobile.css" rel="stylesheet" /> 11 <link href="~/Scripts/jquery-easyui-1.4.5/themes/icon.css" rel="stylesheet" /> 12 </head> 13 <body> 14 <p> 15 模式一:生成掃描支付模式 16 <br /> 17 <div id="QRCode1"> 18 </div> 19 </p> 20 <p> 21 模式二:生成直接支付url,支付url有效期爲2小時 22 <br /> 23 <div id="QRCode2"> 24 </div> 25 </p> 26 <script src="~/Scripts/jquery-1.10.2.js"></script> 27 <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.min.js"></script> 28 <script src="~/Scripts/jquery-easyui-1.4.5/jquery.easyui.mobile.js"></script> 29 <script src="~/Scripts/jquery-easyui-1.4.5/easyloader.js"></script> 30 <script src="~/Scripts/jquery.qrcode.min.js"></script> 31 <script type="text/javascript"> 32 $(function () { 33 fGetQRCode1(); 34 }) 35 function fGetQRCode1() { 36 $.messager.progress({ 37 title: "", 38 msg: "正在生成二維碼:模式一,請稍後..." 39 }); 40 $.ajax({ 41 type: "post", 42 url: "/Home/GetQRCode1", 43 data: { 44 time: new Date(), 45 productId:7788 46 }, 47 success: function (json) { 48 $.messager.progress('close');//記得關閉 49 if (json.result) { 50 $('#QRCode1').qrcode(json.str); //生成二維碼 51 } 52 else { 53 $('#QRCode1').html("二維碼生成失敗"); 54 } 55 fGetQRCode2(); 56 }, 57 error: function (json) { 58 $('#QRCode1').html("二維碼生成失敗"); 59 fGetQRCode2(); 60 } 61 }) 62 } 63 function fGetQRCode2() { 64 $.messager.progress({ 65 title: "", 66 msg: "正在生成二維碼:模式二,請稍後..." 67 }); 68 $.ajax({ 69 type: "post", 70 url: "/Home/GetQRCode2", 71 data: { 72 time: new Date(), 73 productId: 7788 74 }, 75 success: function (json) { 76 $.messager.progress('close');//記得關閉 77 if (json.result) { 78 $('#QRCode2').qrcode(json.str); //生成二維碼 79 } 80 else { 81 $('#QRCode2').html("二維碼生成失敗"); 82 } 83 }, 84 error: function (json) { 85 $('#QRCode2').html("二維碼生成失敗"); 86 } 87 }) 88 } 89 </script> 90 </body> 91 </html>
後端:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.Mvc; 6 using WxPayAPI; 7 namespace WxPay.Controllers 8 { 9 public class HomeController : Controller 10 { 11 // GET: Home 12 public ActionResult Index() 13 { 14 return View(); 15 } 16 /// <summary> 17 /// 模式一 18 /// </summary> 19 /// <returns></returns> 20 [HttpPost] 21 public ActionResult GetQRCode1() 22 { 23 object objResult = ""; 24 string strProductID = Request.Form["productId"]; 25 string strQRCodeStr = GetPrePayUrl(strProductID); 26 if (!string.IsNullOrWhiteSpace(strProductID)) 27 { 28 objResult = new { result = true, str = strQRCodeStr }; 29 } 30 else 31 { 32 objResult = new { result = false }; 33 } 34 return Json(objResult); 35 } 36 /// <summary> 37 /// 模式二 38 /// </summary> 39 /// <returns></returns> 40 [HttpPost] 41 public ActionResult GetQRCode2() 42 { 43 object objResult = ""; 44 string strProductID = Request.Form["productId"]; 45 string strQRCodeStr = GetPayUrl(strProductID); 46 if (!string.IsNullOrWhiteSpace(strProductID)) 47 { 48 objResult = new { result = true, str = strQRCodeStr }; 49 } 50 else 51 { 52 objResult = new { result = false }; 53 } 54 return Json(objResult); 55 } 56 /** 57 * 生成掃描支付模式一URL 58 * @param productId 商品ID 59 * @return 模式一URL 60 */ 61 public string GetPrePayUrl(string productId) 62 { 63 WxPayData data = new WxPayData(); 64 data.SetValue("appid", WxPayConfig.APPID);//公衆賬號id 65 data.SetValue("mch_id", WxPayConfig.MCHID);//商戶號 66 data.SetValue("time_stamp", WxPayApi.GenerateTimeStamp());//時間戳 67 data.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//隨機字符串 68 data.SetValue("product_id", productId);//商品ID 69 data.SetValue("sign", data.MakeSign());//簽名 70 string str = ToUrlParams(data.GetValues());//轉換爲URL串 71 string url = "weixin://wxpay/bizpayurl?" + str; 72 return url; 73 } 74 /** 75 * 參數數組轉換爲url格式 76 * @param map 參數名與參數值的映射表 77 * @return URL字符串 78 */ 79 private string ToUrlParams(SortedDictionary<string, object> map) 80 { 81 string buff = ""; 82 foreach (KeyValuePair<string, object> pair in map) 83 { 84 buff += pair.Key + "=" + pair.Value + "&"; 85 } 86 buff = buff.Trim('&'); 87 return buff; 88 } 89 /** 90 * 生成直接支付url,支付url有效期爲2小時,模式二 91 * @param productId 商品ID 92 * @return 模式二URL 93 */ 94 public string GetPayUrl(string productId) 95 { 96 WxPayData data = new WxPayData(); 97 data.SetValue("body", "廣東XXXX股份有限公司");//商品描述 98 data.SetValue("attach", "附加信息,用於後臺或者存入數據庫,作本身的判斷");//附加數據 99 data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//隨機字符串 100 data.SetValue("total_fee", 1);//總金額 101 data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始時間 102 data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易結束時間 103 data.SetValue("goods_tag", "商品的備忘,能夠自定義");//商品標記 104 data.SetValue("trade_type", "NATIVE");//交易類型 105 data.SetValue("product_id", productId);//商品ID 106 WxPayData result = WxPayApi.UnifiedOrder(data);//調用統一下單接口 107 string url = result.GetValue("code_url").ToString();//得到統一下單接口返回的二維碼連接 108 109 return url; 110 } 111 } 112 }
因爲模式二是沒有支付結果回調的,因此,咱們要查詢支付成功與否,須要本身寫方法來查詢,官方提供的查詢支付成功與否的方法有如下,
1 /*** 2 * 訂單查詢完整業務流程邏輯 3 * @param transaction_id 微信訂單號(優先使用) 4 * @param out_trade_no 商戶訂單號 5 * @return 訂單查詢結果(xml格式) 6 */ 7 public static string Run(string transaction_id, string out_trade_no) 8 { 9 Log.Info("OrderQuery", "OrderQuery is processing..."); 10 WxPayData data = new WxPayData(); 11 if(!string.IsNullOrEmpty(transaction_id))//若是微信訂單號存在,則以微信訂單號爲準 12 { 13 data.SetValue("transaction_id", transaction_id); 14 } 15 else//微信訂單號不存在,才根據商戶訂單號去查單 16 { 17 data.SetValue("out_trade_no", out_trade_no); 18 } 19 WxPayData result = WxPayApi.OrderQuery(data);//提交訂單查詢請求給API,接收返回數據 20 Log.Info("OrderQuery", "OrderQuery process complete, result : " + result.ToXml()); 21 return result.ToPrintStr(); 22 }
out_trade_no 是一個隨機字符串,咱們能夠把這個字符串記錄好,放數據庫仍是放哪裏,你本身喜歡,而後寫一個ajsx長輪詢來,定時查詢這個商戶訂單號,看看有沒有支付成功,來作支付確認。