直接上干货 ,我们的宗旨就是为人民服务、授人以鱼不如授人以渔、不吹毛求疵、不浮夸、不虚伪、不忽悠、一切都是为了社会共同进步,繁荣昌盛,小程序猿、大程序猿、老程序猿还是嫩程序猿,希望这个社会不要太急功近利 ,希望每个IT行业的BOSS要有良知,程序猿的青春年华都是无私默默奉献,都是拿命拼出来了现在的成就,如果卸磨杀驴,如果逼良为娼,请MM你的良心对得起你爹妈吗,你也有家,你也有小孩,你也有父母的。
在这里致敬程序猿, 致敬我们的攻城狮,致敬我们最可爱的人! 珍惜生命,换种活法也是依然精彩。
View层代码:
NativePay.cshtml:
@{ ViewBag.Title = "微信扫码支付"; } <style> .container .row{ margin-left: 0;margin-right: 0;} .page-header .header img{width:40px;} .page-header .row div,.payinfo{padding-left: 0;} .row .paymoney{text-align: right;} .payinfo img{height: 30px;} .payinfo span{vertical-align: middle;color: gray} .paymoney span.warning{color:orangered;margin: 0 5px;} .qrcode {width: 200px;height: 200px; display: block;margin-top: 20px;margin-bottom: 20px;} .payqr img{width: 200px;} </style> <div class="container"> <div class="row"> <div class="page"> <div class="page-header"> <div class="row header"> <h2><img src="~/WxPayAPI/imgs/logo.png" /> 收银台</h2> </div> <div class="row"> <div class="col-md-8"> <p>订单编号:@ViewBag.OrderNumber</p> </div> <div class="col-md-4 paymoney"> <h2>应付金额:@ViewBag.OrderPrice</h2> </div> </div> </div> <div class="row"> <div class="col-md-8 payinfo"> <img src="~/WxPayAPI/imgs/WePayLogo.png" /> <img src="~/WxPayAPI/imgs/按钮标签.png" /> <span>亿万用户的选择,更快更安全</span> </div> <div class="col-md-4 paymoney">支付<span class="warning">@ViewBag.OrderPrice</span>元</div> </div> <div class="row payqr"> <img src="@ViewBag.QRCode" class="qrcode" /> <img src="~/WxPayAPI/imgs/说明文字.png" /> </div> <input type="hidden" id="trade" value="@ViewBag.OrderNumber"/> </div> </div> </div> <script> $(function() { var trade = $("#trade").val(); setInterval(function() { $.post("/WeChatPay/WXNativeNotifyPage", { tradeno: trade }, function (data) { if (data == 1) { location.href = "/WeChatPay/PaySuccess?tradeno=" + trade; } if (data == 2) { location.href = "/WeChatPay/PaySuccess?tradeno=" + trade; } }); }, 1000); }); </script>
通知页面 可以忽略:
WXNativeNotifyPage.cshtml
@{ ViewBag.Title = "WXNativeNotifyPage"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>WXNativeNotifyPage</h2>
PaySuccess.cshtml
<@using WeChatPayMvc.Models @model PayOrder @{ ViewBag.Title = "PaySuccess"; } <style> .container .row{ margin-left: 0;margin-right: 0;} </style> <div class="container"> <div class="row"> <div class="page"> <div class="page-header"> <div class="row header"> @if (Model.PayStatus ==1) { <h2>支付成功!</h2> } else { <h2>支付失败!</h2> } </div> <div>订单号:@Model.OrderNumber</div> </div> </div> </div> </div>
Controller 控制器代码:
WeChatPayController
using Business; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Web; using System.Web.Mvc; using System.Xml; using ThoughtWorks.QRCode.Codec; using WeChatPayMvc.Models; using System.Text.RegularExpressions; namespace WeChatPayMvc.Controllers { public class WeChatPayController : Controller { // // GET: /WeChatPay/ public ActionResult Index() { return RedirectToAction("NativePay"); } /// <summary> /// 扫码支付下单入口 /// </summary> /// <returns></returns> public ActionResult NativePay() { var order = new PayOrder(); //order.OrderNumber = GenerateOutTradeNo(); //order.OrderPrice = (Convert.ToInt32(decimal.Parse("0.01") * 100)).ToString(); ViewBag.OrderNumber = GenerateOutTradeNo(); ViewBag.OrderPrice = decimal.Parse("0.01").ToString(); int total_fee = (Convert.ToInt32(decimal.Parse(ViewBag.OrderPrice) * 100)); string productid = "2017121000000"; WechatPayHelper wxpay = new WechatPayHelper(); //主要参数依次是 订单号 金额 openid 公众号 产品productid string return_response = wxpay.GetUnifiedOrderResultNative(ViewBag.OrderNumber, total_fee, "财政专费", "oCmg80qvyJeOgvlWf6pCKkLxJgu4", productid); //将url生成二维码图片 ViewBag.QRCode = "http://localhost:38773/WeChatPay/MakeQRCode?data=" + HttpUtility.UrlEncode(return_response); return View(); } /// <summary> /// 二维码生成工具 /// </summary> /// <param name="data"></param> /// <returns></returns> public FileResult MakeQRCode(string data) { if (string.IsNullOrEmpty(data)) throw new ArgumentException("data"); //初始化二维码生成工具 QRCodeEncoder qrCodeEncoder = new QRCodeEncoder(); qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE; qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M; qrCodeEncoder.QRCodeVersion = 0; qrCodeEncoder.QRCodeScale = 4; //将字符串生成二维码图片 Bitmap image = qrCodeEncoder.Encode(data, Encoding.Default); //保存为PNG到内存流 MemoryStream ms = new MemoryStream(); image.Save(ms, ImageFormat.Jpeg); return File(ms.ToArray(), "image/jpeg"); } /** * 根据当前系统时间加随机序列来生成订单号 * @return 订单号 */ public static string GenerateOutTradeNo() { var ran = new Random(); return string.Format("{0}{1}", DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(99999)); } public ActionResult PaySuccess(string tradeno) { var order = new PayOrder() { OrderNumber = tradeno }; return View(order); } /// <summary> /// //接收从微信后台POST过来的数据 通知地址信息 /// </summary> public ActionResult WXNativeNotifyPage() { //接收从微信后台POST过来的数据 //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(); ////转换数据格式并验证签名 //WxPayData data = new WxPayData(); //try //{ // data.FromXml(builder.ToString()); //} StreamReader reader = new StreamReader(Request.InputStream); String xmlData = reader.ReadToEnd(); WriteLogFile("接收post来的微信异步回调:" + xmlData, "微信异步回调"); //序列化xml //转换数据格式并验证签名 Dictionary<string, string> dicParam = GetInfoFromXml(xmlData); string data = ""; try { //当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。 if (dicParam.ContainsKey("return_code") && dicParam["return_code"] == "SUCCESS") { WechatPayHelper wcHelper = new WechatPayHelper(); string strRequestData = ""; //对返回的参数信息进行签名 string strSign = wcHelper.MakeSignData(dicParam, ref strRequestData); //判断返回签名是否正确 if (strSign == dicParam["sign"]) { //判断业务结果 if ("SUCCESS" == dicParam["result_code"]) { //////检查openid和product_id是否返回 if (string.IsNullOrEmpty(dicParam["openid"]) || string.IsNullOrEmpty(dicParam["product_id"])) { data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[产品ID不存在回调数据异常]]></return_msg></xml>"; Response.Write(data); } //判断业务是否处理过 应该有通知日志表 先暂通过缴费表做判断 string out_trade_no = dicParam["out_trade_no"];//订单编号 if (out_trade_no != null) { //查询订单 PayOrderBLL payoderBll = new PayOrderBLL(); PayOrder pay = payoderBll.Query(out_trade_no); if (pay != null) { //商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。 if (pay.OrderPrice.Equals(decimal.Parse(dicParam["total_fee"]) / 100)) { data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[金额不一致回调数据异常]]></return_msg></xml>"; Response.Write(data); } if (pay.PayStatus == 1) { //已经支付 视为处理过 直接返回 data = "<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>"; Response.Write(data); } else { //收到确认后,更新订单的状态 //修改支付状态 if (payoderBll.UpdatePayStatus(out_trade_no, "1", 1) > 0) { data = "<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>"; Response.Write(data); } } } else { data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>"; Response.Write(data); } } } else { //错误信息 string error = dicParam["err_code"] + ":" + dicParam["err_code_des"]; data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>"; Response.Write(data); } } else { data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>"; Response.Write(data); } } } catch (Exception ex) { WriteLogFile("微信异步回调异常:" + ex.Message, "异常日志"); data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>"; Response.Write(data); } return View(); } /// <summary> /// 把XML数据转换为SortedDictionary<string, string>集合 /// </summary> /// <param name="strxml"></param> /// <returns></returns> public Dictionary<string, string> GetInfoFromXml(string xmlstring) { Dictionary<string, string> sParams = new Dictionary<string, string>(); try { XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlstring); XmlElement root = doc.DocumentElement; int len = root.ChildNodes.Count; for (int i = 0; i < len; i++) { string name = root.ChildNodes[i].Name; if (!sParams.ContainsKey(name)) { sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim()); } } } catch (Exception ex) { } return sParams; } /// <summary> /// 写日志文件 /// </summary> /// <param name="Infos">日志内容</param> /// <param name="fileNameParam">文件名(不带后缀)</param> public static void WriteLogFile(string Infos, string fileNameParam) { try { StackTrace trace = new StackTrace(); MethodBase method = trace.GetFrame(1).GetMethod(); Infos = "[" + method.Name + "]" + Infos; } catch { } WriteLogFile(Infos, fileNameParam, ""); } /// <summary> /// 写日志文件 /// </summary> /// <param name="Infos">日志内容</param> /// <param name="fileNameParam">文件名(不带后缀)</param> /// <param name="filePathParam">附加子路径</param> public static void WriteLogFile(string Infos, string fileNameParam, string filePathParam) { FileStream fs = null; try { string filename = ""; //年月日 string str = System.DateTime.Now.Date.Year.ToString() + "-" + System.DateTime.Now.Date.Month.ToString() + "-" + System.DateTime.Now.Date.Day.ToString(); filename = AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + filePathParam + "\\" + str + fileNameParam + ".log"; //如果不存在该目录就创建该目录 if (!Directory.Exists(AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + filePathParam + "\\")) { Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "\\Logs\\" + filePathParam + "\\"); } //如果该文件存在则往里面写日志 //ERROR: “System.Web.Mvc.Controller.File(string, string, string)”是一个“方法”,这在给定的上下文中无效 // 这是一个与Controller.File方法和System.IO.File类名称冲突的问题,只要完整输入明确类名就可解决。 if (System.IO.File.Exists(filename)) { fs = new FileStream(filename, FileMode.Open, FileAccess.Write); } else { fs = new FileStream(filename, FileMode.Create, FileAccess.Write); } byte[] Bt; string curLine; //时分秒+日志信息 curLine = DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second + " " + Infos + "\r\n\r\n"; Bt = new byte[curLine.Length * 2]; Bt = Encoding.UTF8.GetBytes(curLine); fs.Position = fs.Length; fs.Write(Bt, 0, Bt.Length); fs.Close(); } catch (Exception) { if (fs != null) { fs.Close(); } } } } }
实用类WechatPayHelper代码:
using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Net; using System.Security.Cryptography; using System.Text; using System.Web; using System.Xml; namespace WeChatPayMvc { public class WechatPayHelper { private string RequestUrl = "";//接口调用地址 //交易安全检验码,由数字和字母组成的32位字符串 private string key = ""; private string appid = "";//应用ID private string mch_id = "";//商户号 private string nonce_str = "";//随机字符串 private string sign = "";//签名 // private string body = "";//商品描述 // private string out_trade_no = "";//商户订单号 private string spbill_create_ip = "";//终端IP private string notify_url = "";//通知地址 private string trade_type = "";//交易类型 private string pay_url = ""; //字符编码格式 目前支持 utf-8 private string input_charset = "utf-8"; //签名方式,选择项:0001(RSA)、MD5 private string sign_type = "MD5"; public WechatPayHelper() { HttpContext Context = System.Web.HttpContext.Current; DataTable dt = null; //native 扫码支付配置 string strXML = "Wechat_Pay_Native.xml"; ////////////////////////////////////////////////// object objValue = GetCache(strXML); if (objValue == null) { dt = GetConfigXml("//PayConfig/" + strXML); SetCache(strXML, dt); } else { dt = (DataTable)objValue; } if (dt != null) { appid = dt.Rows[0]["appid"].ToString(); mch_id = dt.Rows[0]["mch_id"].ToString(); notify_url = dt.Rows[0]["notify_url"].ToString(); pay_url = dt.Rows[0]["pay_url"].ToString(); spbill_create_ip = GetUserIp(); nonce_str = StrRodamNo(16); trade_type = dt.Rows[0]["trade_type"].ToString(); key = dt.Rows[0]["key"].ToString(); } } /// <summary> /// 获取当前应用程序指定CacheKey的Cache值 /// </summary> /// <param name="CacheKey"></param> /// <returns></returns> public static object GetCache(string CacheKey) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; return objCache[CacheKey]; } /// <summary> /// 设置当前应用程序指定CacheKey的Cache值 /// </summary> /// <param name="CacheKey"></param> /// <param name="objObject"></param> public static void SetCache(string CacheKey, object objObject) { System.Web.Caching.Cache objCache = HttpRuntime.Cache; if (objObject != null) objCache.Insert(CacheKey, objObject, null, DateTime.UtcNow.AddDays(7), TimeSpan.Zero); } /// <summary> /// 获得指定XML文件内容 /// </summary> /// <param name="strPath">XML文件相对路径</param> /// <returns>XML数据</returns> public static DataTable GetConfigXml(string strPath) { DataTable dt = null; try { DataSet ds = new DataSet(); ds.ReadXml(HttpContext.Current.Server.MapPath(strPath)); dt = ds.Tables[0]; } catch { } return dt; } /// <summary> /// 生成直接支付url 调用统一下单,获得下单结果 扫码支付模式二 支付url有效期为2小时, /// </summary> /// <param name="out_trade_no"></param> /// <param name="total_fee"></param> /// <param name="body"></param> /// <returns></returns> public string GetUnifiedOrderResultNative(string out_trade_no, int total_fee, string body, string openid, string productId) { //请求业务参数详细 StringBuilder sb = new StringBuilder(); sb.AppendFormat("<xml><appid>{0}</appid><mch_id>{1}</mch_id> <body>{2}</body><nonce_str>{3}</nonce_str>", appid, mch_id, body, nonce_str); sb.AppendFormat("<out_trade_no>{0}</out_trade_no><total_fee>{1}</total_fee> <spbill_create_ip>{2}</spbill_create_ip><trade_type>{3}</trade_type>", out_trade_no, total_fee.ToString(), spbill_create_ip, trade_type); sb.AppendFormat("<notify_url>{0}</notify_url>", notify_url); sb.AppendFormat("<openid>{0}</openid>", openid); sb.AppendFormat("<product_id>{0}</product_id>", productId); //把请求参数打包成数组 Dictionary<string, string> softdic = new Dictionary<string, string>(); softdic.Add("appid", appid); softdic.Add("mch_id", mch_id); softdic.Add("nonce_str", nonce_str); softdic.Add("body", body); softdic.Add("out_trade_no", out_trade_no); softdic.Add("total_fee", total_fee.ToString()); softdic.Add("spbill_create_ip", spbill_create_ip); softdic.Add("trade_type", trade_type); softdic.Add("notify_url", notify_url); softdic.Add("openid", openid); softdic.Add("product_id", productId); //请求参数体 string strRequest = ""; //加密签名 string strSign = MakeSignData(softdic, ref strRequest); strRequest += "&sign=" + strSign; //打包xml sb.AppendFormat("<sign>{0}</sign></xml>", strSign); //发送请求 string strResponse = RequestWechatpay(sb.ToString()); //URLDECODE返回的信息 Encoding code = Encoding.GetEncoding(input_charset); strResponse = HttpUtility.UrlDecode(strResponse, code); string ResponseURL = ReadXmlNode(strResponse);//获得统一下单接口返回的二维码链接code_url return ResponseURL; } /// <summary> /// 签名原始串 /// </summary> /// <param name="dicParm">所有非空参数</param> /// <param name="strQueryString">请求串</param> /// <returns>签名串</returns> public string MakeSignData(Dictionary<string, string> dicParm, ref string strQueryString) { //先排序 Dictionary<string, string> dicSort = dicParm.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value); StringBuilder sb = new StringBuilder(); //再转换成URL字符串 foreach (KeyValuePair<string, string> kvParm in dicSort) { if (null != kvParm.Value && "".CompareTo(kvParm.Value) != 0 && "sign".CompareTo(kvParm.Key) != 0 && "key".CompareTo(kvParm.Key) != 0 && "sign_type".CompareTo(kvParm.Key) != 0) { if (sb.Length > 0) { sb.Append("&"); strQueryString += "&"; } sb.Append(kvParm.Key + "=" + HttpUtility.UrlDecode(kvParm.Value)); strQueryString += kvParm.Key + "=" + HttpUtility.UrlEncode(kvParm.Value); } } //再和key拼装成字符串 sb.Append("&key=" + key); //再进行MD5加密转成大写 return MD5Create(sb.ToString(), input_charset).ToUpper(); } public static string MD5Create(string str, string charset) { string retStr; MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider(); //创建md5对象 byte[] inputBye; byte[] outputBye; //使用GB2312编码方式把字符串转化为字节数组. try { inputBye = Encoding.GetEncoding(charset).GetBytes(str); } catch (Exception ex) { inputBye = Encoding.GetEncoding("GB2312").GetBytes(str); } outputBye = m5.ComputeHash(inputBye); retStr = System.BitConverter.ToString(outputBye); retStr = retStr.Replace("-", ""); return retStr; } /// <summary> ///把请求参数信息打包发送请求微信支付地址 /// </summary> /// <param name="strRequestData">请求参数字符串(QueryString)</param> /// <returns></returns> private string RequestWechatpay(string strRequestData) { Encoding code = Encoding.GetEncoding(input_charset); //把数组转换成流中所需字节数组类型 byte[] bytesRequestData = code.GetBytes(strRequestData); //请求远程HTTP string strResult = ""; try { //设置HttpWebRequest基本信息 HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(pay_url); myReq.Method = "post"; myReq.ContentType = "text/xml"; //填充POST数据 myReq.ContentLength = bytesRequestData.Length; Stream requestStream = myReq.GetRequestStream(); requestStream.Write(bytesRequestData, 0, bytesRequestData.Length); requestStream.Close(); //发送POST数据请求服务器 HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse(); Stream myStream = HttpWResp.GetResponseStream(); //获取服务器返回信息 StreamReader reader = new StreamReader(myStream, code); StringBuilder responseData = new StringBuilder(); String line; while ((line = reader.ReadLine()) != null) { responseData.Append(line); } //释放 myStream.Close(); strResult = responseData.ToString(); } catch (Exception exp) { strResult = "报错:" + exp.Message; } return strResult; } /// <summary> /// 获得客户端的IP /// </summary> /// <returns>当前页面客户端的IP</returns> public static string GetUserIp() { string userHostAddress = HttpContext.Current.Request.UserHostAddress; if (string.IsNullOrEmpty(userHostAddress)) { userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要) if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress)) { return userHostAddress; } return "127.0.0.1"; } /// <summary> /// 检查IP地址格式 /// </summary> /// <param name="ip"></param> /// <returns></returns> public static bool IsIP(string ip) { return System.Text.RegularExpressions.Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$"); } /// <summary> /// 生成随机字母与数字 /// </summary> /// <param name="IntStr">生成长度</param> /// <returns></returns> public static string StrRodamNo(int Length) { return StrRodam(Length, false); } /// <summary> /// 生成随机字母与数字 /// </summary> /// <param name="Length">生成长度</param> /// <param name="Sleep">是否要在生成前将当前线程阻止以避免重复</param> /// <returns></returns> public static string StrRodam(int Length, bool Sleep) { if (Sleep) System.Threading.Thread.Sleep(3); char[] Pattern = new char[] { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘, ‘N‘, ‘O‘, ‘P‘, ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, ‘Y‘, ‘Z‘ }; string result = ""; int n = Pattern.Length; System.Random random = new Random(~unchecked((int)DateTime.Now.Ticks)); for (int i = 0; i < Length; i++) { int rnd = random.Next(0, n); result += Pattern[rnd]; } return result; } #region 读取xml中的指定节点的值 /// <summary> /// 读取xml中的指定节点的值 /// </summary> private string ReadXmlNode(string filename) { string result = "调用微信服务异常"; XmlDocument xmlDoc = new XmlDocument(); try { xmlDoc.LoadXml(filename); XmlNode root = xmlDoc.SelectSingleNode("xml"); if (root != null) result = (root.SelectSingleNode("code_url")).InnerText; } catch (Exception e) { } return result; } #endregion } }
配置文件XML :
Wechat_Pay_Native.xml
<?xml version="1.0" encoding="utf-8" ?> <data> <!--接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数--> <notify_url>http://5.20.7.8:300/PayNotifyPage/WXNativeNotifyPage</notify_url> <pay_url>https://api.mch.weixin.qq.com/pay/unifiedorder</pay_url> <!--微信开放平台审核通过的应用APPID--> <appid>wxf888888888888</appid> <!--微信支付分配的商户号--> <mch_id>1485555555</mch_id> <key>16ce99d5252525525252529d</key> <subject>财政专费</subject> <trade_type>NATIVE</trade_type> </data>
Models 代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace WeChatPayMvc.Models { public class PayOrder { public PayOrder() { } public string OrderNumber { get; set; } public string OrderPrice { get; set; } public int PayStatus { get; set; } } }
即可完成整个扫码支付过程, 有图有真相:
打开微信进行扫码支付即可。