.NET微信掃碼支付接入(模式二-NATIVE)
一、前言
經(jīng)過兩三天的琢磨總算完成了微信掃碼支付功能,不得不感嘆幾句:
微信提供的DEMO不錯(cuò),直接復(fù)制粘貼就可以跑起來了;
微信的配置平臺(tái)我真是服了。公眾平臺(tái)、商戶平臺(tái)、開放平臺(tái),一個(gè)平臺(tái)一套賬戶密碼,大寫的惡心
DEMO地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1
.NET版DEMO中的Lib文件夾是關(guān)鍵,直接復(fù)制到自己的代碼里,或者打成dll隨個(gè)人意愿。
二、正文
Step1:肯定是產(chǎn)生商戶訂單號(hào),然后傳給微信后臺(tái),由微信去組成二維碼字符串,然后返給你,你再把字符串做成圖片;
/// <summary> /// 獲取二維碼 /// </summary> /// <param name="orderNumber"></param> /// <returns></returns> public string GetCodeUrl(string orderNumber) { var result = string.Empty; if (!string.IsNullOrEmpty(orderNumber)) { var matchedItem = db.OrderInfoForProducts.FirstOrDefault(x => x.OrderNumber == orderNumber); if (matchedItem != null && matchedItem.IsPaid == false) { WxPayData data = new WxPayData(); data.SetValue("body", "productBody");//商品描述 data.SetValue("attach", "attach data");//附加數(shù)據(jù) data.SetValue("out_trade_no", WxPayApi.GenerateOutTradeNo());//隨機(jī)字符串 data.SetValue("total_fee", price);//總金額 data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始時(shí)間 data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易結(jié)束時(shí)間 data.SetValue("goods_tag", "tag");//商品標(biāo)記 data.SetValue("trade_type", "NATIVE");//交易類型 data.SetValue("product_id", WxPayApi.GenerateOutTradeNo());//商品ID result = WxPayApi.UnifiedOrder(data).GetValue("code_url").ToString();//調(diào)用統(tǒng)一下單接口 } } return result; }
在這里,我是把公司的商戶訂單號(hào)放在了attach字段上,因?yàn)楣镜纳虘粲唵翁?hào)比較長(zhǎng),超過了32位。out_trade_no與product_id字段最多32位,請(qǐng)慎重!
微信中的價(jià)格不能帶小數(shù),所以0.01元要寫成100。
Step2: 成功返回二維碼字符串之后就可以在生成圖片了,我這邊使用了ThoughtWorks.QRCode.dll來生成圖片:
/// <summary> /// 根據(jù)字符串得到相應(yīng)的二維碼 /// </summary> /// <param name="qrInfo"></param> /// <param name="productName"></param> /// <param name="version"></param> /// <returns></returns> public static Image CreateQRCodeImage(string qrInfo, string productName, string version) { try { if (!string.IsNullOrEmpty(qrInfo)) { QRCodeEncoder encoder = new QRCodeEncoder { QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE, QRCodeScale = 4, QRCodeVersion = 0, QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M }; //編碼方式(注意:BYTE能支持中文,ALPHA_NUMERIC掃描出來的都是數(shù)字) //大小(值越大生成的二維碼圖片像素越高) //版本(注意:設(shè)置為0主要是防止編碼的字符串太長(zhǎng)時(shí)發(fā)生錯(cuò)誤) //錯(cuò)誤效驗(yàn)、錯(cuò)誤更正(有4個(gè)等級(jí)) Image image = encoder.Encode(qrInfo, Encoding.GetEncoding("utf-8")); string filename = $"{productName}_{version}.png"; var userLocalPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var docPath = Path.Combine(userLocalPath, @"Your Product\QRCode"); if (!Directory.Exists(docPath)) { Directory.CreateDirectory(docPath); } string filepath = Path.Combine(docPath, filename); using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write)) { image.Save(fs, System.Drawing.Imaging.ImageFormat.Png); fs.Close(); image.Dispose(); } return image; } } catch (Exception) { return null; } return null; }
Step3: 當(dāng)用戶掃完二維碼之后,微信會(huì)發(fā)起回調(diào),這時(shí)候我們就可以處理自己的業(yè)務(wù)邏輯了。這里我的UpdatePayStatus返回的是一個(gè)空頁(yè)面
/// <summary> /// 回調(diào)函數(shù) /// </summary> public ActionResult UpdatePayStatus() { //接收從微信后臺(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(); //轉(zhuǎn)換數(shù)據(jù)格式并驗(yàn)證簽名 WxPayData data = new WxPayData(); try { data.FromXml(builder.ToString()); } catch (WxPayException ex) { //若簽名錯(cuò)誤,則立即返回結(jié)果給微信支付后臺(tái) WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", ex.Message); LogEntity signErrorLog = new LogEntity(); signErrorLog.errorMessage = ex.Message; LogHelper.WriteLog(signErrorLog, null); Response.Write(res.ToXml()); Response.End(); } ProcessNotify(data); return View(); } /// <summary> /// 處理回調(diào)數(shù)據(jù) /// </summary> /// <param name="data"></param> public void ProcessNotify(WxPayData data) { WxPayData notifyData = data; //檢查支付結(jié)果中transaction_id是否存在 if (!notifyData.IsSet("transaction_id")) { //若transaction_id不存在,則立即返回結(jié)果給微信支付后臺(tái) WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "支付結(jié)果中微信訂單號(hào)不存在"); LogEntity orderLog = new LogEntity(); orderLog.errorMessage = "支付結(jié)果中微信訂單號(hào)不存在"; LogHelper.WriteLog(orderLog, null); Response.Write(res.ToXml()); Response.End(); } string transaction_id = notifyData.GetValue("transaction_id").ToString(); //查詢訂單,判斷訂單真實(shí)性 if (!QueryOrder(transaction_id)) { //若訂單查詢失敗,則立即返回結(jié)果給微信支付后臺(tái) WxPayData res = new WxPayData(); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "訂單查詢失敗"); LogEntity orderqueryLog = new LogEntity(); orderqueryLog.errorMessage = "訂單查詢失敗"; LogHelper.WriteLog(orderqueryLog, null); Response.Write(res.ToXml()); Response.End(); } //查詢訂單成功 else { WxPayData res = new WxPayData(); res.SetValue("return_code", "SUCCESS"); res.SetValue("return_msg", "OK"); SetPaymentResult(data); //這里的參數(shù)是 data !?。?不是 res ?。。? Response.Write(res.ToXml()); Response.End(); } } /// <summary> /// 商戶后臺(tái)更新 /// </summary> /// <param name="res"></param> private void SetPaymentResult(WxPayData res) { var isSucessFlagOne = res.GetValue("return_code").ToString(); var isSuccessFlagTwo = res.GetValue("result_code").ToString(); if (isSucessFlagOne == "SUCCESS" && isSuccessFlagTwo == "SUCCESS") { //自己的業(yè)務(wù)邏輯 ?。。?! } } //查詢訂單 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; } }
三、結(jié)尾
做完支付寶與微信掃碼支付發(fā)現(xiàn)支付寶的接入要比微信方便很多,還有一個(gè)同步請(qǐng)求。而且吐槽個(gè)其它的,微信開放平臺(tái)的審批速度要比支付寶的審批慢很多。還有微信支付最后上線前不需要非得用沙箱測(cè)試,做完之后直接一分錢一分錢測(cè)試即可。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MS SQL 實(shí)現(xiàn)驗(yàn)證字符串是否包含有大小寫字母的功能
這篇文章主要介紹了MS SQL 實(shí)現(xiàn)驗(yàn)證字符串是否包含有大小寫字母的功能的相關(guān)資料,這樣的功能通常應(yīng)用在字符串的復(fù)雜度需要的朋友可以參考下2016-11-11編寫的vs2005水晶報(bào)表程序在vs2008下正常使用的一些實(shí)現(xiàn)方法
以前用vs2005編寫的WEB程序,現(xiàn)在使用vs2008時(shí)總是出現(xiàn)水晶報(bào)表的錯(cuò)誤,不能使用。經(jīng)過本人實(shí)踐,總結(jié)一下錯(cuò)誤原因。2009-09-09使用jQuery Uploader顯示文件上傳進(jìn)度
在上傳大文件的時(shí)候, 我們都希望可以向用戶顯示上傳的進(jìn)度, 那么這里介紹的就是使用 jQuery Uploader 來實(shí)現(xiàn)這樣的效果2011-12-12DataList 中動(dòng)態(tài)綁定服務(wù)器子控件的代碼
DataList 中動(dòng)態(tài)綁定服務(wù)器子控件的代碼...2007-09-09MVC使用T4模板生成其他類的具體實(shí)現(xiàn)學(xué)習(xí)筆記2
這篇文章主要為大家詳細(xì)介紹了MVC使用T4模板生成其他類的具體實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09asp.net datalist綁定數(shù)據(jù)后可以上移下移實(shí)現(xiàn)示例
這篇文章主要介紹了asp.net datalist綁定數(shù)據(jù)后可以上移下移的示例代碼,需要的朋友可以參考下2014-02-02.Net Core使用OpenXML導(dǎo)出、導(dǎo)入Excel
這篇文章主要為大家詳細(xì)介紹了.Net Core使用OpenXML導(dǎo)出、導(dǎo)入Excel的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04基于.NET中建構(gòu)子中傳遞子對(duì)象的對(duì)象詳解
本篇文章介紹了,基于.NET中建構(gòu)子中傳遞子對(duì)象的對(duì)象詳解。需要的朋友參考下2013-05-05aspx文件格式使用URLRewriter實(shí)現(xiàn)靜態(tài)化變成html
如何隱藏aspx文件格式,變成html,使用asp.net 開發(fā)的網(wǎng)頁(yè)程序,使用URLRewriter.dll 實(shí)現(xiàn)靜態(tài)化,接下來將介紹下具體操作步驟,感興趣的朋友可以參考下2013-04-04