ASP.NET Core 2.0 支付寶當面付之掃碼支付

前言

自從微軟更換了CEO之後,微軟的戰略方向有了至關大的變化,再也不是那麼封閉,開源了許多東西,擁抱開源社區,.NET實現跨平臺,收購xamarin並免費提供給開發者等等。我本人是很喜歡.net的,並但願.net core可以崛起。我是從.net core 1.1的時候開始使用的,到如今的.net core 2.0。.net core 2.0比1.1有了一些改變,api也增長了不少,用着更順手了,最近在作asp.net core 對接支付寶,百度了一下沒找到關於core的支付寶支付相關資料,因此便本身研究了一下,把官方的服務端sdk修改爲.net standard 2.0的(https://github.com/stulzq/Alipay.AopSdk.Core) ,而且根據官方的Demo成功作出了asp.net core 2.0的PC網站支付Demo,前面寫了篇文章介紹了一下:ASP.NET Core 2.0 使用支付寶PC網站支付,你們能夠看一看。今天講的是支付寶當面付中的掃碼支付。html

掃碼支付簡單介紹

掃碼支付是支付寶當面付中的一種支付方式,當面付包含條碼支付、掃碼支付、聲波支付。git

掃碼支付,指用戶打開支付寶錢包中的「掃一掃」功能,掃描商家展現在某收銀場景下的二維碼並進行支付的模式。該模式適用於線下實體店支付、面對面支付等場景。github

使用示例:express

1.某直播平臺充值api

2.某視頻網站開通vip網絡

掃碼支付比傳統的跳轉網頁支付方便快捷。asp.net

業務流程:dom

使用步驟:異步

  1. 收銀員在商家收銀系統操做生成支付寶訂單,並生成二維碼;
  2. 用戶登陸支付寶錢包,點擊首頁「付款-掃碼付」或直接點擊「掃一掃」,進入掃一掃界面;
  3. 用戶掃收銀員提供的二維碼,覈對金額,確認支付;
  4. 用戶付款後商家收銀系統會拿到支付成功或者失敗的結果。

詳細介紹請查閱官方文檔:https://docs.open.alipay.com/194ide

配置

建立一個ASP.NET Core 2.0 MVC 項目

新建一個配置類Config

public class Config { // 應用ID,您的APPID public static string AppId = ""; /// <summary> /// 合做商戶uid /// </summary> public static string Uid = ""; // 支付寶網關 public static string Gatewayurl = "https://openapi.alipaydev.com/gateway.do"; // 商戶私鑰,您的原始格式RSA私鑰 public static string PrivateKey = ""; // 支付寶公鑰,查看地址:https://openhome.alipay.com/platform/keyManage.htm 對應APPID下的支付寶公鑰。 public static string AlipayPublicKey = ""; // 簽名方式 public static string SignType = "RSA2"; // 編碼格式 public static string CharSet = "UTF-8"; }

如下演示均是使用的支付寶沙箱環境,支付寶沙箱環境指的協助開發者進行接口功能開發及主要功能聯調的輔助環境。沙箱環境模擬了開放平臺部分產品的主要功能和主要邏輯,在開發者應用上線審覈前,開發者能夠根據自身需求,先在沙箱環境中瞭解、組合和調試各類開放接口,進行開發調通工做,從而幫助開發者在應用上線審覈完成後,能更快速、更順利的進行線上調試和驗收工做。
若是在簽約或建立應用前想要進行集成測試,可使用沙箱環境

配置的詳細說明,請看我前一篇文章:ASP.NET Core 2.0 使用支付寶PC網站支付

ASP.NET Core 2.0 實現掃碼支付

使用的生成二維碼的組件名爲QRCoder,該組件引用了一個第三方實現的System.Drawing類庫,當面付SDK爲Alipay.AopSdk.F2FPay,已經更新到github和nuget。Nuget: https://www.nuget.org/packages/Alipay.AopSdk.F2FPay/ ,github: https://github.com/stulzq/Alipay.AopSdk.Core

新建控制器FTFPayController

1.生成二維碼Action

/// <summary> /// 生成支付二維碼 /// </summary> /// <param name="orderName">訂單名稱</param> /// <param name="orderAmount">訂單金額</param> /// <param name="outTradeNo">訂單號</param> /// <returns></returns> [HttpGet] public IActionResult ScanCodeGen(string orderName, string orderAmount, string outTradeNo) { AlipayTradePrecreateContentBuilder builder = BuildPrecreateContent(orderName,orderAmount,outTradeNo); //若是須要接收掃碼支付異步通知,那麼請把下面兩行註釋代替本行。 //推薦使用輪詢撤銷機制,不推薦使用異步通知,避免單邊帳問題發生。 AlipayF2FPrecreateResult precreateResult = _serviceClient.tradePrecreate(builder); //string notify_url = "http://10.5.21.14/Pay/Notify"; //商戶接收異步通知的地址 //AlipayF2FPrecreateResult precreateResult = serviceClient.tradePrecreate(builder, notify_url); //如下返回結果的處理供參考。 //payResponse.QrCode即二維碼對於的連接 //將連接用二維碼工具生成二維碼打印出來,顧客能夠用支付寶錢包掃碼支付。 var bitmap = new Bitmap(Path.Combine(_hostingEnvironment.WebRootPath, "images/error.png")); switch (precreateResult.Status) { case ResultEnum.SUCCESS: bitmap.Dispose(); bitmap=RenderQrCode(precreateResult.response.QrCode); //輪詢訂單結果 //根據業務須要,選擇是否新起線程進行輪詢 ParameterizedThreadStart parStart = new ParameterizedThreadStart(LoopQuery); Thread myThread = new Thread(parStart); object o = precreateResult.response.OutTradeNo; myThread.Start(o); break; case ResultEnum.FAILED: Console.WriteLine("生成二維碼失敗:"+ precreateResult.response.Body); break; case ResultEnum.UNKNOWN: Console.WriteLine("生成二維碼失敗:" + (precreateResult.response == null ? "配置或網絡異常,請檢查後重試" : "系統異常,請更新外部訂單後從新發起請求")); break; } MemoryStream ms = new MemoryStream(); bitmap.Save(ms, ImageFormat.Png); byte[] bytes = ms.GetBuffer(); return File(bytes, "image/png"); }

2.構造支付請求數據

/// <summary> /// 構造支付請求數據 /// </summary> /// <param name="orderName">訂單名稱</param> /// <param name="orderAmount">訂單金額</param> /// <param name="outTradeNo">訂單編號</param> /// <returns>請求結果集</returns> private AlipayTradePrecreateContentBuilder BuildPrecreateContent(string orderName,string orderAmount,string outTradeNo) { //線上聯調時,請輸入真實的外部訂單號。 if (string.IsNullOrEmpty(outTradeNo)) { outTradeNo = System.DateTime.Now.ToString("yyyyMMddHHmmss") + "0000" + (new Random()).Next(1, 10000).ToString(); } AlipayTradePrecreateContentBuilder builder = new AlipayTradePrecreateContentBuilder(); //收款帳號 builder.seller_id = Config.Uid; //訂單編號 builder.out_trade_no = outTradeNo; //訂單總金額 builder.total_amount = orderAmount; //參與優惠計算的金額 //builder.discountable_amount = ""; //不參與優惠計算的金額 //builder.undiscountable_amount = ""; //訂單名稱 builder.subject = orderName; //自定義超時時間 builder.timeout_express = "5m"; //訂單描述 builder.body = ""; //門店編號,很重要的參數,能夠用做以後的營銷 builder.store_id = "test store id"; //操做員編號,很重要的參數,能夠用做以後的營銷 builder.operator_id = "test"; //傳入商品信息詳情 List<GoodsInfo> gList = new List<GoodsInfo>(); GoodsInfo goods = new GoodsInfo(); goods.goods_id = "goods id"; goods.goods_name = "goods name"; goods.price = "0.01"; goods.quantity = "1"; gList.Add(goods); builder.goods_detail = gList; //系統商接入能夠填此參數用做返傭 //ExtendParams exParam = new ExtendParams(); //exParam.sysServiceProviderId = "20880000000000"; //builder.extendParams = exParam; return builder; }

3.渲染二維碼

/// <summary> /// 渲染二維碼 /// </summary> /// <param name="str"></param> /// <returns></returns> private Bitmap RenderQrCode(string str) { QRCodeGenerator.ECCLevel eccLevel = QRCodeGenerator.ECCLevel.L; using (QRCodeGenerator qrGenerator = new QRCodeGenerator()) { using (QRCodeData qrCodeData = qrGenerator.CreateQrCode(str, eccLevel)) { using (QRCode qrCode = new QRCode(qrCodeData)) { Bitmap bp= qrCode.GetGraphic(20, Color.Black, Color.White, new Bitmap(Path.Combine(_hostingEnvironment.WebRootPath, "images/alipay.png")), 15); return bp; } } } }

4.輪詢支付結果

/// <summary> /// 輪詢支付結果 /// </summary> /// <param name="o">訂單號</param> public void LoopQuery(object o) { AlipayF2FQueryResult queryResult = new AlipayF2FQueryResult(); int count = 100; int interval = 10000; string outTradeNo = o.ToString(); for (int i = 1; i <= count; i++) { Thread.Sleep(interval); queryResult = _serviceClient.tradeQuery(outTradeNo); if (queryResult?.Status == ResultEnum.SUCCESS) { DoSuccessProcess(queryResult); return; } } DoFailedProcess(queryResult); } /// <summary> /// 請添加支付成功後的處理 /// </summary> private void DoSuccessProcess(AlipayF2FQueryResult queryResult) { //支付成功,請更新相應單據 Console.WriteLine("掃碼支付成功:商戶訂單號 " + queryResult.response.OutTradeNo); } /// <summary> /// 請添加支付失敗後的處理 /// </summary> private void DoFailedProcess(AlipayF2FQueryResult queryResult) { //支付失敗,請更新相應單據 Console.WriteLine("掃碼支付失敗:商戶訂單號 " + queryResult.response.OutTradeNo); }

關於支付結果,可使用輪詢或者異步通知來獲取,異步通知我這裏沒條件就沒有演示,可是代碼已經實現了的,本身能夠下載Demo測試。

以上代碼只是做爲演示,實際中使用請根據本身的需求來修改,好比輪詢應該是用專門的一個或多個後臺任務線程來輪詢而不是每一個訂單開一個線程,請注意。

Demo演示

1.生成二維碼

生成二維碼必須提供商戶訂單號、訂單金額、訂單名稱三個參數,否則會出現錯誤。

2.掃描支付

打開手機支付寶,點開掃一掃,掃描二維碼完成付款。

若是使用的是沙箱環境,那麼必須下載沙箱版支付寶,使用正式版支付寶掃描沙箱環境api生成的二維碼,會出現二維碼失效,沙箱環境後臺能夠下載。沙箱環境必須使用沙箱環境帳號。

(1)掃碼以後:

(2)支付成功:

3.支付結果

經過輪詢得到的結果:

地址集合

前一篇文章:ASP.NET Core 2.0 使用支付寶PC網站支付

當面付官方文檔:https://docs.open.alipay.com/194

Nuget組件:

QRCoder(二維碼生成):https://www.nuget.org/packages/QRCoder/

Alipay.AopSdk.F2FPay(當面付SDK):https://www.nuget.org/packages/Alipay.AopSdk.F2FPay/

支付寶當面付與服務端SDK:https://github.com/stulzq/Alipay.AopSdk.Core

本文Demohttps://github.com/stulzq/Alipay.Demo.PCPayment

若是你以爲對你有用,歡迎來個star!

相關文章
相關標籤/搜索