热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

.NET支付宝App支付接入的实例分析

最近也是为了新产品忙得起飞,博客都更新的慢了。新产品为了方便用户支付,需要支付宝扫码接入。这活落到了我的身上。产品是Windows系统下的桌面软件,通过软件生成二维码支付。界面以原生的MVVM编写,下面叙述一下基本的过程,做过的老司机可以直接点关闭了。
一、前言

最近也是为了新产品忙得起飞,博客都更新的慢了。新产品为了方便用户支付,需要支付宝扫码接入。这活落到了我的身上。产品是Windows系统下的桌面软件,通过软件生成二维码支付。界面以原生的MVVM编写,下面叙述一下基本的过程,做过的老司机可以直接点关闭了。

二、申请接口

申请接口是第一步,首先有这么几件事:

  1. 公司具有支付宝账户

  2. 公司具有营业资质(废话)

  3. 创建应用,签约电脑网站支付,手机支付,App支付。

  4. 创建私钥、公钥、支付宝公钥

  5. 配置网关及回调地址

需要注意的是以下几点:

  1. 创建应用时,名称不要带有“支付”、“pay”等字样,图片建议高清

  2. 创建应用时,签约支付需要一些申请材料,如:营业资质照片,公司照片4张,应用的介绍(名称,下载地址,公司网站是否有该应用,该应用出现支付宝支付的界面样式)

  3. 签约后需要审核,大致一天,(阿里确实快,腾讯微信要4天),审核通过会发送一份邮件,里面有链接,点击链接完成签约

  4. 创建私钥、公钥、支付宝公钥,在支付宝接口网站上有官方工具,下载使用即可

  5. 网关与回调地址要与公司网站形成关联,比如是二级域名;如果网关、回调地址与公司网站没什么联系,恐怕不行。

三、代码流程

有三个构成元素。客户端软件,商户服务器后台,支付宝后台

客户端软件点击“获取支付二维码”去获得一个可支付的二维码:

封装客户端的一些必要信息发送给商户服务器后台形成一个商户订单

        /// 
        /// 获取二维码信息        /// 
        /// 封装信息
        /// 商户产品服务器地址
        /// 
        public static void GetQRCodeInfo(string packageClientInfo, string serverAddress, Action getQRCodeAction)
        {            if (!string.IsNullOrEmpty(packageClientInfo))
            {                try
                {
                    HttpClient httpsClient = new HttpClient
                    {
                        BaseAddress = new Uri(serverAddress),
                        Timeout = TimeSpan.FromMinutes(20)
                    };                    if (DsClientOperation.ConnectionTest(httpsClient))
                    {
                        StringContent strData = new StringContent(
                                                           packageClientInfo,
                                                           Encoding.UTF8,
                                                           RcCommonNames.JasonMediaType);                        
                                                           string PostUrl = httpsClient.BaseAddress + "api/AlipayForProduct/GetQRCodeString";
                        Uri address = new Uri(PostUrl);
                        Task respOnse= httpsClient.PostAsync(address, strData);
                        response.ContinueWith(
                            (postTask) =>
                            {                                
                            if (postTask.IsFaulted)
                                {                                    
                                throw postTask.Exception;
                                }
                                HttpResponseMessage postRespOnse= postTask.Result;
                                postResponse.EnsureSuccessStatusCode();                                
                                var result = postResponse.Content.ReadAsStringAsync().Result;
                                getQRCodeAction(JsonConvert.DeserializeObject(result)); //注意这个委托                      
                                          return result;
                            });
                    }
                }                catch
                {                    // ignored                }
            }
        }

这里的委托方法是用来生成二维码的,当你从这个“api/AlipayForProduct/GetQRCodeString”返回一些字符串(result),比如返回的是:

"http://xxx.xxx.com/AlipayForProduct/SendInfoToAlipay?ordernumber=" + $"{orderNumber}";(orderNumber为商户订单号)

然后使用ThoughtWorks.QRCode.dll去生成二维码

        /// 
        /// 根据字符串得到相应的二维码        /// 
        /// 
        /// 
        /// 
        /// 
        public static Image CreateQRCodeImage(string qrInfo, string productName, string version)
        {            try
            {                if (!string.IsNullOrEmpty(qrInfo))
                {
                    QRCodeEncoder encoder = new QRCodeEncoder
                    {
                        QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE,
                        QRCodeScale = 4,
                        QRCodeVersion = 0,
                        QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M
                    };                    
                    //编码方式(注意:BYTE能支持中文,ALPHA_NUMERIC扫描出来的都是数字)                    
                    //大小(值越大生成的二维码图片像素越高)                    
                    //版本(注意:设置为0主要是防止编码的字符串太长时发生错误)                    
                    //错误效验、错误更正(有4个等级)
                    Image image = encoder.Encode(qrInfo, Encoding.GetEncoding("utf-8"));                    
                    string filename = $"{productName}_{version}.png";                    
                    var userLocalPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);                    
                    var docPath = Path.Combine(userLocalPath, @"YourProduct\QRCode");                    
                    if (!Directory.Exists(docPath))
                    {
                        Directory.CreateDirectory(docPath);
                    }                    string filepath = Path.Combine(docPath, filename); 
                    using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        image.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
                        fs.Close();
                        image.Dispose();
                    }                    return image;
                }
            }            catch (Exception)
            {                return null;
            }            return null;
        }

这样就产生了二维码,说白了,就是把一个服务的api由字符串变成了图片,当用户使用支付宝app去扫这个二维码时,会去请求这个api:

"http://xxx.xxx.com/AlipayForProduct/SendInfoToAlipay?ordernumber=" + $"{orderNumber}";(orderNumber为商户订单号)

          orderNumber = Request[ (! matchedItem = db.OrderInfoForProduct.FirstOrDefault(x => x.OrderNumber == (matchedItem !=  && matchedItem.IsPaid == 
                     alipayServerURL =  app_id = privateKeyPem = format =  version =  signType = 
                     out_trade_no = orderNumber; 
                     product_code = ; 
                     total_amount = ;  
                     subject = ; 
                     body = ; =  returnurl = $ notifyurl == =  +                                      + body +  +                                      + subject +  +                                      + out_trade_no +  +                                      + total_amount +  +                                      + product_code +  +                                     
                    requestWap.SetReturnUrl(returnurl); = pNOne=  + responseWap.Body +

异步请求一般需要做这么几件事:

  1. 用户扫码支付完之后,支付宝后台会把所有需要验证的信息发给你,除了一个参数不需要验签完,其余都需要验签;

  2. 如果验签成功且支付状态也是成功交易后,你需要更新商户服务器后台关于此条商户订单的状态,比如将其支付状态变成已支付,填充支付时间等等;

 
          <, > sPara = (sPara.Count > 
                 sign_type = Request.Form[
                 seller_id = Request.Form[]; 
                 trade_status = Request.Form[]; 
                 notify_time = Request.Form[]; 
                 app_id = Request.Form[]; 
                 out_trade_no = Request.Form[]; 
                 total_amount = Request.Form[]; 
                 receipt_amount = Request.Form[]; 
                 invoice_amount = Request.Form[]; 
                 buyer_pay_amount = Request.Form[]; 
                 body = Request.Form[]; 
                 gmt_payment = Request.Form[]; 

                 tradeGuid = 
                 isVerfied = AlipaySignature.RSACheckV1(sPara, alipayPublicKey, , sign_type,  (app_id == appID && seller_id == isTradeSuccess = .Equals(trade_status, ) || .Equals(trade_status,  (

同步请求一般需要做这么几件事:

1. 当异步调用完后,如果支付成功而且商户服务器后台对此条订单号处理也正确的话;同步请求可以再做一次验证

2. 如果验证成功,跳转支付成功页面;如果失败,跳转支付失败页面。

        public ActionResult AlipayResult()
        {
            SortedDictionary sPara = GetRequestGet();            if (sPara.Count > 0)
            {                //非验签参数
                var sign_type = Request.QueryString["sign_type"];                //接收参数并排序
                var seller_id = Request.QueryString["seller_id"]; //卖家支付宝用户号
                var app_id = Request.QueryString["app_id"]; //开发者AppId
                var out_trade_no = Request.QueryString["out_trade_no"]; //交易订单号

                var orderNumberGuid = new Guid(out_trade_no);                try
                {                    var isVerfied = AlipaySignature.RSACheckV1(sPara, alipayPublicKey, "utf-8", sign_type, false);    
                                if (isVerfied)
                    {                        if (app_id == appID && seller_id == sellerID)
                        {
                           //你的支付成功页面
                        }
                    }

                }                catch
                {
                   //你的支付失败页面
                }
            }            else
            {               //你的支付失败页面
            }            return View();
        }        /// 
        /// 参数排序字典        /// 
        /// 
        private SortedDictionary GetRequestGet()
        {
            SortedDictionary sArray = new SortedDictionary();
            NameValueCollection coll = Request.QueryString;

            String[] requestItem = coll.AllKeys;            foreach (string t in requestItem)
            {
                sArray.Add(t, Request.QueryString[t]);
            }            return sArray;
        }

以上就是.NET支付宝App支付接入的实例分析的详细内容,更多请关注其它相关文章!


推荐阅读
  • STM32代码编写STM32端不需要写关于连接MQTT服务器的代码,连接的工作交给ESP8266来做,STM32只需要通过串口接收和发送数据,间接的与服务器交互。串口三配置串口一已 ... [详细]
  • 深入解析轻量级数据库 SQL Server Express LocalDB
    本文详细介绍了 SQL Server Express LocalDB,这是一种轻量级的本地 T-SQL 数据库解决方案,特别适合开发环境使用。文章还探讨了 LocalDB 与其他轻量级数据库的对比,并提供了安装和连接 LocalDB 的步骤。 ... [详细]
  • 解决远程桌面连接时的身份验证错误问题
    本文介绍了如何解决在尝试远程访问服务器时遇到的身份验证错误,特别是当系统提示‘要求的函数不受支持’时的具体解决步骤。通过调整Windows注册表设置,您可以轻松解决这一常见问题。 ... [详细]
  • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
  • 时序数据是指按时间顺序排列的数据集。通过时间轴上的数据点连接,可以构建多维度报表,揭示数据的趋势、规律及异常情况。 ... [详细]
  • 本文介绍了如何使用Workman框架构建一个功能全面的即时通讯系统,该系统不仅支持一对一聊天、群组聊天,还集成了视频会议和实时音视频通话功能,同时提供了红包发送等附加功能。 ... [详细]
  • 集群与负载均衡技术解析
    本文探讨了集群(Cluster)的概念,即通过网络连接的一组计算机系统,它们作为一个整体提供服务,实现分布式计算。文章还详细介绍了负载均衡技术,旨在提高网络服务的效率和可靠性。 ... [详细]
  • 构建高性能Feed流系统的设计指南
    随着移动互联网的发展,Feed流系统成为了众多社交应用的核心组成部分。本文将深入探讨如何设计一个高效、稳定的Feed流系统,涵盖从基础架构到高级特性的各个方面。 ... [详细]
  • 本文详细解析了Java中流的概念,特别是OutputStream和InputStream的区别,并通过实际案例介绍了如何实现Java对象的序列化。文章不仅解释了流的基本概念,还探讨了序列化的重要性和具体实现步骤。 ... [详细]
  • 本文介绍了如何使用C# Winform开发局域网内的文件传输功能,详细描述了从用户界面到后端网络通信的具体实现。 ... [详细]
  • 尤洋:夸父AI系统——大规模并行训练的深度学习解决方案
    自从AlexNet等模型在计算机视觉领域取得突破以来,深度学习技术迅速发展。近年来,随着BERT等大型模型的广泛应用,AI模型的规模持续扩大,对硬件提出了更高的要求。本文介绍了新加坡国立大学尤洋教授团队开发的夸父AI系统,旨在解决大规模模型训练中的并行计算挑战。 ... [详细]
  • Node.js 断点调试指南
    本文详细介绍了利用Google Chrome DevTools和Visual Studio Code两种工具进行Node.js应用的断点调试技巧。 ... [详细]
  • 现在的新手程序猿,动不动就是框架,就连外面培训的也是框架,我就问一句,没了框架是不是就啥也不会了 ... [详细]
  • 深入理解Java字节码:方法调用详解
    本文详细介绍了Java字节码中的方法调用机制,通过具体示例解析了字节码如何处理方法调用及其参数传递。文章由Mahmoud Anouti撰写,原文链接:https://dzone.com/articles/introduction-to-java-bytecode ... [详细]
  • 本文深入探讨了微信小程序直播中点赞动画的实现方法,特别是如何利用三阶贝塞尔曲线使点赞图标沿预设路径移动,以及相关的数学计算与代码实现。 ... [详细]
author-avatar
黄家驹1994
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有