所有配置以及相關信息均可以從PC支付中獲取
使用的生成二維碼的組件名為QRCoder,該組件引用了一個第三方實現的System.Drawing類庫,和支付寶官網類似
當面付SDK為Alipay.AopSdk.F2FPay 直接使用Nuget工具下載安裝即可


view 中的Scan.cshtml頁面代碼:
@{ ViewData["Title"] = "掃碼支付"; } <div class="row"> <div class="col-sm-12"> <h1>掃碼支付</h1> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="tradeno" class="control-label col-sm-2">商戶訂單號:</label> <div class="col-sm-10"> <input type="text" name="tradeno" class="form-control" id="tradeno" value="" /> </div> </div> <div class="form-group"> <label for="orderName" class="control-label col-sm-2">訂單名稱:</label> <div class="col-sm-10"> <input type="text" name="orderName" class="form-control" id="orderName" value="iPhone X" /> </div> </div> <div class="form-group"> <label for="orderAmount" class="control-label col-sm-2">付款金額:</label> <div class="col-sm-10"> <input type="number" max="9.99" name="orderAmount" class="form-control" id="orderAmount" value="9.99" /> </div> </div> <div class="form-group"> <div class="col-sm-10 col-sm-offset-2"> <button class="btn btn-success btn-block" type="button" id="btnGen" onclick="GenCode()" >生成二維碼</button> <p class="help-block text-center">支付結果將顯示在返回信息中,需要啟用異步通知請使用公網ip或者域名等。</p> <p class="help-block text-center">生產環境建議通過輪詢加異步通知的方式保證支付結果,本頁面若要在支付成功后自動跳轉建議使用SignalR來實現</p> </div> </div> </form> </div> <div class="col-sm-12" s> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="tradeno" class="control-label col-sm-2">二維碼:</label> <div class="col-sm-10"> <img id="imgqrcode" style="height:255px;width:249px;"/> </div> </div> </form> </div> </div> @section Scripts{ <script> function GenCode() { $("#imgqrcode").attr("src", "/FTFPay/ScanCodeGen?orderName=" + $("#orderName").val() + "&orderAmount=" + $("#orderAmount").val() + "&outTradeNo=" + $("#tradeno").val() + "&rand=" + new Date().getTime()); } function GetDateNow() { var vNow = new Date(); var sNow = ""; sNow += String(vNow.getFullYear()); sNow += String(vNow.getMonth() + 1); sNow += String(vNow.getDate()); sNow += String(vNow.getHours()); sNow += String(vNow.getMinutes()); sNow += String(vNow.getSeconds()); sNow += String(vNow.getMilliseconds()); document.getElementById("tradeno").value = sNow; } GetDateNow(); </script> }
此代碼:

controllers: FTFPayController.cs 代碼:
using System; using System.Collections.Generic; using System.DrawingCore; using System.DrawingCore.Imaging; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Alipay.AopSdk.F2FPay.AspnetCore; using Alipay.AopSdk.F2FPay.Business; using Alipay.AopSdk.F2FPay.Domain; using Alipay.AopSdk.F2FPay.Model; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using QRCoder; namespace Alipay.PCPayment.Controllers { /// <summary> /// 掃碼支付 /// </summary> public class FTFPayController : Controller { private readonly IAlipayF2FService _alipayF2FService; private readonly IHostingEnvironment _hostingEnvironment; public FTFPayController(IHostingEnvironment hostingEnvironment, IAlipayF2FService alipayF2FService) { _hostingEnvironment = hostingEnvironment; _alipayF2FService = alipayF2FService; } public IActionResult Index() { return View(); } #region 掃碼支付 public IActionResult Scan() { return View(); } /// <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 = _alipayF2FService.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); // return Config.ResponseFail("生成二維碼失敗:" + precreateResult.response.Body); break; case ResultEnum.UNKNOWN: // return Config.ResponseFail("生成二維碼失敗:" + (precreateResult.response == null ? "配置或網絡異常,請檢查后重試" : "系統異常,請更新外部訂單后重新發起請求")); Console.WriteLine("生成二維碼失敗:" + (precreateResult.response == null ? "配置或網絡異常,請檢查后重試" : "系統異常,請更新外部訂單后重新發起請求")); break; } MemoryStream ms = new MemoryStream(); bitmap.Save(ms, ImageFormat.Png); byte[] bytes = ms.GetBuffer(); return File(bytes, "image/png"); } /// <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 = "9.99"; goods.quantity = "1"; gList.Add(goods); builder.goods_detail = gList; //系統商接入可以填此參數用作返佣 //ExtendParams exParam = new ExtendParams(); //exParam.sysServiceProviderId = "20880000000000"; //builder.extendParams = exParam; return builder; } /// <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; } } } } /// <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 = _alipayF2FService.TradeQuery(outTradeNo); if (queryResult?.Status == ResultEnum.SUCCESS) { DoSuccessProcess(queryResult); return; } } DoFailedProcess(queryResult); } /// <summary> /// 請添加支付成功后的處理 /// </summary> private ContentResult DoSuccessProcess(AlipayF2FQueryResult queryResult) { //支付成功,請更新相應單據 return Config.Response_Success("掃碼支付成功:商戶訂單號 " + queryResult.response.OutTradeNo); //Console.WriteLine("掃碼支付成功:商戶訂單號 " + queryResult.response.OutTradeNo); } /// <summary> /// 請添加支付成功后的處理 控制台的輸出結果信息 /// </summary> private void DoSuccess_Process(AlipayF2FQueryResult queryResult) { //支付成功,請更新相應單據 Console.WriteLine("掃碼支付成功:商戶訂單號 " + queryResult.response.OutTradeNo); } /// <summary> /// 請添加支付失敗后的處理 /// </summary> private ContentResult DoFailedProcess(AlipayF2FQueryResult queryResult) { //支付失敗,請更新相應單據 return Config.Response_Success("掃碼支付成功:商戶訂單號 " + queryResult.response.OutTradeNo); // Console.WriteLine("掃碼支付失敗:商戶訂單號 " + queryResult.response.OutTradeNo); } /// <summary> /// 請添加支付失敗后的處理 控制台的輸出信息 /// </summary> private void DoFailed_Process(AlipayF2FQueryResult queryResult) { //支付失敗,請更新相應單據 Console.WriteLine("掃碼支付失敗:商戶訂單號 " + queryResult.response.OutTradeNo); } #endregion } }
生成二維碼支付界面:

用沙箱版支付寶測試掃碼支付 掃一掃即可支付,在這里發現掃碼反應效果有點慢
