2018-08-13更新生成二維碼的方法前端
在作微信支付前,首先要了解你須要什麼方式的微信支付,目前本人作過的支付包含掃碼支付、H5支付、公衆號支付、App支付等,本人使用的是asp.net mvc core2.0框架開發,core技術目前國內用的不算多,因此本人總結使用asp.net mvc core開發微信支付的一些經驗,以前都在博客園學習,沒有寫過文章,文筆差,歡迎指正。web
首先定義個微信支付參數保存的類,本人定義類以下,具體參數意義就只有去參考微信官方文檔了,後臺接口開發都將用到這邊的參數,若支付不使用公衆號支付和app支付的話appSecret參數將不用獲取。ajax
。數據庫
public class WxPayConfig { public static WxPayConfig Instance = new WxPayConfig(); public string appid = "";//APPID public string mchid = "";//商戶號 public string key = "";//商戶API密鑰 public string appSecret = "";//公衆號支付和app支付時候將用到 public string notify_url = "http://www.baidu.com/Pay/WxNotify";//回調頁地址 public string api_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";//微信支付調用接口地址 }
首先說一下掃碼支付大致流程,首先微信得開通商戶平臺得掃碼支付功能具體在 https://pay.weixin.qq.com上登錄,填寫相關才材料開通掃碼支付,開通完成後支付產品裏將出現已開通的支付列表,而後使用獲取到的參數拼接成對應格式的xml文件上傳到微信服務器,若是配置正常服務器將返回一串xml文本,獲取xml文本中的code_url地址,將該地址轉爲圖片二維碼展現在網站中。api
1.申請掃碼支付接口安全
2.配置微信掃碼支付回調連接(貌似不配置掃碼支付也能夠用)服務器
3.編寫掃碼支付服務, 掃碼支付須要用到的appid,mchid,key 等參數,代碼以下微信
首先在nuget中安裝Senparc.Weixin.MPmvc
掃碼支付服務類方法:app
/// <summary> /// 獲取微信掃碼支付URL /// </summary> /// <param name="out_trade_no">訂單號</param> /// <param name="body">描述</param> /// <param name="total_fee">總價</param> /// <param name="ip">客戶IP</param> /// <param name="product_id">商品id</param> /// <returns></returns> public string GetWxSMPayUrl(string out_trade_no, string body, string total_fee, string ip, string product_id) { Senparc.Weixin.MP.TenPayLibV3.RequestHandler packageReqHandler = new Senparc.Weixin.MP.TenPayLibV3.RequestHandler(); #region 構造請求參數 packageReqHandler.SetParameter("appid", wxPayConfig.appid);//APPID packageReqHandler.SetParameter("mch_id", wxPayConfig.mchid);//商戶號 packageReqHandler.SetParameter("nonce_str", Senparc.Weixin.MP.TenPayLibV3.TenPayV3Util.GetNoncestr());//隨機串 packageReqHandler.SetParameter("body", body); packageReqHandler.SetParameter("out_trade_no", out_trade_no);//訂單號 packageReqHandler.SetParameter("total_fee", (int)(Convert.ToDecimal(total_fee) * 100) + ""); //金額,以分爲單位 packageReqHandler.SetParameter("spbill_create_ip", ip);//IP packageReqHandler.SetParameter("notify_url", wxPayConfig.notify_url); //回調地址 packageReqHandler.SetParameter("trade_type", "NATIVE");//掃碼支付 packageReqHandler.SetParameter("product_id", product_id);//商品ID packageReqHandler.SetParameter("sign", packageReqHandler.CreateMd5Sign("key", wxPayConfig.key));//商戶API密鑰(簽名) #endregion //將參數轉爲xml字符串 string data = packageReqHandler.ParseXML(); //發起post異步請求,獲取返回的內容 var result = PostWithStringFile(wxPayConfig.api_url, data); Log.Info("【GetWxSMPayUrl】訂單:" + out_trade_no + ",請求獲得的xml:" + result, "微信支付"); //解析xml,獲取掃碼須要的mweb_url。 var res = System.Xml.Linq.XDocument.Parse(result); try { string mweb_url = res.Element("xml").Element("code_url").Value; Log.Info("【GetWxSMPayUrl】訂單:" + out_trade_no + ",請求獲得的url:" + mweb_url, "微信支付"); return mweb_url; } catch (Exception ex) { Log.Info("【GetWxSMPayUrl】訂單:" + out_trade_no + ",異常:" + ex.ToString(), "微信支付"); return ""; } }
後臺控制器中代碼參考
/// <summary> /// ajax請求生成訂單,插入訂單到數據庫, /// </summary> /// <param name="body"></param> /// <param name="total_fee"></param> /// <param name="product_id"></param> /// <returns></returns> public IActionResult GetWxSMPayUrl(string body, string total_fee, string product_id) { string no = DateTime.Now.ToString("yyyyMMddHHmmssfff");//構造訂單號 //訂單相關邏輯代碼 //訂單相關邏輯代碼結束 //構造支付地址信息 WxPayService wxPayService = new WxPayService(); //服務類,自行優化 //獲取請求ip var ip = Request.Headers["X-Forwarded-For"].FirstOrDefault(); if (string.IsNullOrEmpty(ip)) { ip = HttpContext.Connection.RemoteIpAddress.ToString(); } string code_url = wxPayService.GetWxSMPayUrl(no, body, total_fee, ip, product_id); return Content(code_url); //返回支付的Url,前端ajax請求獲得該url後,將該url賦值到存放圖片的src中 }
若是業務正常運行ajax將請求獲得一串url,後臺控制器中添加一個能夠根據參數生成二維碼圖片文件的action,首先在nuget中添加QRCode引用,代碼例如
該段代碼無效
[HttpGet]
/// <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, System.Text.Encoding.Default);
//保存爲PNG到內存流
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return File(ms.ToArray(), "image/jpeg");
}
該段代碼無效結束
以上生成二維碼的方法是在.net framework下的,並且缺乏一個dll的引用,在core平臺下無效,替換爲以下而在.net core平臺應該使用以下方法:
在Home控制器中添加MakeQRCode的方法,代碼以下:
public FileResult MakeQRCode(string data) { var image = QRCoderHelper.CreateQrcode(data); MemoryStream ms = new MemoryStream(); image.Save(ms, System.DrawingCore.Imaging.ImageFormat.Jpeg); return File(ms.ToArray(), "image/jpeg"); }
QRCoderHelper.cs須要引用NUGET裏的ZKWeb.Fork.QRCoder,注:若是以前在NUGET中引用了QRCode請將他移除否則沒法使用
QRCoderHelper

代碼內容以下
using System; using System.DrawingCore; using System.DrawingCore.Drawing2D; using System.DrawingCore.Imaging; using System.IO; using QRCoder; public class QRCoderHelper { /// <summary> /// 生成二維碼 /// </summary> /// <returns></returns> public static Bitmap CreateQrcode(string codeToken, int version = 10) { EncoderParameter myEncoderParameter; EncoderParameters myEncoderParameters; QRCodeGenerator qrGenerator = new QRCodeGenerator(); // 設置二維碼排錯率,可選L(7%)、M(15%)、Q(25%)、H(30%),排錯率越高可存儲的信息越少,但對二維碼清晰度的要求越小 QRCodeData qrCodeData = qrGenerator.CreateQrCode(codeToken, QRCodeGenerator.ECCLevel.Q); QRCode qrCode = new QRCode(qrCodeData); // 設置設置二維碼版本,取值範圍1-40,值越大尺寸越大,可存儲的信息越大(實測9(297*297),10(330*330),20(660*600),每一個擋位33左右,3個擋位100個像素) Bitmap qrCodeImage = qrCode.GetGraphic(version); Encoder myEncoder = Encoder.Quality; myEncoderParameters = new EncoderParameters(1); myEncoderParameter = new EncoderParameter(myEncoder, 25L); myEncoderParameters.Param[0] = myEncoderParameter; return qrCodeImage; } }
該action做用爲請求該方法傳入data參數,返回的是該參數值的二維碼圖片文件,前端src指向該action並加上以前獲取獲得的code_url信息,格式以下, /Home/MakeQRCode?data=xxxxx,若是img標籤正確顯示了掃碼的圖片,那麼就大功告成了,支付完成,可是還有支付回調更新訂單的邏輯要寫。
效果以下:
這裏再貼上微信支付回調的代碼
/// <summary> /// 微信支付異步回調 /// </summary> /// <returns></returns> public IActionResult WxNotify() { try { //使用微信工具獲取ResponseHandler ResponseHandler wxResponseHandler = new ResponseHandler(HttpContext);
string out_trade_no = wxResponseHandler.GetParameter("out_trade_no");//訂單號 string total_fee = wxResponseHandler.GetParameter("total_fee");//訂單金額,單位分 total_fee = (Convert.ToDecimal(total_fee) / 100).ToString("#0.00");//訂單金額,單位元 Log.Info("微信測試收到數據,訂單號:" + out_trade_no + "訂單金額:" + total_fee, "【微信支付回調】"); //驗證訂單是否有支付過邏輯 //驗證訂單信息,獲取支付配置 WxPayConfig payConfigModel = new WxPayConfig();//後面去能夠去配置或者數據庫中獲取
//驗證是否經過微信安全認證 WxPayService wxPayService = new WxPayService(); bool vxCheck = wxPayService.WxPayCheck(wxResponseHandler);//使用sdk去驗證 if (vxCheck) { //更新訂單 //ProcessOrder(out_trade_no); Log.Info("微信驗證成功" + out_trade_no, "【微信支付回調】"); return SuccessRes(""); } else { Log.Info("微信測試失敗" + out_trade_no, "【微信支付回調】"); return ErrRes("微信測試失敗"); } } catch (Exception ex) { Log.Error("微信測試回調異常", ex, "【微信支付回調】"); return ErrRes("微信測試回調異常"); } }
具體業務邏輯實現得看本身的需求,日誌類Log和返回成功或者錯誤信息可自由替換。
附上方法中用到post請求方法
/// <summary> /// post請求,將字符串轉爲流上傳到url中 /// </summary> /// <param name="url"></param> /// <param name="file"></param> /// <returns></returns> public string PostWithStringFile(string url, string file) { var formDataBytes = file == null ? new byte[0] : Encoding.UTF8.GetBytes(file);//將xml字符串轉爲字節流 MemoryStream ms = new MemoryStream(formDataBytes);//將字節流轉爲內存流 StreamContent streamContent = new StreamContent(ms);//封裝爲StreamContent對象 //發起post異步請求,獲取返回的內容 var result = httpClient.PostAsync(wxPayConfig.api_url, streamContent).Result.Content.ReadAsStringAsync().Result; return result; } //以及服務類包含字段 #region 字段 public WxPayConfig wxPayConfig = new WxPayConfig();//微信配置文件 public HttpClient httpClient = new HttpClient();//http請求客戶端 #endregion
附上寫日誌的一個老師傅寫類庫Sky.Logger,在項目中添加引用便可使用日誌:連接: https://pan.baidu.com/s/1eHdNGZN0pmNHsO_yHzgE_g 密碼: ta2x
歡迎指正。
QRCoderHelper