日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

C# 微信支付教程系列之扫码支付

發(fā)布時間:2024/8/26 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 C# 微信支付教程系列之扫码支付 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

微信支付教程系列之掃碼支付



今天,我們來一起探討一下這個微信掃碼支付。何為掃碼支付呢?這里面,掃的碼就是二維碼了,就是我們經(jīng)常掃一掃的那種二維碼圖片,例如,我們自己添加好友的時候,可以通過輸入對方的微信號,也可以掃一掃對方的二維碼。掃碼支付,作為,微信支付里面,不可或缺的一個功能,對商品的支付提供了極為方便的體驗,用途也非常的多。例如我們在地鐵、公交站常見的那些自動售貨機(jī)(不錯,就是那種投硬幣,就可以自動出貨的那種機(jī)器)中都用到。以前,那種機(jī)器,只能通過投硬幣或者紙幣,但是,這里面也有一定的風(fēng)險,例如:假幣,盜竊(真有人把機(jī)器砸了,把機(jī)器里面的錢偷走的),所以,微信(支付寶)的掃碼支付的出現(xiàn),大大的減少了這方面的風(fēng)險,近些年來,二維碼的應(yīng)用越來越廣,甚至有些地方,直接用來自動售票(就是把起始點設(shè)定好,票價設(shè)定好,直接把二維碼貼出來,讓乘客自動掃相關(guān)的二維碼,完成購票,上車的時候,只需要提供自己的支付憑證給乘車員驗證即可),這樣,不僅綠色環(huán)保了,還大大的提高了售票的速度(去過大車站購票的人應(yīng)該深有體驗,排隊買個票,好歹半個小時以上,心里也是萬頭草泥馬在奔騰的)。

咱就不扯遠(yuǎn)了,說回咱么今天要做的微信支付之掃碼支付。微信官方的文檔,這個掃碼支付(NativePay)分為兩種,一種是“生成掃描支付模式”,另外一種是“生成直接支付url,支付url有效期為2小時”,至于這里面,兩種掃碼模式,怎么靈活利用呢,官方也沒有一個明確的說明。個人理解為,第一種(生成掃描支付模式),適用于固定二維碼的,就是永久使用的那種,例如一些商家的公眾號的二維碼,是永久的,什么時候掃,都是關(guān)注這個公眾號的,但是,這種的話,我記得微信是有限量的,貌似是一個公眾號,限量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,代碼如下:

1  // GET: Home
2         public ActionResult Index()
3         {
4             return View();
5         } 

再添加一個View,代碼如下:

 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的一些我們會用到的東西拷貝過來,其中包括以下幾個文件夾,如下圖:

就這個lib和business兩個,把這兩個文件夾,支付復(fù)制到咱們的新項目中,并且包含在項目中,如下:

然后我們再“重新生成”以下項目,或者快捷鍵:ctrl+shift+b,這時候,會提下如下錯誤:

這時候,我們?nèi)ヌ砑右茫?strong>lib文件夾中的LitJson.dll添加上即可,如下圖:

到這里,我們就基本把官方的demo的環(huán)境給搭建好了,接下來,我們就要開始編寫代碼了。

首先,我的邏輯是,從前到后,就是從前端到后端。前端是顯示二維碼的地方,那么我們就先給他一個div(本文使用到的是jquery的二維碼生成插件,全名叫:jquery.qrcode.min.js,我會傳到附件上),然后在頁面加載完畢的時候,會請求后臺,讓他返回二維碼字符串,然后再通過jquery的二維碼生成插件,讓他生成二維碼并顯示在前臺,代碼如下:

前端:

 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');//記得關(guān)閉
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>

后端:

 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());//隨機(jī)字符串
48             data.SetValue("product_id", productId);//商品ID
49             data.SetValue("sign", data.MakeSign());//簽名
50             string str = ToUrlParams(data.GetValues());//轉(zhuǎn)換為URL串
51             string url = "weixin://wxpay/bizpayurl?" + str;
52             return url;
53         }
54         /**
55        * 參數(shù)數(shù)組轉(zhuǎn)換為url格式
56        * @param map 參數(shù)名與參數(shù)值的映射表
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 }

這時候,模式一是不是感覺就完成了?那么我們現(xiàn)在試試,我們?yōu)g覽該頁面,如下:

然后用微信掃一掃功能掃一下,發(fā)現(xiàn)提示如下:


這是什么鬼,是不是,你心里面是不是想知道為啥,那我來告訴你,這是為啥,這是因為,你還沒有設(shè)置回調(diào)頁面或者回調(diào)頁面有問題,這個時候,我們再新建一個Control,命名為:NativeNotifyController.cs,代碼如下:

  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", "回調(diào)數(shù)據(jù)異常");
 28                 return res.ToXml();
 29             }
 30             //調(diào)統(tǒng)一下單接口,獲得下單結(jié)果
 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)//若在調(diào)統(tǒng)一下單接口時拋異常,立即返回結(jié)果給微信支付后臺
 39             {
 40                 WxPayData res = new WxPayData();
 41                 res.SetValue("return_code", "FAIL");
 42                 res.SetValue("return_msg", "統(tǒng)一下單失敗");
 43                 return res.ToXml();
 44             }
 45             //若下單失敗,則立即返回結(jié)果給微信支付后臺
 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", "統(tǒng)一下單失敗");
 51                 return res.ToXml();
 52             }
 53             //統(tǒng)一下單成功,則返回成功結(jié)果給微信支付后臺
 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         /// 接收從微信支付后臺發(fā)送過來的數(shù)據(jù)并驗證簽名
 68         /// </summary>
 69         /// <returns>微信支付后臺返回的數(shù)據(jù)</returns>
 70         public WxPayData GetNotifyData()
 71         {
 72             //接收從微信后臺POST過來的數(shù)據(jù)
 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             //轉(zhuǎn)換數(shù)據(jù)格式并驗證簽名
 85             WxPayData data = new WxPayData();
 86             try
 87             {
 88                 data.FromXml(builder.ToString());
 89             }
 90             catch (WxPayException ex)
 91             {
 92                 //若簽名錯誤,則立即返回結(jié)果給微信支付后臺
 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             //統(tǒng)一下單
102             WxPayData req = new WxPayData();
103             req.SetValue("body", "廣東XXXX股份有限公司");
104             req.SetValue("attach", "附加信息,用于后臺或者存入數(shù)據(jù)庫,做自己的判斷");
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的代碼如下(你沒眼花,就是空的,不管他):

 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>

接著,把這個項目,發(fā)布出來,放到服務(wù)器的iis上,這里面,我把他發(fā)布在http://sm.lmx.ren/上面(必須要發(fā)布到網(wǎng)上哈,如果不懂發(fā)布的,你可以自己去學(xué)習(xí)基礎(chǔ)知識先了),這還沒完,還需要把到公眾平臺上,設(shè)置回調(diào)頁面,操作如下:




這樣,就大功告成了。這時候,我們再試試掃碼,發(fā)現(xiàn)已經(jīng)得到以下提示了,這樣子,就代表,我們的模式一,已經(jīng)成功完成了。如下圖:



這時候,細(xì)心的朋友就會提問了,我這都支付成功了,怎么頁面沒啥提示呀,這頁面不交互很不友好啊。嗯,沒錯,童鞋,你有前途,現(xiàn)在我就告訴你,怎么做交互,但是,為了你日后更加有前途,我只告訴你邏輯,具體怎么實現(xiàn),自己來想,多動腦。

那么邏輯是怎么的呢?常規(guī)邏輯下,我們微信掃頁面上的這個二維碼的時候,這個時候,他已經(jīng)把我們二維碼里面的參數(shù),傳到微信服務(wù)器,然后有他們開始統(tǒng)一下單(如果對邏輯不清晰,可以看看官方的文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_3):他們在統(tǒng)一下單的時候,就會生成一個product_id,這個家伙的作用呢 ,就是告訴你現(xiàn)在微信服務(wù)器,已經(jīng)生成了一個單號,勞資已經(jīng)收到你的支付請求了,趕緊給老子付款,O(∩_∩)O哈哈~。。。停,停,停。這時候,思路不能繼續(xù)往下走了。記得,前面有個叫做“統(tǒng)一下單“,那既然有這個步驟,那我們可以利用一下,就是當(dāng)他統(tǒng)一下單成功的時候,我們可以在頁面更新一下狀態(tài),告訴客戶:您已成功掃描,并下單成功,請支付。是不是,我們可以提示他們這個。然后等用戶在手機(jī)上,支付成功的時候,這個時候,頁面是不是也要反饋給用戶,告訴他,小子,你的錢已經(jīng)到我的口袋了,你可以走了(你走,我沒有你這樣的寶寶)。O(∩_∩)O哈哈~,但是,你還要停,停住,停下來。我們服務(wù)公司怎么知道這個微信用戶已經(jīng)付款成功了呢?來,我們把視線回到代碼上,找到lib/Config.cs,如下圖:



然后打開config.cs,找到以下代碼:


對了,你很聰明。微信的處理邏輯就是,等用戶支付成功之后,他會給這個鏈接發(fā)送支付結(jié)果,默認(rèn)是以前那個aspx的頁面,現(xiàn)在我換成mvc,所以,我們得手動新建一個control了,命名為:ResultNotifyController,然后代碼如下:

  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             //檢查支付結(jié)果中transaction_id是否存在
 24             if (!notifyData.IsSet("transaction_id"))
 25             {
 26                 //若transaction_id不存在,則立即返回結(jié)果給微信支付后臺
 27                 WxPayData res = new WxPayData();
 28                 res.SetValue("return_code", "FAIL");
 29                 res.SetValue("return_msg", "支付結(jié)果中微信訂單號不存在");
 30                 return res.ToXml();
 31             }
 32             string transaction_id = notifyData.GetValue("transaction_id").ToString();
 33             //查詢訂單,判斷訂單真實性
 34             if (!QueryOrder(transaction_id))
 35             {
 36                 //若訂單查詢失敗,則立即返回結(jié)果給微信支付后臺
 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();//如果我們走到這一步了,那就代表,用戶已經(jīng)支付成功了,所以,該干嘛干嘛了。
 52             }
 53         }
 54         /// <summary>
 55         /// 接收從微信支付后臺發(fā)送過來的數(shù)據(jù)并驗證簽名
 56         /// </summary>
 57         /// <returns>微信支付后臺返回的數(shù)據(jù)</returns>
 58         public WxPayData GetNotifyData()
 59         {
 60             //接收從微信后臺POST過來的數(shù)據(jù)
 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             //轉(zhuǎn)換數(shù)據(jù)格式并驗證簽名
 74             WxPayData data = new WxPayData();
 75             try
 76             {
 77                 data.FromXml(builder.ToString());
 78             }
 79             catch (WxPayException ex)
 80             {
 81                 //若簽名錯誤,則立即返回結(jié)果給微信支付后臺
 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,代碼如下(沒錯,也是空的)

 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小時


由于有了上面模式一的詳細(xì)說明,模式二,我就簡單一點的來說了,如果又不懂的,到群里來問我吧。

模式二,前端,增加一些代碼,如下(完整的,包括模式一的代碼了):

 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');//記得關(guān)閉
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');//記得關(guān)閉
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());//隨機(jī)字符串
 68             data.SetValue("product_id", productId);//商品ID
 69             data.SetValue("sign", data.MakeSign());//簽名
 70             string str = ToUrlParams(data.GetValues());//轉(zhuǎn)換為URL串
 71             string url = "weixin://wxpay/bizpayurl?" + str;
 72             return url;
 73         }
 74         /**
 75        * 參數(shù)數(shù)組轉(zhuǎn)換為url格式
 76        * @param map 參數(shù)名與參數(shù)值的映射表
 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", "附加信息,用于后臺或者存入數(shù)據(jù)庫,做自己的判斷");//附加數(shù)據(jù)
 99             data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//隨機(jī)字符串
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"));//交易結(jié)束時間
103             data.SetValue("goods_tag", "商品的備忘,可以自定義");//商品標(biāo)記
104             data.SetValue("trade_type", "NATIVE");//交易類型
105             data.SetValue("product_id", productId);//商品ID
106             WxPayData result = WxPayApi.UnifiedOrder(data);//調(diào)用統(tǒng)一下單接口
107             string url = result.GetValue("code_url").ToString();//獲得統(tǒng)一下單接口返回的二維碼鏈接
108             
109             return url;
110         }
111     }
112 }

由于模式二是沒有支付結(jié)果回調(diào)的,所以,我們要查詢支付成功與否,需要自己寫方法來查詢,官方提供的查詢支付成功與否的方法有以下,

 1 /***
 2         * 訂單查詢完整業(yè)務(wù)流程邏輯
 3         * @param transaction_id 微信訂單號(優(yōu)先使用)
 4         * @param out_trade_no 商戶訂單號
 5         * @return 訂單查詢結(jié)果(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))//如果微信訂單號存在,則以微信訂單號為準(zhǔn)
12             {
13                 data.SetValue("transaction_id", transaction_id);
14             }
15             else//微信訂單號不存在,才根據(jù)商戶訂單號去查單
16             {
17                 data.SetValue("out_trade_no", out_trade_no);
18             }
19             WxPayData result = WxPayApi.OrderQuery(data);//提交訂單查詢請求給API,接收返回數(shù)據(jù)
20             Log.Info("OrderQuery", "OrderQuery process complete, result : " + result.ToXml());
21             return result.ToPrintStr();
22         }

可以通過這個微信訂單號(transaction_id)來查詢,也可以通過商戶訂單號(out_trade_no),所以,我們要合理利用這里面的技巧,上述模式二,我用的

out_trade_no 是一個隨機(jī)字符串,我們可以把這個字符串記錄好,放數(shù)據(jù)庫還是放哪里,你自己喜歡,然后寫一個ajsx長輪詢來,定時查詢這個商戶訂單號,看看有沒有支付成功,來做支付確認(rèn)。

總結(jié)

以上是生活随笔為你收集整理的C# 微信支付教程系列之扫码支付的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。