c#版在pc端發(fā)起微信掃碼支付的實(shí)例
等了好久,微信官方終于發(fā)布了.net的demo。
主要代碼:
/** * 生成直接支付url,支付url有效期為2小時(shí),模式二 * @param productId 商品ID * @return 模式二URL */ public string GetPayUrl(string productId, string body, string attach, int total_fee, string goods_tag) { Log.Info(this.GetType().ToString(), "Native pay mode 2 url is producing..."); WxPayData data = new WxPayData(); data.SetValue("body", body);//商品描述 data.SetValue("attach", attach);//附加數(shù)據(jù) data.SetValue("out_trade_no", productId);//隨機(jī)字符串 data.SetValue("total_fee", total_fee);//總金額 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", goods_tag);//商品標(biāo)記 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)一下單接口返回的二維碼鏈接 Log.Info(this.GetType().ToString(), "Get native pay mode 2 url : " + url); return url; }
配置信息:
public class Config { //=======【基本信息設(shè)置】===================================== /* 微信公眾號(hào)信息配置 * APPID:綁定支付的APPID(必須配置) * MCHID:商戶號(hào)(必須配置) * KEY:商戶支付密鑰,參考開戶郵件設(shè)置(必須配置) * APPSECRET:公眾帳號(hào)secert(僅JSAPI支付的時(shí)候需要配置) */ public const string APPID = "你的微信公眾號(hào)APPID"; public const string MCHID = "你的微信公眾號(hào)的商戶號(hào)"; public const string KEY = "你的微信公眾號(hào)的商戶支付密鑰"; public const string APPSECRET = "你的微信公眾號(hào)的APPSECRET"; //=======【證書路徑設(shè)置】===================================== /* 證書路徑,注意應(yīng)該填寫絕對(duì)路徑(僅退款、撤銷訂單時(shí)需要) */ public const string SSLCERT_PATH = "cert/apiclient_cert.p12"; public const string SSLCERT_PASSWORD = "1233410002"; //=======【支付結(jié)果通知url】===================================== /* 支付結(jié)果通知回調(diào)url,用于商戶接收支付結(jié)果 */ public const string NOTIFY_URL = "http://你的網(wǎng)站/Pay/ResultNotifyPage.aspx"; //=======【商戶系統(tǒng)后臺(tái)機(jī)器IP】===================================== /* 此參數(shù)可手動(dòng)配置也可在程序中自動(dòng)獲取 */ public const string IP = "你的服務(wù)器IP"; //=======【代理服務(wù)器設(shè)置】=================================== /* 默認(rèn)IP和端口號(hào)分別為0.0.0.0和0,此時(shí)不開啟代理(如有需要才設(shè)置) */ public const string PROXY_URL = ""; //=======【上報(bào)信息配置】=================================== /* 測速上報(bào)等級(jí),0.關(guān)閉上報(bào); 1.僅錯(cuò)誤時(shí)上報(bào); 2.全量上報(bào) */ public const int REPORT_LEVENL = 1; //=======【日志級(jí)別】=================================== /* 日志等級(jí),0.不輸出日志;1.只輸出錯(cuò)誤信息; 2.輸出錯(cuò)誤和正常信息; 3.輸出錯(cuò)誤信息、正常信息和調(diào)試信息 */ public const int LOG_LEVENL = 0; }
不使用代理要注釋HttpService.cs里面post和get方法的下面代碼:
//設(shè)置代理服務(wù)器 //WebProxy proxy = new WebProxy(); //定義一個(gè)網(wǎng)關(guān)對(duì)象 //proxy.Address = new Uri(Config.PROXY_URL); //網(wǎng)關(guān)服務(wù)器端口:端口 //request.Proxy = proxy;
統(tǒng)一下單:
/** * * 統(tǒng)一下單 * @param WxPaydata inputObj 提交給統(tǒng)一下單API的參數(shù) * @param int timeOut 超時(shí)時(shí)間 * @throws WxPayException * @return 成功時(shí)返回,其他拋異常 */ public static WxPayData UnifiedOrder(WxPayData inputObj, int timeOut = 6) { string url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //檢測必填參數(shù) if (!inputObj.IsSet("out_trade_no")) { throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)out_trade_no!"); } else if (!inputObj.IsSet("body")) { throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)body!"); } else if (!inputObj.IsSet("total_fee")) { throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)total_fee!"); } else if (!inputObj.IsSet("trade_type")) { throw new WxPayException("缺少統(tǒng)一支付接口必填參數(shù)trade_type!"); } //關(guān)聯(lián)參數(shù) if (inputObj.GetValue("trade_type").ToString() == "JSAPI" && !inputObj.IsSet("openid")) { throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)openid!trade_type為JSAPI時(shí),openid為必填參數(shù)!"); } if (inputObj.GetValue("trade_type").ToString() == "NATIVE" && !inputObj.IsSet("product_id")) { throw new WxPayException("統(tǒng)一支付接口中,缺少必填參數(shù)product_id!trade_type為JSAPI時(shí),product_id為必填參數(shù)!"); } //異步通知url未設(shè)置,則使用配置文件中的url if (!inputObj.IsSet("notify_url")) { inputObj.SetValue("notify_url", Config.NOTIFY_URL);//異步通知url } inputObj.SetValue("appid", Config.APPID);//公眾賬號(hào)ID inputObj.SetValue("mch_id", Config.MCHID);//商戶號(hào) inputObj.SetValue("spbill_create_ip", Config.IP);//終端ip inputObj.SetValue("nonce_str", GenerateNonceStr());//隨機(jī)字符串 //簽名 inputObj.SetValue("sign", inputObj.MakeSign()); string xml = inputObj.ToXml(); var start = DateTime.Now; Log.Debug("WxPayApi", "UnfiedOrder request : " + xml); string response = HttpService.Post(xml, url, false, timeOut); Log.Debug("WxPayApi", "UnfiedOrder response : " + response); var end = DateTime.Now; int timeCost = (int)((end - start).TotalMilliseconds); WxPayData result = new WxPayData(); result.FromXml(response); ReportCostTime(url, timeCost, result);//測速上報(bào) return result; }
看我的調(diào)用例子:
MakeQRCode.aspx頁面照抄:
public partial class Pay_MakeQRCode : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!string.IsNullOrEmpty(base.Request.QueryString["data"])) { string str = base.Request.QueryString["data"]; Bitmap image = new QRCodeEncoder { QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE, QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M, QRCodeVersion = 0, QRCodeScale = 4 }.Encode(str, Encoding.Default); MemoryStream ms = new MemoryStream(); image.Save(ms, ImageFormat.Png); base.Response.BinaryWrite(ms.GetBuffer()); base.Response.End(); } } }
這個(gè)頁面是用來生成二維碼的,需要引入ThoughtWorks.QRCode.dll組件。
我使用模式二,回調(diào)頁面是ResultNotifyPage.aspx,就是在配置信息那里填寫的那個(gè)回調(diào)頁面。
protected void Page_Load(object sender, EventArgs e) { ResultNotify resultNotify = new ResultNotify(this); WxPayData res = resultNotify.ProcessNotify2(); if (res.GetValue("return_code") == "SUCCESS") { //查詢微信訂單信息 string paySignKey = ConfigurationManager.AppSettings["paySignKey"].ToString(); string mch_id = ConfigurationManager.AppSettings["mch_id"].ToString(); string appId = ConfigurationManager.AppSettings["AppId"].ToString(); QueryOrder queryorder = new QueryOrder(); queryorder.appid = appId; queryorder.mch_id = mch_id; queryorder.transaction_id = res.GetValue("transaction_id").ToString(); queryorder.out_trade_no = ""; queryorder.nonce_str = TenpayUtil.getNoncestr(); TenpayUtil tenpay = new TenpayUtil(); OrderDetail orderdeatil = tenpay.getOrderDetail(queryorder, paySignKey); //寫微信記錄 (new vinson()).WriteReturnWXDetail(orderdeatil); //寫充值記錄 FilliedOnline(orderdeatil.out_trade_no); } Response.Write(res.ToXml()); Response.End(); }
掃碼支付成功后會(huì)異步到這個(gè)頁面執(zhí)行代碼,我們自己的業(yè)務(wù)邏輯就要寫在這里。使用微信官方的ProcessNotify()函數(shù)可不行,我們稍微修改下就好了。增加ProcessNotify2函數(shù):
public WxPayData ProcessNotify2() { WxPayData notifyData = GetNotifyData(); //檢查支付結(jié)果中transaction_id是否存在 if (!notifyData.IsSet("transaction_id")) { //若transaction_id不存在,則立即返回結(jié)果給微信支付后臺(tái) WxPayData res = new WxPayData(); res.SetValue("transaction_id", ""); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "支付結(jié)果中微信訂單號(hào)不存在"); return res; } string transaction_id = notifyData.GetValue("transaction_id").ToString(); //查詢訂單,判斷訂單真實(shí)性 if (!QueryOrder(transaction_id)) { //若訂單查詢失敗,則立即返回結(jié)果給微信支付后臺(tái) WxPayData res = new WxPayData(); res.SetValue("transaction_id", transaction_id); res.SetValue("return_code", "FAIL"); res.SetValue("return_msg", "訂單查詢失敗"); return res; } //查詢訂單成功 else { WxPayData res = new WxPayData(); res.SetValue("transaction_id", transaction_id); res.SetValue("return_code", "SUCCESS"); res.SetValue("return_msg", "OK"); return res; } }
返回WxPayData對(duì)象,這樣一判斷
if (res.GetValue("return_code") == "SUCCESS")
表示支付成功,就可以進(jìn)入我們的業(yè)務(wù)邏輯。
然后我們還要對(duì)當(dāng)前訂單查單,獲取訂單的相關(guān)信息,之前微信未出demo的時(shí)候我自己寫了個(gè)查單的,就直接用了,關(guān)鍵WxPayData對(duì)象會(huì)返回微信的訂單號(hào):res.GetValue("transaction_id").ToString()。
完事后還要發(fā)送信息回給微信,通知微信后臺(tái)不要繼續(xù)發(fā)送異步請(qǐng)求了:
Response.Write(res.ToXml()); Response.End();
這個(gè)代碼比較重要了。
再說說放置二維碼的頁面:
<div class="g-body"> <div class="g-wrap"> <div class="m-weixin"> <div class="m-weixin-header"> <p><strong>請(qǐng)您及時(shí)付款,以便訂單盡快處理!訂單號(hào):<asp:Label ID="trade_no" runat="server" Text="Label"></asp:Label></strong></p> <p>請(qǐng)您在提交訂單后1小時(shí)內(nèi)支付,否則訂單會(huì)自動(dòng)取消。</p> </div> <div class="m-weixin-main"> <h1 class="m-weixin-title"> <img alt="微信支付" src="../images/wxlogo_pay.png"/> </h1> <p class="m-weixin-money"><font>掃一掃付款</font><br/><strong>¥<asp:Label ID="money" runat="server" Text="Label"></asp:Label></strong></p> <p> <img id="payQRImg" width="260" height="260" class="m-weixin-code" style="position: absolute;" src="<%=ImageUrl %>" alt="二維碼" style="border-width:0px;" /> <img class="m-weixin-demo" src="../images/wxwebpay_guide.png" alt="掃一掃" /> <img style="margin-top:300px;" src="../images/weixin_1.png" alt="請(qǐng)使用微信掃描二維碼以完成支付" /> </p> <p id="we_ok" style="display:none;"> <input value="完成" style="width: 300px; height: 50px; background: rgb(21, 164, 21) none repeat scroll 0% 0%; color: white; font-size: 30px; border: medium none; cursor: pointer;" type="button" /> </p> </div> </div> </div> </div>
寫個(gè)js查單支付情況進(jìn)行顯示:
$(function () { var success = "<%=success %>"; if (success == "error") { $(".g-body").hide(); } }) var iCount = setInterval(check, 2000); //每隔2秒執(zhí)行一次check函數(shù)。 function check() { $.ajax({ contentType: "application/json", url: "/WebService/vinson.asmx/queryWeiXin", data: "{OrderID:'" + $("#trade_no").text() + "'}", type: "POST", dataType: "json", success: function (json) { json = eval("(" + json.d + ")"); if (json.success == "success") { clearInterval(iCount); $(".m-weixin-money font").html("已成功付款"); $("#payQRImg").remove(); $(".m-weixin-demo").before('<img alt="" src="../images/wx_ok.jpg" width="200">'); $(".m-weixin-demo").next().remove(); $("#we_ok").show(); } }, error: function (err, ex) { } }); }
是的,我又寫了個(gè)給ajax使用的查單函數(shù)queryWeiXin。
我這里才是生成訂單和二維碼:
恩,還有啥呢,恩,看看效果吧:
支付成功后:
原文鏈接:http://www.cnblogs.com/vinsonLu/p/5166214.html
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#控制臺(tái)程序輸出等腰三角形并居中顯示實(shí)例
這篇文章主要介紹了C#控制臺(tái)程序輸出等腰三角形并居中顯示實(shí)例,本文直接給出實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-03-03C#中控件動(dòng)態(tài)添加事件綁定的時(shí)機(jī)詳解
這篇文章主要給大家介紹了在C#中為控件動(dòng)態(tài)添加事件綁定的時(shí)機(jī)的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。2017-06-06C#中const,readonly和static關(guān)鍵字的用法介紹
這篇文章介紹了C#中const,readonly和static關(guān)鍵字的用法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08C#通過創(chuàng)建Windows服務(wù)啟動(dòng)程序的方法詳解
這篇文章主要介紹了C#通過創(chuàng)建Windows服務(wù)啟動(dòng)程序的方法,較為詳細(xì)的分析了C#創(chuàng)建Windows服務(wù)應(yīng)用程序的步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-06-06C#實(shí)現(xiàn)實(shí)體類和XML相互轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了C#實(shí)現(xiàn)實(shí)體類和XML相互轉(zhuǎn)換的資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03VS2010寫的程序在自己電腦可以運(yùn)行、其他電腦上不能運(yùn)行的解決方案
自己用Visual Studio 2010 旗艦版寫了一個(gè)軟件,在自己電腦上運(yùn)行完全沒有問題,但是拷貝到其他人電腦上之后不管雙擊還是以管理身份運(yùn)行,均沒有反應(yīng),進(jìn)程管理器中相關(guān)進(jìn)程也只是一閃而過2013-04-04采用C#代碼動(dòng)態(tài)設(shè)置文件權(quán)限
在開發(fā)中,我們經(jīng)常會(huì)使用IO操作,例如創(chuàng)建,刪除文件等操作。在項(xiàng)目中這樣的需求也較多,我們也會(huì)經(jīng)常對(duì)這些操作進(jìn)行編碼,但是對(duì)文件的權(quán)限進(jìn)行設(shè)置,這樣的操作可能會(huì)手動(dòng)操作,本文介紹一種采用代碼動(dòng)態(tài)對(duì)文件設(shè)置權(quán)限的操作。2016-12-12