asp.net core 微信掃碼支付(掃碼支付,H5支付,公衆號支付,app支付)之1

  2018-08-13更新生成二維碼的方法

  在做微信支付前,首先要了解你需要什麼方式的微信支付,目前本人做過的支付包含掃碼支付、H5支付、公衆號支付、App支付等,本人使用的是asp.net mvc core2.0框架開發,core技術目前國內用的不算多,所以本人總結使用asp.net mvc core開發微信支付的一些經驗,之前都在博客園學習,沒有寫過文章,文筆差,歡迎指正。

  首先定義個微信支付參數保存的類,本人定義類如下,具體參數意義就只有去參考微信官方文檔了,後臺接口開發都將用到這邊的參數,若支付不使用公衆號支付和app支付的話appSecret參數將不用獲取。

 

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地址,將該地址轉爲圖片二維碼展示在網站中。

1.申請掃碼支付接口


 

 

2.配置微信掃碼支付回調鏈接(貌似不配置掃碼支付也可以用)


 

 

3.編寫掃碼支付服務, 掃碼支付需要用到的appid,mchid,key 等參數,代碼如下


 

首先在nuget中安裝Senparc.Weixin.MP

掃碼支付服務類方法:

/// <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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章