.NET Core2.0 環境下MVC模式的支付寶掃碼支付接口-沙箱環境開發測試


所有配置以及相關信息均可以從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
    }
}

 生成二維碼支付界面:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM