ASP.NET Core 2.0 支付宝当面付之扫码支付

    ASP.NET Core 2.0 支付宝当面付之扫码支付

    • 商品编号:
      #36708616_367
      • 原价:
        免费
      • 会员价:
        免费
    • 版本:
      • V2.0.0
    • 数量:
      库存(不限)

    购物车中已存在此商品,请在购物车中操作单击跳转购物车

    • 开源协议:BSD协议
    • 编码格式:UTF-8
    • 数据库:无
    • 开发语言:C#
    • 源码架构:B/S
    • 开发环境:Visual Studio
    • 开发者:晓晨Master
    • 版本工具管理:GitHub

    前言

        自从微软更换了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网站支付,大家可以看一看。今天讲的是支付宝当面付中的扫码支付。

    扫码支付简单介绍

        扫码支付是支付宝当面付中的一种支付方式,当面付包含条码支付、扫码支付、声波支付。

        扫码支付,指用户打开支付宝钱包中的“扫一扫”功能,扫描商家展示在某收银场景下的二维码并进行支付的模式。该模式适用于线下实体店支付、面对面支付等场景。

        使用示例:

    1.某直播平台充值

    o_eureka2

    2.某视频网站开通vip

    668104-20171011085824215-1875959573

    扫码支付比传统的跳转网页支付方便快捷。

    业务流程:

    668104-20171010213131809-199418024

    使用步骤:

        1. 收银员在商家收银系统操作生成支付宝订单,并生成二维码;

        2. 用户登录支付宝钱包,点击首页“付款-扫码付”或直接点击“扫一扫”,进入扫一扫界面;

        3. 用户扫收银员提供的二维码,核对金额,确认支付;

        4. 用户付款后商家收银系统会拿到支付成功或者失败的结果。

    详细介绍请查阅官方文档:https://docs.open.alipay.com/194

    配置

    创建一个ASP.NET Core 2.0 MVC 项目

    668104-20170928120255184-232813832

    新建一个配置类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演示

    1.生成二维码

    生成二维码必须提供商户订单号、订单金额、订单名称三个参数,不然会出现错误。

    668104-20171011092228574-1492676896

    2.扫描支付

    打开手机支付宝,点开扫一扫,扫描二维码完成付款。

        如果使用的是沙箱环境,那么必须下载沙箱版支付宝,使用正式版支付宝扫描沙箱环境api生成的二维码,会出现二维码失效,沙箱环境后台可以下载。沙箱环境必须使用沙箱环境账号。

    (1)扫码之后:

    (2)支付成功:

    668104-20171011094544918-1372873580

    668104-20171011095213434-51450322

    3.支付结果

    通过轮询获得的结果:

    668104-20171011094857652-1928340838

    668104-20171011094755934-826205448

    地址集合

    前一篇文章: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

    如果你觉得对你有用,欢迎来个star!

    权利声明:本站所有商品信息、客户评价等信息是初心商城重要的数据资源,未经许可,禁止非法转载使用。 注:本站商品信息均来自初心商城,其真实性、准确性和合法性由初心商城负责。

                    初心源说明:初心商城主要为程序员提供开发基础的代码源以及成熟项目,网站中所有的商品有提供收费版本的, 也有提供免费版本的,按照大家各自不同的需求进行购买。实实在在的让程序员只用专注于自己的业务实现你的小梦想, 如果您对我们的成果表示认同并且觉得对你有所帮助我们愿意接受来自各方面的支持^_^。

                    支持:用手机扫描二维码支付

                    支付宝支持我们 微信支持我们

                    您的支持将被用于:
                    1、持续深入的上传更多更好的源代码
                    2、建立更加完善的技术社区
                    3、完善现在系统出现各种问题
                    4、购买域名和租赁服务器

                    1、交易规则

                    2、发货方式

                    1、自动:在上方保障服务中标有自动发货的商品,拍下后,将会自动收到来自卖家的商品获取(下载)链接

                    2、手动:在上方保障服务中标有手动发货的商品,拍下后,卖家会收到邮件,也可通过QQ或订单中的电话联系对方。

                    3、退款说明

                    1、描述:源码描述(含标题)与实际源码不一致的(例:描述PHP实际为ASP、描述的功能实际缺少、版本不符等)

                    2、演示:有演示站时,与实际源码小于95%一致的(但描述中有"不保证完全一样、有变化的可能性"类似显著声明的除外)

                    3、发货:手动发货源码,在卖家未发货前,已申请退款的

                    4、服务:卖家不提供安装服务或需额外收费的(但描述中有显著声明的除外)

                    5、其它:如质量方面的硬性常规问题等

                    备注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。交易中的商品,卖家无法对描述进行修改!

                    4、注意事项

                    1、客户买完之后未确认收货,将不会收到下载地址和下载码,确认收货之后才能收到下载地址和下载码。

                    2、在未拍下前,双方在QQ上所商定的内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准);

                    3、在商品同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外);

                    4、在没有"无任何正当退款依据"的前提下,写有"一旦售出,概不支持退款"等类似的声明,视为无效声明;

                    5、虽然交易产生纠纷的几率很小,但请尽量保留如聊天记录这样的重要信息,以防产生纠纷时出现问题不明确的情况。

                    5、交易声明

                    1、本站作为直卖平台,依据交易合同(商品描述、交易前商定的内容)来保障交易的安全及买卖双方的权益;

                    2、非平台线上交易的商品,出现任何后果均与本站无关;无论卖家以何理由要求线下交易的,请联系管理举报。

                    初心Logo

                    初心商城| 初心系列| 初心博客| 版本历史| 通知公告| 系统反馈

                    © 2016-2019 上海吾永网络科技有限公司 保留所有权利 沪ICP备19028491号
                    违法和不良信息举报电话:186-2950-9347,本网站所列数据,除特殊说明,所有数据均出自我工作室
                    本网站兼容所有主流浏览器,不支持手机自适应

                    返回顶部小火箭