ASP.NET Core2.0 环境下MVC模式的支付宝PC网站支付接口-沙箱环境开发测试

news/2024/6/16 23:33:21/文章来源:https://blog.csdn.net/weixin_30577801/article/details/99363643

1.新建.NET Core web项目

2.Controllers-Models-Views 分三个大部分

3.下载安装最新sdk

官方的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下载安装,直接使用集成的SDK即可,道理和官网支付宝demo一个样。

通过Nuget安装:Install-Package Alipay.AopSdk.Core

4.首先要配置支付宝商户信息 在这里使用的是沙箱账号

新建一个配置类基本不用但是后续代码还是可以方便使用。

Config.cs

using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;namespace Alipay.PCPayment
{public class Config{// 应用ID,您的APPID 沙箱public static string AppId= "2016********3";/// <summary>/// 合作商户uid 沙箱/// </summary>public static string Uid= "208**********2";// 支付宝网关 沙箱地址public static string Gatewayurl="https://openapi.alipaydev.com/gateway.do";// 支付宝网关 生产地址// public static string Gatewayurl = "https://openapi.alipay.com/gateway.do";/// <summary>/// 异步通知 处理支付宝接口通知返回 获取是否是支付宝服务器发来的请求的验证结果/// </summary>/// <param name="notifyId">通知验证ID</param>/// <returns>验证结果</returns>public static async Task<string> VerifyNotifyAsync(string notifyId){return await SendAsync(Uid, notifyId);}/// <summary>///  //支付宝消息验证地址/// </summary>private const string API_URL = "https://mapi.alipay.com/gateway.do?service=notify_verify&";/// <summary>/// 获取是否是支付宝服务器发来的请求的验证结果/// </summary>/// <param name="partner">partner 合作身份ID</param>/// <param name="notify_id">通知验证ID</param>/// <returns>验证结果</returns>public static async Task<string> SendAsync(string partner, string notify_id){string strResult;string verifyUrl = API_URL + "partner=" + partner + "&notify_id=" + notify_id;//获取远程服务器ATN结果,验证是否是支付宝服务器发来的请求try{using (var client = new HttpClient()){//client.Timeout = 120000;var response = await client.GetAsync(verifyUrl);if (response.IsSuccessStatusCode){byte[] data = await response.Content.ReadAsByteArrayAsync();Encoding.UTF8.GetString(data);return strResult= "true";}}}catch (Exception exp){strResult = "错误信息:" + exp.Message;}return string.Empty;}
 public static ContentResult Response_Success(string msg = null)
        {
            return new ContentResult
            {
                Content = msg ?? "success"
            };
        }
        public static ContentResult ResponseFail(string msg = null)
        {
            return new ContentResult
            {
                Content = msg ?? "fail"
            };
        }
}}

 5. 添加一个控制器 PayController

using System;
using System.Collections.Generic;
using Alipay.AopSdk.AspnetCore;
using Alipay.AopSdk.Core;
using Alipay.AopSdk.Core.Domain;
using Alipay.AopSdk.Core.Request;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Alipay.Demo.PCPayment.Interfaces;
using Microsoft.Extensions.Logging;
namespace Alipay.PCPayment.Controllers
{   /// <summary>/// PC网站支付/// </summary>public class PayController : Controller{private readonly IAlipayService _alipayService;private readonly IAccounts _IAccounts;private readonly ILogger _logger;public PayController(IAlipayService alipayService,  ILogger<PayController> logger){_alipayService = alipayService;_logger = logger;}//_alipayService.Execute();#region 发起支付public IActionResult Index(){return View();}/// <summary>/// 发起支付请求/// </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{Body = itemBody,Subject = subject,TotalAmount = totalAmout,OutTradeNo = tradeno,ProductCode = "FAST_INSTANT_TRADE_PAY"};AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();// 设置同步回调地址 可以是调试模式地址 并非公网或域名地址 Pay走的是控制器的request.SetReturnUrl("http://190.120.120.01:110/Pay/Callback");// 设置异步通知接收地址 必须是公网或域名地址 Pay走的是控制器的方法request.SetNotifyUrl("http://50.200.50.10:110/Pay/AlipayNotify");// 将业务model载入到request
            request.SetBizModel(model);var response = _alipayService.SdkExecute(request);Console.WriteLine($"订单支付发起成功,订单号:{tradeno}");//跳转支付宝支付 支付网关地址Response.Redirect(Config.Gatewayurl + "?" + response.Body);}#endregion
支付异步回调通知 使用异步通知来获取支付结果,异步通知即支付宝主动请求我们提供的地址,我们根据请求数据来校验,获取支付结果。
#region 支付异步回调通知/// <summary>/// 异步通知即支付宝主动请求我们提供的地址,我们根据请求数据来校验,获取支付结果。/// 支付异步回调通知 需配置域名 因为是支付宝主动post请求这个action 所以要通过域名访问或者公网ip/// </summary>//public async Task<IActionResult> AlipayNotify([FromForm]Dictionary<string,string> NotifyArray)public async Task<IActionResult> AlipayNotify(){/* 实际验证过程建议商户添加以下校验。1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)*/Dictionary<string, string> NotifyArray = GetRequestPost();//通知验证IDstring notifyId = NotifyArray["notify_id"];try{ if (NotifyArray.Count != 0){ //验签以及验证合作伙伴IDbool flag = _alipayService.RSACheckV1(NotifyArray);if (await Config.VerifyNotifyAsync(notifyId) == "true" && flag){//交易状态if (NotifyArray["trade_status"] == "TRADE_FINISHED" ||NotifyArray["trade_status"] == "TRADE_SUCCESS"){if (NotifyArray["app_id"] == Config.AppId){ // 修改支付信息以及状态//return await UpdateAliPayAsyn(NotifyArray); }}await Response.WriteAsync("success");}else{await Response.WriteAsync("fail");}}}catch (Exception e){_logger.LogError("Alipay notify fail, {0}", e);}return View();//string msg = null;//return new ContentResult//{// Content = msg ?? "fail"//}; }/// <summary>/// 更新支付宝支付结果信息/// 判断该笔订单是否已经做过处理///如果没有做过处理,根据订单号(out_trade_no)在商户的订单系统中查到该笔订单的详细,并执行商户的业务程序///请务必判断请求时的total_amount与通知时获取的total_fee为一致的///如果有做过处理,不执行商户的业务程序/// </summary>/// <param name="dict"></param>/// <returns></returns>//private async Task<ContentResult> UpdateAliPayAsyn(Dictionary<string, string> dict)//{// //获取支付的订单号// string msg = null;// var orderNO = await accountsOrder.GetOrderAsync(dict["out_trade_no"]);// if (orderNO == null || !accountsOrder.ReadyOrderStatus(orderNO))// {// _logger.LogInformation("充值订单号不存在");// // return new ContentResult// {// Content = msg ?? "fail"// };// }// //if (!EqualAmountAliPay(order.PayPrice, dict["total_amount"]))// //{// // return AliPay.ResponseFail("订单金额不匹配");// //}// 更新订单支付通知结果// //if (await accountsOrder.UpdateOrderAsync(order))// //{// // await accountsOrder.SaveAliPayNotifyDataAsync(dict);// // _logger.LogInformation("[支付宝]支付成功,系统于 " + dtStartTime.ToString() + " 接收到请求,于 " + dict["notify_time"] + " 完成处理,交易流水号:" + dict["trade_no"] + ",交易单号:" + dict["out_trade_no"], "支付宝日志");// // return AliPay.ResponseSuccess();// //}// //else// //{// // _logger.LogInformation("[支付宝]订单号:" + dict["out_trade_no"] + "状态:" + dict["trade_status"], "支付宝日志");// // if (dict["trade_status"] == "TRADE_CLOSED")// // {// // return AliPay.ResponseSuccess();// // }// // else// // { //成功// // if (order.PayStatus == 1)// // {// // _logger.LogInformation("[支付宝]已支付过:" + order.RechargeOrderNO, "支付宝日志");// // return AliPay.ResponseSuccess();// // }// // else// // //等待支付// // {// // _logger.LogInformation("[支付宝]未支付:" + order.RechargeOrderNO, "支付宝日志");// // return AliPay.ResponseFail("等待支付");// // }// // }// return new ContentResult// {// Content = msg ?? "fail"// };// }#endregion

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

        #region 支付同步回调/// <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 = _alipayService.RSACheckV1(sArray);if (flag){Console.WriteLine($"同步验证通过,订单号:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步验证通过";Response.Redirect("http://190.120.120.01:110/");}else{Console.WriteLine($"同步验证失败,订单号:{sArray["out_trade_no"]}");ViewData["PayResult"] = "同步验证失败";}}return View();}#endregion#region 解析请求参数private Dictionary<string, string> GetRequestGet(){Dictionary<string, string> sArray = new Dictionary<string, string>();ICollection<string> requestItem = Request.Query.Keys;foreach (var item in requestItem){sArray.Add(item, Request.Query[item]);}return sArray;}/// <summary>/// 获取返回的请求结果/// </summary>/// <returns></returns>private Dictionary<string, string> GetRequestPost(){Dictionary<string, string> sArray = new Dictionary<string, string>();ICollection<string> requestItem = Request.Form.Keys;foreach (var item in requestItem){sArray.Add(item, Request.Form[item]);}return sArray;}#endregion    }
} }

 7.支付订单信息页面

Index.cshtml 支付请求action POST

@{ViewData["Title"] = "PC网站支付";
}
<h2>PC网站支付</h2>
<div class="row"><div class="col-sm-12" s><form  asp-action="PayRequest" method="post" 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="subject" class="control-label col-sm-2">订单名称:</label><div class="col-sm-10"><input type="text" name="subject" class="form-control" id="subject" value="iPhone X" /></div></div><div class="form-group"><label for="totalAmout" class="control-label col-sm-2">付款金额:</label><div class="col-sm-10"><input type="number" min="0.01" name="totalAmout" class="form-control" id="totalAmout" value="99.99" /></div></div><div class="form-group"><label for="itemBody" class="control-label col-sm-2">商品描述:</label><div class="col-sm-10"><input type="text"  name="itemBody" class="form-control" id="itemBody" value="苹果手机" /></div></div><div class="form-group"><div class="col-sm-10 col-sm-offset-2"><button class="btn btn-success btn-block">付款</button><p class="help-block text-center">如果您点击“付款”按钮,即表示您同意该次的执行操作。</p></div></div></form></div></div><script>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>

 8.配置系统启动项目信息

Startup.cs

public class Startup{public Startup(IConfiguration configuration){Configuration = configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){services.AddMvc();Console.WriteLine(Configuration["Alipay:AlipayPublicKey"]);services.AddAlipay(options =>{options.AlipayPublicKey = Configuration["Alipay:AlipayPublicKey"];options.AppId = Configuration["Alipay:AppId"];options.CharSet = Configuration["Alipay:CharSet"];options.Gatewayurl = Configuration["Alipay:Gatewayurl"];options.PrivateKey = Configuration["Alipay:PrivateKey"];options.SignType = Configuration["Alipay:SignType"];options.Uid = Configuration["Alipay:Uid"];}).AddAlipayF2F();}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory){loggerFactory.AddConsole(Configuration.GetSection("Logging"));loggerFactory.AddDebug();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();app.UseBrowserLink();}else{app.UseExceptionHandler("/Home/Error");}app.UseStaticFiles();app.UseMvc(routes =>{routes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}");});}}

appsettings.json

{"Logging": {"IncludeScopes": false,"LogLevel": {"Default": "Error"}},"WriteTo": ["LiterateConsole",{"Name": "RollingFile","Args": { "pathFormat": "logs\\log-{Date}.txt" }}],"Alipay": {"AlipayPublicKey": "/fVCQx+B+++++HLB7K9yTNoBWBGsOsNpTiErj2wqdyOp8KVSp/5P1","AppId": "2016******03","CharSet": "UTF-8","Gatewayurl": "https://openapi.alipaydev.com/gateway.do","PrivateKey": "/eQ1ykzA5hecyw4K/+/pIFjLm/M/+/vj0gy+eqabgVUjyOLDuEc"\",": null,"SignType": "RSA2","Uid": "208********2"}
}

9、支付演示
支付请求页面

 

跳转到支付宝支付网关沙箱地址

 拿起手机APP沙箱版的进行扫码支付 或者进行沙箱账号买家账户登录支付

支付成功提示页面

 

转载于:https://www.cnblogs.com/Warmsunshine/p/7904609.html

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

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

相关文章

postgis安装_从零开始,构建电子地图网站:0_2_数据处理postgis

软件安装完&#xff0c;开始数据处理。从China Historical GIS下载一份数据。一、数据下载数据来源&#xff1a;China Historical GIS&#xff1a;https://sites.fas.harvard.edu/~chgis/data/chgis/v6/先下载一份时间序列数据&#xff1a;Download CHGIS V6 TIME SERIES Datah…

fis pure开发php,50个精品网站鉴赏

50个精品网站鉴赏介绍给大家的是几千个世界优秀网站中的精中之精的作品&#xff0c;都有非常不错的创意&#xff0c;推荐给众多网站的设计人员&#xff0c;好好借鉴一下别人是怎么设计网站的。这些网站主要的制作工具为FLASH&#xff0c;因为它有较好、较强的动态效果&#xff…

前端工程师必备的几个实用网站

一、配色类网站 http://colorhunt.co 这个网站给我们提供了很多的配色方案&#xff0c;我们直接使用就OK了。使用方法也很简单&#xff0c;鼠标移动到对应的颜色上&#xff0c;我们就可以看到颜色的十六进制码&#xff0c;复制这个颜色到工具里就可以使用了。 https://webgra…

使用prismjs为网站添加代码高亮功能

prismjs 是一款轻量、可扩展的代码语法高亮库&#xff0c;使用现代化的 Web 标准构建&#xff0c;使用 Prismjs 可以快速为网站添加代码高亮功能&#xff0c;支持超过113中编程语言&#xff0c;还支持多种插件&#xff0c;是简洁、高效的代码高亮解决方案。科技爱好者博客就是使…

d4d#9 玩Docker只要浏览器就够了,PWD是个神奇的网站

本文是d4d系列的第9篇&#xff0c;在这一篇中给大家介绍一个学习Docker最为快捷高效的方式&#xff0c;你不需要自己搭建环境&#xff0c;也不用担心把自己的开发环境搞乱&#xff0c;你需要的只是一个浏览器&#xff0c;就可以立即开始学习Docker的常用命令&#xff1b;你甚至…

图的顺序存储(邻接矩阵存储)【摘录自严长生老师的网站】

图是表达多对多关系的一种数据结构&#xff0c;组成要素为顶点和连接顶点的边。 根据边有无方向可分为有向图和无向图 当边有权重时&#xff0c;升级为有向网和无向网 图在存储时&#xff0c;可采用邻接矩阵&#xff0c;比如下面的无向图&#xff08;A&#xff09;和&#xff0…

怎么将自己做好的网站发布到互联网上呢?

如何将自己的网站上传到网站空间。 1.需要有一个上传网站的软件&#xff0c;在这里推荐大家使用 FTP全称是flashfxp这个软件&#xff0c;这个功能功能齐全而且操作简单。大家可以先去下载一下这个软 件 2. 打开FTP&#xff0c;界面如下 3.我们要点击链接按钮&#xff0c;然后FT…

左斜杠和右斜杠有什么区别_「斜杠云」SEO推广和SEO优化有什么区别?

1&#xff0c;首先&#xff0c;从概念上来说&#xff0c;网络推广就是企业从开始申请域名、租用空间、网站备-案、建立网站、直到网站正式上线开始就算是介入了网络推广活动&#xff0c;而通常我们所指的网络推广是指通过互联网的种种手段&#xff0c;进行的宣传推广等活动&…

php前台用户权限开通,vue实现网站前台的权限管理

本文主要介绍了基于vue实现网站前台的权限管理(前后端分离实践)&#xff0c;小编觉得挺不错的&#xff0c;现在分享给大家&#xff0c;也给大家做个参考。一起跟随小编过来看看吧&#xff0c;希望能帮助到大家。Javascript做为当下的热门语言&#xff0c;用途很广泛&#xff0c…

文件服务器磁盘配额管理,Windows2008 (FSRM)文件服务器资源管理器网站文件夹磁盘配额管理...

在windows server里提供了一个功能强大的管理工具&#xff0c;就是文件服务器资源管理器。简称FSRM(File Server Resource Manager)通过此工具&#xff0c;可能对网站进去配额以及相关服务。我们通过使用FSRM&#xff0c;可以为文件夹和卷设置配额&#xff0c;主动屏蔽文件&…

23套新鲜出炉的网站和手机界面 PSD 素材

Web 用户界面&#xff0c;移动用户界面和线框套件对设计师很有用&#xff0c;因为这些套件让他们使用快速和有效的方式复制用户界面。这些类型的工具包提供了一个基本的用户界面元素&#xff0c;用于它们需要制作的网站或软件模型。 在这篇文章中&#xff0c;我们展示的是自由和…

经典案例:2012年最佳25个响应式网站设计作品《下篇》

2012年&#xff0c;响应式网站设计成为主流&#xff0c;这个概念由著名网页设计师 Ethan Marcotte 在2010年5月份提出&#xff0c;其目标是要让设计的网站能够响应用户的行为&#xff0c;根据不同终端设备自动调整尺寸。 响应式设计不再只是一个概念&#xff0c;众多大公司也把…

网站页面左右_广州网站优化的技巧是什么?

说到网站优化&#xff0c;大家都不陌生&#xff0c;但首先&#xff0c;我们知道为什么要优化网站吗?我们网站优化是为了改善网站在百度&#xff0c;搜狗等搜索引擎搜索结果排名中的网站页面&#xff0c;以增强搜索引擎的流量。下面拓王朝广州网站优化公司小编针对网站的优化技…

支持在iPad中播放的HTML5视频网站推荐

YouTube是最早支持HTML5视频的网站&#xff0c;随着iPad等平板电脑的流行&#xff0c;越来越多的视频网站开始支持HTML5视频播放。下面就向大家分享一些国内的HTML5视频网站&#xff0c;是根据网上信息整理而成&#xff0c;欢迎大家反馈和推荐更多的HTML5视频网站。 腾讯 优酷…

获取 HTML5 网页设计灵感的10个网站推荐

这篇文章向大家推荐10个收集 HTML5 网页作品的网站&#xff0c;让大家感受一下 HTML5 的魅力。作为下一代网页标准&#xff0c;HTML5 增加了很多新标签以及新特性&#xff0c;正引领网页技术革命。希望这些优秀的 HTML5 网页案例能带给大家制作 HTML5 网页的灵感。 HTML5 Gall…

12款精美的免费 HTML 网站模板下载

这篇文章收集了12款精美的免费HTML网站模板分享给大家&#xff0c;您可以免费下载使用。相信这些漂亮的HTML网站模板既能够帮助您节省大量的时间和精力&#xff0c;又能有很满意的效果。感谢那些优秀的设计师分享他们的劳动成果&#xff0c;让更多的人可以使用他们的创意设计&a…

非常酷!10个基于 HTML5 的字体应用演示网站

HTML5 是现在Web开发领域的热点&#xff0c;更多的开发人员开始使用HTML5来开发交互性强、效果出众的网站和各种应用。这是 HTML5 网站大观系列第四篇&#xff0c;本文与大家分享5个非常酷的基于 HTML5 的字体应用演示网站&#xff0c;一起欣赏。 Web Typography For The Lone…

通过小程序实现网站扫码登录!每年都可以省 300 块...代替微信开放平台和服务号的登陆模式!

我们知道&#xff0c;要接入微信登陆有两种方式 1、微信开放平台2、微信服务号 这两种方式均可生成带参数的二维码&#xff0c;然后扫码获取用户基本信息的&#xff0c;所以我们可以在网站上用这两种方式开发网站的扫码登录&#xff0c;也是现在很多网站的通用做法。 微信开…

php如何清理网站缓存,php怎么清除opcache缓存

php清除opcache缓存的方法&#xff1a;1、开发环境中修改php.ini文件&#xff0c;将“opcache.revalidate_freq”的值改为1&#xff1b;2、在线上环境中&#xff0c;可以在PHP文件中执行“opcache_reset();”代码&#xff0c;重启web服务器。本教程操作环境&#xff1a;windows…

html 拼接onmouseout,HTML onmouseout事件用法及代码示例

将鼠标指针移出元素或其子元素时&#xff0c;将发生HTML DOM onmouseout事件。用法:在HTML中&#xff1a;在JavaScript中&#xff1a;object.onmouseout function(){myScript};在JavaScript中&#xff0c;使用addEventListener()方法&#xff1a;object.addEventListener(&quo…