.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
    }
}

 生成二维码支付界面:

用沙箱版支付宝测试扫码支付 扫一扫即可支付,在这里发现扫码反应效果有点慢

posted @ 2017-11-29 15:27  蜜雪粮液  阅读(1679)  评论(0编辑  收藏  举报