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

简介: 原文:ASP.NET Core 2.0 支付宝当面付之扫码支付前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等。
原文: 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网站支付,大家可以看一看。今天讲的是支付宝当面付中的扫码支付。

扫码支付简单介绍

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

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

使用示例:

1.某直播平台充值

img_f77f30fade18faff1de28ed599083b57.png

2.某视频网站开通vip

img_867c98e78316cd1c7e2e1225d5d946d2.png

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

业务流程:

img_6e7ae6e700a7952c090fc79ff26ac230.png

使用步骤:

  1. 收银员在商家收银系统操作生成支付宝订单,并生成二维码;
  2. 用户登录支付宝钱包,点击首页“付款-扫码付”或直接点击“扫一扫”,进入扫一扫界面;
  3. 用户扫收银员提供的二维码,核对金额,确认支付;
  4. 用户付款后商家收银系统会拿到支付成功或者失败的结果。

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

配置

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

img_1514d095c3b68b71d0f3e769d59f73a0.png

新建一个配置类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.生成二维码

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

img_5abeb1d21f723d1a608cb54f4df5a332.gif

2.扫描支付

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

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

(1)扫码之后:

img_b7cdaab7680c291152aa1cae2210ad1b.png

(2)支付成功:

img_d12f50d48dccaaf2c91090f9823efc73.png

img_56bb8ae13f6e75e4f9dda7d5dbffc7bf.png

3.支付结果

通过轮询获得的结果:

img_bdf053337b11ec2e1b597ecc552277b5.png

img_13431fc49c2629ca8cc85f451af3fab5.png

地址集合

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

目录
相关文章
|
28天前
|
存储 开发框架 JSON
ASP.NET Core OData 9 正式发布
【10月更文挑战第8天】Microsoft 在 2024 年 8 月 30 日宣布推出 ASP.NET Core OData 9,此版本与 .NET 8 的 OData 库保持一致,改进了数据编码以符合 OData 规范,并放弃了对旧版 .NET Framework 的支持,仅支持 .NET 8 及更高版本。新版本引入了更快的 JSON 编写器 `System.Text.UTF8JsonWriter`,优化了内存使用和序列化速度。
|
28天前
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
mcr.microsoft.com/dotnet/core/aspnet:2.1安装libgdiplus
27 1
|
2月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。
|
2月前
|
开发框架 .NET 中间件
ASP.NET Core Web 开发浅谈
本文介绍ASP.NET Core,一个轻量级、开源的跨平台框架,专为构建高性能Web应用设计。通过简单步骤,你将学会创建首个Web应用。文章还深入探讨了路由配置、依赖注入及安全性配置等常见问题,并提供了实用示例代码以助于理解与避免错误,帮助开发者更好地掌握ASP.NET Core的核心概念。
82 3
|
19天前
|
开发框架 JavaScript 前端开发
一个适用于 ASP.NET Core 的轻量级插件框架
一个适用于 ASP.NET Core 的轻量级插件框架
|
2月前
|
开发框架 NoSQL .NET
利用分布式锁在ASP.NET Core中实现防抖
【9月更文挑战第5天】在 ASP.NET Core 中,可通过分布式锁实现防抖功能,仅处理连续相同请求中的首个请求,其余请求返回 204 No Content,直至锁释放。具体步骤包括:安装分布式锁库如 `StackExchange.Redis`;创建分布式锁服务接口及其实现;构建防抖中间件;并在 `Startup.cs` 中注册相关服务和中间件。这一机制有效避免了短时间内重复操作的问题。
|
2月前
|
开发框架 前端开发 JavaScript
ASP.NET MVC 教程
ASP.NET 是一个使用 HTML、CSS、JavaScript 和服务器脚本创建网页和网站的开发框架。
35 7
|
2月前
|
存储 开发框架 前端开发
ASP.NET MVC 迅速集成 SignalR
ASP.NET MVC 迅速集成 SignalR
49 0
|
3月前
|
开发框架 前端开发 .NET
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
ASP.NET MVC WebApi 接口返回 JOSN 日期格式化 date format
44 0
|
3月前
|
开发框架 前端开发 安全
ASP.NET MVC 如何使用 Form Authentication?
ASP.NET MVC 如何使用 Form Authentication?