直接上干货 ,我们的宗旨就是为人民服务、授人以鱼不如授人以渔、不吹毛求疵、不浮夸、不虚伪、不忽悠、一切都是为了社会共同进步,繁荣昌盛,小程序猿、大程序猿、老程序猿还是嫩程序猿,希望这个社会不要太急功近利 ,希望每个IT行业的BOSS要有良知,程序猿的青春年华都是无私默默奉献,都是拿命拼出来了现在的成就,如果卸磨杀驴,如果逼良为娼,请MM你的良心对得起你爹妈吗,你也有家,你也有小孩,你也有父母的。

在这里致敬程序猿, 致敬我们的攻城狮,致敬我们最可爱的人! 珍惜生命,换种活法也是依然精彩。

View层代码:

NativePay.cshtml:

  1. @{
  2. ViewBag.Title = "微信扫码支付";
  3. }
  4. <style>
  5. .container .row{ margin-left: 0;margin-right: 0;}
  6. .page-header .header img{width:40px;}
  7. .page-header .row div,.payinfo{padding-left: 0;}
  8. .row .paymoney{text-align: right;}
  9. .payinfo img{height: 30px;}
  10. .payinfo span{vertical-align: middle;color: gray}
  11. .paymoney span.warning{color:orangered;margin: 0 5px;}
  12. .qrcode {width: 200px;height: 200px; display: block;margin-top: 20px;margin-bottom: 20px;}
  13. .payqr img{width: 200px;}
  14. </style>
  15. <div class="container">
  16. <div class="row">
  17. <div class="page">
  18. <div class="page-header">
  19. <div class="row header">
  20. <h2><img src="~/WxPayAPI/imgs/logo.png" /> 收银台</h2>
  21. </div>
  22. <div class="row">
  23. <div class="col-md-8">
  24. <p>订单编号:@ViewBag.OrderNumber</p>
  25. </div>
  26. <div class="col-md-4 paymoney">
  27. <h2>应付金额:@ViewBag.OrderPrice</h2>
  28. </div>
  29. </div>
  30. </div>
  31. <div class="row">
  32. <div class="col-md-8 payinfo">
  33. <img src="~/WxPayAPI/imgs/WePayLogo.png" />
  34. <img src="~/WxPayAPI/imgs/按钮标签.png" />
  35. <span>亿万用户的选择,更快更安全</span>
  36. </div>
  37. <div class="col-md-4 paymoney">支付<span class="warning">@ViewBag.OrderPrice</span>元</div>
  38. </div>
  39. <div class="row payqr">
  40. <img src="@ViewBag.QRCode" class="qrcode" />
  41. <img src="~/WxPayAPI/imgs/说明文字.png" />
  42. </div>
  43. <input type="hidden" id="trade" value="@ViewBag.OrderNumber"/>
  44. </div>
  45. </div>
  46. </div>
  47.  
  48. <script>
  49. $(function() {
  50. var trade = $("#trade").val();
  51. setInterval(function() {
  52. $.post("/WeChatPay/WXNativeNotifyPage", { tradeno: trade }, function (data) {
  53. if (data == 1) {
  54. location.href = "/WeChatPay/PaySuccess?tradeno=" + trade;
  55. } if (data == 2) {
  56. location.href = "/WeChatPay/PaySuccess?tradeno=" + trade;
  57. }
  58. });
  59. }, 1000);
  60.  
  61. });
  62.  
  63. </script>

通知页面 可以忽略:

WXNativeNotifyPage.cshtml

  1. @{
  2. ViewBag.Title = "WXNativeNotifyPage";
  3. Layout = "~/Views/Shared/_Layout.cshtml";
  4. }
  5.  
  6. <h2>WXNativeNotifyPage</h2>

PaySuccess.cshtml

  1. <@using WeChatPayMvc.Models
  2. @model PayOrder
  3.  
  4. @{
  5. ViewBag.Title = "PaySuccess";
  6. }
  7. <style>
  8. .container .row{ margin-left: 0;margin-right: 0;}
  9. </style>
  10. <div class="container">
  11. <div class="row">
  12. <div class="page">
  13. <div class="page-header">
  14. <div class="row header">
  15. @if (Model.PayStatus ==1)
  16. {
  17. <h2>支付成功!</h2>
  18. }
  19. else
  20. {
  21. <h2>支付失败!</h2>
  22. }
  23. </div>
  24. <div>订单号:@Model.OrderNumber</div>
  25. </div>
  26. </div>
  27. </div>
  28. </div>

Controller 控制器代码:

WeChatPayController

  1. using Business;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Reflection;
  10. using System.Text;
  11. using System.Web;
  12. using System.Web.Mvc;
  13. using System.Xml;
  14. using ThoughtWorks.QRCode.Codec;
  15. using WeChatPayMvc.Models;
  16. using System.Text.RegularExpressions;
  17.  
  18. namespace WeChatPayMvc.Controllers
  19. {
  20. public class WeChatPayController : Controller
  21. {
  22. //
  23. // GET: /WeChatPay/
  24.  
  25. public ActionResult Index()
  26. {
  27. return RedirectToAction("NativePay");
  28. }
  29.  
  30. /// <summary>
  31. /// 扫码支付下单入口
  32. /// </summary>
  33. /// <returns></returns>
  34. public ActionResult NativePay()
  35. {
  36. var order = new PayOrder();
  37. //order.OrderNumber = GenerateOutTradeNo();
  38. //order.OrderPrice = (Convert.ToInt32(decimal.Parse("0.01") * 100)).ToString();
  39. ViewBag.OrderNumber = GenerateOutTradeNo();
  40. ViewBag.OrderPrice = decimal.Parse("0.01").ToString();
  41. int total_fee = (Convert.ToInt32(decimal.Parse(ViewBag.OrderPrice) * ));
  42. string productid = "";
  43.  
  44. WechatPayHelper wxpay = new WechatPayHelper();
  45. //主要参数依次是 订单号 金额 openid 公众号 产品productid
  46. string return_response = wxpay.GetUnifiedOrderResultNative(ViewBag.OrderNumber, total_fee, "财政专费", "oC88888df99jdfdWf6p999Jgu4", productid);
  47. //将url生成二维码图片
  48.  
  49. ViewBag.QRCode = "http://localhost:38773/WeChatPay/MakeQRCode?data=" + HttpUtility.UrlEncode(return_response);
  50. return View();
  51. }
  52. /// <summary>
  53. /// 二维码生成工具
  54. /// </summary>
  55. /// <param name="data"></param>
  56. /// <returns></returns>
  57. public FileResult MakeQRCode(string data)
  58. {
  59. if (string.IsNullOrEmpty(data))
  60. throw new ArgumentException("data");
  61.  
  62. //初始化二维码生成工具
  63. QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
  64. qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
  65. qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
  66. qrCodeEncoder.QRCodeVersion = ;
  67. qrCodeEncoder.QRCodeScale = ;
  68.  
  69. //将字符串生成二维码图片
  70. Bitmap image = qrCodeEncoder.Encode(data, Encoding.Default);
  71.  
  72. //保存为PNG到内存流
  73. MemoryStream ms = new MemoryStream();
  74. image.Save(ms, ImageFormat.Jpeg);
  75.  
  76. return File(ms.ToArray(), "image/jpeg");
  77. }
  78.  
  79. /**
  80. * 根据当前系统时间加随机序列来生成订单号
  81. * @return 订单号
  82. */
  83. public static string GenerateOutTradeNo()
  84. {
  85. var ran = new Random();
  86. return string.Format("{0}{1}", DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next());
  87. }
  88.  
  89. public ActionResult PaySuccess(string tradeno)
  90. {
  91.  
  92. var order = new PayOrder() { OrderNumber = tradeno };
  93. return View(order);
  94. }
  95.  
  96. /// <summary>
  97. /// //接收从微信后台POST过来的数据 通知地址信息
  98. /// </summary>
  99. public ActionResult WXNativeNotifyPage()
  100. {
  101. //接收从微信后台POST过来的数据
  102. //Stream s = Request.InputStream;
  103. //int count = 0;
  104. //byte[] buffer = new byte[1024];
  105. //StringBuilder builder = new StringBuilder();
  106. //while ((count = s.Read(buffer, 0, 1024)) > 0)
  107. //{
  108. // builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
  109. //}
  110. //s.Flush();
  111. //s.Close();
  112. //s.Dispose();
  113.  
  114. ////转换数据格式并验证签名
  115. //WxPayData data = new WxPayData();
  116. //try
  117. //{
  118. // data.FromXml(builder.ToString());
  119. //}
  120. StreamReader reader = new StreamReader(Request.InputStream);
  121. String xmlData = reader.ReadToEnd();
  122. WriteLogFile("接收post来的微信异步回调:" + xmlData, "微信异步回调");
  123. //序列化xml //转换数据格式并验证签名
  124. Dictionary<string, string> dicParam = GetInfoFromXml(xmlData);
  125. string data = "";
  126. try
  127. {
  128. //当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
  129.  
  130. if (dicParam.ContainsKey("return_code") && dicParam["return_code"] == "SUCCESS")
  131. {
  132.  
  133. WechatPayHelper wcHelper = new WechatPayHelper();
  134. string strRequestData = "";
  135. //对返回的参数信息进行签名
  136. string strSign = wcHelper.MakeSignData(dicParam, ref strRequestData);
  137. //判断返回签名是否正确
  138. if (strSign == dicParam["sign"])
  139. {
  140. //判断业务结果
  141. if ("SUCCESS" == dicParam["result_code"])
  142. {
  143. //////检查openid和product_id是否返回
  144. if (string.IsNullOrEmpty(dicParam["openid"]) || string.IsNullOrEmpty(dicParam["product_id"]))
  145. {
  146. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[产品ID不存在回调数据异常]]></return_msg></xml>";
  147. Response.Write(data);
  148. }
  149.  
  150. //判断业务是否处理过 应该有通知日志表 先暂通过缴费表做判断
  151. string out_trade_no = dicParam["out_trade_no"];//订单编号
  152.  
  153. if (out_trade_no != null)
  154. {
  155. //查询订单
  156. PayOrderBLL payoderBll = new PayOrderBLL();
  157. PayOrder pay = payoderBll.Query(out_trade_no);
  158.  
  159. if (pay != null)
  160. {
  161. //商户系统对于支付结果通知的内容一定要做签名验证,并校验返回的订单金额是否与商户侧的订单金额一致,防止数据泄漏导致出现“假通知”,造成资金损失。
  162. if (pay.OrderPrice.Equals(decimal.Parse(dicParam["total_fee"]) / ))
  163. {
  164. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[金额不一致回调数据异常]]></return_msg></xml>";
  165. Response.Write(data);
  166. }
  167. if (pay.PayStatus == )
  168. {
  169. //已经支付 视为处理过 直接返回
  170. data = "<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>";
  171. Response.Write(data);
  172. }
  173. else
  174. { //收到确认后,更新订单的状态
  175. //修改支付状态
  176. if (payoderBll.UpdatePayStatus(out_trade_no, "", ) > )
  177. {
  178.  
  179. data = "<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>";
  180. Response.Write(data);
  181. }
  182. }
  183. }
  184.  
  185. else
  186. {
  187. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>";
  188. Response.Write(data);
  189. }
  190. }
  191. }
  192. else
  193. {
  194. //错误信息
  195. string error = dicParam["err_code"] + ":" + dicParam["err_code_des"];
  196. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>";
  197. Response.Write(data);
  198. }
  199. }
  200. else
  201. {
  202. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>";
  203. Response.Write(data);
  204. }
  205. }
  206.  
  207. }
  208. catch (Exception ex)
  209. {
  210. WriteLogFile("微信异步回调异常:" + ex.Message, "异常日志");
  211. data = "<xml><return_code><![CDATA[FAIL]]></return_code> <return_msg><![CDATA[系统调用超时]]></return_msg></xml>";
  212. Response.Write(data);
  213. }
  214. return View();
  215.  
  216. }
  217.  
  218. /// <summary>
  219. /// 把XML数据转换为SortedDictionary<string, string>集合
  220. /// </summary>
  221. /// <param name="strxml"></param>
  222. /// <returns></returns>
  223. public Dictionary<string, string> GetInfoFromXml(string xmlstring)
  224. {
  225. Dictionary<string, string> sParams = new Dictionary<string, string>();
  226. try
  227. {
  228. XmlDocument doc = new XmlDocument();
  229. doc.LoadXml(xmlstring);
  230. XmlElement root = doc.DocumentElement;
  231. int len = root.ChildNodes.Count;
  232. for (int i = ; i < len; i++)
  233. {
  234. string name = root.ChildNodes[i].Name;
  235. if (!sParams.ContainsKey(name))
  236. {
  237. sParams.Add(name.Trim(), root.ChildNodes[i].InnerText.Trim());
  238. }
  239. }
  240. }
  241. catch (Exception ex)
  242. {
  243.  
  244. }
  245. return sParams;
  246. }
  247.  
  248. }
  249. }

实用类WechatPayHelper代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Security.Cryptography;
  8. using System.Text;
  9. using System.Web;
  10. using System.Xml;
  11.  
  12. namespace WeChatPayMvc
  13. {
  14. public class WechatPayHelper
  15. {
  16. private string RequestUrl = "";//接口调用地址
  17. //交易安全检验码,由数字和字母组成的32位字符串
  18. private string key = "";
  19. private string appid = "";//应用ID
  20. private string mch_id = "";//商户号
  21. private string nonce_str = "";//随机字符串
  22. private string sign = "";//签名
  23. // private string body = "";//商品描述
  24. // private string out_trade_no = "";//商户订单号
  25. private string spbill_create_ip = "";//终端IP
  26. private string notify_url = "";//通知地址
  27. private string trade_type = "";//交易类型
  28. private string pay_url = "";
  29. //字符编码格式 目前支持 utf-8
  30. private string input_charset = "utf-8";
  31. //签名方式,选择项:0001(RSA)、MD5
  32. private string sign_type = "MD5";
  33. public WechatPayHelper()
  34. {
  35. HttpContext Context = System.Web.HttpContext.Current;
  36. DataTable dt = null;
  37.  
  38. //native 扫码支付配置
  39. string strXML = "Wechat_Pay_Native.xml";
  40. //////////////////////////////////////////////////
  41. object objValue = GetCache(strXML);
  42. if (objValue == null)
  43. {
  44. dt = GetConfigXml("//PayConfig/" + strXML);
  45. SetCache(strXML, dt);
  46. }
  47. else
  48. {
  49. dt = (DataTable)objValue;
  50. }
  51. if (dt != null)
  52. {
  53. appid = dt.Rows[]["appid"].ToString();
  54. mch_id = dt.Rows[]["mch_id"].ToString();
  55. notify_url = dt.Rows[]["notify_url"].ToString();
  56. pay_url = dt.Rows[]["pay_url"].ToString();
  57. spbill_create_ip = GetUserIp();
  58. nonce_str = StrRodamNo();
  59. trade_type = dt.Rows[]["trade_type"].ToString();
  60. key = dt.Rows[]["key"].ToString();
  61. }
  62. }
  63.  
  64. /// <summary>
  65. /// 获取当前应用程序指定CacheKey的Cache值
  66. /// </summary>
  67. /// <param name="CacheKey"></param>
  68. /// <returns></returns>
  69. public static object GetCache(string CacheKey)
  70. {
  71. System.Web.Caching.Cache objCache = HttpRuntime.Cache;
  72. return objCache[CacheKey];
  73. }
  74. /// <summary>
  75. /// 设置当前应用程序指定CacheKey的Cache值
  76. /// </summary>
  77. /// <param name="CacheKey"></param>
  78. /// <param name="objObject"></param>
  79. public static void SetCache(string CacheKey, object objObject)
  80. {
  81. System.Web.Caching.Cache objCache = HttpRuntime.Cache;
  82. if (objObject != null)
  83. objCache.Insert(CacheKey, objObject, null, DateTime.UtcNow.AddDays(), TimeSpan.Zero);
  84. }
  85.  
  86. /// <summary>
  87. /// 生成直接支付url 调用统一下单,获得下单结果 扫码支付模式二 支付url有效期为2小时,
  88. /// </summary>
  89. /// <param name="out_trade_no"></param>
  90. /// <param name="total_fee"></param>
  91. /// <param name="body"></param>
  92. /// <returns></returns>
  93. public string GetUnifiedOrderResultNative(string out_trade_no, int total_fee, string body, string openid, string productId)
  94. {
  95. //请求业务参数详细
  96. StringBuilder sb = new StringBuilder();
  97. 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);
  98. 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);
  99. sb.AppendFormat("<notify_url>{0}</notify_url>", notify_url);
  100. sb.AppendFormat("<openid>{0}</openid>", openid);
  101. sb.AppendFormat("<product_id>{0}</product_id>", productId);
  102.  
  103. //把请求参数打包成数组
  104. Dictionary<string, string> softdic = new Dictionary<string, string>();
  105. softdic.Add("appid", appid);
  106. softdic.Add("mch_id", mch_id);
  107. softdic.Add("nonce_str", nonce_str);
  108. softdic.Add("body", body);
  109. softdic.Add("out_trade_no", out_trade_no);
  110. softdic.Add("total_fee", total_fee.ToString());
  111. softdic.Add("spbill_create_ip", spbill_create_ip);
  112. softdic.Add("trade_type", trade_type);
  113. softdic.Add("notify_url", notify_url);
  114. softdic.Add("openid", openid);
  115. softdic.Add("product_id", productId);
  116. //请求参数体
  117. string strRequest = "";
  118.  
  119. //加密签名
  120. string strSign = MakeSignData(softdic, ref strRequest);
  121.  
  122. strRequest += "&sign=" + strSign;
  123.  
  124. //打包xml
  125. sb.AppendFormat("<sign>{0}</sign></xml>", strSign);
  126.  
  127. //发送请求
  128. string strResponse = RequestWechatpay(sb.ToString());
  129.  
  130. //URLDECODE返回的信息
  131. Encoding code = Encoding.GetEncoding(input_charset);
  132. strResponse = HttpUtility.UrlDecode(strResponse, code);
  133. string ResponseURL = ReadXmlNode(strResponse);//获得统一下单接口返回的二维码链接code_url
  134.  
  135. return ResponseURL;
  136. }
  137.  
  138. /// <summary>
  139. /// 签名原始串
  140. /// </summary>
  141. /// <param name="dicParm">所有非空参数</param>
  142. /// <param name="strQueryString">请求串</param>
  143. /// <returns>签名串</returns>
  144. public string MakeSignData(Dictionary<string, string> dicParm, ref string strQueryString)
  145. { //先排序
  146. Dictionary<string, string> dicSort = dicParm.OrderBy(o => o.Key).ToDictionary(o => o.Key, p => p.Value);
  147. StringBuilder sb = new StringBuilder();
  148. //再转换成URL字符串
  149. foreach (KeyValuePair<string, string> kvParm in dicSort)
  150. {
  151. if (null != kvParm.Value && "".CompareTo(kvParm.Value) !=
  152. && "sign".CompareTo(kvParm.Key) != && "key".CompareTo(kvParm.Key) != && "sign_type".CompareTo(kvParm.Key) != )
  153. {
  154. if (sb.Length > )
  155. {
  156. sb.Append("&");
  157. strQueryString += "&";
  158. }
  159. sb.Append(kvParm.Key + "=" + HttpUtility.UrlDecode(kvParm.Value));
  160. strQueryString += kvParm.Key + "=" + HttpUtility.UrlEncode(kvParm.Value);
  161. }
  162. }
  163. //再和key拼装成字符串
  164. sb.Append("&key=" + key);
  165. //再进行MD5加密转成大写
  166. return MD5Create(sb.ToString(), input_charset).ToUpper();
  167.  
  168. }
  169.  
  170. public static string MD5Create(string str, string charset)
  171. {
  172. string retStr;
  173. MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider();
  174.  
  175. //创建md5对象
  176. byte[] inputBye;
  177. byte[] outputBye;
  178.  
  179. //使用GB2312编码方式把字符串转化为字节数组.
  180. try
  181. {
  182. inputBye = Encoding.GetEncoding(charset).GetBytes(str);
  183. }
  184. catch (Exception ex)
  185. {
  186. inputBye = Encoding.GetEncoding("GB2312").GetBytes(str);
  187. }
  188. outputBye = m5.ComputeHash(inputBye);
  189.  
  190. retStr = System.BitConverter.ToString(outputBye);
  191. retStr = retStr.Replace("-", "");
  192. return retStr;
  193. }
  194.  
  195. /// <summary>
  196. ///把请求参数信息打包发送请求微信支付地址
  197. /// </summary>
  198. /// <param name="strRequestData">请求参数字符串(QueryString)</param>
  199. /// <returns></returns>
  200. private string RequestWechatpay(string strRequestData)
  201. {
  202. Encoding code = Encoding.GetEncoding(input_charset);
  203.  
  204. //把数组转换成流中所需字节数组类型
  205. byte[] bytesRequestData = code.GetBytes(strRequestData);
  206.  
  207. //请求远程HTTP
  208. string strResult = "";
  209. try
  210. {
  211. //设置HttpWebRequest基本信息
  212. HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(pay_url);
  213. myReq.Method = "post";
  214. myReq.ContentType = "text/xml";
  215.  
  216. //填充POST数据
  217. myReq.ContentLength = bytesRequestData.Length;
  218. Stream requestStream = myReq.GetRequestStream();
  219. requestStream.Write(bytesRequestData, , bytesRequestData.Length);
  220. requestStream.Close();
  221.  
  222. //发送POST数据请求服务器
  223. HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();
  224. Stream myStream = HttpWResp.GetResponseStream();
  225.  
  226. //获取服务器返回信息
  227. StreamReader reader = new StreamReader(myStream, code);
  228. StringBuilder responseData = new StringBuilder();
  229. String line;
  230. while ((line = reader.ReadLine()) != null)
  231. {
  232. responseData.Append(line);
  233. }
  234.  
  235. //释放
  236. myStream.Close();
  237.  
  238. strResult = responseData.ToString();
  239. }
  240. catch (Exception exp)
  241. {
  242. strResult = "报错:" + exp.Message;
  243. }
  244.  
  245. return strResult;
  246. }
  247.  
  248. /// <summary>
  249. /// 获得客户端的IP
  250. /// </summary>
  251. /// <returns>当前页面客户端的IP</returns>
  252. public static string GetUserIp()
  253. {
  254.  
  255. string userHostAddress = HttpContext.Current.Request.UserHostAddress;
  256.  
  257. if (string.IsNullOrEmpty(userHostAddress))
  258. {
  259. userHostAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
  260. }
  261.  
  262. //最后判断获取是否成功,并检查IP地址的格式(检查其格式非常重要)
  263. if (!string.IsNullOrEmpty(userHostAddress) && IsIP(userHostAddress))
  264. {
  265. return userHostAddress;
  266. }
  267. return "127.0.0.1";
  268.  
  269. }
  270.  
  271. /// <summary>
  272. /// 检查IP地址格式
  273. /// </summary>
  274. /// <param name="ip"></param>
  275. /// <returns></returns>
  276. public static bool IsIP(string ip)
  277. {
  278. 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?)$");
  279. }
  280.  
  281. /// <summary>
  282. /// 生成随机字母与数字
  283. /// </summary>
  284. /// <param name="IntStr">生成长度</param>
  285. /// <returns></returns>
  286. public static string StrRodamNo(int Length)
  287. {
  288. return StrRodam(Length, false);
  289. }
  290.  
  291. /// <summary>
  292. /// 生成随机字母与数字
  293. /// </summary>
  294. /// <param name="Length">生成长度</param>
  295. /// <param name="Sleep">是否要在生成前将当前线程阻止以避免重复</param>
  296. /// <returns></returns>
  297. public static string StrRodam(int Length, bool Sleep)
  298. {
  299. if (Sleep)
  300. System.Threading.Thread.Sleep();
  301. char[] Pattern = new char[] { '', '', '', '', '', '', '', '', '', '', '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' };
  302. string result = "";
  303. int n = Pattern.Length;
  304. System.Random random = new Random(~unchecked((int)DateTime.Now.Ticks));
  305. for (int i = ; i < Length; i++)
  306. {
  307. int rnd = random.Next(, n);
  308. result += Pattern[rnd];
  309. }
  310. return result;
  311. }
  312.  
  313. #region 读取xml中的指定节点的值
  314. /// <summary>
  315. /// 读取xml中的指定节点的值
  316. /// </summary>
  317. private string ReadXmlNode(string filename)
  318. {
  319. string result = "调用微信服务异常";
  320. XmlDocument xmlDoc = new XmlDocument();
  321. try
  322. {
  323. xmlDoc.LoadXml(filename);
  324.  
  325. XmlNode root = xmlDoc.SelectSingleNode("xml");
  326. if (root != null)
  327. result = (root.SelectSingleNode("code_url")).InnerText;
  328.  
  329. }
  330. catch (Exception e)
  331. {
  332.  
  333. }
  334. return result;
  335. }
  336.  
  337. #endregion
  338. }
  339. }

配置文件XML :
Wechat_Pay_Native.xml

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <data>
  3. <!--接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数-->
  4. <notify_url>http://5.20.7.8:300/PayNotifyPage/WXNativeNotifyPage</notify_url>
  5. <pay_url>https://api.mch.weixin.qq.com/pay/unifiedorder</pay_url>
  6. <!--微信开放平台审核通过的应用APPID-->
  7. <appid>wxf888888888888</appid>
  8. <!--微信支付分配的商户号-->
  9. <mch_id>1485555555</mch_id>
  10. <key>16ce99d5252525525252529d</key>
  11. <subject>财政专费</subject>
  12. <trade_type>NATIVE</trade_type>
  13. </data>

Models 代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5.  
  6. namespace WeChatPayMvc.Models
  7. {
  8. public class PayOrder
  9. {
  10. public PayOrder()
  11. { }
  12. public string OrderNumber { get; set; }
  13. public string OrderPrice { get; set; }
  14. public int PayStatus { get; set; }
  15. }
  16. }

即可完成整个扫码支付过程, 有图有真相:

打开微信进行扫码支付即可。

最后说明 扫码支付 openID不需要传递

.NET MVC结构框架下的微信扫码支付模式二 API接口开发测试的更多相关文章

  1. .NET微信扫码支付模式二API接口开发测试

    主要实现微信扫码支付,官网的SDKdemo 就不要使用 一直不能调试通过的,还是自己按照API接口文档一步一步来实现,吐槽下微信一点责任感都木有,能不能demo搞个正常的吗,不要坑惨了一大群码农们有点 ...

  2. JAVA微信扫码支付模式二功能实现完整例子

    概述 本例子实现微信扫码支付模式二的支付功能,应用场景是,web网站微信扫码支付.实现从点击付费按钮.到弹出二维码.到用户用手机微信扫码支付.到手机上用户付费成功.web网页再自动调整到支付成功后的页 ...

  3. C# 微信扫码支付API (微信扫码支付模式二)

    一.SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1,下载.NET C#版本: 二.微信相关设置:(微信扫码 ...

  4. thinkphp5.0 微信扫码支付模式二

    仅供个人参考,方便大家. 一.1)https://pay.weixin.qq.com/index.php/core/home/login  复制此地址 打开微信商户平台. 2)下载安全操作证书(最好在 ...

  5. Python实现微信扫码支付模式二(NativePay)

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/7649207.html 核心代码github地址:https://github.com/ygj0930/Pyth ...

  6. 微信公众号 扫码支付 模式二 demo

    扫码支付 本文附有代码,在下方,如果不熟悉场景的可以看看下面的场景介绍 场景介绍 官网介绍地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?ch ...

  7. 微信支付Native扫码支付模式二之CodeIgniter集成篇

    CI:3.0.5 微信支付API类库来自:https://github.com/zhangv/wechat-pay 请先看一眼官方场景及支付时序图:https://pay.weixin.qq.com/ ...

  8. Java之微信支付(扫码支付模式二)案例实战

    摘要:最近的一个项目中涉及到了支付业务,其中用到了微信支付和支付宝支付,在做的过程中也遇到些问题,所以现在总结梳理一下,分享给有需要的人,也为自己以后回顾留个思路. 一:微信支付接入准备工作: 首先, ...

  9. ThinkPHP 整合微信支付 扫码支付 模式二 图文教程

    这篇文章主要介绍扫码支付场景二. 目前有两种模式,模式一比模式二稍微复杂点,至于模式一与模式二的具体内容,流程,微信开发文档都有详细介绍,这里就不多说废话,接下来赶紧上教程! [title]下载SDK ...

随机推荐

  1. JetBrains全系列在线激活中心pycharm

     题记:有能力还是建议购买正版授权! 01.pycharm下载 https://www.jetbrains.com/pycharm/download/ https://download.jetbrai ...

  2. PAC Manager的重生: Asbru

    PAC Manager在2016年停更后, 在Ubuntu18.04上的各种bug就无人修复了. 我在Windows下对XShell是重度依赖, 而在Linux下没有其他更好的替代品. 在上一次安装1 ...

  3. EMS_PM_STORAGE

    /*Navicat MySQL Data Transfer Source Server : 10.62.102.118Source Server Version : 50712Source Host ...

  4. ext4文件系统的delalloc选项造成单次写延迟增加的分析

    最近我们的服务进程遇到kill -15后处于Z的状态,变为了僵尸进程,经过/proc/{thread_id}/stack查看其上线程的栈,发现是卡在了fwrite的过程中,而我们的系统中所有文件系统挂 ...

  5. kafka和websocket实时数据推送

    需求 ​ 已有Kafka服务,通过kafka服务数据(GPS)落地到本地磁盘(以文本文件存储).现要根据echarts实现一个实时车辆的地图. 分析 前端实时展现:使用websocket技术,实现服务 ...

  6. 【LeetCode】210. Course Schedule II

    Course Schedule II There are a total of n courses you have to take, labeled from 0 to n - 1. Some co ...

  7. Redis学习之路(004)- 报错及问题

    在i配置编译的过程中,遇到一下问题: 1. /redis_test: error while loading shared libraries: libhiredis.so.0.13: cannot ...

  8. rviz学习笔记(二)——Markers: Points and Lines (C++) 点和线

    一.在using_marker/src中编写点和线代码 vim ~/catkin_ws/src/using_marker/src/points_and_lines.cpp 编写代码,其中有注释 #in ...

  9. 【struts2】核心概念

    1)FilterDispatcher Struts2的前端控制器,也是Struts2的MVC中的控制器部分.在实际开发中,只需要在web.xml中配置一次即可,如下所示: <filter> ...

  10. FreeSWITCH在会议室中持续播放音频文件

    最近遇到一个客户需求,希望在会议室建立起来后,自动播放一段指定的声音. 已知会议室命令,假设建立起一个会议室号码3000,很容易实现以下功能: 一.播放一个声音文件一次 conference 3000 ...