ASP.NET Core 2.0 使用支付宝PC网站支付

前言

最近在使用ASP.NET Core来进行开发,刚好有个接入支付宝支付的需求,百度了一下没找到相关的资料,看了官方的SDK以及Demo都还是.NET Framework的,所以就先根据官方SDK的源码,用.NET Standard 2.0 实现了支付宝服务端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET CORE 2.0。为了使用方便,已上传至Nuget可以直接使用。

支付宝有比较多的支付产品,比如当面付、APP支付、手机网站支付、电脑网站支付等,本次将的是电脑网站支付。

如果你没有时间阅读文章,可以直接从github获取Demo原来进行查看,非常简单。github: https://github.com/stulzq/Alipay.Demo.PCPayment

创建项目

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

配置

由于我在开发的时候支付接口并没有申请下来,所以使用的是支付宝沙箱环境来进行开发的。

支付宝沙箱环境介绍:蚂蚁沙箱环境(Beta)是协助开发者进行接口功能开发及主要功能联调的辅助环境。沙箱环境模拟了开放平台部分产品的主要功能和主要逻辑,在开发者应用上线审核前,开发者可以根据自身需求,先在沙箱环境中了解、组合和调试各种开放接口,进行开发调通工作,从而帮助开发者在应用上线审核完成后,能更快速、更顺利的进行线上调试和验收工作。
如果在签约或创建应用前想要进行集成测试,可以使用沙箱环境。
沙箱环境支持使用个人账号或企业账号登陆。

沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info

1.生成密钥

下载支付宝官方提供的密钥生成工具来进行生成,详细介绍:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1

2.设置应用公钥

我们生成密钥之后,需要到支付宝后台设置应用公钥,就是我们生成的公钥。

设置之后,支付宝会给我们一个支付宝公钥,保存这个支付宝公钥

这个支付宝公钥和我们自己生成的公钥是不一样的,我们在配置SDK时用的公钥就是支付宝公钥

3.配置SDK

新建一个Config类,在里面存储我们的配置。

public class Config{    // 应用ID,您的APPIDpublic static string AppId = "";    // 支付宝网关public static string Gatewayurl = "";    // 商户私钥,您的原始格式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";
}
  • 应用ID和支付宝网关都可以在支付宝后台查看。

  • 商户私钥即我们自己生成的私钥,公钥就是支付宝公钥这里一定要注意,别用错了。这里的公钥私钥直接填写字符串即可。

  • 签名方式推荐使用RSA2,使用RSA2,支付宝会用SHA256withRsa算法进行接口调用时的验签(不限制密钥长度)。

  • 编码格式,如果我们是直接配置的字符串(公钥、私钥),那么就是我们代码的编码,如果使用的是文件(公钥、私钥),那么就是文件的编码。

  • 完成配置如下:

添加SDK

官方SDK的源码(.NET Framework),用.NET Standard 2.0 实现的支付宝服务端SDK,Alipay.AopSdk.Core(github:https://github.com/stulzq/Alipay.AopSdk.Core) ,支持.NET Core 2.0。
通过Nuget安装:Install-Package Alipay.AopSdk.Core

支付

添加一个控制器 PayController

/// 发起支付请求
/// </summary>
/// <param name="tradeno">外部订单号,商户网站订单系统中唯一的订单号</param>
/// <param name="subject">订单名称</param>
/// <param name="totalAmout">付款金额</param>
/// <param name="itemBody">商品描述</param>
/// <returns></returns>
[HttpPost]
public void PayRequest(string tradeno,string subject,string totalAmout,string itemBody){DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);    // 组装业务参数modelAlipayTradePagePayModel model = new AlipayTradePagePayModel();model.Body = itemBody;model.Subject = subject;model.TotalAmount = totalAmout;model.OutTradeNo = tradeno;model.ProductCode = "FAST_INSTANT_TRADE_PAY";AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();    // 设置同步回调地址request.SetReturnUrl("http://localhost:5000/Pay/Callback");    // 设置异步通知接收地址request.SetNotifyUrl("");    // 将业务model载入到requestrequest.SetBizModel(model);    var response = client.SdkExecute(request);Console.WriteLine($"订单支付发起成功,订单号:{tradeno}");    //跳转支付宝支付Response.Redirect(Config.Gatewayurl + "?" + response.Body); }

运行:

  • 图1

  • 图2

  • 图3

支付异步回调通知

支付宝同步回调通知(支付成功后跳转到商户网站),是不可靠的,所以这里必须使用异步通知来获取支付结果,异步通知即支付宝主动请求我们提供的地址,我们根据请求数据来校验,获取支付结果。

/// <summary>
/// 支付异步回调通知 需配置域名 因为是支付宝主动post请求这个action 所以要通过域名访问或者公网ip
/// </summary>
public async void Notify(){    
/* 实际验证过程建议商户添加以下校验。1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)4、验证app_id是否为该商户本身。*/Dictionary<string, string> sArray = GetRequestPost();  
 if (sArray.Count != 0){      
   bool flag = AlipaySignature.RSACheckV1(sArray, Config.AlipayPublicKey,Config.CharSet, Config.SignType, false);  
        if (flag){            //交易状态//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//请务必判断请求时的total_amount与通知时获取的total_fee为一致的//如果有做过处理,不执行商户的业务程序//注意://退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知Console.WriteLine(Request.Form["trade_status"]);            await Response.WriteAsync("success");}        else{            await Response.WriteAsync("fail");}} }

同步回调

同步回调即支付成功跳转回商户网站

运行:

/// <summary>
/// 支付同步回调
/// </summary>
[HttpGet]
public  IActionResult Callback(){  
 /* 实际验证过程建议商户添加以下校验。1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)4、验证app_id是否为该商户本身。*/Dictionary<string, string> sArray = GetRequestGet();    
 if (sArray.Count != 0){      
   bool flag = AlipaySignature.RSACheckV1(sArray, Config.AlipayPublicKey, Config.CharSet, Config.SignType, false);    
      if (flag){Console.WriteLine($"同步验证通过,订单号:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步验证通过";}        else{Console.WriteLine($"同步验证失败,订单号:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步验证失败";}}    return View(); }

订单查询

查询订单当前状态:已付款、未付款等等。

运行:

[HttpPost]
public JsonResult Query(string tradeno, string alipayTradeNo){DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);AlipayTradeQueryModel model = new AlipayTradeQueryModel();model.OutTradeNo = tradeno;model.TradeNo = alipayTradeNo;AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();request.SetBizModel(model);    var response = client.Execute(request);    return Json(response.Body); }

订单退款

退回该订单金额。

运行:

/// <summary>
/// 订单退款
/// </summary>
/// <param name="tradeno">商户订单号</param>
/// <param name="alipayTradeNo">支付宝交易号</param>
/// <param name="refundAmount">退款金额</param>
/// <param name="refundReason">退款原因</param>
/// <param name="refundNo">退款单号</param>
/// <returns></returns>[HttpPost]public JsonResult Refund(string tradeno,string alipayTradeNo,string refundAmount,string refundReason,string refundNo){DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);AlipayTradeRefundModel model = new AlipayTradeRefundModel();model.OutTradeNo = tradeno;model.TradeNo = alipayTradeNo;model.RefundAmount = refundAmount;model.RefundReason = refundReason;model.OutRequestNo = refundNo;AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();request.SetBizModel(model);    var response = client.Execute(request);    return Json(response.Body); }

退款查询

查询退款信息。

运行:

/// <summary>
/// 退款查询
/
// </summary>
/// <param name="tradeno">商户订单号</param>
/// <param name="alipayTradeNo">支付宝交易号</param>
/// <param name="refundNo">退款单号</param>
/// <returns></returns>
[HttpPost]
public JsonResult RefundQuery(string tradeno,string alipayTradeNo,string refundNo){DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);    if (string.IsNullOrEmpty(refundNo)){refundNo = tradeno;}AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel();model.OutTradeNo = tradeno;model.TradeNo = alipayTradeNo;model.OutRequestNo = refundNo;AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();request.SetBizModel(model);    var response = client.Execute(request);    return Json(response.Body); }

订单关闭

对一定时间以后没有进行付款的订单进行关闭,订单状态需为:待付款,已完成支付的订单无法关闭。

运行:

/// <summary>
/// 关闭订单
/// </summary>
/// <param name="tradeno">商户订单号</param>
/// <param name="alipayTradeNo">支付宝交易号</param>
/// <returns></returns>
[HttpPost]
public JsonResult OrderClose(string tradeno, string alipayTradeNo){DefaultAopClient client = new DefaultAopClient(Config.Gatewayurl, Config.AppId, Config.PrivateKey, "json", "2.0",Config.SignType, Config.AlipayPublicKey, Config.CharSet, false);AlipayTradeCloseModel model = new AlipayTradeCloseModel();model.OutTradeNo = tradeno;model.TradeNo = alipayTradeNo;AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();request.SetBizModel(model);    var response = client.Execute(request);    return Json(response.Body); }

地址集合

  • 支付宝API文档

  • 支付宝沙箱环境

  • 支付宝密钥生成工具

  • 支付宝服务端SDK源码

  • 支付宝服务端SDK Nuget

最重要的:

本文Demo:https://github.com/stulzq/Alipay.Demo.PCPayment

原文地址:http://www.cnblogs.com/stulzq/p/7606164.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql实现查询分组查询最后一次的记录

大家好&#xff0c;我是雄雄。 前言 又好久没有写博客了&#xff0c;为什么呢&#xff1f;因为最近没怎么写代码…说起来也惭愧。 今天在项目上遇到了个需求&#xff0c;是这样的&#xff1a;我们数据库中有一表检测记录表&#xff0c;该表中存储的是所有居民每次的检测记录&…

常用公有云接入——华为

一、介绍 1、什么是弹性云服务器? 弹性云服务器是由CPU、内存、镜像、云硬盘组成的一种可随时获取、弹性可扩展的计算服务器&#xff0c;同时它结合虚拟私有云、虚拟防火墙、数据多副本保存等能力&#xff0c;为您打造一个高效、可靠、安全的计算环境&#xff0c;确保您的服…

jenkins~集群分发功能和职责处理

jenkins的多节点集群 在进行自动化部署时&#xff0c;你可以按着它们的项目类型去进行分别部署&#xff0c;这样即可以达到负载均衡&#xff0c;又可以达到一种职责的明确&#xff0c;比如像java的项目你可以使用linux服务来进行部署&#xff08;拉代码&#xff0c;还原&#x…

nginx中配置https的步骤

大家好&#xff0c;我是雄雄。 想必大家都有过配置https的需求吧&#xff0c;今天我就来整理一下&#xff0c;如何在nginx里面配置https 这里先忽略https申请&#xff0c;一般在你申请域名的那里直接弄就行&#xff0c;下面是nginx中的配置代码&#xff1a; server {listen …

爬取网页图片

前言 这几天又看了下python的视频&#xff0c;突然又对python感兴趣起来。以前只是学了下python的基础&#xff0c;感觉和其他语言没什么大的区别&#xff0c;再加上编程游戏的插件pygame一直没装上&#xff0c;遂放弃了。 最近心血来潮突然又想用python来搞游戏开发&#xff…

sql中索引不会被用到的几种情况

转载自 sql中索引不会被用到的几种情况 1、查询谓词没有使用索引的主要边界,换句话说就是select *&#xff0c;可能会导致不走索引。 比如&#xff0c;你查询的是SELECT * FROM T WHERE YXXX;假如你的T表上有一个包含Y值的组合索引&#xff0c;但是优化器会认为需要一行行的…

asp.net core合并压缩资源文件引发的学习之旅

0. 在asp.net core中使用BuildBundlerMinifier合并压缩资源文件 在asp.net mvc中可以使用Bundle来压缩合并css,js 不知道的见&#xff1a;http://www.cnblogs.com/morang/p/7207176.html 在asp.net core中则可以使用BuildBundlerMinifier来进行css&#xff0c;js的压缩合并 新建…

新服务器中如何安装jdk(一行命令)

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 今天我们看看如何在服务器中安装jdk&#xff0c;这里指的服务器是linux。 服务器版本&#xff1a;centos 7.8 jdk版本&#xff1a;jdk1.8 下面我们来介绍下命令是什么&#xff1a; yum -…

关于腾讯云域名解析

前言 在浏览qq空间的时候看到了腾讯云的广告&#xff0c;只要一块钱即可注册一个.club域名。想起前段时间看的博客&#xff0c;自己早晚要入手网站搭方面的内容&#xff0c;按捺不住心悸&#xff0c;遂买了个域名&#xff0c;起了个叫woyidiankuan的域名&#xff0c;本来想写k…

linux服务器中如何安装mysql数据库(一次性完成,包含远程连接)

大家好。我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 今天给大家介绍一下&#xff0c;如何在新服务器中安装mysql数据库&#xff0c;总是捣鼓服务器&#xff0c;每次都去网上查&#xff0c;次次都不一样&#xff0c;浪费好多时间&#xff0c;这次自己记录…

Postman高级应用——流程控制、调试、公共函数、外部数据文件

postman客户端下载地址&#xff1a;https://www.getpostman.com/apps 流程控制 流程控制简言之就是设置接口的执行顺序&#xff0c;流程控制只有在collection runner或Newman里才生效 如果需要实现多个接口的一次循环&#xff0c;只需在每个接口的Tests中编写脚本 postman.setN…

ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: N O)

今天早上起来原想着学习python的&#xff0c;想看看mysql&#xff0c;于是陷进去了。 明明没碰啊&#xff0c;怎么突然就启动不了了呢 输入mysql net start mysql 一直显示正在启动&#xff0c;最后蹦出个服务无法启动 网上查了下输入 mysqld --initialize 早上的时候输入的…

如何将base64图像数据以图片的形式上传到云存储obs中

大家好&#xff0c;我是雄雄。欢迎关注微信公众号&#xff1a;雄雄的小课堂。 今天分享个方法&#xff0c;如标题所示&#xff1a; 在日常开发中&#xff0c;我们经常会有这样的需求&#xff0c;将前台拿到的base64图像格式的数据&#xff0c;上传到云存储服务器上&#xff0c…

linux上还原自主nuget包需要注意的问题

问题的产生的背景 由于我们使用了jenkins进行部署&#xff08;jenkins~集群分发功能和职责处理&#xff09;&#xff0c;而对于.net core项目来说又是跨平台的&#xff0c;所以对它的项目拉取&#xff0c;包的还原&#xff0c;项目的编译和项目的发布都是在一台linux的jenkins节…

python爬虫进阶(初始)

该内容主要是爬虫爬取图片以及html&#xff0c;属于库的基本内容&#xff0c;以后再在此基础上进阶更智能更全面的python代码 整体框架大致 目标&#xff1a; 下载图片 创建文件夹并在文件夹里加入东西 批量下载图片到文件夹里 筛选数据 批量筛选指定数据到文件夹里 将数据导入…

Net知识图谱

对于Web系统开发来说&#xff0c;Net其实也是有好多知识点需要学的&#xff0c;虽然目前JAVA是主流&#xff0c;就业市场比较大&#xff0c;但Net也在积极的拥抱开源&#xff0c;大Net Core 2 出来了&#xff0c;这无疑给Net开发者带来更大的希望&#xff0c;好了&#xff0c;以…

域名配置https时,请求无响应的解决方法

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 前言 在项目需要上线时&#xff0c;我们经常会遇到这样的需求&#xff0c;将http的域名换成https&#xff0c;或者当我们使用小程序开发时&#xff0c;只支持https的请求方式&#xff0c…

三步搭建网站

这两天无意中想了解更广泛的编程知识&#xff0c;便去看了些php的视频。我想把本机当成服务器来用&#xff0c;因为事先已经注册了域名&#xff0c;但当我又重新登录腾讯云的时候&#xff0c;上面显示我可以免费领取一个15天的服务器&#xff0c;抱着试一试的心态&#xff0c;领…

jenkins~集群分发功能的具体实现

前一讲主要说了jenkins分发的好处《jenkins~集群分发功能和职责处理》&#xff0c;它可以让具体的节点干自己具体的事&#xff0c;比如windows环境下的节点&#xff0c;它只负责编译&#xff0c;发布windows的生态环境的项目&#xff1b;而linux节点主要负责和它相关的项目&…

一个经典面试题:如何保证缓存与数据库的双写一致性?

转载自 一个经典面试题&#xff1a;如何保证缓存与数据库的双写一致性&#xff1f; 只要用缓存&#xff0c;就可能会涉及到缓存与数据库双存储双写&#xff0c;你只要是双写&#xff0c;就一定会有数据一致性的问题&#xff0c;那么你如何解决一致性问题&#xff1f; 面试题…